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
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
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
-rw-r--r--CHANGELOG12
-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
-rw-r--r--config/initializers/devise.rb3
-rw-r--r--config/routes.rb59
-rw-r--r--db/migrate/20140125162722_add_avatar_to_projects.rb5
-rw-r--r--db/schema.rb1
-rw-r--r--doc/README.md2
-rw-r--r--doc/api/users.md25
-rw-r--r--doc/ssh/ssh.md19
-rw-r--r--doc/workflow/README.md2
-rw-r--r--doc/workflow/workflow.md2
-rw-r--r--features/project/project.feature13
-rw-r--r--features/steps/project/project.rb57
-rw-r--r--features/steps/project/source/browse_files.rb2
-rw-r--r--features/steps/shared/paths.rb4
-rw-r--r--lib/extracts_path.rb8
-rw-r--r--lib/gitlab/satellite/files/new_file_action.rb12
-rw-r--r--spec/helpers/application_helper_spec.rb124
-rw-r--r--spec/models/project_spec.rb69
-rw-r--r--spec/routing/project_routing_spec.rb360
-rw-r--r--spec/services/issues/update_service_spec.rb1
-rw-r--r--spec/services/merge_requests/update_service_spec.rb2
-rw-r--r--spec/services/notification_service_spec.rb7
75 files changed, 995 insertions, 601 deletions
diff --git a/CHANGELOG b/CHANGELOG
index bd519002531..91409707c87 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,7 +3,7 @@ Note: The upcoming release contains empty lines to reduce the number of merge co
v 7.8.0
- Replace highlight.js with rouge-fork rugments (Stefan Tatschner)
- Make project search case insensitive (Hannes Rosenögger)
- -
+ - Include issue/mr participants in list of recipients for reassign/close/reopen emails
- Expose description in groups API
-
-
@@ -17,12 +17,12 @@ v 7.8.0
- Show tags in commit view (Hannes Rosenögger)
- Only count a user's vote once on a merge request or issue (Michael Clarke)
-
- -
- -
+ - Increate font size when browse source files and diffs
+ - Create new file in empty repository using GitLab UI
-
- Upgrade Sidekiq gem to version 3.3.0
- Stop git zombie creation during force push check
- -
+ - Show success/error messages for test setting button in services
-
- Fix commits pagination
-
@@ -34,10 +34,10 @@ v 7.8.0
-
-
-
+ - Add Project Avatars (Steven Thonus and Hannes Rosenögger)
-
-
- -
- -
+ - Password reset token validity increased from 2 hours to 2 days since it is also send on account creation.
-
-
-
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'
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index c6eb3e51036..79abe3c695d 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -145,7 +145,8 @@ Devise.setup do |config|
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
- config.reset_password_within = 2.hours
+ # When someone else invites you to GitLab this time is also used so it should be pretty long.
+ config.reset_password_within = 2.days
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
diff --git a/config/routes.rb b/config/routes.rb
index ef3c5aedfcb..f29b620e079 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,8 +10,8 @@ Gitlab::Application.routes.draw do
#
# Search
#
- get 'search' => "search#show"
- get 'search/autocomplete' => "search#autocomplete", as: :search_autocomplete
+ get 'search' => 'search#show'
+ get 'search/autocomplete' => 'search#autocomplete', as: :search_autocomplete
# API
API::API.logger Rails.logger
@@ -20,9 +20,9 @@ Gitlab::Application.routes.draw do
# Get all keys of user
get ':username.keys' => 'profiles/keys#get_keys' , constraints: { username: /.*/ }
- constraint = lambda { |request| request.env["warden"].authenticate? and request.env['warden'].user.admin? }
+ constraint = lambda { |request| request.env['warden'].authenticate? and request.env['warden'].user.admin? }
constraints constraint do
- mount Sidekiq::Web, at: "/admin/sidekiq", as: :sidekiq
+ mount Sidekiq::Web, at: '/admin/sidekiq', as: :sidekiq
end
# Enable Grack support
@@ -46,10 +46,10 @@ Gitlab::Application.routes.draw do
#
resources :snippets do
member do
- get "raw"
+ get 'raw'
end
end
- get "/s/:username" => "snippets#user_index", as: :user_snippets, constraints: { username: /.*/ }
+ get '/s/:username' => 'snippets#user_index', as: :user_snippets, constraints: { username: /.*/ }
#
# Github importer area
@@ -61,7 +61,7 @@ Gitlab::Application.routes.draw do
end
#
- # Explroe area
+ # Explore area
#
namespace :explore do
resources :projects, only: [:index] do
@@ -72,12 +72,12 @@ Gitlab::Application.routes.draw do
end
resources :groups, only: [:index]
- root to: "projects#trending"
+ root to: 'projects#trending'
end
# Compatibility with old routing
- get 'public' => "explore/projects#index"
- get 'public/projects' => "explore/projects#index"
+ get 'public' => 'explore/projects#index'
+ get 'public/projects' => 'explore/projects#index'
#
# Attachments serving
@@ -122,7 +122,7 @@ Gitlab::Application.routes.draw do
resource :application_settings, only: [:show, :update]
- root to: "dashboard#index"
+ root to: 'dashboard#index'
end
#
@@ -163,7 +163,7 @@ Gitlab::Application.routes.draw do
#
# Dashboard Area
#
- resource :dashboard, controller: "dashboard", only: [:show] do
+ resource :dashboard, controller: 'dashboard', only: [:show] do
member do
get :projects
get :issues
@@ -194,12 +194,12 @@ Gitlab::Application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords, sessions: :sessions, confirmations: :confirmations }
devise_scope :user do
- get "/users/auth/:provider/omniauth_error" => "omniauth_callbacks#omniauth_error", as: :omniauth_error
+ get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
end
#
# Project Area
#
- resources :projects, constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
+ resources :projects, constraints: { id: /[a-zA-Z.0-9_\-]+\/[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: '/' do
member do
put :transfer
post :archive
@@ -211,16 +211,20 @@ Gitlab::Application.routes.draw do
end
scope module: :projects do
+ # Blob routes:
+ get '/new/:id', to: 'blob#new', constraints: {id: /.+/}, as: 'new_blob'
+ post '/create/:id', to: 'blob#create', constraints: {id: /.+/}, as: 'create_blob'
+ get '/edit/:id', to: 'blob#edit', constraints: {id: /.+/}, as: 'edit_blob'
+ put '/update/:id', to: 'blob#update', constraints: {id: /.+/}, as: 'update_blob'
+ post '/preview/:id', to: 'blob#preview', constraints: {id: /.+/}, as: 'preview_blob'
+
resources :blob, only: [:show, :destroy], constraints: { id: /.+/, format: false } do
get :diff, on: :member
end
+
resources :raw, only: [:show], constraints: {id: /.+/}
resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
- resources :edit_tree, only: [:show, :update], constraints: { id: /.+/ }, path: 'edit' do
- # Cannot be GET to differentiate from GET paths that end in preview.
- post :preview, on: :member
- end
- resources :new_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'new'
+ resource :avatar, only: [:show, :destroy]
resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
resources :compare, only: [:index, :create]
@@ -237,7 +241,7 @@ Gitlab::Application.routes.draw do
resources :snippets, constraints: {id: /\d+/} do
member do
- get "raw"
+ get 'raw'
end
end
@@ -249,7 +253,7 @@ Gitlab::Application.routes.draw do
end
member do
- get "history"
+ get 'history'
end
end
@@ -258,7 +262,7 @@ Gitlab::Application.routes.draw do
resource :repository, only: [:show, :create] do
member do
- get "archive", constraints: { format: Gitlab::Regex.archive_formats_regex }
+ get 'archive', constraints: { format: Gitlab::Regex.archive_formats_regex }
end
end
@@ -281,13 +285,13 @@ Gitlab::Application.routes.draw do
resources :refs, only: [] do
collection do
- get "switch"
+ get 'switch'
end
member do
# tree viewer logs
- get "logs_tree", constraints: { id: Gitlab::Regex.git_reference_regex }
- get "logs_tree/:path" => "refs#logs_tree",
+ get 'logs_tree', constraints: { id: Gitlab::Regex.git_reference_regex }
+ get 'logs_tree/:path' => 'refs#logs_tree',
as: :logs_file,
constraints: {
id: Gitlab::Regex.git_reference_regex,
@@ -353,10 +357,11 @@ Gitlab::Application.routes.draw do
delete :delete_attachment
end
end
+
end
end
- get ':id' => "namespaces#show", constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
+ get ':id' => 'namespaces#show', constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
- root to: "dashboard#show"
+ root to: 'dashboard#show'
end
diff --git a/db/migrate/20140125162722_add_avatar_to_projects.rb b/db/migrate/20140125162722_add_avatar_to_projects.rb
new file mode 100644
index 00000000000..9523ac722f2
--- /dev/null
+++ b/db/migrate/20140125162722_add_avatar_to_projects.rb
@@ -0,0 +1,5 @@
+class AddAvatarToProjects < ActiveRecord::Migration
+ def change
+ add_column :projects, :avatar, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b453164d712..29466f048eb 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -327,6 +327,7 @@ ActiveRecord::Schema.define(version: 20150116234544) do
t.integer "star_count", default: 0, null: false
t.string "import_type"
t.string "import_source"
+ t.string "avatar"
end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
diff --git a/doc/README.md b/doc/README.md
index 3c8f8ad3d03..8c6d13e8506 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -9,7 +9,7 @@
- [Public access](public_access/public_access.md) Learn how you can allow public and internal access to projects.
- [SSH](ssh/README.md) Setup your ssh keys and deploy keys for secure access to your projects.
- [Web hooks](web_hooks/web_hooks.md) Let GitLab notify you when new code has been pushed to your project.
-- [Workflow](workflow/README.md) Learn how to get the maximum out of GitLab.
+- [Workflow](workflow/README.md) Using GitLab functionality and importing projects from GitHub and SVN.
## Administrator documentation
diff --git a/doc/api/users.md b/doc/api/users.md
index b30a31deccc..71fa62bdd65 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -322,6 +322,31 @@ Parameters:
- `title` (required) - new SSH Key's title
- `key` (required) - new SSH key
+```json
+{
+ "created_at": "2015-01-21T17:44:33.512Z",
+ "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAMLrhYgI3atfrSD6KDas1b/3n6R/HP+bLaHHX6oh+L1vg31mdUqK0Ac/NjZoQunavoyzqdPYhFz9zzOezCrZKjuJDS3NRK9rspvjgM0xYR4d47oNZbdZbwkI4cTv/gcMlquRy0OvpfIvJtjtaJWMwTLtM5VhRusRuUlpH99UUVeXAAAAFQCVyX+92hBEjInEKL0v13c/egDCTQAAAIEAvFdWGq0ccOPbw4f/F8LpZqvWDydAcpXHV3thwb7WkFfppvm4SZte0zds1FJ+Hr8Xzzc5zMHe6J4Nlay/rP4ewmIW7iFKNBEYb/yWa+ceLrs+TfR672TaAgO6o7iSRofEq5YLdwgrwkMmIawa21FrZ2D9SPao/IwvENzk/xcHu7YAAACAQFXQH6HQnxOrw4dqf0NqeKy1tfIPxYYUZhPJfo9O0AmBW2S36pD2l14kS89fvz6Y1g8gN/FwFnRncMzlLY/hX70FSc/3hKBSbH6C6j8hwlgFKfizav21eS358JJz93leOakJZnGb8XlWvz1UJbwCsnR2VEY8Dz90uIk1l/UqHkA= loic@call",
+ "title": "ABC",
+ "id": 4
+}
+```
+
+Will return created key with status `201 Created` on success. If an
+error occurs a `400 Bad Request` is returned with a message explaining the error:
+
+```json
+{
+ "message": {
+ "fingerprint": [
+ "has already been taken"
+ ],
+ "key": [
+ "has already been taken"
+ ]
+ }
+}
+```
+
## Add SSH key for user
Create new key owned by specified user. Available only for admin
diff --git a/doc/ssh/ssh.md b/doc/ssh/ssh.md
index d466c1bde72..f9ee627f1f5 100644
--- a/doc/ssh/ssh.md
+++ b/doc/ssh/ssh.md
@@ -18,4 +18,21 @@ Use the code below to show your public key.
cat ~/.ssh/id_rsa.pub
```
-Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with `ssh-` and ending with your username and host.
+Copy-paste the key to the 'My SSH Keys' section under the 'SSH' tab in your user profile. Please copy the complete key starting with `ssh-` and ending with your username and host.
+
+Use code below to copy your public key to the clipboard. Depending on your OS you'll need to use a different command:
+
+**Windows:**
+```bash
+clip < ~/.ssh/id_rsa.pub
+```
+
+**Mac:**
+```bash
+pbcopy < ~/.ssh/id_rsa.pub
+```
+
+**Linux (requires xclip):**
+```bash
+xclip -sel clip < ~/.ssh/id_rsa.pub
+```
diff --git a/doc/workflow/README.md b/doc/workflow/README.md
index 1fe63274c29..33176aaba44 100644
--- a/doc/workflow/README.md
+++ b/doc/workflow/README.md
@@ -1,6 +1,6 @@
# Workflow
-- [Workflow](workflow.md)
+- [Feature branch workflow](workflow.md)
- [Project Features](project_features.md)
- [Authorization for merge requests](authorization_for_merge_requests.md)
- [Groups](groups.md)
diff --git a/doc/workflow/workflow.md b/doc/workflow/workflow.md
index ab29cfb670b..f70e41df842 100644
--- a/doc/workflow/workflow.md
+++ b/doc/workflow/workflow.md
@@ -1,4 +1,4 @@
-# Workflow
+# Feature branch workflow
1. Clone project:
diff --git a/features/project/project.feature b/features/project/project.feature
index 7bb24e013a9..3e1fd54bee8 100644
--- a/features/project/project.feature
+++ b/features/project/project.feature
@@ -5,6 +5,19 @@ Feature: Project
And project "Shop" has push event
And I visit project "Shop" page
+ Scenario: I edit the project avatar
+ Given I visit edit project "Shop" page
+ When I change the project avatar
+ And I should see new project avatar
+ And I should see the "Remove avatar" button
+
+ Scenario: I remove the project avatar
+ Given I visit edit project "Shop" page
+ And I have an project avatar
+ When I remove my project avatar
+ Then I should see the default project avatar
+ And I should not see the "Remove avatar" button
+
@javascript
Scenario: I should see project activity
When I visit project "Shop" page
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
index 5e7312d90ff..033d45e0253 100644
--- a/features/steps/project/project.rb
+++ b/features/steps/project/project.rb
@@ -17,17 +17,58 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
step 'change project path settings' do
- fill_in "project_path", with: "new-path"
- click_button "Rename"
+ fill_in 'project_path', with: 'new-path'
+ click_button 'Rename'
end
step 'I should see project with new path settings' do
- project.path.should == "new-path"
+ project.path.should == 'new-path'
+ end
+
+ step 'I change the project avatar' do
+ attach_file(
+ :project_avatar,
+ File.join(Rails.root, 'public', 'gitlab_logo.png')
+ )
+ click_button 'Save changes'
+ @project.reload
+ end
+
+ step 'I should see new project avatar' do
+ @project.avatar.should be_instance_of AttachmentUploader
+ url = @project.avatar.url
+ url.should == "/uploads/project/avatar/#{ @project.id }/gitlab_logo.png"
+ end
+
+ step 'I should see the "Remove avatar" button' do
+ page.should have_link('Remove avatar')
+ end
+
+ step 'I have an project avatar' do
+ attach_file(
+ :project_avatar,
+ File.join(Rails.root, 'public', 'gitlab_logo.png')
+ )
+ click_button 'Save changes'
+ @project.reload
+ end
+
+ step 'I remove my project avatar' do
+ click_link 'Remove avatar'
+ @project.reload
+ end
+
+ step 'I should see the default project avatar' do
+ @project.avatar?.should be_false
+ end
+
+ step 'I should not see the "Remove avatar" button' do
+ page.should_not have_link('Remove avatar')
end
step 'I should see project "Shop" version' do
within '.project-side' do
- page.should have_content "Version: 6.7.0.pre"
+ page.should have_content 'Version: 6.7.0.pre'
end
end
@@ -45,12 +86,12 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
step 'I should see project "Forum" README' do
- page.should have_link "README.md"
- page.should have_content "Sample repo for testing gitlab features"
+ page.should have_link 'README.md'
+ page.should have_content 'Sample repo for testing gitlab features'
end
step 'I should see project "Shop" README' do
- page.should have_link "README.md"
- page.should have_content "testme"
+ page.should have_link 'README.md'
+ page.should have_content 'testme'
end
end
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 805e6ff0eac..1caad73654b 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -78,7 +78,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I click link "Diff"' do
- click_link 'Diff'
+ click_link 'Preview changes'
end
step 'I click on "Commit Changes"' do
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 33ef6ccacf1..cef48c179b2 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -284,11 +284,11 @@ module SharedPaths
end
step 'I am on the new file page' do
- current_path.should eq(project_new_tree_path(@project, root_ref))
+ current_path.should eq(project_create_blob_path(@project, root_ref))
end
step 'I am on the ".gitignore" edit file page' do
- current_path.should eq(project_edit_tree_path(
+ current_path.should eq(project_edit_blob_path(
@project, File.join(root_ref, '.gitignore')))
end
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index e51cb30bdd9..19215cfb7e6 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -1,17 +1,9 @@
# Module providing methods for dealing with separating a tree-ish string and a
# file path string when combined in a request parameter
module ExtractsPath
- extend ActiveSupport::Concern
-
# Raised when given an invalid file path
class InvalidPathError < StandardError; end
- included do
- if respond_to?(:before_filter)
- before_filter :assign_ref_vars
- end
- end
-
# Given a string containing both a Git tree-ish, such as a branch or tag, and
# a filesystem path joined by forward slashes, attempts to separate the two.
#
diff --git a/lib/gitlab/satellite/files/new_file_action.rb b/lib/gitlab/satellite/files/new_file_action.rb
index 15e9b7a6f77..c230239d390 100644
--- a/lib/gitlab/satellite/files/new_file_action.rb
+++ b/lib/gitlab/satellite/files/new_file_action.rb
@@ -14,7 +14,14 @@ module Gitlab
prepare_satellite!(repo)
# create target branch in satellite at the corresponding commit from bare repo
- repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+ current_ref =
+ if repo.commits.any?
+ repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+ ref
+ else
+ # skip this step if we want to add first file to empty repo
+ Satellite::PARKING_BRANCH
+ end
file_path_in_satellite = File.join(repo.working_dir, file_path)
dir_name_in_satellite = File.dirname(file_path_in_satellite)
@@ -38,10 +45,9 @@ module Gitlab
# will raise CommandFailed when commit fails
repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
-
# push commit back to bare repo
# will raise CommandFailed when push fails
- repo.git.push({raise: true, timeout: true}, :origin, ref)
+ repo.git.push({raise: true, timeout: true}, :origin, "#{current_ref}:#{ref}")
# everything worked
true
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 1738f3443cf..a46883b3c99 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -6,15 +6,15 @@ describe ApplicationHelper do
controller.stub(:controller_name).and_return('foo')
end
- it "returns true when controller matches argument" do
+ it 'returns true when controller matches argument' do
current_controller?(:foo).should be_true
end
- it "returns false when controller does not match argument" do
+ it 'returns false when controller does not match argument' do
current_controller?(:bar).should_not be_true
end
- it "should take any number of arguments" do
+ it 'should take any number of arguments' do
current_controller?(:baz, :bar).should_not be_true
current_controller?(:baz, :bar, :foo).should be_true
end
@@ -25,49 +25,71 @@ describe ApplicationHelper do
allow(self).to receive(:action_name).and_return('foo')
end
- it "returns true when action matches argument" do
+ it 'returns true when action matches argument' do
current_action?(:foo).should be_true
end
- it "returns false when action does not match argument" do
+ it 'returns false when action does not match argument' do
current_action?(:bar).should_not be_true
end
- it "should take any number of arguments" do
+ it 'should take any number of arguments' do
current_action?(:baz, :bar).should_not be_true
current_action?(:baz, :bar, :foo).should be_true
end
end
- describe "group_icon" do
+ describe 'group_icon' do
avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
- it "should return an url for the avatar" do
+ it 'should return an url for the avatar' do
group = create(:group)
group.avatar = File.open(avatar_file_path)
group.save!
group_icon(group.path).to_s.should match("/uploads/group/avatar/#{ group.id }/gitlab_logo.png")
end
- it "should give default avatar_icon when no avatar is present" do
+ it 'should give default avatar_icon when no avatar is present' do
group = create(:group)
group.save!
- group_icon(group.path).should match("group_avatar.png")
+ group_icon(group.path).should match('group_avatar.png')
end
end
- describe "avatar_icon" do
+ describe 'project_icon' do
avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
- it "should return an url for the avatar" do
+ it 'should return an url for the avatar' do
+ project = create(:project)
+ project.avatar = File.open(avatar_file_path)
+ project.save!
+ project_icon(project.to_param).to_s.should ==
+ "<img alt=\"Gitlab logo\" src=\"/uploads/project/avatar/#{ project.id }/gitlab_logo.png\" />"
+ end
+
+ it 'should give uploaded icon when present' do
+ project = create(:project)
+ project.save!
+
+ Project.any_instance.stub(:avatar_in_git).and_return(true)
+
+ project_icon(project.to_param).to_s.should match(
+ image_tag(project_avatar_path(project)))
+ end
+ end
+
+ describe 'avatar_icon' do
+ avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
+
+ it 'should return an url for the avatar' do
user = create(:user)
user.avatar = File.open(avatar_file_path)
user.save!
avatar_icon(user.email).to_s.should match("/uploads/user/avatar/#{ user.id }/gitlab_logo.png")
end
- it "should return an url for the avatar with relative url" do
- Gitlab.config.gitlab.stub(relative_url_root: "/gitlab")
+ it 'should return an url for the avatar with relative url' do
+ Gitlab.config.gitlab.stub(relative_url_root: '/gitlab')
Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url))
user = create(:user)
@@ -76,58 +98,58 @@ describe ApplicationHelper do
avatar_icon(user.email).to_s.should match("/gitlab/uploads/user/avatar/#{ user.id }/gitlab_logo.png")
end
- it "should call gravatar_icon when no avatar is present" do
+ it 'should call gravatar_icon when no avatar is present' do
user = create(:user, email: 'test@example.com')
user.save!
- avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon"
+ avatar_icon(user.email).to_s.should == 'http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon'
end
end
- describe "gravatar_icon" do
+ describe 'gravatar_icon' do
let(:user_email) { 'user@email.com' }
- it "should return a generic avatar path when Gravatar is disabled" do
+ it 'should return a generic avatar path when Gravatar is disabled' do
ApplicationSetting.any_instance.stub(gravatar_enabled?: false)
gravatar_icon(user_email).should match('no_avatar.png')
end
- it "should return a generic avatar path when email is blank" do
+ it 'should return a generic avatar path when email is blank' do
gravatar_icon('').should match('no_avatar.png')
end
- it "should return default gravatar url" do
+ it 'should return default gravatar url' do
Gitlab.config.gitlab.stub(https: false)
gravatar_icon(user_email).should match('http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118')
end
- it "should use SSL when appropriate" do
+ it 'should use SSL when appropriate' do
Gitlab.config.gitlab.stub(https: true)
gravatar_icon(user_email).should match('https://secure.gravatar.com')
end
- it "should return custom gravatar path when gravatar_url is set" do
+ it 'should return custom gravatar path when gravatar_url is set' do
allow(self).to receive(:request).and_return(double(:ssl? => false))
Gitlab.config.gravatar.stub(:plain_url).and_return('http://example.local/?s=%{size}&hash=%{hash}')
gravatar_icon(user_email, 20).should == 'http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118'
end
- it "should accept a custom size" do
+ it 'should accept a custom size' do
allow(self).to receive(:request).and_return(double(:ssl? => false))
gravatar_icon(user_email, 64).should match(/\?s=64/)
end
- it "should use default size when size is wrong" do
+ it 'should use default size when size is wrong' do
allow(self).to receive(:request).and_return(double(:ssl? => false))
gravatar_icon(user_email, nil).should match(/\?s=40/)
end
- it "should be case insensitive" do
+ it 'should be case insensitive' do
allow(self).to receive(:request).and_return(double(:ssl? => false))
- gravatar_icon(user_email).should == gravatar_icon(user_email.upcase + " ")
+ gravatar_icon(user_email).should == gravatar_icon(user_email.upcase + ' ')
end
end
- describe "grouped_options_refs" do
+ describe 'grouped_options_refs' do
# Override Rails' grouped_options_for_select helper since HTML is harder to work with
def grouped_options_for_select(options, *args)
options
@@ -140,17 +162,17 @@ describe ApplicationHelper do
@project = create(:project)
end
- it "includes a list of branch names" do
+ it 'includes a list of branch names' do
options[0][0].should == 'Branches'
options[0][1].should include('master', 'feature')
end
- it "includes a list of tag names" do
+ it 'includes a list of tag names' do
options[1][0].should == 'Tags'
options[1][1].should include('v1.0.0','v1.1.0')
end
- it "includes a specific commit ref if defined" do
+ it 'includes a specific commit ref if defined' do
# Must be an instance variable
@ref = '2ed06dc41dbb5936af845b87d79e05bbf24c73b8'
@@ -158,26 +180,26 @@ describe ApplicationHelper do
options[2][1].should == [@ref]
end
- it "sorts tags in a natural order" do
+ it 'sorts tags in a natural order' do
# Stub repository.tag_names to make sure we get some valid testing data
- expect(@project.repository).to receive(:tag_names).and_return(["v1.0.9", "v1.0.10", "v2.0", "v3.1.4.2", "v1.0.9a"])
+ expect(@project.repository).to receive(:tag_names).and_return(['v1.0.9', 'v1.0.10', 'v2.0', 'v3.1.4.2', 'v1.0.9a'])
- options[1][1].should == ["v3.1.4.2", "v2.0", "v1.0.10", "v1.0.9a", "v1.0.9"]
+ options[1][1].should == ['v3.1.4.2', 'v2.0', 'v1.0.10', 'v1.0.9a', 'v1.0.9']
end
end
- describe "user_color_scheme_class" do
- context "with current_user is nil" do
- it "should return a string" do
+ describe 'user_color_scheme_class' do
+ context 'with current_user is nil' do
+ it 'should return a string' do
allow(self).to receive(:current_user).and_return(nil)
user_color_scheme_class.should be_kind_of(String)
end
end
- context "with a current_user" do
+ context 'with a current_user' do
(1..5).each do |color_scheme_id|
context "with color_scheme_id == #{color_scheme_id}" do
- it "should return a string" do
+ it 'should return a string' do
current_user = double(:color_scheme_id => color_scheme_id)
allow(self).to receive(:current_user).and_return(current_user)
user_color_scheme_class.should be_kind_of(String)
@@ -187,43 +209,43 @@ describe ApplicationHelper do
end
end
- describe "simple_sanitize" do
+ describe 'simple_sanitize' do
let(:a_tag) { '<a href="#">Foo</a>' }
- it "allows the a tag" do
+ it 'allows the a tag' do
simple_sanitize(a_tag).should == a_tag
end
- it "allows the span tag" do
+ it 'allows the span tag' do
input = '<span class="foo">Bar</span>'
simple_sanitize(input).should == input
end
- it "disallows other tags" do
+ it 'disallows other tags' do
input = "<strike><b>#{a_tag}</b></strike>"
simple_sanitize(input).should == a_tag
end
end
- describe "link_to" do
+ describe 'link_to' do
- it "should not include rel=nofollow for internal links" do
- expect(link_to("Home", root_path)).to eq("<a href=\"/\">Home</a>")
+ it 'should not include rel=nofollow for internal links' do
+ expect(link_to('Home', root_path)).to eq("<a href=\"/\">Home</a>")
end
- it "should include rel=nofollow for external links" do
- expect(link_to("Example", "http://www.example.com")).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
+ it 'should include rel=nofollow for external links' do
+ expect(link_to('Example', 'http://www.example.com')).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
end
- it "should include re=nofollow for external links and honor existing html_options" do
+ it 'should include re=nofollow for external links and honor existing html_options' do
expect(
- link_to("Example", "http://www.example.com", class: "toggle", data: {toggle: "dropdown"})
+ link_to('Example', 'http://www.example.com', class: 'toggle', data: {toggle: 'dropdown'})
).to eq("<a class=\"toggle\" data-toggle=\"dropdown\" href=\"http://www.example.com\" rel=\"nofollow\">Example</a>")
end
- it "should include rel=nofollow for external links and preserver other rel values" do
+ it 'should include rel=nofollow for external links and preserver other rel values' do
expect(
- link_to("Example", "http://www.example.com", rel: "noreferrer")
+ link_to('Example', 'http://www.example.com', rel: 'noreferrer')
).to eq("<a href=\"http://www.example.com\" rel=\"noreferrer nofollow\">Example</a>")
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 8bc8c2f9252..092c02d552e 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.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,12 +26,13 @@
# star_count :integer default(0), not null
# import_type :string(255)
# import_source :string(255)
+# avatar :string(255)
#
require 'spec_helper'
describe Project do
- describe "Associations" do
+ describe 'Associations' do
it { should belong_to(:group) }
it { should belong_to(:namespace) }
it { should belong_to(:creator).class_name('User') }
@@ -52,10 +53,10 @@ describe Project do
it { should have_one(:pushover_service).dependent(:destroy) }
end
- describe "Mass assignment" do
+ describe 'Mass assignment' do
end
- describe "Validation" do
+ describe 'Validation' do
let!(:project) { create(:project) }
it { should validate_presence_of(:name) }
@@ -70,7 +71,7 @@ describe Project do
it { should ensure_length_of(:issues_tracker_id).is_within(0..255) }
it { should validate_presence_of(:namespace) }
- it "should not allow new projects beyond user limits" do
+ it 'should not allow new projects beyond user limits' do
project2 = build(:project)
project2.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
project2.should_not be_valid
@@ -78,7 +79,7 @@ describe Project do
end
end
- describe "Respond to" do
+ describe 'Respond to' do
it { should respond_to(:url_to_repo) }
it { should respond_to(:repo_exists?) }
it { should respond_to(:satellite) }
@@ -89,27 +90,27 @@ describe Project do
it { should respond_to(:path_with_namespace) }
end
- it "should return valid url to repo" do
- project = Project.new(path: "somewhere")
- project.url_to_repo.should == Gitlab.config.gitlab_shell.ssh_path_prefix + "somewhere.git"
+ it 'should return valid url to repo' do
+ project = Project.new(path: 'somewhere')
+ project.url_to_repo.should == Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git'
end
- it "returns the full web URL for this repo" do
- project = Project.new(path: "somewhere")
+ it 'returns the full web URL for this repo' do
+ project = Project.new(path: 'somewhere')
project.web_url.should == "#{Gitlab.config.gitlab.url}/somewhere"
end
- it "returns the web URL without the protocol for this repo" do
- project = Project.new(path: "somewhere")
- project.web_url_without_protocol.should == "#{Gitlab.config.gitlab.url.split("://")[1]}/somewhere"
+ it 'returns the web URL without the protocol for this repo' do
+ project = Project.new(path: 'somewhere')
+ project.web_url_without_protocol.should == "#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere"
end
- describe "last_activity methods" do
+ describe 'last_activity methods' do
let(:project) { create(:project) }
let(:last_event) { double(created_at: Time.now) }
- describe "last_activity" do
- it "should alias last_activity to last_event" do
+ describe 'last_activity' do
+ it 'should alias last_activity to last_event' do
project.stub(last_event: last_event)
project.last_activity.should == last_event
end
@@ -134,13 +135,13 @@ describe Project do
let(:prev_commit_id) { merge_request.commits.last.id }
let(:commit_id) { merge_request.commits.first.id }
- it "should close merge request if last commit from source branch was pushed to target branch" do
+ it 'should close merge request if last commit from source branch was pushed to target branch' do
project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user)
merge_request.reload
merge_request.merged?.should be_true
end
- it "should update merge request commits with new one if pushed to source branch" do
+ it 'should update merge request commits with new one if pushed to source branch' do
project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user)
merge_request.reload
merge_request.last_commit.id.should == commit_id
@@ -166,14 +167,14 @@ describe Project do
@project = create(:project, name: 'gitlabhq', namespace: @group)
end
- it { @project.to_param.should == "gitlab/gitlabhq" }
+ it { @project.to_param.should == 'gitlab/gitlabhq' }
end
end
describe :repository do
let(:project) { create(:project) }
- it "should return valid repo" do
+ it 'should return valid repo' do
project.repository.should be_kind_of(Repository)
end
end
@@ -184,15 +185,15 @@ describe Project do
let(:not_existed_issue) { create(:issue) }
let(:ext_project) { create(:redmine_project) }
- it "should be true or if used internal tracker and issue exists" do
+ it 'should be true or if used internal tracker and issue exists' do
project.issue_exists?(existed_issue.iid).should be_true
end
- it "should be false or if used internal tracker and issue not exists" do
+ it 'should be false or if used internal tracker and issue not exists' do
project.issue_exists?(not_existed_issue.iid).should be_false
end
- it "should always be true if used other tracker" do
+ it 'should always be true if used other tracker' do
ext_project.issue_exists?(rand(100)).should be_true
end
end
@@ -214,15 +215,15 @@ describe Project do
let(:project) { create(:project) }
let(:ext_project) { create(:redmine_project) }
- it "should be true for projects with external issues tracker if issues enabled" do
+ it 'should be true for projects with external issues tracker if issues enabled' do
ext_project.can_have_issues_tracker_id?.should be_true
end
- it "should be false for projects with internal issue tracker if issues enabled" do
+ it 'should be false for projects with internal issue tracker if issues enabled' do
project.can_have_issues_tracker_id?.should be_false
end
- it "should be always false if issues disabled" do
+ it 'should be always false if issues disabled' do
project.issues_enabled = false
ext_project.issues_enabled = false
@@ -310,4 +311,18 @@ describe Project do
expect(project.star_count).to eq(0)
end
end
+
+ describe :avatar_type do
+ let(:project) { create(:project) }
+
+ it 'should be true if avatar is image' do
+ project.update_attribute(:avatar, 'uploads/avatar.png')
+ project.avatar_type.should be_true
+ end
+
+ it 'should be false if avatar is html page' do
+ project.update_attribute(:avatar, 'uploads/avatar.html')
+ project.avatar_type.should == ['only images allowed']
+ end
+ end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index f149f3f62a9..e36b266a1ff 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -12,43 +12,43 @@ require 'spec_helper'
# Examples
#
# # Default behavior
-# it_behaves_like "RESTful project resources" do
+# it_behaves_like 'RESTful project resources' do
# let(:controller) { 'issues' }
# end
#
# # Customizing actions
-# it_behaves_like "RESTful project resources" do
+# it_behaves_like 'RESTful project resources' do
# let(:actions) { [:index] }
# let(:controller) { 'issues' }
# end
-shared_examples "RESTful project resources" do
+shared_examples 'RESTful project resources' do
let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
- it "to #index" do
+ it 'to #index' do
get("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlab/gitlabhq') if actions.include?(:index)
end
- it "to #create" do
+ it 'to #create' do
post("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlab/gitlabhq') if actions.include?(:create)
end
- it "to #new" do
+ it 'to #new' do
get("/gitlab/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlab/gitlabhq') if actions.include?(:new)
end
- it "to #edit" do
+ it 'to #edit' do
get("/gitlab/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:edit)
end
- it "to #show" do
+ it 'to #show' do
get("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:show)
end
- it "to #update" do
+ it 'to #update' do
put("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:update)
end
- it "to #destroy" do
+ it 'to #destroy' do
delete("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:destroy)
end
end
@@ -61,33 +61,33 @@ end
# PUT /:id(.:format) projects#update
# DELETE /:id(.:format) projects#destroy
# markdown_preview_project GET /:id/markdown_preview(.:format) projects#markdown_preview
-describe ProjectsController, "routing" do
- it "to #create" do
- post("/projects").should route_to('projects#create')
+describe ProjectsController, 'routing' do
+ it 'to #create' do
+ post('/projects').should route_to('projects#create')
end
- it "to #new" do
- get("/projects/new").should route_to('projects#new')
+ it 'to #new' do
+ get('/projects/new').should route_to('projects#new')
end
- it "to #edit" do
- get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq')
+ it 'to #edit' do
+ get('/gitlab/gitlabhq/edit').should route_to('projects#edit', id: 'gitlab/gitlabhq')
end
- it "to #autocomplete_sources" do
- get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlab/gitlabhq")
+ it 'to #autocomplete_sources' do
+ get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: 'gitlab/gitlabhq')
end
- it "to #show" do
- get("/gitlab/gitlabhq").should route_to('projects#show', id: 'gitlab/gitlabhq')
+ it 'to #show' do
+ get('/gitlab/gitlabhq').should route_to('projects#show', id: 'gitlab/gitlabhq')
end
- it "to #update" do
- put("/gitlab/gitlabhq").should route_to('projects#update', id: 'gitlab/gitlabhq')
+ it 'to #update' do
+ put('/gitlab/gitlabhq').should route_to('projects#update', id: 'gitlab/gitlabhq')
end
- it "to #destroy" do
- delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq')
+ it 'to #destroy' do
+ delete('/gitlab/gitlabhq').should route_to('projects#destroy', id: 'gitlab/gitlabhq')
end
it 'to #markdown_preview' do
@@ -103,16 +103,16 @@ end
# edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit
# project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show
# DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy
-describe Projects::WikisController, "routing" do
- it "to #pages" do
- get("/gitlab/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq')
+describe Projects::WikisController, 'routing' do
+ it 'to #pages' do
+ get('/gitlab/gitlabhq/wikis/pages').should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq')
end
- it "to #history" do
- get("/gitlab/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #history' do
+ get('/gitlab/gitlabhq/wikis/1/history').should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1')
end
- it_behaves_like "RESTful project resources" do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:create, :edit, :show, :destroy] }
let(:controller) { 'wikis' }
end
@@ -122,45 +122,45 @@ end
# tags_project_repository GET /:project_id/repository/tags(.:format) projects/repositories#tags
# archive_project_repository GET /:project_id/repository/archive(.:format) projects/repositories#archive
# edit_project_repository GET /:project_id/repository/edit(.:format) projects/repositories#edit
-describe Projects::RepositoriesController, "routing" do
- it "to #archive" do
- get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
+describe Projects::RepositoriesController, 'routing' do
+ it 'to #archive' do
+ get('/gitlab/gitlabhq/repository/archive').should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq')
end
- it "to #archive format:zip" do
- get("/gitlab/gitlabhq/repository/archive.zip").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip')
+ it 'to #archive format:zip' do
+ get('/gitlab/gitlabhq/repository/archive.zip').should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip')
end
- it "to #archive format:tar.bz2" do
- get("/gitlab/gitlabhq/repository/archive.tar.bz2").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2')
+ it 'to #archive format:tar.bz2' do
+ get('/gitlab/gitlabhq/repository/archive.tar.bz2').should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2')
end
- it "to #show" do
- get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
+ it 'to #show' do
+ get('/gitlab/gitlabhq/repository').should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq')
end
end
-describe Projects::BranchesController, "routing" do
- it "to #branches" do
- get("/gitlab/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq')
- delete("/gitlab/gitlabhq/branches/feature%2345").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
- delete("/gitlab/gitlabhq/branches/feature%2B45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
- delete("/gitlab/gitlabhq/branches/feature@45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
- delete("/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
- delete("/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
- delete("/gitlab/gitlabhq/branches/feature@45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
+describe Projects::BranchesController, 'routing' do
+ it 'to #branches' do
+ get('/gitlab/gitlabhq/branches').should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq')
+ delete('/gitlab/gitlabhq/branches/feature%2345').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
+ delete('/gitlab/gitlabhq/branches/feature%2B45').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
+ delete('/gitlab/gitlabhq/branches/feature@45').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
+ delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
+ delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
+ delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz').should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
end
end
-describe Projects::TagsController, "routing" do
- it "to #tags" do
- get("/gitlab/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq')
- delete("/gitlab/gitlabhq/tags/feature%2345").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
- delete("/gitlab/gitlabhq/tags/feature%2B45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
- delete("/gitlab/gitlabhq/tags/feature@45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
- delete("/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
- delete("/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
- delete("/gitlab/gitlabhq/tags/feature@45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
+describe Projects::TagsController, 'routing' do
+ it 'to #tags' do
+ get('/gitlab/gitlabhq/tags').should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq')
+ delete('/gitlab/gitlabhq/tags/feature%2345').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45')
+ delete('/gitlab/gitlabhq/tags/feature%2B45').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45')
+ delete('/gitlab/gitlabhq/tags/feature@45').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45')
+ delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz')
+ delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz')
+ delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz').should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz')
end
end
@@ -172,8 +172,8 @@ end
# project_deploy_key GET /:project_id/deploy_keys/:id(.:format) deploy_keys#show
# PUT /:project_id/deploy_keys/:id(.:format) deploy_keys#update
# DELETE /:project_id/deploy_keys/:id(.:format) deploy_keys#destroy
-describe Projects::DeployKeysController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::DeployKeysController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:controller) { 'deploy_keys' }
end
end
@@ -181,8 +181,8 @@ end
# project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index
# POST /:project_id/protected_branches(.:format) protected_branches#create
# project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy
-describe Projects::ProtectedBranchesController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::ProtectedBranchesController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :create, :destroy] }
let(:controller) { 'protected_branches' }
end
@@ -191,21 +191,21 @@ end
# switch_project_refs GET /:project_id/refs/switch(.:format) refs#switch
# logs_tree_project_ref GET /:project_id/refs/:id/logs_tree(.:format) refs#logs_tree
# logs_file_project_ref GET /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree
-describe Projects::RefsController, "routing" do
- it "to #switch" do
- get("/gitlab/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq')
- end
-
- it "to #logs_tree" do
- get("/gitlab/gitlabhq/refs/stable/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable')
- get("/gitlab/gitlabhq/refs/feature%2345/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45')
- get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45')
- get("/gitlab/gitlabhq/refs/feature@45/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45')
- get("/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz')
- get("/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
- get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
- get("/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45', path: 'foo/bar/baz')
- get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
+describe Projects::RefsController, 'routing' do
+ it 'to #switch' do
+ get('/gitlab/gitlabhq/refs/switch').should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq')
+ end
+
+ it 'to #logs_tree' do
+ get('/gitlab/gitlabhq/refs/stable/logs_tree').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable')
+ get('/gitlab/gitlabhq/refs/feature%2345/logs_tree').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45')
+ get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45')
+ get('/gitlab/gitlabhq/refs/feature@45/logs_tree').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45')
+ get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz')
+ get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
+ get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
+ get('/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45', path: 'foo/bar/baz')
+ get('/gitlab/gitlabhq/refs/stable/logs_tree/files.scss').should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
end
end
@@ -221,36 +221,36 @@ end
# project_merge_request GET /:project_id/merge_requests/:id(.:format) projects/merge_requests#show
# PUT /:project_id/merge_requests/:id(.:format) projects/merge_requests#update
# DELETE /:project_id/merge_requests/:id(.:format) projects/merge_requests#destroy
-describe Projects::MergeRequestsController, "routing" do
- it "to #diffs" do
- get("/gitlab/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1')
+describe Projects::MergeRequestsController, 'routing' do
+ it 'to #diffs' do
+ get('/gitlab/gitlabhq/merge_requests/1/diffs').should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #automerge" do
+ it 'to #automerge' do
post('/gitlab/gitlabhq/merge_requests/1/automerge').should route_to(
'projects/merge_requests#automerge',
project_id: 'gitlab/gitlabhq', id: '1'
)
end
- it "to #automerge_check" do
- get("/gitlab/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #automerge_check' do
+ get('/gitlab/gitlabhq/merge_requests/1/automerge_check').should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #branch_from" do
- get("/gitlab/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq')
+ it 'to #branch_from' do
+ get('/gitlab/gitlabhq/merge_requests/branch_from').should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq')
end
- it "to #branch_to" do
- get("/gitlab/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq')
+ it 'to #branch_to' do
+ get('/gitlab/gitlabhq/merge_requests/branch_to').should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq')
end
- it "to #show" do
- get("/gitlab/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff')
- get("/gitlab/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch')
+ it 'to #show' do
+ get('/gitlab/gitlabhq/merge_requests/1.diff').should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff')
+ get('/gitlab/gitlabhq/merge_requests/1.patch').should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch')
end
- it_behaves_like "RESTful project resources" do
+ it_behaves_like 'RESTful project resources' do
let(:controller) { 'merge_requests' }
let(:actions) { [:index, :create, :new, :edit, :show, :update] }
end
@@ -264,37 +264,37 @@ end
# project_snippet GET /:project_id/snippets/:id(.:format) snippets#show
# PUT /:project_id/snippets/:id(.:format) snippets#update
# DELETE /:project_id/snippets/:id(.:format) snippets#destroy
-describe SnippetsController, "routing" do
- it "to #raw" do
- get("/gitlab/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1')
+describe SnippetsController, 'routing' do
+ it 'to #raw' do
+ get('/gitlab/gitlabhq/snippets/1/raw').should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #index" do
- get("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlab/gitlabhq')
+ it 'to #index' do
+ get('/gitlab/gitlabhq/snippets').should route_to('projects/snippets#index', project_id: 'gitlab/gitlabhq')
end
- it "to #create" do
- post("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlab/gitlabhq')
+ it 'to #create' do
+ post('/gitlab/gitlabhq/snippets').should route_to('projects/snippets#create', project_id: 'gitlab/gitlabhq')
end
- it "to #new" do
- get("/gitlab/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlab/gitlabhq')
+ it 'to #new' do
+ get('/gitlab/gitlabhq/snippets/new').should route_to('projects/snippets#new', project_id: 'gitlab/gitlabhq')
end
- it "to #edit" do
- get("/gitlab/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #edit' do
+ get('/gitlab/gitlabhq/snippets/1/edit').should route_to('projects/snippets#edit', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #show" do
- get("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #show' do
+ get('/gitlab/gitlabhq/snippets/1').should route_to('projects/snippets#show', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #update" do
- put("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #update' do
+ put('/gitlab/gitlabhq/snippets/1').should route_to('projects/snippets#update', project_id: 'gitlab/gitlabhq', id: '1')
end
- it "to #destroy" do
- delete("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlab/gitlabhq', id: '1')
+ it 'to #destroy' do
+ delete('/gitlab/gitlabhq/snippets/1').should route_to('projects/snippets#destroy', project_id: 'gitlab/gitlabhq', id: '1')
end
end
@@ -302,24 +302,24 @@ end
# project_hooks GET /:project_id/hooks(.:format) hooks#index
# POST /:project_id/hooks(.:format) hooks#create
# project_hook DELETE /:project_id/hooks/:id(.:format) hooks#destroy
-describe Projects::HooksController, "routing" do
- it "to #test" do
- get("/gitlab/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1')
+describe Projects::HooksController, 'routing' do
+ it 'to #test' do
+ get('/gitlab/gitlabhq/hooks/1/test').should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1')
end
- it_behaves_like "RESTful project resources" do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :create, :destroy] }
let(:controller) { 'hooks' }
end
end
# project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /[[:alnum:]]{6,40}/, project_id: /[^\/]+/}
-describe Projects::CommitController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb')
- get("/gitlab/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff')
- get("/gitlab/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch')
- get("/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
+describe Projects::CommitController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/commit/4246fb').should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb')
+ get('/gitlab/gitlabhq/commit/4246fb.diff').should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff')
+ get('/gitlab/gitlabhq/commit/4246fb.patch').should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch')
+ get('/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5').should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5')
end
end
@@ -327,14 +327,14 @@ end
# project_commits GET /:project_id/commits(.:format) commits#index
# POST /:project_id/commits(.:format) commits#create
# project_commit GET /:project_id/commits/:id(.:format) commits#show
-describe Projects::CommitsController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::CommitsController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:show] }
let(:controller) { 'commits' }
end
- it "to #show" do
- get("/gitlab/gitlabhq/commits/master.atom").should route_to('projects/commits#show', project_id: 'gitlab/gitlabhq', id: "master", format: "atom")
+ it 'to #show' do
+ get('/gitlab/gitlabhq/commits/master.atom').should route_to('projects/commits#show', project_id: 'gitlab/gitlabhq', id: 'master', format: 'atom')
end
end
@@ -345,8 +345,8 @@ end
# project_team_member GET /:project_id/team_members/:id(.:format) team_members#show
# PUT /:project_id/team_members/:id(.:format) team_members#update
# DELETE /:project_id/team_members/:id(.:format) team_members#destroy
-describe Projects::TeamMembersController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::TeamMembersController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:new, :create, :update, :destroy] }
let(:controller) { 'team_members' }
end
@@ -359,17 +359,17 @@ end
# project_milestone GET /:project_id/milestones/:id(.:format) milestones#show
# PUT /:project_id/milestones/:id(.:format) milestones#update
# DELETE /:project_id/milestones/:id(.:format) milestones#destroy
-describe Projects::MilestonesController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::MilestonesController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:controller) { 'milestones' }
let(:actions) { [:index, :create, :new, :edit, :show, :update] }
end
end
# project_labels GET /:project_id/labels(.:format) labels#index
-describe Projects::LabelsController, "routing" do
- it "to #index" do
- get("/gitlab/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq')
+describe Projects::LabelsController, 'routing' do
+ it 'to #index' do
+ get('/gitlab/gitlabhq/labels').should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq')
end
end
@@ -383,12 +383,12 @@ end
# project_issue GET /:project_id/issues/:id(.:format) issues#show
# PUT /:project_id/issues/:id(.:format) issues#update
# DELETE /:project_id/issues/:id(.:format) issues#destroy
-describe Projects::IssuesController, "routing" do
- it "to #bulk_update" do
- post("/gitlab/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq')
+describe Projects::IssuesController, 'routing' do
+ it 'to #bulk_update' do
+ post('/gitlab/gitlabhq/issues/bulk_update').should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq')
end
- it_behaves_like "RESTful project resources" do
+ it_behaves_like 'RESTful project resources' do
let(:controller) { 'issues' }
let(:actions) { [:index, :create, :new, :edit, :show, :update] }
end
@@ -397,54 +397,50 @@ end
# project_notes GET /:project_id/notes(.:format) notes#index
# POST /:project_id/notes(.:format) notes#create
# project_note DELETE /:project_id/notes/:id(.:format) notes#destroy
-describe Projects::NotesController, "routing" do
- it_behaves_like "RESTful project resources" do
+describe Projects::NotesController, 'routing' do
+ it_behaves_like 'RESTful project resources' do
let(:actions) { [:index, :create, :destroy] }
let(:controller) { 'notes' }
end
end
# project_blame GET /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::BlameController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
- get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::BlameController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/blame/master/app/models/project.rb').should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
+ get('/gitlab/gitlabhq/blame/master/files.scss').should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
# project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::BlobController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
- get("/gitlab/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb')
- get("/gitlab/gitlabhq/blob/master/app/models/diff.js").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/diff.js')
- get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::BlobController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/blob/master/app/models/project.rb').should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
+ get('/gitlab/gitlabhq/blob/master/app/models/compare.rb').should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb')
+ get('/gitlab/gitlabhq/blob/master/app/models/diff.js').should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/diff.js')
+ get('/gitlab/gitlabhq/blob/master/files.scss').should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
# project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/}
-describe Projects::TreeController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
- get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
+describe Projects::TreeController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/tree/master/app/models/project.rb').should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb')
+ get('/gitlab/gitlabhq/tree/master/files.scss').should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
end
end
-describe Projects::EditTreeController, 'routing' do
- it 'to #show' do
+describe Projects::BlobController, 'routing' do
+ it 'to #edit' do
get('/gitlab/gitlabhq/edit/master/app/models/project.rb').should(
- route_to('projects/edit_tree#show',
+ route_to('projects/blob#edit',
project_id: 'gitlab/gitlabhq',
id: 'master/app/models/project.rb'))
- get('/gitlab/gitlabhq/edit/master/app/models/project.rb/preview').should(
- route_to('projects/edit_tree#show',
- project_id: 'gitlab/gitlabhq',
- id: 'master/app/models/project.rb/preview'))
end
it 'to #preview' do
- post('/gitlab/gitlabhq/edit/master/app/models/project.rb/preview').should(
- route_to('projects/edit_tree#preview',
+ post('/gitlab/gitlabhq/preview/master/app/models/project.rb').should(
+ route_to('projects/blob#preview',
project_id: 'gitlab/gitlabhq',
id: 'master/app/models/project.rb'))
end
@@ -453,40 +449,48 @@ end
# project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/}
# POST /:project_id/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/}
# project_compare /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/}
-describe Projects::CompareController, "routing" do
- it "to #index" do
- get("/gitlab/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq')
+describe Projects::CompareController, 'routing' do
+ it 'to #index' do
+ get('/gitlab/gitlabhq/compare').should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq')
end
- it "to #compare" do
- post("/gitlab/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq')
+ it 'to #compare' do
+ post('/gitlab/gitlabhq/compare').should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq')
end
- it "to #show" do
- get("/gitlab/gitlabhq/compare/master...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable')
- get("/gitlab/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable')
+ it 'to #show' do
+ get('/gitlab/gitlabhq/compare/master...stable').should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable')
+ get('/gitlab/gitlabhq/compare/issue/1234...stable').should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable')
end
end
-describe Projects::NetworkController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master')
- get("/gitlab/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: "json")
+describe Projects::NetworkController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/network/master').should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master')
+ get('/gitlab/gitlabhq/network/master.json').should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: 'json')
end
end
-describe Projects::GraphsController, "routing" do
- it "to #show" do
- get("/gitlab/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master')
+describe Projects::GraphsController, 'routing' do
+ it 'to #show' do
+ get('/gitlab/gitlabhq/graphs/master').should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master')
end
end
-describe Projects::ForksController, "routing" do
- it "to #new" do
- get("/gitlab/gitlabhq/fork/new").should route_to("projects/forks#new", project_id: 'gitlab/gitlabhq')
+describe Projects::ForksController, 'routing' do
+ it 'to #new' do
+ get('/gitlab/gitlabhq/fork/new').should route_to('projects/forks#new', project_id: 'gitlab/gitlabhq')
+ end
+
+ it 'to #create' do
+ post('/gitlab/gitlabhq/fork').should route_to('projects/forks#create', project_id: 'gitlab/gitlabhq')
end
+end
- it "to #create" do
- post("/gitlab/gitlabhq/fork").should route_to("projects/forks#create", project_id: 'gitlab/gitlabhq')
+# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy
+describe Projects::AvatarsController, 'routing' do
+ it 'to #destroy' do
+ delete('/gitlab/gitlabhq/avatar').should route_to(
+ 'projects/avatars#destroy', project_id: 'gitlab/gitlabhq')
end
end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 347560414e7..36030577835 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -22,6 +22,7 @@ describe Issues::UpdateService do
}
@issue = Issues::UpdateService.new(project, user, opts).execute(issue)
+ @issue.reload
end
it { @issue.should be_valid }
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index c8f40f48bab..0e60baae2c4 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -21,12 +21,14 @@ describe MergeRequests::UpdateService do
state_event: 'close'
}
end
+
let(:service) { MergeRequests::UpdateService.new(project, user, opts) }
before do
service.stub(:execute_hooks)
@merge_request = service.execute(merge_request)
+ @merge_request.reload
end
it { @merge_request.should be_valid }
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index e305536f7ee..2ba1e3372b9 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -187,7 +187,7 @@ describe NotificationService do
end
describe 'Issues' do
- let(:issue) { create :issue, assignee: create(:user) }
+ let(:issue) { create :issue, assignee: create(:user), description: 'cc @participant' }
before do
build_team(issue.project)
@@ -197,6 +197,7 @@ describe NotificationService do
it do
should_email(issue.assignee_id)
should_email(@u_watcher.id)
+ should_email(@u_participant_mentioned.id)
should_not_email(@u_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
@@ -222,6 +223,7 @@ describe NotificationService do
it 'should email new assignee' do
should_email(issue.assignee_id)
should_email(@u_watcher.id)
+ should_email(@u_participant_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
@@ -242,6 +244,7 @@ describe NotificationService do
should_email(issue.assignee_id)
should_email(issue.author_id)
should_email(@u_watcher.id)
+ should_email(@u_participant_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
@@ -262,6 +265,7 @@ describe NotificationService do
should_email(issue.assignee_id)
should_email(issue.author_id)
should_email(@u_watcher.id)
+ should_email(@u_participant_mentioned.id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
@@ -404,6 +408,7 @@ describe NotificationService do
def build_team(project)
@u_watcher = create(:user, notification_level: Notification::N_WATCH)
@u_participating = create(:user, notification_level: Notification::N_PARTICIPATING)
+ @u_participant_mentioned = create(:user, username: 'participant', notification_level: Notification::N_PARTICIPATING)
@u_disabled = create(:user, notification_level: Notification::N_DISABLED)
@u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION)
@u_committer = create(:user, username: 'committer')