summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/contexts/projects/update_context.rb8
-rw-r--r--app/controllers/dashboard_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb1
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/controllers/projects/notes_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb20
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/models/ability.rb37
-rw-r--r--app/models/issue.rb14
-rw-r--r--app/models/merge_request.rb14
-rw-r--r--app/models/note.rb15
-rw-r--r--app/models/project.rb17
-rw-r--r--app/views/dashboard/projects.html.haml4
-rw-r--r--app/views/projects/_home_panel.html.haml4
-rw-r--r--app/views/projects/edit.html.haml27
15 files changed, 147 insertions, 23 deletions
diff --git a/app/contexts/projects/update_context.rb b/app/contexts/projects/update_context.rb
index 55a4a6abecb..ed0d451a31a 100644
--- a/app/contexts/projects/update_context.rb
+++ b/app/contexts/projects/update_context.rb
@@ -10,13 +10,7 @@ module Projects
new_branch = params[:project].delete(:default_branch)
if project.repository.exists? && new_branch != project.default_branch
- GitlabShellWorker.perform_async(
- :update_repository_head,
- project.path_with_namespace,
- new_branch
- )
-
- project.reload_default_branch
+ project.change_head(new_branch)
end
project.update_attributes(params[:project], as: role)
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 045e5805bd0..aaab4b40c4c 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -73,6 +73,6 @@ class DashboardController < ApplicationController
protected
def load_projects
- @projects = current_user.authorized_projects.sorted_by_activity
+ @projects = current_user.authorized_projects.sorted_by_activity.non_archived
end
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 5dcdba5d388..e7b4c837ae3 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -74,6 +74,7 @@ class Projects::IssuesController < Projects::ApplicationController
def update
@issue.update_attributes(params[:issue].merge(author_id_of_changes: current_user.id))
+ @issue.reset_events_cache
respond_to do |format|
format.js
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 7d7c1104ec9..6d39673194a 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -97,6 +97,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if @merge_request.update_attributes(params[:merge_request].merge(author_id_of_changes: current_user.id))
@merge_request.reload_code
@merge_request.mark_as_unchecked
+ @merge_request.reset_events_cache
redirect_to [@merge_request.target_project, @merge_request], notice: 'Merge request was successfully updated.'
else
render "edit"
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 2738a99459d..5ff5c5b7d96 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -39,6 +39,7 @@ class Projects::NotesController < Projects::ApplicationController
@note = @project.notes.find(params[:id])
return access_denied! unless can?(current_user, :admin_note, @note)
@note.destroy
+ @note.reset_events_cache
respond_to do |format|
format.js { render nothing: true }
@@ -50,6 +51,7 @@ class Projects::NotesController < Projects::ApplicationController
return access_denied! unless can?(current_user, :admin_note, @note)
@note.update_attributes(params[:note])
+ @note.reset_events_cache
respond_to do |format|
format.js do
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 1835671fe98..e1c55e7d913 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -5,7 +5,7 @@ class ProjectsController < ApplicationController
# Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create]
- before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer]
+ before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
before_filter :require_non_empty_project, only: [:blob, :tree, :graph]
layout 'navless', only: [:new, :create, :fork]
@@ -116,6 +116,24 @@ class ProjectsController < ApplicationController
end
end
+ def archive
+ return access_denied! unless can?(current_user, :archive_project, project)
+ project.archive!
+
+ respond_to do |format|
+ format.html { redirect_to @project }
+ end
+ end
+
+ def unarchive
+ return access_denied! unless can?(current_user, :archive_project, project)
+ project.unarchive!
+
+ respond_to do |format|
+ format.html { redirect_to @project }
+ end
+ end
+
private
def set_title
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 109acfd192b..f24156e4d85 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -73,14 +73,14 @@ module SearchHelper
# Autocomplete results for the current user's projects
def projects_autocomplete
- current_user.authorized_projects.map do |p|
+ current_user.authorized_projects.non_archived.map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
end
end
# Autocomplete results for the current user's projects
def public_projects_autocomplete
- Project.public_or_internal_only(current_user).map do |p|
+ Project.public_or_internal_only(current_user).non_archived.map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) }
end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 6df56eed5b8..cf925141f2d 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -59,31 +59,35 @@ class Ability
# Rules based on role in project
if team.masters.include?(user)
- rules << project_master_rules
+ rules += project_master_rules
elsif team.developers.include?(user)
- rules << project_dev_rules
+ rules += project_dev_rules
elsif team.reporters.include?(user)
- rules << project_report_rules
+ rules += project_report_rules
elsif team.guests.include?(user)
- rules << project_guest_rules
+ rules += project_guest_rules
end
if project.public? || project.internal?
- rules << public_project_rules
+ rules += public_project_rules
end
if project.owner == user || user.admin?
- rules << project_admin_rules
+ rules += project_admin_rules
end
if project.group && project.group.has_owner?(user)
- rules << project_admin_rules
+ rules += project_admin_rules
end
- rules.flatten
+ if project.archived?
+ rules -= project_archived_rules
+ end
+
+ rules
end
def public_project_rules
@@ -125,6 +129,16 @@ class Ability
]
end
+ def project_archived_rules
+ [
+ :write_merge_request,
+ :push_code,
+ :push_code_to_protected_branches,
+ :modify_merge_request,
+ :admin_merge_request
+ ]
+ end
+
def project_master_rules
project_dev_rules + [
:push_code_to_protected_branches,
@@ -147,7 +161,8 @@ class Ability
:change_namespace,
:change_visibility_level,
:rename_project,
- :remove_project
+ :remove_project,
+ :archive_project
]
end
@@ -160,7 +175,7 @@ class Ability
# Only group owner and administrators can manage group
if group.has_owner?(user) || user.admin?
- rules << [
+ rules += [
:manage_group,
:manage_namespace
]
@@ -174,7 +189,7 @@ class Ability
# Only namespace owner and administrators can manage it
if namespace.owner == user || user.admin?
- rules << [
+ rules += [
:manage_namespace
]
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index d350b237d37..b3609cf2f45 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -64,4 +64,18 @@ class Issue < ActiveRecord::Base
def gfm_reference
"issue ##{iid}"
end
+
+ # Reset issue events cache
+ #
+ # Since we do cache @event we need to reset cache in special cases:
+ # * when an issue is updated
+ # Events cache stored like events/23-20130109142513.
+ # The cache key includes updated_at timestamp.
+ # Thus it will automatically generate a new fragment
+ # when the event is updated because the key changes.
+ def reset_events_cache
+ Event.where(target_id: self.id, target_type: 'Issue').
+ order('id DESC').limit(100).
+ update_all(updated_at: Time.now)
+ end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index e862f35819c..e59aee8b445 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -305,6 +305,20 @@ class MergeRequest < ActiveRecord::Base
self.target_project.repository.branch_names.include?(self.target_branch)
end
+ # Reset merge request events cache
+ #
+ # Since we do cache @event we need to reset cache in special cases:
+ # * when a merge request is updated
+ # Events cache stored like events/23-20130109142513.
+ # The cache key includes updated_at timestamp.
+ # Thus it will automatically generate a new fragment
+ # when the event is updated because the key changes.
+ def reset_events_cache
+ Event.where(target_id: self.id, target_type: 'MergeRequest').
+ order('id DESC').limit(100).
+ update_all(updated_at: Time.now)
+ end
+
private
def dump_commits(commits)
diff --git a/app/models/note.rb b/app/models/note.rb
index 8284da8616f..b23f7df7742 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -239,4 +239,19 @@ class Note < ActiveRecord::Base
def noteable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end
+
+ # Reset notes events cache
+ #
+ # Since we do cache @event we need to reset cache in special cases:
+ # * when a note is updated
+ # * when a note is removed
+ # Events cache stored like events/23-20130109142513.
+ # The cache key includes updated_at timestamp.
+ # Thus it will automatically generate a new fragment
+ # when the event is updated because the key changes.
+ def reset_events_cache
+ Event.where(target_id: self.id, target_type: 'Note').
+ order('id DESC').limit(100).
+ update_all(updated_at: Time.now)
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 506f34ca6b6..1bfc27d723d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -116,6 +116,8 @@ class Project < ActiveRecord::Base
scope :public_only, -> { where(visibility_level: PUBLIC) }
scope :public_or_internal_only, ->(user) { where("visibility_level IN (:levels)", levels: user ? [ INTERNAL, PUBLIC ] : [ PUBLIC ]) }
+ scope :non_archived, -> { where(archived: false) }
+
enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
class << self
@@ -132,7 +134,7 @@ class Project < ActiveRecord::Base
end
def search query
- joins(:namespace).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
+ joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
end
def find_with_namespace(id)
@@ -472,4 +474,17 @@ class Project < ActiveRecord::Base
def visibility_level_field
visibility_level
end
+
+ def archive!
+ update_attribute(:archived, true)
+ end
+
+ def unarchive!
+ update_attribute(:archived, false)
+ end
+
+ def change_head(branch)
+ gitlab_shell.update_repository_head(self.path_with_namespace, branch)
+ reload_default_branch
+ end
end
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
index b42bbf58dc4..23d78720881 100644
--- a/app/views/dashboard/projects.html.haml
+++ b/app/views/dashboard/projects.html.haml
@@ -82,6 +82,10 @@
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
.project-info
.pull-right
+ - if project.archived?
+ %span.label
+ %i.icon-book
+ Archived
- project.labels.each do |label|
%span.label.label-info
%i.icon-tag
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 19c150b54fb..ae5deb0b6de 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -7,6 +7,10 @@
%span.visibility-level-label
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
+ - if @project.archived?
+ %span.visibility-level-label
+ %i.icon-book
+ Archived
.span7
- unless empty_repo
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 57936cff10f..c56919e792c 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -98,6 +98,33 @@
%i.icon-chevron-down
.js-toggle-visibility-container.hide
+ - if can? current_user, :archive_project, @project
+ .ui-box.ui-box-danger
+ .title
+ - if @project.archived?
+ Unarchive project
+ - else
+ Archive project
+ .ui-box-body
+ - if @project.archived?
+ %p
+ Unarchiving the project will mark its repository as active.
+ %br
+ The project can be committed to.
+ %br
+ %strong Once active this project shows up in the search and on the dashboard.
+ = link_to 'Unarchive', unarchive_project_path(@project), confirm: "Are you sure that you want to unarchive this project?\nWhen this project is unarchived it is active and can be comitted to again.", method: :post, class: "btn btn-remove"
+ - else
+ %p
+ Archiving the project will mark its repository as read-only.
+ %br
+ It is hidden from the dashboard and doesn't show up in searches.
+ %br
+ %strong Archived projects cannot be committed to!
+ = link_to 'Archive', archive_project_path(@project), confirm: "Are you sure that you want to archive this project?\nAn archived project cannot be committed to.", method: :post, class: "btn btn-remove"
+ - else
+ %p.nothing_here_message Only the project owner can archive a project
+
- if can?(current_user, :change_namespace, @project)
.ui-box.ui-box-danger
.title Transfer project