Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorMarin Jankovski <maxlazio@gmail.com>2015-01-27 09:12:53 +0300
committerMarin Jankovski <maxlazio@gmail.com>2015-01-27 09:12:53 +0300
commit0da59cb55bfc8b6bb50f45d0ccdb19edc8b0a6e9 (patch)
tree52a372f621a96f5261f926968141313f29cf6da3 /app
parent33913f9b8fef1f8df45dc26239faf8fa4cffc982 (diff)
parente6b97d09470b01b5b65e87dab339c500f1bac45f (diff)
Merge branch 'master' into move_external_issue_tracker_away_from_yml_config
Conflicts: app/models/project.rb spec/models/project_spec.rb
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee1
-rw-r--r--app/assets/javascripts/project_avatar.js.coffee9
-rw-r--r--app/assets/stylesheets/generic/avatar.scss20
-rw-r--r--app/assets/stylesheets/generic/buttons.scss5
-rw-r--r--app/assets/stylesheets/generic/highlight.scss8
-rw-r--r--app/assets/stylesheets/main/variables.scss2
-rw-r--r--app/assets/stylesheets/sections/dashboard.scss21
-rw-r--r--app/assets/stylesheets/sections/diff.scss6
-rw-r--r--app/assets/stylesheets/sections/projects.scss18
-rw-r--r--app/controllers/passwords_controller.rb4
-rw-r--r--app/controllers/projects/avatars_controller.rb29
-rw-r--r--app/controllers/projects/base_tree_controller.rb7
-rw-r--r--app/controllers/projects/blame_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb98
-rw-r--r--app/controllers/projects/commits_controller.rb2
-rw-r--r--app/controllers/projects/edit_tree_controller.rb60
-rw-r--r--app/controllers/projects/network_controller.rb2
-rw-r--r--app/controllers/projects/new_tree_controller.rb20
-rw-r--r--app/controllers/projects/protected_branches_controller.rb2
-rw-r--r--app/controllers/projects/raw_controller.rb2
-rw-r--r--app/controllers/projects/refs_controller.rb2
-rw-r--r--app/controllers/projects/services_controller.rb8
-rw-r--r--app/controllers/projects/tree_controller.rb9
-rw-r--r--app/controllers/projects_controller.rb42
-rw-r--r--app/helpers/application_helper.rb64
-rw-r--r--app/helpers/blob_helper.rb38
-rw-r--r--app/helpers/projects_helper.rb6
-rw-r--r--app/helpers/tree_helper.rb38
-rw-r--r--app/models/project.rb95
-rw-r--r--app/services/files/create_service.rb19
-rw-r--r--app/services/issues/close_service.rb2
-rw-r--r--app/services/issues/update_service.rb2
-rw-r--r--app/services/merge_requests/auto_merge_service.rb2
-rw-r--r--app/services/merge_requests/close_service.rb2
-rw-r--r--app/services/merge_requests/merge_service.rb2
-rw-r--r--app/services/merge_requests/reopen_service.rb2
-rw-r--r--app/services/merge_requests/update_service.rb2
-rw-r--r--app/services/notification_service.rb44
-rw-r--r--app/services/projects/autocomplete_service.rb4
-rw-r--r--app/services/projects/fork_service.rb9
-rw-r--r--app/views/dashboard/_project.html.haml2
-rw-r--r--app/views/dashboard/_projects.html.haml4
-rw-r--r--app/views/dashboard/projects.html.haml2
-rw-r--r--app/views/groups/_projects.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml2
-rw-r--r--app/views/projects/blob/edit.html.haml (renamed from app/views/projects/edit_tree/show.html.haml)11
-rw-r--r--app/views/projects/blob/new.html.haml (renamed from app/views/projects/new_tree/show.html.haml)2
-rw-r--r--app/views/projects/blob/preview.html.haml (renamed from app/views/projects/edit_tree/preview.html.haml)0
-rw-r--r--app/views/projects/edit.html.haml29
-rw-r--r--app/views/projects/empty.html.haml14
-rw-r--r--app/views/projects/services/index.html.haml25
-rw-r--r--app/views/projects/tree/_tree.html.haml2
-rw-r--r--app/views/users/_groups.html.haml2
53 files changed, 523 insertions, 284 deletions
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 9457f88817f..acce4ad5096 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -96,6 +96,7 @@ class Dispatcher
new Profile()
when 'projects'
new Project()
+ new ProjectAvatar()
switch path[1]
when 'edit'
shortcut_handler = new ShortcutsNavigation()
diff --git a/app/assets/javascripts/project_avatar.js.coffee b/app/assets/javascripts/project_avatar.js.coffee
new file mode 100644
index 00000000000..8bec6e2ccca
--- /dev/null
+++ b/app/assets/javascripts/project_avatar.js.coffee
@@ -0,0 +1,9 @@
+class @ProjectAvatar
+ constructor: ->
+ $('.js-choose-project-avatar-button').bind 'click', ->
+ form = $(this).closest('form')
+ form.find('.js-project-avatar-input').click()
+ $('.js-project-avatar-input').bind 'change', ->
+ form = $(this).closest('form')
+ filename = $(this).val().replace(/^.*[\\\/]/, '')
+ form.find('.js-avatar-filename').text(filename)
diff --git a/app/assets/stylesheets/generic/avatar.scss b/app/assets/stylesheets/generic/avatar.scss
index 4e0e546872b..b6886206739 100644
--- a/app/assets/stylesheets/generic/avatar.scss
+++ b/app/assets/stylesheets/generic/avatar.scss
@@ -8,10 +8,11 @@
&.avatar-inline {
float: none;
- margin-left: 3px;
+ margin-left: 4px;
+ margin-bottom: 2px;
- &.s16 { margin-right: 2px; }
- &.s24 { margin-right: 2px; }
+ &.s16 { margin-right: 4px; }
+ &.s24 { margin-right: 4px; }
}
&.s16 { width: 16px; height: 16px; margin-right: 6px; }
@@ -22,3 +23,16 @@
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
&.s160 { width: 160px; height: 160px; margin-right: 20px; }
}
+
+.identicon {
+ text-align: center;
+ vertical-align: top;
+
+ &.s16 { font-size: 12px; line-height: 1.33; }
+ &.s24 { font-size: 14px; line-height: 1.8; }
+ &.s26 { font-size: 20px; line-height: 1.33; }
+ &.s32 { font-size: 24px; line-height: 1.33; }
+ &.s60 { font-size: 45px; line-height: 1.33; }
+ &.s90 { font-size: 68px; line-height: 1.33; }
+ &.s160 { font-size: 120px; line-height: 1.33; }
+}
diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss
index d098f1ecaa2..3b360275065 100644
--- a/app/assets/stylesheets/generic/buttons.scss
+++ b/app/assets/stylesheets/generic/buttons.scss
@@ -173,6 +173,11 @@
margin-right: 0px;
}
}
+
+ &.btn-lg {
+ font-size: 15px;
+ line-height: 1.4;
+ }
}
.btn-block {
diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/generic/highlight.scss
index 83dc7ab491a..e1ca86af816 100644
--- a/app/assets/stylesheets/generic/highlight.scss
+++ b/app/assets/stylesheets/generic/highlight.scss
@@ -10,8 +10,8 @@
border: none;
border-radius: 0;
font-family: $monospace_font;
- font-size: 12px !important;
- line-height: 16px !important;
+ font-size: $code_font_size !important;
+ line-height: $code_line_height !important;
margin: 0;
overflow: auto;
overflow-y: hidden;
@@ -38,8 +38,8 @@
a {
font-family: $monospace_font;
display: block;
- font-size: 12px !important;
- line-height: 16px !important;
+ font-size: $code_font_size !important;
+ line-height: $code_line_height !important;
white-space: nowrap;
i {
diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss
index 6bbce70a782..acbf5be94a3 100644
--- a/app/assets/stylesheets/main/variables.scss
+++ b/app/assets/stylesheets/main/variables.scss
@@ -59,3 +59,5 @@ $list-font-size: 15px;
$sidebar_width: 230px;
$avatar_radius: 50%;
+$code_font_size: 13px;
+$code_line_height: 1.5;
diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss
index e540f7ff940..90010781af0 100644
--- a/app/assets/stylesheets/sections/dashboard.scss
+++ b/app/assets/stylesheets/sections/dashboard.scss
@@ -75,6 +75,9 @@
}
}
}
+.project-avatar {
+ float: left;
+}
.project-description {
overflow: hidden;
@@ -92,8 +95,24 @@
}
}
+.dash-project-avatar {
+ float: left;
+}
.dash-project-access-icon {
float: left;
- margin-right: 3px;
+ margin-right: 5px;
width: 16px;
}
+
+.dash-new-project {
+ background: $bg_success;
+ border: 1px solid $border_success;
+
+ a {
+ color: #FFF;
+ }
+}
+
+.dash-list .str-truncated {
+ max-width: 72%;
+}
diff --git a/app/assets/stylesheets/sections/diff.scss b/app/assets/stylesheets/sections/diff.scss
index 758f15c8013..da50dbe4715 100644
--- a/app/assets/stylesheets/sections/diff.scss
+++ b/app/assets/stylesheets/sections/diff.scss
@@ -37,7 +37,7 @@
overflow-y: hidden;
background: #FFF;
color: #333;
- font-size: 12px;
+ font-size: $code_font_size;
.old {
span.idiff {
background-color: #F99;
@@ -64,8 +64,8 @@
margin: 0px;
padding: 0px;
td {
- line-height: 18px;
- font-size: 12px;
+ line-height: $code_line_height;
+ font-size: $code_font_size;
}
}
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index 93c0c2bc518..0a7671e3feb 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -16,6 +16,8 @@
.project-home-panel {
margin-bottom: 15px;
+ position: relative;
+ padding-left: 85px;
&.empty-project {
border-bottom: 0px;
@@ -23,6 +25,22 @@
margin-bottom: 0px;
}
+ .project-identicon-holder {
+ position: absolute;
+ left: 0;
+
+ .avatar {
+ width: 70px;
+ height: 70px;
+ @include border-radius(0px);
+ }
+
+ .identicon {
+ font-size: 45px;
+ line-height: 1.6;
+ }
+ }
+
.project-home-dropdown {
margin-left: 10px;
float: right;
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index 988ede3007b..dcbbe5baa4b 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -5,12 +5,12 @@ class PasswordsController < Devise::PasswordsController
resource_found = resource_class.find_by_email(email)
if resource_found && resource_found.ldap_user?
flash[:alert] = "Cannot reset password for LDAP user."
- respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name)) and return
+ respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) and return
end
self.resource = resource_class.send_reset_password_instructions(resource_params)
if successfully_sent?(resource)
- respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
+ respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with(resource)
end
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
new file mode 100644
index 00000000000..a482b90880d
--- /dev/null
+++ b/app/controllers/projects/avatars_controller.rb
@@ -0,0 +1,29 @@
+class Projects::AvatarsController < Projects::ApplicationController
+ layout 'project'
+
+ before_filter :project
+
+ def show
+ @blob = @project.repository.blob_at_branch('master', @project.avatar_in_git)
+ if @blob
+ headers['X-Content-Type-Options'] = 'nosniff'
+ send_data(
+ @blob.data,
+ type: @blob.mime_type,
+ disposition: 'inline',
+ filename: @blob.name
+ )
+ else
+ not_found!
+ end
+ end
+
+ def destroy
+ @project.remove_avatar!
+
+ @project.save
+ @project.reset_events_cache
+
+ redirect_to edit_project_path(@project)
+ end
+end
diff --git a/app/controllers/projects/base_tree_controller.rb b/app/controllers/projects/base_tree_controller.rb
deleted file mode 100644
index a7b1b7b40e8..00000000000
--- a/app/controllers/projects/base_tree_controller.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class Projects::BaseTreeController < Projects::ApplicationController
- include ExtractsPath
-
- before_filter :authorize_download_code!
- before_filter :require_non_empty_project
-end
-
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 367d1295f34..106f21b83e6 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -2,7 +2,7 @@
class Projects::BlameController < Projects::ApplicationController
include ExtractsPath
- # Authorize
+ before_filter :assign_ref_vars
before_filter :authorize_download_code!
before_filter :require_non_empty_project
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 2412800c493..b471d57f698 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -2,16 +2,70 @@
class Projects::BlobController < Projects::ApplicationController
include ExtractsPath
- # Authorize
+ # Raised when given an invalid file path
+ class InvalidPathError < StandardError; end
+
before_filter :authorize_download_code!
- before_filter :require_non_empty_project
+ before_filter :require_non_empty_project, except: [:new, :create]
before_filter :authorize_push_code!, only: [:destroy]
+ before_filter :assign_blob_vars
+ before_filter :commit, except: [:new, :create]
+ before_filter :blob, except: [:new, :create]
+ before_filter :from_merge_request, only: [:edit, :update]
+ before_filter :after_edit_path, only: [:edit, :update]
+ before_filter :require_branch_head, only: [:edit, :update]
+
+ def new
+ commit unless @repository.empty?
+ end
- before_filter :blob
+ def create
+ file_path = File.join(@path, File.basename(params[:file_name]))
+ result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+
+ if result[:status] == :success
+ flash[:notice] = "Your changes have been successfully committed"
+ redirect_to project_blob_path(@project, File.join(@ref, file_path))
+ else
+ flash[:alert] = result[:message]
+ render :new
+ end
+ end
def show
end
+ def edit
+ @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
+ end
+
+ def update
+ result = Files::UpdateService.
+ new(@project, current_user, params, @ref, @path).execute
+
+ if result[:status] == :success
+ flash[:notice] = "Your changes have been successfully committed"
+
+ if from_merge_request
+ from_merge_request.reload_code
+ end
+
+ redirect_to after_edit_path
+ else
+ flash[:alert] = result[:message]
+ render :edit
+ end
+ end
+
+ def preview
+ @content = params[:content]
+ diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
+ include_diff_info: true)
+ @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
+
+ render layout: false
+ end
+
def destroy
result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute
@@ -46,10 +100,44 @@ class Projects::BlobController < Projects::ApplicationController
if @blob
@blob
- elsif tree.entries.any?
- redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
else
+ if tree = @repository.tree(@commit.id, @path)
+ if tree.entries.any?
+ redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
+ end
+ end
+
return not_found!
end
end
+
+ def commit
+ @commit = @repository.commit(@ref)
+
+ return not_found! unless @commit
+ end
+
+ def assign_blob_vars
+ @id = params[:id]
+ @ref, @path = extract_ref(@id)
+
+
+ rescue InvalidPathError
+ not_found!
+ end
+
+ def after_edit_path
+ @after_edit_path ||=
+ if from_merge_request
+ diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
+ "#file-path-#{hexdigest(@path)}"
+ else
+ project_blob_path(@project, @id)
+ end
+ end
+
+ def from_merge_request
+ # If blob edit was initiated from merge request page
+ @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
+ end
end
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 9476b6c0284..0a85c36a758 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -3,7 +3,7 @@ require "base64"
class Projects::CommitsController < Projects::ApplicationController
include ExtractsPath
- # Authorize
+ before_filter :assign_ref_vars
before_filter :authorize_download_code!
before_filter :require_non_empty_project
diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
deleted file mode 100644
index 65661c80410..00000000000
--- a/app/controllers/projects/edit_tree_controller.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-class Projects::EditTreeController < Projects::BaseTreeController
- before_filter :require_branch_head
- before_filter :blob
- before_filter :authorize_push_code!
- before_filter :from_merge_request
- before_filter :after_edit_path
-
- def show
- @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
- end
-
- def update
- result = Files::UpdateService.
- new(@project, current_user, params, @ref, @path).execute
-
- if result[:status] == :success
- flash[:notice] = "Your changes have been successfully committed"
-
- if from_merge_request
- from_merge_request.reload_code
- end
-
- redirect_to after_edit_path
- else
- flash[:alert] = result[:message]
- render :show
- end
- end
-
- def preview
- @content = params[:content]
-
- diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
- include_diff_info: true)
- @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
-
- render layout: false
- end
-
- private
-
- def blob
- @blob ||= @repository.blob_at(@commit.id, @path)
- end
-
- def after_edit_path
- @after_edit_path ||=
- if from_merge_request
- diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
- "#file-path-#{hexdigest(@path)}"
- else
- project_blob_path(@project, @id)
- end
- end
-
- def from_merge_request
- # If blob edit was initiated from merge request page
- @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
- end
-end
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index ada1aed0df7..59f2a745367 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -2,7 +2,7 @@ class Projects::NetworkController < Projects::ApplicationController
include ExtractsPath
include ApplicationHelper
- # Authorize
+ before_filter :assign_ref_vars
before_filter :authorize_download_code!
before_filter :require_non_empty_project
diff --git a/app/controllers/projects/new_tree_controller.rb b/app/controllers/projects/new_tree_controller.rb
deleted file mode 100644
index ffba706b2f6..00000000000
--- a/app/controllers/projects/new_tree_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class Projects::NewTreeController < Projects::BaseTreeController
- before_filter :require_branch_head
- before_filter :authorize_push_code!
-
- def show
- end
-
- def update
- file_path = File.join(@path, File.basename(params[:file_name]))
- result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
-
- if result[:status] == :success
- flash[:notice] = "Your changes have been successfully committed"
- redirect_to project_blob_path(@project, File.join(@ref, file_path))
- else
- flash[:alert] = result[:message]
- render :show
- end
- end
-end
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index 02160d973b3..f45df38b87c 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -24,7 +24,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
)
respond_to do |format|
- format.json { render :json => protected_branch, status: :ok }
+ format.json { render json: protected_branch, status: :ok }
end
else
respond_to do |format|
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index fdbc4c5a098..84888265dc1 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -2,7 +2,7 @@
class Projects::RawController < Projects::ApplicationController
include ExtractsPath
- # Authorize
+ before_filter :assign_ref_vars
before_filter :authorize_download_code!
before_filter :require_non_empty_project
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 67665f5f601..cede0ebe0ae 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -1,7 +1,7 @@
class Projects::RefsController < Projects::ApplicationController
include ExtractsPath
- # Authorize
+ before_filter :assign_ref_vars
before_filter :authorize_download_code!
before_filter :require_non_empty_project
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index a2cb4ae1ae9..c7cc38b9c67 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -29,9 +29,13 @@ class Projects::ServicesController < Projects::ApplicationController
def test
data = Gitlab::PushDataBuilder.build_sample(project, current_user)
- @service.execute(data)
+ if @service.execute(data)
+ message = { notice: 'We sent a request to the provided URL' }
+ else
+ message = { alert: 'We tried to send a request to the provided URL but error occured' }
+ end
- redirect_to :back
+ redirect_to :back, message
end
private
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 4d033b36848..5b52640a4e1 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -1,7 +1,12 @@
# Controller for viewing a repository's file structure
-class Projects::TreeController < Projects::BaseTreeController
- def show
+class Projects::TreeController < Projects::ApplicationController
+ include ExtractsPath
+
+ before_filter :assign_ref_vars
+ before_filter :authorize_download_code!
+ before_filter :require_non_empty_project, except: [:new, :create]
+ def show
if tree.entries.empty?
if @repository.blob_at(@commit.id, @path)
redirect_to project_blob_path(@project, File.join(@ref, @path)) and return
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 7fc283ef3d4..ebe48265c63 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -14,7 +14,7 @@ class ProjectsController < ApplicationController
end
def edit
- render 'edit', layout: "project_settings"
+ render 'edit', layout: 'project_settings'
end
def create
@@ -36,7 +36,7 @@ class ProjectsController < ApplicationController
format.html { redirect_to edit_project_path(@project), notice: 'Project was successfully updated.' }
format.js
else
- format.html { render "edit", layout: "project_settings" }
+ format.html { render 'edit', layout: 'project_settings' }
format.js
end
end
@@ -66,17 +66,17 @@ class ProjectsController < ApplicationController
format.html do
if @project.repository_exists?
if @project.empty_repo?
- render "projects/empty", layout: user_layout
+ render 'projects/empty', layout: user_layout
else
@last_push = current_user.recent_push(@project.id) if current_user
render :show, layout: user_layout
end
else
- render "projects/no_repo", layout: user_layout
+ render 'projects/no_repo', layout: user_layout
end
end
- format.json { pager_json("events/_events", @events.count) }
+ format.json { pager_json('events/_events', @events.count) }
end
end
@@ -87,9 +87,9 @@ class ProjectsController < ApplicationController
respond_to do |format|
format.html do
- flash[:alert] = "Project deleted."
+ flash[:alert] = 'Project deleted.'
- if request.referer.include?("/admin")
+ if request.referer.include?('/admin')
redirect_to admin_projects_path
else
redirect_to projects_dashboard_path
@@ -104,22 +104,15 @@ class ProjectsController < ApplicationController
autocomplete = ::Projects::AutocompleteService.new(@project)
participants = ::Projects::ParticipantsService.new(@project).execute(note_type, note_id)
- emojis = Emoji.names.map do |e|
- {
- name: e,
- path: view_context.image_url("emoji/#{e}.png")
- }
- end
-
@suggestions = {
- emojis: emojis,
+ emojis: autocomplete_emojis,
issues: autocomplete.issues,
mergerequests: autocomplete.merge_requests,
members: participants
}
respond_to do |format|
- format.json { render :json => @suggestions }
+ format.json { render json: @suggestions }
end
end
@@ -148,7 +141,7 @@ class ProjectsController < ApplicationController
if link_to_image
format.json { render json: { link: link_to_image } }
else
- format.json { render json: "Invalid file.", status: :unprocessable_entity }
+ format.json { render json: 'Invalid file.', status: :unprocessable_entity }
end
end
end
@@ -179,14 +172,25 @@ class ProjectsController < ApplicationController
end
def user_layout
- current_user ? "projects" : "public_projects"
+ current_user ? 'projects' : 'public_projects'
end
def project_params
params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
- :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id
+ :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar
)
end
+
+ def autocomplete_emojis
+ Rails.cache.fetch("autocomplete-emoji-#{Emoji::VERSION}") do
+ Emoji.names.map do |e|
+ {
+ name: e,
+ path: view_context.image_url("emoji/#{e}.png")
+ }
+ end
+ end
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index f65e04af205..104ae517a08 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -50,6 +50,38 @@ module ApplicationHelper
args.any? { |v| v.to_s.downcase == action_name }
end
+ def project_icon(project_id, options = {})
+ project = Project.find_with_namespace(project_id)
+ if project.avatar.present?
+ image_tag project.avatar.url, options
+ elsif project.avatar_in_git
+ image_tag project_avatar_path(project), options
+ else # generated icon
+ project_identicon(project, options)
+ end
+ end
+
+ def project_identicon(project, options = {})
+ allowed_colors = {
+ red: 'FFEBEE',
+ purple: 'F3E5F5',
+ indigo: 'E8EAF6',
+ blue: 'E3F2FD',
+ teal: 'E0F2F1',
+ orange: 'FBE9E7',
+ gray: 'EEEEEE'
+ }
+
+ options[:class] ||= ''
+ options[:class] << ' identicon'
+ bg_key = project.id % 7
+
+ content_tag(:div, class: options[:class],
+ style: "background-color: ##{ allowed_colors.values[bg_key] }; color: #555") do
+ project.name[0, 1].upcase
+ end
+ end
+
def group_icon(group_path)
group = Group.find_by(path: group_path)
if group && group.avatar.present?
@@ -82,24 +114,24 @@ module ApplicationHelper
if project.repo_exists?
time_ago_with_tooltip(project.repository.commit.committed_date)
else
- "Never"
+ 'Never'
end
rescue
- "Never"
+ 'Never'
end
def grouped_options_refs
repository = @project.repository
options = [
- ["Branches", repository.branch_names],
- ["Tags", VersionSorter.rsort(repository.tag_names)]
+ ['Branches', repository.branch_names],
+ ['Tags', VersionSorter.rsort(repository.tag_names)]
]
# If reference is commit id - we should add it to branch/tag selectbox
if(@ref && !options.flatten.include?(@ref) &&
@ref =~ /^[0-9a-zA-Z]{6,52}$/)
- options << ["Commit", [@ref]]
+ options << ['Commit', [@ref]]
end
grouped_options_for_select(options, @ref || @project.default_branch)
@@ -161,7 +193,7 @@ module ApplicationHelper
path = controller.controller_path.split('/')
namespace = path.first if path.second
- [namespace, controller.controller_name, controller.action_name].compact.join(":")
+ [namespace, controller.controller_name, controller.action_name].compact.join(':')
end
# shortcut for gitlab config
@@ -176,13 +208,13 @@ module ApplicationHelper
def search_placeholder
if @project && @project.persisted?
- "Search in this project"
+ 'Search in this project'
elsif @snippet || @snippets || @show_snippets
'Search snippets'
elsif @group && @group.persisted?
- "Search in this group"
+ 'Search in this group'
else
- "Search"
+ 'Search'
end
end
@@ -193,7 +225,7 @@ module ApplicationHelper
def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago')
capture_haml do
haml_tag :time, date.to_s,
- class: html_class, datetime: date.getutc.iso8601, title: date.stamp("Aug 21, 2011 9:23pm"),
+ class: html_class, datetime: date.getutc.iso8601, title: date.stamp('Aug 21, 2011 9:23pm'),
data: { toggle: 'tooltip', placement: placement }
haml_tag :script, "$('." + html_class + "').timeago().tooltip()"
@@ -216,8 +248,8 @@ module ApplicationHelper
end
def spinner(text = nil, visible = false)
- css_class = "loading"
- css_class << " hide" unless visible
+ css_class = 'loading'
+ css_class << ' hide' unless visible
content_tag :div, class: css_class do
content_tag(:i, nil, class: 'fa fa-spinner fa-spin') + text
@@ -234,17 +266,17 @@ module ApplicationHelper
absolute_uri = nil
end
- # Add "nofollow" only to external links
+ # Add 'nofollow' only to external links
if host && host != Gitlab.config.gitlab.host && absolute_uri
if html_options
if html_options[:rel]
- html_options[:rel] << " nofollow"
+ html_options[:rel] << ' nofollow'
else
- html_options.merge!(rel: "nofollow")
+ html_options.merge!(rel: 'nofollow')
end
else
html_options = Hash.new
- html_options[:rel] = "nofollow"
+ html_options[:rel] = 'nofollow'
end
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 3a282803963..e75eebd2da9 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -19,4 +19,42 @@ module BlobHelper
def no_highlight_files
%w(credits changelog copying copyright license authors)
end
+
+ def edit_blob_link(project, ref, path, options = {})
+ blob =
+ begin
+ project.repository.blob_at(ref, path)
+ rescue
+ nil
+ end
+
+ if blob && blob.text?
+ text = 'Edit'
+ after = options[:after] || ''
+ from_mr = options[:from_merge_request_id]
+ link_opts = {}
+ link_opts[:from_merge_request_id] = from_mr if from_mr
+ cls = 'btn btn-small'
+ if allowed_tree_edit?(project, ref)
+ link_to text, project_edit_blob_path(project, tree_join(ref, path),
+ link_opts), class: cls
+ else
+ content_tag :span, text, class: cls + ' disabled'
+ end + after.html_safe
+ else
+ ''
+ end
+ end
+
+ def leave_edit_message
+ "Leave edit mode?\nAll unsaved changes will be lost."
+ end
+
+ def editing_preview_title(filename)
+ if Gitlab::MarkdownHelper.previewable?(filename)
+ 'Preview'
+ else
+ 'Preview changes'
+ end
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 9f2b8277a92..eab9a5d2e14 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -175,7 +175,11 @@ module ProjectsHelper
"Issues - " + title
end
elsif current_controller?(:blob)
- "#{@project.path}\/#{@blob.path} at #{@ref} - " + title
+ if current_action?(:new) || current_action?(:create)
+ "New file at #{@ref}"
+ elsif @blob
+ "Edit file #{@blob.path} at #{@ref}"
+ end
elsif current_controller?(:commits)
"Commits at #{@ref} - " + title
elsif current_controller?(:merge_requests)
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 1d987a6ffc0..727ec3fb231 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -64,32 +64,6 @@ module TreeHelper
::Gitlab::GitAccess.can_push_to_branch?(current_user, project, ref)
end
- def edit_blob_link(project, ref, path, options = {})
- blob =
- begin
- project.repository.blob_at(ref, path)
- rescue
- nil
- end
-
- if blob && blob.text?
- text = 'Edit'
- after = options[:after] || ''
- from_mr = options[:from_merge_request_id]
- link_opts = {}
- link_opts[:from_merge_request_id] = from_mr if from_mr
- cls = 'btn btn-small'
- if allowed_tree_edit?(project, ref)
- link_to text, project_edit_tree_path(project, tree_join(ref, path),
- link_opts), class: cls
- else
- content_tag :span, text, class: cls + ' disabled'
- end + after.html_safe
- else
- ''
- end
- end
-
def tree_breadcrumbs(tree, max_links = 2)
if @path.present?
part_path = ""
@@ -121,16 +95,4 @@ module TreeHelper
return tree.name
end
end
-
- def leave_edit_message
- "Leave edit mode?\nAll unsaved changes will be lost."
- end
-
- def editing_preview_title(filename)
- if Gitlab::MarkdownHelper.previewable?(filename)
- 'Preview'
- else
- 'Diff'
- end
- end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 43b61897a3c..12751bb77e6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -14,7 +14,7 @@
# merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null
# namespace_id :integer
-# issues_tracker :string(255) default("gitlab"), not null
+# issues_tracker :string(255) default('gitlab'), not null
# issues_tracker_id :string(255)
# snippets_enabled :boolean default(TRUE), not null
# last_activity_at :datetime
@@ -26,8 +26,12 @@
# star_count :integer default(0), not null
# import_type :string(255)
# import_source :string(255)
+# avatar :string(255)
#
+require 'carrierwave/orm/activerecord'
+require 'file_size_validator'
+
class Project < ActiveRecord::Base
include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel
@@ -49,8 +53,8 @@ class Project < ActiveRecord::Base
attr_accessor :new_default_branch
# Relations
- belongs_to :creator, foreign_key: "creator_id", class_name: "User"
- belongs_to :group, -> { where(type: Group) }, foreign_key: "namespace_id"
+ belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
+ belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id'
belongs_to :namespace
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id'
@@ -75,19 +79,20 @@ class Project < ActiveRecord::Base
has_one :custom_issue_tracker_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
+
has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it
- has_many :merge_requests, dependent: :destroy, foreign_key: "target_project_id"
+ has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id'
# Merge requests from source project should be kept when source project was removed
- has_many :fork_merge_requests, foreign_key: "source_project_id", class_name: MergeRequest
+ has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
has_many :issues, -> { order 'issues.state DESC, issues.created_at DESC' }, dependent: :destroy
has_many :labels, dependent: :destroy
has_many :services, dependent: :destroy
has_many :events, dependent: :destroy
has_many :milestones, dependent: :destroy
has_many :notes, dependent: :destroy
- has_many :snippets, dependent: :destroy, class_name: "ProjectSnippet"
- has_many :hooks, dependent: :destroy, class_name: "ProjectHook"
+ has_many :snippets, dependent: :destroy, class_name: 'ProjectSnippet'
+ has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy
has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
has_many :users, through: :project_members
@@ -119,22 +124,27 @@ class Project < ActiveRecord::Base
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
validates :import_url,
- format: { with: URI::regexp(%w(git http https)), message: "should be a valid url" },
+ format: { with: URI::regexp(%w(git http https)), message: 'should be a valid url' },
if: :import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
+ validate :avatar_type,
+ if: ->(project) { project.avatar && project.avatar_changed? }
+ validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
+
+ mount_uploader :avatar, AttachmentUploader
# Scopes
- scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
- scope :without_team, ->(team) { team.projects.present? ? where("projects.id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped }
- scope :not_in_group, ->(group) { where("projects.id NOT IN (:ids)", ids: group.project_ids ) }
- scope :in_team, ->(team) { where("projects.id IN (:ids)", ids: team.projects.map(&:id)) }
+ scope :without_user, ->(user) { where('projects.id NOT IN (:ids)', ids: user.authorized_projects.map(&:id) ) }
+ scope :without_team, ->(team) { team.projects.present? ? where('projects.id NOT IN (:ids)', ids: team.projects.map(&:id)) : scoped }
+ scope :not_in_group, ->(group) { where('projects.id NOT IN (:ids)', ids: group.project_ids ) }
+ scope :in_team, ->(team) { where('projects.id IN (:ids)', ids: team.projects.map(&:id)) }
scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
scope :in_group_namespace, -> { joins(:group) }
- scope :sorted_by_activity, -> { reorder("projects.last_activity_at DESC") }
- scope :sorted_by_stars, -> { reorder("projects.star_count DESC") }
+ scope :sorted_by_activity, -> { reorder('projects.last_activity_at DESC') }
+ scope :sorted_by_stars, -> { reorder('projects.star_count DESC') }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
- scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
+ scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
scope :public_only, -> { where(visibility_level: Project::PUBLIC) }
scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) }
scope :non_archived, -> { where(archived: false) }
@@ -185,26 +195,26 @@ class Project < ActiveRecord::Base
end
def active
- joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
+ joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC')
end
def search(query)
- joins(:namespace).where("projects.archived = ?", false).
- where("LOWER(projects.name) LIKE :query OR
+ joins(:namespace).where('projects.archived = ?', false).
+ where('LOWER(projects.name) LIKE :query OR
LOWER(projects.path) LIKE :query OR
LOWER(namespaces.name) LIKE :query OR
- LOWER(projects.description) LIKE :query",
+ LOWER(projects.description) LIKE :query',
query: "%#{query.try(:downcase)}%")
end
def search_by_title(query)
- where("projects.archived = ?", false).where("LOWER(projects.name) LIKE :query", query: "%#{query.downcase}%")
+ where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end
def find_with_namespace(id)
- return nil unless id.include?("/")
+ return nil unless id.include?('/')
- id = id.split("/")
+ id = id.split('/')
namespace = Namespace.find_by(path: id.first)
return nil unless namespace
@@ -222,7 +232,7 @@ class Project < ActiveRecord::Base
when 'recently_updated' then reorder('projects.updated_at DESC')
when 'last_updated' then reorder('projects.updated_at ASC')
when 'largest_repository' then reorder('projects.repository_size DESC')
- else reorder("namespaces.path, projects.name ASC")
+ else reorder('namespaces.path, projects.name ASC')
end
end
end
@@ -272,19 +282,19 @@ class Project < ActiveRecord::Base
end
def to_param
- namespace.path + "/" + path
+ namespace.path + '/' + path
end
def web_url
- [gitlab_config.url, path_with_namespace].join("/")
+ [gitlab_config.url, path_with_namespace].join('/')
end
def web_url_without_protocol
- web_url.split("://")[1]
+ web_url.split('://')[1]
end
def build_commit_note(commit)
- notes.new(commit_id: commit.id, noteable_type: "Commit")
+ notes.new(commit_id: commit.id, noteable_type: 'Commit')
end
def last_activity
@@ -357,6 +367,24 @@ class Project < ActiveRecord::Base
@ci_service ||= ci_services.select(&:activated?).first
end
+ def avatar_type
+ unless self.avatar.image?
+ self.errors.add :avatar, 'only images allowed'
+ end
+ end
+
+ def avatar_in_git
+ @avatar_file ||= 'logo.png' if repository.blob_at_branch('master', 'logo.png')
+ @avatar_file ||= 'logo.jpg' if repository.blob_at_branch('master', 'logo.jpg')
+ @avatar_file ||= 'logo.gif' if repository.blob_at_branch('master', 'logo.gif')
+ @avatar_file
+ end
+
+ # For compatibility with old code
+ def code
+ path
+ end
+
def items_for(entity)
case entity
when 'issue' then
@@ -379,7 +407,7 @@ class Project < ActiveRecord::Base
end
def team_member_by_name_or_email(name = nil, email = nil)
- user = users.where("name like ? or email like ?", name, email).first
+ user = users.where('name like ? or email like ?', name, email).first
project_members.where(user: user) if user
end
@@ -391,7 +419,7 @@ class Project < ActiveRecord::Base
def name_with_namespace
@name_with_namespace ||= begin
if namespace
- namespace.human_name + " / " + name
+ namespace.human_name + ' / ' + name
else
name
end
@@ -426,7 +454,7 @@ class Project < ActiveRecord::Base
def valid_repo?
repository.exists?
rescue
- errors.add(:path, "Invalid repository path")
+ errors.add(:path, 'Invalid repository path')
false
end
@@ -485,7 +513,7 @@ class Project < ActiveRecord::Base
end
def http_url_to_repo
- [gitlab_config.url, "/", path_with_namespace, ".git"].join('')
+ [gitlab_config.url, '/', path_with_namespace, '.git'].join('')
end
# Check if current branch name is marked as protected in the system
@@ -548,6 +576,7 @@ class Project < ActiveRecord::Base
# Since we do cache @event we need to reset cache in special cases:
# * when project was moved
# * when project was renamed
+ # * when the project avatar changes
# Events cache stored like events/23-20130109142513.
# The cache key includes updated_at timestamp.
# Thus it will automatically generate a new fragment
@@ -612,7 +641,7 @@ class Project < ActiveRecord::Base
if gitlab_shell.add_repository(path_with_namespace)
true
else
- errors.add(:base, "Failed to create repository")
+ errors.add(:base, 'Failed to create repository')
false
end
end
@@ -625,7 +654,7 @@ class Project < ActiveRecord::Base
ProjectWiki.new(self, self.owner).wiki
true
rescue ProjectWiki::CouldNotCreateWikiError => ex
- errors.add(:base, "Failed create wiki")
+ errors.add(:base, 'Failed create wiki')
false
end
end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index b90adeef00a..2c457ef2cef 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -9,10 +9,6 @@ module Files
return error("You are not allowed to create file in this branch")
end
- unless repository.branch_names.include?(ref)
- return error("You can only create files if you are on top of a branch")
- end
-
file_name = File.basename(path)
file_path = path
@@ -23,12 +19,21 @@ module Files
)
end
- blob = repository.blob_at_branch(ref, file_path)
+ if project.empty_repo?
+ # everything is ok because repo does not have a commits yet
+ else
+ unless repository.branch_names.include?(ref)
+ return error("You can only create files if you are on top of a branch")
+ end
- if blob
- return error("Your changes could not be committed, because file with such name exists")
+ blob = repository.blob_at_branch(ref, file_path)
+
+ if blob
+ return error("Your changes could not be committed, because file with such name exists")
+ end
end
+
new_file_action = Gitlab::Satellite::NewFileAction.new(current_user, project, ref, file_path)
created_successfully = new_file_action.commit!(
params[:content],
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index ffed13a12e1..f670019cc63 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -2,9 +2,9 @@ module Issues
class CloseService < Issues::BaseService
def execute(issue, commit = nil)
if issue.close
- notification_service.close_issue(issue, current_user)
event_service.close_issue(issue, current_user)
create_note(issue, commit)
+ notification_service.close_issue(issue, current_user)
execute_hooks(issue, 'close')
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 0ee9635ed99..83e413d7248 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -23,8 +23,8 @@ module Issues
end
if issue.previous_changes.include?('assignee_id')
- notification_service.reassigned_issue(issue, current_user)
create_assignee_note(issue)
+ notification_service.reassigned_issue(issue, current_user)
end
issue.notice_added_references(issue.project, current_user)
diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb
index b5d90a74e15..378b39bb9d6 100644
--- a/app/services/merge_requests/auto_merge_service.rb
+++ b/app/services/merge_requests/auto_merge_service.rb
@@ -11,9 +11,9 @@ module MergeRequests
if Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message)
merge_request.merge
- notification_service.merge_mr(merge_request, current_user)
create_merge_event(merge_request, current_user)
create_note(merge_request)
+ notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request)
true
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index 4249a84f382..47454f9f0c2 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -7,8 +7,8 @@ module MergeRequests
if merge_request.close
event_service.close_mr(merge_request, current_user)
- notification_service.close_mr(merge_request, current_user)
create_note(merge_request)
+ notification_service.close_mr(merge_request, current_user)
execute_hooks(merge_request, 'close')
end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 1e1614028f7..327ead4ff3f 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -9,9 +9,9 @@ module MergeRequests
def execute(merge_request, commit_message)
merge_request.merge
- notification_service.merge_mr(merge_request, current_user)
create_merge_event(merge_request, current_user)
create_note(merge_request)
+ notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request, 'merge')
true
diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb
index a2a9c933f63..8279ad2001b 100644
--- a/app/services/merge_requests/reopen_service.rb
+++ b/app/services/merge_requests/reopen_service.rb
@@ -3,8 +3,8 @@ module MergeRequests
def execute(merge_request)
if merge_request.reopen
event_service.reopen_mr(merge_request, current_user)
- notification_service.reopen_mr(merge_request, current_user)
create_note(merge_request)
+ notification_service.reopen_mr(merge_request, current_user)
execute_hooks(merge_request, 'reopen')
merge_request.reload_code
merge_request.mark_as_unchecked
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 56c8510e0ae..10c401756eb 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -33,8 +33,8 @@ module MergeRequests
end
if merge_request.previous_changes.include?('assignee_id')
- notification_service.reassigned_merge_request(merge_request, current_user)
create_assignee_note(merge_request)
+ notification_service.reassigned_merge_request(merge_request, current_user)
end
merge_request.notice_added_references(merge_request.project, current_user)
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 72c9149378e..2fc63b9f4b7 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -314,15 +314,7 @@ class NotificationService
end
def new_resource_email(target, project, method)
- if target.respond_to?(:participants)
- recipients = target.participants
- else
- recipients = []
- end
-
- recipients = reject_muted_users(recipients, project)
- recipients = reject_mention_users(recipients, project)
- recipients = recipients.concat(project_watchers(project)).uniq
+ recipients = build_recipients(target, project)
recipients.delete(target.author)
recipients.each do |recipient|
@@ -331,9 +323,7 @@ class NotificationService
end
def close_resource_email(target, project, current_user, method)
- recipients = reject_muted_users([target.author, target.assignee], project)
- recipients = reject_mention_users(recipients, project)
- recipients = recipients.concat(project_watchers(project)).uniq
+ recipients = build_recipients(target, project)
recipients.delete(current_user)
recipients.each do |recipient|
@@ -343,17 +333,7 @@ class NotificationService
def reassign_resource_email(target, project, current_user, method)
assignee_id_was = previous_record(target, "assignee_id")
-
- recipients = User.where(id: [target.assignee_id, assignee_id_was])
-
- # Add watchers to email list
- recipients = recipients.concat(project_watchers(project))
-
- # reject users with disabled notifications
- recipients = reject_muted_users(recipients, project)
- recipients = reject_mention_users(recipients, project)
-
- # Reject me from recipients if I reassign an item
+ recipients = build_recipients(target, project)
recipients.delete(current_user)
recipients.each do |recipient|
@@ -362,9 +342,7 @@ class NotificationService
end
def reopen_resource_email(target, project, current_user, method, status)
- recipients = reject_muted_users([target.author, target.assignee], project)
- recipients = reject_mention_users(recipients, project)
- recipients = recipients.concat(project_watchers(project)).uniq
+ recipients = build_recipients(target, project)
recipients.delete(current_user)
recipients.each do |recipient|
@@ -372,6 +350,20 @@ class NotificationService
end
end
+ def build_recipients(target, project)
+ recipients =
+ if target.respond_to?(:participants)
+ target.participants
+ else
+ [target.author, target.assignee]
+ end
+
+ recipients = reject_muted_users(recipients, project)
+ recipients = reject_mention_users(recipients, project)
+ recipients = recipients.concat(project_watchers(project)).uniq
+ recipients
+ end
+
def mailer
Notify.delay
end
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index 09fc25cc1b3..7408e09ed1e 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -5,11 +5,11 @@ module Projects
end
def issues
- @project.issues.opened.select([:iid, :title, :description])
+ @project.issues.opened.select([:iid, :title])
end
def merge_requests
- @project.merge_requests.opened.select([:iid, :title, :description])
+ @project.merge_requests.opened.select([:iid, :title])
end
end
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 4930660055a..6b0d4aca3e1 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -14,6 +14,9 @@ module Projects
project.name = @from_project.name
project.path = @from_project.path
project.creator = @current_user
+ if @from_project.avatar.present? && @from_project.avatar.image?
+ project.avatar = @from_project.avatar
+ end
if namespace = @params[:namespace]
project.namespace = namespace
@@ -39,16 +42,16 @@ module Projects
end
#Now fork the repo
unless gitlab_shell.fork_repository(@from_project.path_with_namespace, project.namespace.path)
- raise "forking failed in gitlab-shell"
+ raise 'forking failed in gitlab-shell'
end
project.ensure_satellite_exists
end
rescue => ex
- project.errors.add(:base, "Fork transaction failed.")
+ project.errors.add(:base, 'Fork transaction failed.')
project.destroy
end
else
- project.errors.add(:base, "Invalid fork destination")
+ project.errors.add(:base, 'Invalid fork destination')
end
project
diff --git a/app/views/dashboard/_project.html.haml b/app/views/dashboard/_project.html.haml
index 89ed5102754..76b95264fd8 100644
--- a/app/views/dashboard/_project.html.haml
+++ b/app/views/dashboard/_project.html.haml
@@ -1,6 +1,8 @@
= link_to project_path(project), class: dom_class(project) do
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
+ .dash-project-avatar
+ = project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated
%span.namespace-name
- if project.namespace
diff --git a/app/views/dashboard/_projects.html.haml b/app/views/dashboard/_projects.html.haml
index 304aa17eba8..0596738342f 100644
--- a/app/views/dashboard/_projects.html.haml
+++ b/app/views/dashboard/_projects.html.haml
@@ -3,8 +3,8 @@
.input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
- if current_user.can_create_project?
- .input-group-addon
- = link_to new_project_path, class: "" do
+ .input-group-addon.dash-new-project
+ = link_to new_project_path do
%strong New project
%ul.well-list.dash-list
diff --git a/app/views/dashboard/projects.html.haml b/app/views/dashboard/projects.html.haml
index 944441669e7..f60bcc72e1d 100644
--- a/app/views/dashboard/projects.html.haml
+++ b/app/views/dashboard/projects.html.haml
@@ -11,6 +11,8 @@
- @projects.each do |project|
%li.my-project-row
%h4.project-title
+ .project-avatar
+ = project_icon(project.to_param, alt: '', class: 'avatar s60')
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project_path(project), class: dom_class(project) do
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 2c65b3049e3..34221595fd7 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -14,6 +14,8 @@
= link_to project_path(project), class: dom_class(project) do
.dash-project-access-icon
= visibility_level_icon(project.visibility_level)
+ .dash-project-avatar
+ = project_icon(project.to_param, alt: '', class: 'avatar s24')
%span.str-truncated
%span.project-name
= project.name
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 30d063c7a36..2ed49f83a7a 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,5 +1,7 @@
- empty_repo = @project.empty_repo?
.project-home-panel{:class => ("empty-project" if empty_repo)}
+ .project-identicon-holder
+ = project_icon(@project.to_param, alt: '', class: 'avatar')
.project-home-row
.project-home-desc
- if @project.description.present?
diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/blob/edit.html.haml
index 7e0789853af..883845c03f5 100644
--- a/app/views/projects/edit_tree/show.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -1,11 +1,16 @@
.file-editor
%ul.nav.nav-tabs.js-edit-mode
%li.active
- = link_to 'Edit', '#editor'
+ = link_to '#editor' do
+ %i.fa.fa-edit
+ Edit file
+
%li
- = link_to editing_preview_title(@blob.name), '#preview', 'data-preview-url' => preview_project_edit_tree_path(@project, @id)
+ = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do
+ %i.fa.fa-eye
+ = editing_preview_title(@blob.name)
- = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
+ = form_tag(project_update_blob_path(@project, @id), method: :put, class: "form-horizontal") do
= render 'projects/blob_editor', ref: @ref, path: @path, blob_data: @blob.data
= render 'shared/commit_message_container', params: params,
placeholder: "Update #{@blob.name}"
diff --git a/app/views/projects/new_tree/show.html.haml b/app/views/projects/blob/new.html.haml
index cf7b768694f..57e830d5c56 100644
--- a/app/views/projects/new_tree/show.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -1,7 +1,7 @@
%h3.page-title New file
%hr
.file-editor
- = form_tag(project_new_tree_path(@project, @id), method: :put, class: 'form-horizontal form-new-file') do
+ = form_tag(project_create_blob_path(@project, @id), method: :post, class: 'form-horizontal form-new-file') do
.form-group.commit_message-group
= label_tag 'file_name', class: 'control-label' do
File name
diff --git a/app/views/projects/edit_tree/preview.html.haml b/app/views/projects/blob/preview.html.haml
index e7c3460ad78..e7c3460ad78 100644
--- a/app/views/projects/edit_tree/preview.html.haml
+++ b/app/views/projects/blob/preview.html.haml
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index fb4d8270731..31bdbb562a1 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -7,7 +7,8 @@
%p.light Some settings, such as "Transfer Project", are hidden inside the danger area below.
%hr
.panel-body
- = form_for @project, remote: true, html: { class: "edit_project form-horizontal" } do |f|
+ = form_for @project, remote: true, html: { multipart: true, class: "edit_project form-horizontal" }, authenticity_token: true do |f|
+
%fieldset
.form-group.project_name_holder
= f.label :name, class: 'control-label' do
@@ -71,6 +72,32 @@
= f.check_box :snippets_enabled
%span.descr Share code pastes with others out of git repository
+ %fieldset.features
+ %legend
+ Project avatar:
+ .form-group
+ .col-sm-2
+ .col-sm-10
+ - if @project.avatar?
+ = project_icon(@project.to_param, alt: '', class: 'avatar s160')
+ %p.light
+ - if @project.avatar_in_git
+ Project avatar in repository: #{ @project.avatar_in_git }
+ %p.light
+ - if @project.avatar?
+ You can change your project avatar here
+ - else
+ You can upload an project avatar here
+ %a.choose-btn.btn.btn-small.js-choose-project-avatar-button
+ %i.icon-paper-clip
+ %span Choose File ...
+ &nbsp;
+ %span.file_name.js-avatar-filename File name...
+ = f.file_field :avatar, class: "js-project-avatar-input hidden"
+ .light The maximum file size allowed is 200KB.
+ - if @project.avatar?
+ %hr
+ = link_to 'Remove avatar', project_avatar_path(@project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
.form-actions
= f.submit 'Save changes', class: "btn btn-save"
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 59f19c8b7a3..776a7327bc2 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -1,5 +1,19 @@
+- if current_user && can?(current_user, :download_code, @project)
+ = render 'shared/no_ssh'
+
= render "home_panel"
+.center.well
+ %h3
+ The repository for this project is empty
+ %p.lead
+ You can
+ = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do
+ add a file
+ &nbsp;or push it via command line.
+
+%h4
+ %strong Command line instructions
%div.git-empty
%fieldset
%legend Git global setup
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index 7271dd830ca..4604c0afd8d 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -1,13 +1,22 @@
%h3.page-title Project services
%p.light Project services allow you to integrate GitLab with other applications
-%hr
-%ul.bordered-list
+%table.table
+ %thead
+ %tr
+ %th
+ %th Service
+ %th Desription
+ %th Last edit
- @services.sort_by(&:title).each do |service|
- %li
- %h4
+ %tr
+ %td
+ = boolean_to_icon service.activated?
+ %td
= link_to edit_project_service_path(@project, service.to_param) do
- = service.title
- .pull-right
- = boolean_to_icon service.activated?
- %p= service.description
+ %strong= service.title
+ %td
+ = service.description
+ %td.light
+ = time_ago_in_words service.updated_at
+ ago
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree.html.haml
index 68ccd4d61bb..f902440b3f1 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree.html.haml
@@ -10,7 +10,7 @@
= link_to title, '#'
- if current_user && can_push_branch?(@project, @ref)
%li
- = link_to project_new_tree_path(@project, @id), title: 'New file', id: 'new-file-link' do
+ = link_to project_new_blob_path(@project, @id), title: 'New file', id: 'new-file-link' do
%small
%i.fa.fa-plus
diff --git a/app/views/users/_groups.html.haml b/app/views/users/_groups.html.haml
index b9bd6aa3763..32a1dc83b57 100644
--- a/app/views/users/_groups.html.haml
+++ b/app/views/users/_groups.html.haml
@@ -1,4 +1,4 @@
.clearfix
- groups.each do |group|
= link_to group, class: 'profile-groups-avatars', title: group.name do
- = image_tag group_icon(group.path), class: 'avatar s40'
+ = image_tag group_icon(group.path), class: 'avatar avatar-inline s40'