From 39e54e21cb5dfaddaf4c83bc4509c951675091ea Mon Sep 17 00:00:00 2001 From: jubianchi Date: Sun, 18 Jan 2015 22:17:10 +0100 Subject: [PATCH 01/80] Handle errors on API when a project does not have a repository (Closes #6289) --- lib/api/repositories.rb | 37 ++++++++++++++++++++------ spec/requests/api/repositories_spec.rb | 16 +++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 03a556a2c55..b259914a01c 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -58,11 +58,13 @@ module API # ref_name (optional) - The name of a repository branch or tag, if not given the default branch is used # Example Request: # GET /projects/:id/repository/tree - get ":id/repository/tree" do + get ':id/repository/tree' do ref = params[:ref_name] || user_project.try(:default_branch) || 'master' path = params[:path] || nil commit = user_project.repository.commit(ref) + not_found!('Tree') unless commit + tree = user_project.repository.tree(commit.id, path) present tree.sorted_entries, with: Entities::RepoTreeObject @@ -100,14 +102,18 @@ module API # sha (required) - The blob's sha # Example Request: # GET /projects/:id/repository/raw_blobs/:sha - get ":id/repository/raw_blobs/:sha" do + get ':id/repository/raw_blobs/:sha' do ref = params[:sha] repo = user_project.repository - blob = Gitlab::Git::Blob.raw(repo, ref) + begin + blob = Gitlab::Git::Blob.raw(repo, ref) + rescue + not_found! 'Blob' + end - not_found! "Blob" unless blob + not_found! 'Blob' unless blob env['api.format'] = :txt @@ -122,13 +128,23 @@ module API # sha (optional) - the commit sha to download defaults to the tip of the default branch # Example Request: # GET /projects/:id/repository/archive - get ":id/repository/archive", requirements: { format: Gitlab::Regex.archive_formats_regex } do + get ':id/repository/archive', + requirements: { format: Gitlab::Regex.archive_formats_regex } do authorize! :download_code, user_project - file_path = ArchiveRepositoryService.new.execute(user_project, params[:sha], params[:format]) + + begin + file_path = ArchiveRepositoryService.new.execute( + user_project, + params[:sha], + params[:format]) + rescue + not_found!('File') + end if file_path && File.exists?(file_path) data = File.open(file_path, 'rb').read - header["Content-Disposition"] = "attachment; filename=\"#{File.basename(file_path)}\"" + basename = File.basename(file_path) + header['Content-Disposition'] = "attachment; filename=\"#{basename}\"" content_type MIME::Types.type_for(file_path).first.content_type env['api.format'] = :binary present data @@ -161,7 +177,12 @@ module API get ':id/repository/contributors' do authorize! :download_code, user_project - present user_project.repository.contributors, with: Entities::Contributor + begin + present user_project.repository.contributors, + with: Entities::Contributor + rescue + not_found! + end end end end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index beae71c02d9..5518d2df566 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -101,6 +101,14 @@ describe API::API, api: true do json_response.first['type'].should == 'tree' json_response.first['mode'].should == '040000' end + + it 'should return a 404 for unknown ref' do + get api("/projects/#{project.id}/repository/tree?ref_name=foo", user) + response.status.should == 404 + + json_response.should be_an Object + json_response['message'] == '404 Tree Not Found' + end end context "unauthorized user" do @@ -145,6 +153,14 @@ describe API::API, api: true do get api("/projects/#{project.id}/repository/raw_blobs/#{sample_blob.oid}", user) response.status.should == 200 end + + it 'should return a 404 for unknown blob' do + get api("/projects/#{project.id}/repository/raw_blobs/123456", user) + response.status.should == 404 + + json_response.should be_an Object + json_response['message'] == '404 Blob Not Found' + end end describe "GET /projects/:id/repository/archive(.:format)?:sha" do From 9371c6b90136547e3622622510af9894fc27aeb0 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 20 Jan 2015 16:46:27 -0800 Subject: [PATCH 02/80] Add issue tracker services. --- .../project_services/issue_tracker_service.rb | 14 +++++ app/models/project_services/jira_service.rb | 59 +++++++++++++++++++ .../project_services/redmine_service.rb | 51 ++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 app/models/project_services/issue_tracker_service.rb create mode 100644 app/models/project_services/jira_service.rb create mode 100644 app/models/project_services/redmine_service.rb diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb new file mode 100644 index 00000000000..4ba2f5a9ca2 --- /dev/null +++ b/app/models/project_services/issue_tracker_service.rb @@ -0,0 +1,14 @@ +class IssueTrackerService < Service + + def project_url + # implement inside child + end + + def issues_url + # implement inside child + end + + def new_issue_url + # implement inside child + end +end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb new file mode 100644 index 00000000000..f83f01c55b4 --- /dev/null +++ b/app/models/project_services/jira_service.rb @@ -0,0 +1,59 @@ +class JiraService < IssueTrackerService + + prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + + def title + if self.properties && self.properties['title'].present? + self.properties['title'] + else + 'JIRA' + end + end + + def description + if self.properties && self.properties['description'].present? + self.properties['description'] + else + 'Jira issue tracker' + end + end + + def to_param + 'jira' + end + + def fields + [ + { type: 'text', name: 'title', placeholder: title }, + { type: 'text', name: 'description', placeholder: description }, + { type: 'text', name: 'project_url', placeholder: 'Project url' }, + { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + ] + end + + def initialize_properties + if properties.nil? + if enabled_in_gitlab_config + self.properties = { + title: issues_tracker['title'], + project_url: issues_tracker['project_url'], + issues_url: issues_tracker['issues_url'], + new_issue_url: issues_tracker['new_issue_url'] + } + end + end + end + + private + + def enabled_in_gitlab_config + Gitlab.config.issues_tracker && + Gitlab.config.issues_tracker.values.any? && + issues_tracker + end + + def issues_tracker + Gitlab.config.issues_tracker['jira'] + end +end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb new file mode 100644 index 00000000000..8052fb22461 --- /dev/null +++ b/app/models/project_services/redmine_service.rb @@ -0,0 +1,51 @@ +class RedmineService < IssueTrackerService + + prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + + def title + 'Redmine' + end + + def description + 'Redmine issue tracker' + end + + def to_param + 'redmine' + end + + def fields + [ + { type: 'text', name: 'title', placeholder: title }, + { type: 'text', name: 'description', placeholder: description }, + { type: 'text', name: 'project_url', placeholder: 'Project url' }, + { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + ] + end + + def initialize_properties + if properties.nil? + if enabled_in_gitlab_config + self.properties = { + title: issues_tracker['title'], + project_url: issues_tracker['project_url'], + issues_url: issues_tracker['issues_url'], + new_issue_url: issues_tracker['new_issue_url'] + } + end + end + end + + private + + def enabled_in_gitlab_config + Gitlab.config.issues_tracker && + Gitlab.config.issues_tracker.values.any? && + issues_tracker + end + + def issues_tracker + Gitlab.config.issues_tracker['redmine'] + end +end From 62c00661c43334f8e2bbed508d9517529dbee7e0 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 20 Jan 2015 16:47:29 -0800 Subject: [PATCH 03/80] Allow creation of the jira and redmine services. --- app/controllers/projects/services_controller.rb | 6 ++++-- app/models/project.rb | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index b2ce99aeb45..15f47ed9c9f 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -17,7 +17,8 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.update_attributes(service_params) - redirect_to edit_project_service_path(@project, @service.to_param) + redirect_to edit_project_service_path(@project, @service.to_param), + notice: 'Successfully updated.' else render 'edit' end @@ -41,7 +42,8 @@ class Projects::ServicesController < Projects::ApplicationController :title, :token, :type, :active, :api_key, :subdomain, :room, :recipients, :project_url, :webhook, :user_key, :device, :priority, :sound, :bamboo_url, :username, :password, - :build_key, :server, :teamcity_url, :build_type + :build_key, :server, :teamcity_url, :build_type, + :description, :issues_url, :new_issue_url ) end end diff --git a/app/models/project.rb b/app/models/project.rb index a22f852de6b..a90081ce735 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -68,6 +68,9 @@ class Project < ActiveRecord::Base has_one :bamboo_service, dependent: :destroy has_one :teamcity_service, dependent: :destroy has_one :pushover_service, dependent: :destroy + has_one :jira_service, dependent: :destroy + has_one :redmine_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 @@ -321,7 +324,7 @@ class Project < ActiveRecord::Base def available_services_names %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla - emails_on_push gemnasium slack pushover buildbox bamboo teamcity) + emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira redmine) end def gitlab_ci? From 09de0bfc37c54b84d5a49dbce8c11cfd2f3cfb80 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 20 Jan 2015 16:55:12 -0800 Subject: [PATCH 04/80] Redmine doesn't require title and description change --- app/models/project_services/redmine_service.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 8052fb22461..55841b50055 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -16,8 +16,6 @@ class RedmineService < IssueTrackerService def fields [ - { type: 'text', name: 'title', placeholder: title }, - { type: 'text', name: 'description', placeholder: description }, { type: 'text', name: 'project_url', placeholder: 'Project url' }, { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} From e9d6d1e51afa9f46f19748977739f7d2c078b84f Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 20 Jan 2015 16:55:35 -0800 Subject: [PATCH 05/80] Custom issue tracker service. --- app/models/project.rb | 3 +- .../custom_issue_tracker_service.rb | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 app/models/project_services/custom_issue_tracker_service.rb diff --git a/app/models/project.rb b/app/models/project.rb index a90081ce735..e501ccb59f7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -70,6 +70,7 @@ class Project < ActiveRecord::Base has_one :pushover_service, dependent: :destroy has_one :jira_service, dependent: :destroy has_one :redmine_service, dependent: :destroy + 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 @@ -324,7 +325,7 @@ class Project < ActiveRecord::Base def available_services_names %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla - emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira redmine) + emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira redmine custom_issue_tracker) end def gitlab_ci? diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb new file mode 100644 index 00000000000..69e1b204bac --- /dev/null +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -0,0 +1,38 @@ +class CustomIssueTrackerService < IssueTrackerService + + prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + + def title + if self.properties && self.properties['title'].present? + self.properties['title'] + else + 'Custom Issue Tracker' + end + end + + def description + if self.properties && self.properties['description'].present? + self.properties['description'] + else + 'Custom issue tracker' + end + end + + def to_param + title.parameterize + end + + def fields + [ + { type: 'text', name: 'title', placeholder: title }, + { type: 'text', name: 'description', placeholder: description }, + { type: 'text', name: 'project_url', placeholder: 'Project url' }, + { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + ] + end + + def initialize_properties + self.properties = {} if properties.nil? + end +end From 201b2f1099c6c1a963455d54bacbe473c7e27f95 Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Wed, 21 Jan 2015 18:57:54 +0100 Subject: [PATCH 06/80] Add return value example to ssh key creation Signed-off-by: Loic Dachary --- doc/api/users.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/api/users.md b/doc/api/users.md index b30a31deccc..dd158f124de 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -322,6 +322,15 @@ 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 +} +``` + ## Add SSH key for user Create new key owned by specified user. Available only for admin From d9b946fb3edb3288b6ae39c8882b287639a75cbb Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Wed, 21 Jan 2015 19:08:15 +0100 Subject: [PATCH 07/80] Document ssh key creation error Add the error code returned in the headers as well as an example of the JSON informative message returned in the body. Signed-off-by: Loic Dachary --- doc/api/users.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/api/users.md b/doc/api/users.md index dd158f124de..71fa62bdd65 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -331,6 +331,22 @@ Parameters: } ``` +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 From 22b7d2156c6d67deb85eccba5ca7e542a7f409e6 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 23 Jan 2015 20:36:53 +0900 Subject: [PATCH 08/80] Remember the project default tab for 30days --- app/assets/javascripts/project_show.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/project_show.js.coffee b/app/assets/javascripts/project_show.js.coffee index 02a7d7b731d..d0eaaad92b8 100644 --- a/app/assets/javascripts/project_show.js.coffee +++ b/app/assets/javascripts/project_show.js.coffee @@ -6,7 +6,7 @@ class @ProjectShow new Flash('Star toggle failed. Try again later.', 'alert') $("a[data-toggle='tab']").on "shown.bs.tab", (e) -> - $.cookie "default_view", $(e.target).attr("href") + $.cookie "default_view", $(e.target).attr("href"), { expires: 30 } defaultView = $.cookie("default_view") if defaultView From 737f6516e697ec5876fcdeb55acedfeefd24c9cc Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 Jan 2015 09:14:45 -0800 Subject: [PATCH 09/80] Update new services with initialization based on existing data. --- .../project_services/custom_issue_tracker_service.rb | 2 +- app/models/project_services/jira_service.rb | 12 +++++++++++- app/models/project_services/redmine_service.rb | 11 ++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb index 69e1b204bac..2476b62da89 100644 --- a/app/models/project_services/custom_issue_tracker_service.rb +++ b/app/models/project_services/custom_issue_tracker_service.rb @@ -19,7 +19,7 @@ class CustomIssueTrackerService < IssueTrackerService end def to_param - title.parameterize + 'custom_issue_tracker' end def fields diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index f83f01c55b4..f8b04ddeea7 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -37,7 +37,7 @@ class JiraService < IssueTrackerService if enabled_in_gitlab_config self.properties = { title: issues_tracker['title'], - project_url: issues_tracker['project_url'], + project_url: set_project_url, issues_url: issues_tracker['issues_url'], new_issue_url: issues_tracker['new_issue_url'] } @@ -56,4 +56,14 @@ class JiraService < IssueTrackerService def issues_tracker Gitlab.config.issues_tracker['jira'] end + + def set_project_url + id = self.project.issues_tracker_id + + if id + issues_tracker['project_url'].gsub(":issues_tracker_id", id) + else + issues_tracker['project_url'] + end + end end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 55841b50055..03f7115d84e 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -27,7 +27,7 @@ class RedmineService < IssueTrackerService if enabled_in_gitlab_config self.properties = { title: issues_tracker['title'], - project_url: issues_tracker['project_url'], + project_url: set_project_url, issues_url: issues_tracker['issues_url'], new_issue_url: issues_tracker['new_issue_url'] } @@ -46,4 +46,13 @@ class RedmineService < IssueTrackerService def issues_tracker Gitlab.config.issues_tracker['redmine'] end + + def set_project_url + id = self.project.issue_tracker_id + if id + issues_tracker['project_url'].gsub(":issue_tracker_id", id) + else + issues_tracker['project_url'] + end + end end From 103a1bb06d00c0b3ee1f0148ee8fc809f4f276f8 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 Jan 2015 10:28:38 -0800 Subject: [PATCH 10/80] Use service settings instead of config file settings to present issues. --- app/helpers/issues_helper.rb | 11 +++-------- app/models/project.rb | 12 ++++++++++++ app/models/project_services/issue_tracker_service.rb | 4 ++++ app/models/project_services/redmine_service.rb | 4 ++-- lib/gitlab/markdown.rb | 7 +++---- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index bcf108c5c48..b6ca2a057f7 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -16,7 +16,7 @@ module IssuesHelper def url_for_project_issues(project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? project_issues_path(project) else url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] @@ -28,7 +28,7 @@ module IssuesHelper def url_for_new_issue(project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? url = new_project_issue_path project_id: project else issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] @@ -41,7 +41,7 @@ module IssuesHelper def url_for_issue(issue_iid, project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? url = project_issue_url project_id: project, id: issue_iid else url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] @@ -77,11 +77,6 @@ module IssuesHelper ts.html_safe end - # Checks if issues_tracker setting exists in gitlab.yml - def external_issues_tracker_enabled? - Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any? - end - def bulk_update_milestone_options options_for_select(['None (backlog)']) + options_from_collection_for_select(project_active_milestones, 'id', diff --git a/app/models/project.rb b/app/models/project.rb index e501ccb59f7..0fff5149970 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -309,6 +309,18 @@ class Project < ActiveRecord::Base self.issues_tracker == Project.issues_tracker.default_value end + def external_issues_tracker_enabled? + external_issues_trackers.any? + end + + def external_issues_trackers + services.select { |service| service.category == :issue_tracker } + end + + def external_issue_tracker + @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first + end + def can_have_issues_tracker_id? self.issues_enabled && !self.used_default_issues_tracker? end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 4ba2f5a9ca2..664b55a5951 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,5 +1,9 @@ class IssueTrackerService < Service + def category + :issue_tracker + end + def project_url # implement inside child end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 03f7115d84e..71286d74b58 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -48,9 +48,9 @@ class RedmineService < IssueTrackerService end def set_project_url - id = self.project.issue_tracker_id + id = self.project.issues_tracker_id if id - issues_tracker['project_url'].gsub(":issue_tracker_id", id) + issues_tracker['project_url'].gsub(":issues_tracker_id", id) else issues_tracker['project_url'] end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 068c342398b..5987ee8da99 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -208,7 +208,7 @@ module Gitlab end def reference_issue(identifier, project = @project, prefix_text = nil) - if project.used_default_issues_tracker? || !external_issues_tracker_enabled? + if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? if project.issue_exists? identifier url = url_for_issue(identifier, project) title = title_for_issue(identifier, project) @@ -220,8 +220,7 @@ module Gitlab link_to("#{prefix_text}##{identifier}", url, options) end else - config = Gitlab.config - external_issue_tracker = config.issues_tracker[project.issues_tracker] + external_issue_tracker = project.external_issue_tracker if external_issue_tracker.present? reference_external_issue(identifier, external_issue_tracker, project, prefix_text) @@ -270,7 +269,7 @@ module Gitlab def reference_external_issue(identifier, issue_tracker, project = @project, prefix_text = nil) url = url_for_issue(identifier, project) - title = issue_tracker['title'] + title = issue_tracker.title options = html_options.merge( title: "Issue in #{title}", From 7c701acf573f95cce7f8b1b7756de5d73404f09b Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 Jan 2015 11:01:09 -0800 Subject: [PATCH 11/80] Do a check which issue tracker is used inside the project. --- app/helpers/issues_helper.rb | 8 ++++---- app/models/project.rb | 10 +++++++--- app/views/layouts/nav/_project.html.haml | 2 +- lib/gitlab/markdown.rb | 2 +- spec/models/project_spec.rb | 6 +++--- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index b6ca2a057f7..d3bb1d39203 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -16,7 +16,7 @@ module IssuesHelper def url_for_project_issues(project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? + if project.using_issue_tracker? project_issues_path(project) else url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] @@ -28,7 +28,7 @@ module IssuesHelper def url_for_new_issue(project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? + if project.using_issue_tracker? url = new_project_issue_path project_id: project else issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] @@ -41,7 +41,7 @@ module IssuesHelper def url_for_issue(issue_iid, project = @project) return '' if project.nil? - if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? + if project.using_issue_tracker? url = project_issue_url project_id: project, id: issue_iid else url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] @@ -54,7 +54,7 @@ module IssuesHelper def title_for_issue(issue_iid, project = @project) return '' if project.nil? - if project.used_default_issues_tracker? + if project.default_issues_tracker? issue = project.issues.where(iid: issue_iid).first return issue.title if issue end diff --git a/app/models/project.rb b/app/models/project.rb index 0fff5149970..a79e74105b2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -298,14 +298,14 @@ class Project < ActiveRecord::Base end def issue_exists?(issue_id) - if used_default_issues_tracker? + if default_issues_tracker? self.issues.where(iid: issue_id).first.present? else true end end - def used_default_issues_tracker? + def default_issues_tracker? self.issues_tracker == Project.issues_tracker.default_value end @@ -321,8 +321,12 @@ class Project < ActiveRecord::Base @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first end + def using_issue_tracker? + default_issues_tracker? || !external_issues_tracker_enabled? + end + def can_have_issues_tracker_id? - self.issues_enabled && !self.used_default_issues_tracker? + self.issues_enabled && !self.default_issues_tracker? end def build_missing_services diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 94cee0bd50f..07ac4be2046 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -39,7 +39,7 @@ %i.fa.fa-exclamation-circle %span Issues - - if @project.used_default_issues_tracker? + - if @project.default_issues_tracker? %span.count.issue_counter= @project.issues.opened.count - if project_nav_tab? :merge_requests diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 5987ee8da99..6ba7a0c18fb 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -208,7 +208,7 @@ module Gitlab end def reference_issue(identifier, project = @project, prefix_text = nil) - if project.used_default_issues_tracker? || !project.external_issues_tracker_enabled? + if project.using_issue_tracker? if project.issue_exists? identifier url = url_for_issue(identifier, project) title = title_for_issue(identifier, project) diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 70a15cac1a8..9d633e78187 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -195,16 +195,16 @@ describe Project do end end - describe :used_default_issues_tracker? do + describe :default_issues_tracker? do let(:project) { create(:project) } let(:ext_project) { create(:redmine_project) } it "should be true if used internal tracker" do - project.used_default_issues_tracker?.should be_true + project.default_issues_tracker?.should be_true end it "should be false if used other tracker" do - ext_project.used_default_issues_tracker?.should be_false + ext_project.default_issues_tracker?.should be_false end end From 041bad0fe17a31eb7becde3a656a1d0e50dc85bf Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 Jan 2015 11:10:06 -0800 Subject: [PATCH 12/80] Manipulate external tracker issues urls generated from services. --- app/helpers/issues_helper.rb | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index d3bb1d39203..cfbbed842cd 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -19,9 +19,7 @@ module IssuesHelper if project.using_issue_tracker? project_issues_path(project) else - url = Gitlab.config.issues_tracker[project.issues_tracker]['project_url'] - url.gsub(':project_id', project.id.to_s). - gsub(':issues_tracker_id', project.issues_tracker_id.to_s) + project.external_issue_tracker.project_url end end @@ -31,10 +29,7 @@ module IssuesHelper if project.using_issue_tracker? url = new_project_issue_path project_id: project else - issues_tracker = Gitlab.config.issues_tracker[project.issues_tracker] - url = issues_tracker['new_issue_url'] - url.gsub(':project_id', project.id.to_s). - gsub(':issues_tracker_id', project.issues_tracker_id.to_s) + project.external_issue_tracker.new_issue_url end end @@ -44,10 +39,8 @@ module IssuesHelper if project.using_issue_tracker? url = project_issue_url project_id: project, id: issue_iid else - url = Gitlab.config.issues_tracker[project.issues_tracker]['issues_url'] - url.gsub(':id', issue_iid.to_s). - gsub(':project_id', project.id.to_s). - gsub(':issues_tracker_id', project.issues_tracker_id.to_s) + url = project.external_issue_tracker.issues_url + url.gsub(':id', issue_iid.to_s) end end From a720dde67c2b488117ed57f7f07ab55f8150c352 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Fri, 23 Jan 2015 11:55:41 -0800 Subject: [PATCH 13/80] Remove configuration option from project settings page for external issue trackers. --- app/helpers/projects_helper.rb | 12 ------------ app/models/project.rb | 2 +- app/models/service.rb | 8 ++++++++ app/views/projects/edit.html.haml | 9 --------- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9a31d485188..fea78c6e387 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -72,18 +72,6 @@ module ProjectsHelper @project.milestones.active.order("due_date, title ASC") end - def project_issues_trackers(current_tracker = nil) - values = Project.issues_tracker.values.map do |tracker_key| - if tracker_key.to_sym == :gitlab - ['GitLab', tracker_key] - else - [Gitlab.config.issues_tracker[tracker_key]['title'] || tracker_key, tracker_key] - end - end - - options_for_select(values, current_tracker) - end - def link_to_toggle_star(title, starred, signed_in) cls = 'star-btn' cls += ' disabled' unless signed_in diff --git a/app/models/project.rb b/app/models/project.rb index a79e74105b2..4bf36255a56 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -137,7 +137,7 @@ class Project < ActiveRecord::Base scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) } scope :non_archived, -> { where(archived: false) } - enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab + enumerize :issues_tracker, in: (Service.issue_tracker_service_list).append(:gitlab), default: :gitlab state_machine :import_status, initial: :none do event :import_start do diff --git a/app/models/service.rb b/app/models/service.rb index 71c8aa39e45..42419475349 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -86,4 +86,12 @@ class Service < ActiveRecord::Base def async_execute(data) Sidekiq::Client.enqueue(ProjectServiceWorker, id, data) end + + def issue_tracker? + self.category == :issue_tracker + end + + def self.issue_tracker_service_list + Service.select(&:issue_tracker?).map{ |s| s.to_param } + end end diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index f2bb56b5664..fb4d8270731 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -50,15 +50,6 @@ = f.check_box :issues_enabled %span.descr Lightweight issue tracking system for this project - - if Project.issues_tracker.values.count > 1 - .form-group - = f.label :issues_tracker, "Issues tracker", class: 'control-label' - .col-sm-10= f.select(:issues_tracker, project_issues_trackers(@project.issues_tracker), {}, { disabled: !@project.issues_enabled }) - - .form-group - = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label' - .col-sm-10= f.text_field :issues_tracker_id, disabled: !@project.can_have_issues_tracker_id?, class: 'form-control' - .form-group = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' .col-sm-10 From 7ac648911fb018dafa2708fe29ed59847fe875a1 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Sat, 24 Jan 2015 16:40:25 +0200 Subject: [PATCH 14/80] Add titles to links. Closes #1018. --- app/views/groups/_settings_nav.html.haml | 4 ++-- app/views/layouts/nav/_admin.html.haml | 18 +++++++++--------- app/views/layouts/nav/_dashboard.html.haml | 8 ++++---- app/views/layouts/nav/_group.html.haml | 10 +++++----- app/views/layouts/nav/_profile.html.haml | 19 +++++++++---------- app/views/layouts/nav/_project.html.haml | 19 +++++++++---------- app/views/projects/_settings_nav.html.haml | 12 ++++++------ 7 files changed, 44 insertions(+), 46 deletions(-) diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml index 35180792a0d..e6aee22e529 100644 --- a/app/views/groups/_settings_nav.html.haml +++ b/app/views/groups/_settings_nav.html.haml @@ -1,11 +1,11 @@ %ul.sidebar-subnav = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group) do + = link_to edit_group_path(@group), title: 'Group' do %i.fa.fa-pencil-square-o %span Group = nav_link(path: 'groups#projects') do - = link_to projects_group_path(@group) do + = link_to projects_group_path(@group), title: 'Projects' do %i.fa.fa-folder %span Projects diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index d9c6670d1bc..66770adb5a5 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -5,49 +5,49 @@ %span Overview = nav_link(controller: :projects) do - = link_to admin_projects_path do + = link_to admin_projects_path, title: 'Projects' do %i.fa.fa-cube %span Projects = nav_link(controller: :users) do - = link_to admin_users_path do + = link_to admin_users_path, title: 'Users' do %i.fa.fa-user %span Users = nav_link(controller: :groups) do - = link_to admin_groups_path do + = link_to admin_groups_path, title: 'Groups' do %i.fa.fa-group %span Groups = nav_link(controller: :logs) do - = link_to admin_logs_path do + = link_to admin_logs_path, title: 'Logs' do %i.fa.fa-file-text %span Logs = nav_link(controller: :broadcast_messages) do - = link_to admin_broadcast_messages_path do + = link_to admin_broadcast_messages_path, title: 'Broadcast Messages' do %i.fa.fa-bullhorn %span Messages = nav_link(controller: :hooks) do - = link_to admin_hooks_path do + = link_to admin_hooks_path, title: 'Hooks' do %i.fa.fa-external-link %span Hooks = nav_link(controller: :background_jobs) do - = link_to admin_background_jobs_path do + = link_to admin_background_jobs_path, title: 'Background Jobs' do %i.fa.fa-cog %span Background Jobs = nav_link(controller: :application_settings) do - = link_to admin_application_settings_path do + = link_to admin_application_settings_path, title: 'Settings' do %i.fa.fa-cogs %span Settings = nav_link(controller: :applications) do - = link_to admin_applications_path do + = link_to admin_applications_path, title: 'Applications' do %i.fa.fa-cloud %span Applications diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index a2eaa2d83c5..48c7c999427 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -5,24 +5,24 @@ %span Activity = nav_link(path: 'dashboard#projects') do - = link_to projects_dashboard_path, class: 'shortcuts-projects' do + = link_to projects_dashboard_path, title: 'Projects', class: 'shortcuts-projects' do %i.fa.fa-cube %span Projects = nav_link(path: 'dashboard#issues') do - = link_to assigned_issues_dashboard_path, class: 'shortcuts-issues' do + = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do %i.fa.fa-exclamation-circle %span Issues %span.count= current_user.assigned_issues.opened.count = nav_link(path: 'dashboard#merge_requests') do - = link_to assigned_mrs_dashboard_path, class: 'shortcuts-merge_requests' do + = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do %i.fa.fa-tasks %span Merge Requests %span.count= current_user.assigned_merge_requests.opened.count = nav_link(controller: :help) do - = link_to help_path do + = link_to help_path, title: 'Help' do %i.fa.fa-question-circle %span Help diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 54468d077ab..ddd3df19eec 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -6,33 +6,33 @@ Activity - if current_user = nav_link(controller: [:group, :milestones]) do - = link_to group_milestones_path(@group) do + = link_to group_milestones_path(@group), title: 'Milestones' do %i.fa.fa-clock-o %span Milestones = nav_link(path: 'groups#issues') do - = link_to issues_group_path(@group) do + = link_to issues_group_path(@group), title: 'Issues' do %i.fa.fa-exclamation-circle %span Issues - if current_user %span.count= Issue.opened.of_group(@group).count = nav_link(path: 'groups#merge_requests') do - = link_to merge_requests_group_path(@group) do + = link_to merge_requests_group_path(@group), title: 'Merge Requests' do %i.fa.fa-tasks %span Merge Requests - if current_user %span.count= MergeRequest.opened.of_group(@group).count = nav_link(path: 'groups#members') do - = link_to members_group_path(@group) do + = link_to members_group_path(@group), title: 'Members' do %i.fa.fa-users %span Members - if can?(current_user, :manage_group, @group) = nav_link(html_options: { class: "#{"active" if group_settings_page?} separate-item" }) do - = link_to edit_group_path(@group), class: "tab no-highlight" do + = link_to edit_group_path(@group), title: 'Settings', class: "tab no-highlight" do %i.fa.fa-cogs %span Settings diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index cc50b9b570a..0914d2a167a 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -5,52 +5,51 @@ %span Profile = nav_link(controller: :accounts) do - = link_to profile_account_path do + = link_to profile_account_path, title: 'Account' do %i.fa.fa-gear %span Account = nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do - = link_to applications_profile_path do + = link_to applications_profile_path, title: 'Applications' do %i.fa.fa-cloud %span Applications = nav_link(controller: :emails) do - = link_to profile_emails_path do + = link_to profile_emails_path, title: 'Emails' do %i.fa.fa-envelope-o %span Emails %span.count= current_user.emails.count + 1 - unless current_user.ldap_user? = nav_link(controller: :passwords) do - = link_to edit_profile_password_path do + = link_to edit_profile_password_path, title: 'Password' do %i.fa.fa-lock %span Password = nav_link(controller: :notifications) do - = link_to profile_notifications_path do + = link_to profile_notifications_path, title: 'Notifications' do %i.fa.fa-inbox %span Notifications = nav_link(controller: :keys) do - = link_to profile_keys_path do + = link_to profile_keys_path, title: 'SSH Keys' do %i.fa.fa-key %span SSH Keys %span.count= current_user.keys.count = nav_link(path: 'profiles#design') do - = link_to design_profile_path do + = link_to design_profile_path, title: 'Design' do %i.fa.fa-image %span Design = nav_link(controller: :groups) do - = link_to profile_groups_path do + = link_to profile_groups_path, title: 'Groups' do %i.fa.fa-group %span Groups = nav_link(path: 'profiles#history') do - = link_to history_profile_path do + = link_to history_profile_path, title: 'History' do %i.fa.fa-history %span History - diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 94cee0bd50f..502e350300a 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -6,36 +6,35 @@ Project - if project_nav_tab? :files = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do - = link_to project_tree_path(@project, @ref || @repository.root_ref), class: 'shortcuts-tree' do + = link_to project_tree_path(@project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree' do %i.fa.fa-files-o %span Files - - if project_nav_tab? :commits = nav_link(controller: %w(commit commits compare repositories tags branches)) do - = link_to project_commits_path(@project, @ref || @repository.root_ref), class: 'shortcuts-commits' do + = link_to project_commits_path(@project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits' do %i.fa.fa-history %span Commits - if project_nav_tab? :network = nav_link(controller: %w(network)) do - = link_to project_network_path(@project, @ref || @repository.root_ref), class: 'shortcuts-network' do + = link_to project_network_path(@project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network' do %i.fa.fa-code-fork %span Network - if project_nav_tab? :graphs = nav_link(controller: %w(graphs)) do - = link_to project_graph_path(@project, @ref || @repository.root_ref), class: 'shortcuts-graphs' do + = link_to project_graph_path(@project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs' do %i.fa.fa-area-chart %span Graphs - if project_nav_tab? :issues = nav_link(controller: %w(issues milestones labels)) do - = link_to url_for_project_issues, class: 'shortcuts-issues' do + = link_to url_for_project_issues, title: 'Issues', class: 'shortcuts-issues' do %i.fa.fa-exclamation-circle %span Issues @@ -44,7 +43,7 @@ - if project_nav_tab? :merge_requests = nav_link(controller: :merge_requests) do - = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests' do + = link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do %i.fa.fa-tasks %span Merge Requests @@ -52,21 +51,21 @@ - if project_nav_tab? :wiki = nav_link(controller: :wikis) do - = link_to project_wiki_path(@project, :home), class: 'shortcuts-wiki' do + = link_to project_wiki_path(@project, :home), title: 'Wiki', class: 'shortcuts-wiki' do %i.fa.fa-book %span Wiki - if project_nav_tab? :snippets = nav_link(controller: :snippets) do - = link_to project_snippets_path(@project), class: 'shortcuts-snippets' do + = link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do %i.fa.fa-file-text-o %span Snippets - if project_nav_tab? :settings = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do - = link_to edit_project_path(@project), class: "stat-tab tab no-highlight" do + = link_to edit_project_path(@project), title: 'Settings', class: "stat-tab tab no-highlight" do %i.fa.fa-cogs %span Settings diff --git a/app/views/projects/_settings_nav.html.haml b/app/views/projects/_settings_nav.html.haml index 64eda0bf286..646e48a1e1d 100644 --- a/app/views/projects/_settings_nav.html.haml +++ b/app/views/projects/_settings_nav.html.haml @@ -1,31 +1,31 @@ %ul.project-settings-nav.sidebar-subnav = nav_link(path: 'projects#edit') do - = link_to edit_project_path(@project), class: "stat-tab tab " do + = link_to edit_project_path(@project), title: 'Project', class: "stat-tab tab " do %i.fa.fa-pencil-square-o %span Project = nav_link(controller: [:team_members, :teams]) do - = link_to project_team_index_path(@project), class: "team-tab tab" do + = link_to project_team_index_path(@project), title: 'Members', class: "team-tab tab" do %i.fa.fa-users %span Members = nav_link(controller: :deploy_keys) do - = link_to project_deploy_keys_path(@project) do + = link_to project_deploy_keys_path(@project), title: 'Deploy Keys' do %i.fa.fa-key %span Deploy Keys = nav_link(controller: :hooks) do - = link_to project_hooks_path(@project) do + = link_to project_hooks_path(@project), title: 'Web Hooks' do %i.fa.fa-link %span Web Hooks = nav_link(controller: :services) do - = link_to project_services_path(@project) do + = link_to project_services_path(@project), title: 'Services' do %i.fa.fa-cogs %span Services = nav_link(controller: :protected_branches) do - = link_to project_protected_branches_path(@project) do + = link_to project_protected_branches_path(@project), title: 'Protected Branches' do %i.fa.fa-lock %span Protected branches From 3588a07b8379c98029598cac8050a1f90fd9c354 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 Jan 2015 23:08:52 -0800 Subject: [PATCH 15/80] Remove default project icon --- app/assets/images/no_project_icon.png | Bin 3387 -> 0 bytes app/helpers/application_helper.rb | 2 -- app/views/projects/edit.html.haml | 2 -- 3 files changed, 4 deletions(-) delete mode 100644 app/assets/images/no_project_icon.png diff --git a/app/assets/images/no_project_icon.png b/app/assets/images/no_project_icon.png deleted file mode 100644 index 8e9529c67ec3a7167c59f2c52bdb4b009b9803cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3387 zcmV-B4aD+^P)002t}0ssI2w=C_w00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0007JNklf*|mH|C@wLsj8}`e%XvM&Up|7 zLI@$mtc3GeA1U|y-Sa%(_roxhQvM!wZD;ZTfKo~+#Td)7EQ+GVRvKeWQ51Qek1hmm z)KabW`Fz$|FS%O)K%VDHsY&wi$BfVO9P@0JWt{VWF1Bskb)D9Fs9P?V3uA0h`9Tpf z#u#Jc-aY61eL=4)0MIl|RaN*jD~jT9INdG&D?}qYXEpW9!=9Av+iY5$}~-f{^I0> zNNN1PmLv&YiL)yYF}-2C-Hslx*-qF;=IEJ%)r3;YWzK*(=bOzYilX26%{oFMM1Mvh z48xBf%2>}3Z13K9jq4^oXEGn*2ak@7Fw)wHkO+y82#JsgiI511kO+y82#JsgiO>y0 z=`>YUjs92AkE(u}rXwa0 Date: Sat, 24 Jan 2015 23:35:02 -0800 Subject: [PATCH 16/80] Fix avatar margin for project home page --- app/assets/stylesheets/sections/projects.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 93c0c2bc518..70adc21a7a6 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -36,6 +36,10 @@ float: left; color: #666; font-size: 16px; + + .avatar { + margin-top: -5px; + } } .star-fork-buttons { From a4dad7085850aa62134ed23b90f3a045c3569663 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 24 Jan 2015 23:59:03 -0800 Subject: [PATCH 17/80] Fix project name truncation for dashboard --- app/assets/stylesheets/sections/dashboard.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/sections/dashboard.scss b/app/assets/stylesheets/sections/dashboard.scss index 00795f990bf..90010781af0 100644 --- a/app/assets/stylesheets/sections/dashboard.scss +++ b/app/assets/stylesheets/sections/dashboard.scss @@ -112,3 +112,7 @@ color: #FFF; } } + +.dash-list .str-truncated { + max-width: 72%; +} From ce9686e3f56658f2fb8df8ad6e1335e338875df9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 25 Jan 2015 19:59:04 -0800 Subject: [PATCH 18/80] Include issue/mr participants in list of recipients for close/reopen emails --- app/services/notification_service.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 72c9149378e..87366b65725 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -331,7 +331,14 @@ class NotificationService end def close_resource_email(target, project, current_user, method) - recipients = reject_muted_users([target.author, target.assignee], project) + participants = + if target.respond_to?(:participants) + target.participants + else + [target.author, target.assignee] + end + + recipients = reject_muted_users(participants, project) recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(current_user) @@ -362,7 +369,14 @@ class NotificationService end def reopen_resource_email(target, project, current_user, method, status) - recipients = reject_muted_users([target.author, target.assignee], project) + participants = + if target.respond_to?(:participants) + target.participants + else + [target.author, target.assignee] + end + + recipients = reject_muted_users(participants, project) recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq recipients.delete(current_user) From 615488150bd176088d5b37a2441fd1f11396edf7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 25 Jan 2015 20:01:32 -0800 Subject: [PATCH 19/80] Update CHANGELOG with notify participants change --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index dd9b13ceac2..6af250cb395 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 close/reopen emails - Expose description in groups API - - From 2b02852507466c8cd7dc9a7db7a7e0dd4c7b5183 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 25 Jan 2015 20:31:02 -0800 Subject: [PATCH 20/80] Add issue/mr participants to reasign events Also refactor NotificationService a bit --- CHANGELOG | 2 +- app/services/notification_service.rb | 52 +++++++--------------- spec/services/notification_service_spec.rb | 7 ++- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6af250cb395..72ca2b529d5 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 close/reopen emails + - Include issue/mr participants in list of recipients for reassign/close/reopen emails - Expose description in groups API - - diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 87366b65725..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,16 +323,7 @@ class NotificationService end def close_resource_email(target, project, current_user, method) - participants = - if target.respond_to?(:participants) - target.participants - else - [target.author, target.assignee] - end - - recipients = reject_muted_users(participants, 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| @@ -350,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| @@ -369,21 +342,26 @@ class NotificationService end def reopen_resource_email(target, project, current_user, method, status) - participants = + recipients = build_recipients(target, project) + recipients.delete(current_user) + + recipients.each do |recipient| + mailer.send(method, recipient.id, target.id, status, current_user.id) + 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(participants, project) + recipients = reject_muted_users(recipients, project) recipients = reject_mention_users(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq - recipients.delete(current_user) - - recipients.each do |recipient| - mailer.send(method, recipient.id, target.id, status, current_user.id) - end + recipients end def mailer 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') From 9d85ea3acff1c925118718996afc9daa39d679c7 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 25 Jan 2015 22:49:05 -0800 Subject: [PATCH 21/80] Organize event order execution when update issue or mr --- app/services/issues/close_service.rb | 2 +- app/services/issues/update_service.rb | 2 +- app/services/merge_requests/auto_merge_service.rb | 2 +- app/services/merge_requests/close_service.rb | 2 +- app/services/merge_requests/merge_service.rb | 2 +- app/services/merge_requests/reopen_service.rb | 2 +- app/services/merge_requests/update_service.rb | 2 +- spec/services/issues/update_service_spec.rb | 1 + spec/services/merge_requests/update_service_spec.rb | 4 +++- 9 files changed, 11 insertions(+), 8 deletions(-) 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/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..0cd822bcdae 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 } @@ -46,7 +48,7 @@ describe MergeRequests::UpdateService do end it 'should create system note about merge_request reassign' do - note = @merge_request.notes.last + note = @merge_request.notes.reload.last note.note.should include "Reassigned to \@#{user2.username}" end end From e20dba0299c1395cc8862c44b0b3933266abe001 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 00:23:16 -0800 Subject: [PATCH 22/80] Redesign way how project avatar displayed on project page --- app/assets/stylesheets/sections/projects.scss | 22 +++++++++++++++---- app/views/projects/_home_panel.html.haml | 3 ++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 70adc21a7a6..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; @@ -36,10 +54,6 @@ float: left; color: #666; font-size: 16px; - - .avatar { - margin-top: -5px; - } } .star-fork-buttons { diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 05910c6038c..2ed49f83a7a 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,8 +1,9 @@ - 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 - = project_icon(@project.to_param, alt: '', class: 'avatar s32') - if @project.description.present? = escaped_autolink(@project.description) - if can?(current_user, :admin_project, @project) From 65e700472b471242475eb9d9e3a340c6ce24615a Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 11:39:32 -0800 Subject: [PATCH 23/80] Update the issue tracker attribute on issue tracker change. --- app/controllers/projects/services_controller.rb | 3 +++ app/helpers/issues_helper.rb | 6 +++--- app/models/project.rb | 17 ++++++++--------- lib/gitlab/markdown.rb | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 15f47ed9c9f..a2cb4ae1ae9 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -17,6 +17,9 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.update_attributes(service_params) + if @service.activated? && @service.category == :issue_tracker + @project.update_attributes(issues_tracker: @service.to_param) + end redirect_to edit_project_service_path(@project, @service.to_param), notice: 'Successfully updated.' else diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index cfbbed842cd..2bf430f9142 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -16,7 +16,7 @@ module IssuesHelper def url_for_project_issues(project = @project) return '' if project.nil? - if project.using_issue_tracker? + if project.default_issues_tracker? project_issues_path(project) else project.external_issue_tracker.project_url @@ -26,7 +26,7 @@ module IssuesHelper def url_for_new_issue(project = @project) return '' if project.nil? - if project.using_issue_tracker? + if project.default_issues_tracker? url = new_project_issue_path project_id: project else project.external_issue_tracker.new_issue_url @@ -36,7 +36,7 @@ module IssuesHelper def url_for_issue(issue_iid, project = @project) return '' if project.nil? - if project.using_issue_tracker? + if project.default_issues_tracker? url = project_issue_url project_id: project, id: issue_iid else url = project.external_issue_tracker.issues_url diff --git a/app/models/project.rb b/app/models/project.rb index 20b9a5a34dc..de31f14b98e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -308,11 +308,14 @@ class Project < ActiveRecord::Base end def default_issues_tracker? - self.issues_tracker == Project.issues_tracker.default_value - end - - def external_issues_tracker_enabled? - external_issues_trackers.any? + if external_issue_tracker + false + else + unless self.issues_tracker == Project.issues_tracker.default_value + self.update_attributes(issues_tracker: Project.issues_tracker.default_value) + end + true + end end def external_issues_trackers @@ -323,10 +326,6 @@ class Project < ActiveRecord::Base @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first end - def using_issue_tracker? - default_issues_tracker? || !external_issues_tracker_enabled? - end - def can_have_issues_tracker_id? self.issues_enabled && !self.default_issues_tracker? end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 6ba7a0c18fb..2f041336471 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -208,7 +208,7 @@ module Gitlab end def reference_issue(identifier, project = @project, prefix_text = nil) - if project.using_issue_tracker? + if project.default_issues_tracker? if project.issue_exists? identifier url = url_for_issue(identifier, project) title = title_for_issue(identifier, project) From 05b6bb4bf704c2a47d6b2717308ee2ad9b5eec81 Mon Sep 17 00:00:00 2001 From: Marco Wessel Date: Mon, 26 Jan 2015 21:25:13 +0100 Subject: [PATCH 24/80] Don't require omniauth to be enabled, to use github importer --- app/helpers/projects_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index de232ab4e25..f780a8ffc3b 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -257,7 +257,7 @@ module ProjectsHelper end def github_import_enabled? - Gitlab.config.omniauth.enabled && enabled_oauth_providers.include?(:github) + enabled_oauth_providers.include?(:github) end end From 3e47ea5064f7e93cadb0ef347dfa27517552a4a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 13:31:20 -0800 Subject: [PATCH 25/80] Files::CreateService can now commit file to empty repository --- app/services/files/create_service.rb | 19 ++++++++++++------- lib/gitlab/satellite/files/new_file_action.rb | 12 +++++++++--- 2 files changed, 21 insertions(+), 10 deletions(-) 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/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 From 6a2384e0bc7d0b703c8f6af144c85af47eae6630 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 13:37:18 -0800 Subject: [PATCH 26/80] Make draft UI for creating new file in empty repository --- app/assets/stylesheets/generic/buttons.scss | 5 +++++ app/views/projects/empty.html.haml | 11 +++++++++++ 2 files changed, 16 insertions(+) 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/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 2e46de6bfe0..3a42fce43e9 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -3,6 +3,17 @@ = render "home_panel" +.center.well + %h3 + The repository for this project is empty + %p.lead + You can + = link_to '#', class: 'btn btn-new btn-lg' do + add a file +  or push it via command line. + +%h4 + %strong Command line instructions %div.git-empty %fieldset %legend Git global setup From c916124178645412a554a6b8b39c05bbd42269c8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:01:51 -0800 Subject: [PATCH 27/80] Explicitly set before_filter for ref-related controllers --- app/controllers/projects/blame_controller.rb | 2 +- app/controllers/projects/commits_controller.rb | 2 +- app/controllers/projects/network_controller.rb | 2 +- app/controllers/projects/raw_controller.rb | 2 +- app/controllers/projects/refs_controller.rb | 2 +- app/controllers/projects/tree_controller.rb | 9 +++++++-- lib/extracts_path.rb | 8 -------- 7 files changed, 12 insertions(+), 15 deletions(-) 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/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/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/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/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/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. # From 59b08942aa3de480899f32f1a6f2f948329ae3fc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:02:28 -0800 Subject: [PATCH 28/80] Refactor blob controllers --- .../projects/base_tree_controller.rb | 7 -- app/controllers/projects/blob_controller.rb | 102 ++++++++++++++++-- .../projects/edit_tree_controller.rb | 60 ----------- .../projects/new_tree_controller.rb | 20 ---- 4 files changed, 95 insertions(+), 94 deletions(-) delete mode 100644 app/controllers/projects/base_tree_controller.rb delete mode 100644 app/controllers/projects/edit_tree_controller.rb delete mode 100644 app/controllers/projects/new_tree_controller.rb 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/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 2412800c493..00b82ff1df3 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 - before_filter :authorize_download_code! - before_filter :require_non_empty_project - before_filter :authorize_push_code!, only: [:destroy] + # Raised when given an invalid file path + class InvalidPathError < StandardError; end - before_filter :blob + before_filter :authorize_download_code! + 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 + + 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 :show + 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 :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 + 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/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/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 From e07da5989f5ae14dddc130b80210342ca776e6d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:02:59 -0800 Subject: [PATCH 29/80] SEtup new routes for creating and changing repository files --- config/routes.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/config/routes.rb b/config/routes.rb index 8c3eef23260..f29b620e079 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -211,17 +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 resource :avatar, only: [:show, :destroy] - resources :new_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'new' resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/} resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/} resources :compare, only: [:index, :create] From 21297e78afd5ddfbfdf62f471acf1ab2f0c2a892 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:03:14 -0800 Subject: [PATCH 30/80] Refactor blob helpers --- app/helpers/blob_helper.rb | 38 ++++++++++++++++++++++++++++++++++ app/helpers/projects_helper.rb | 6 +++++- app/helpers/tree_helper.rb | 38 ---------------------------------- 3 files changed, 43 insertions(+), 39 deletions(-) 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 de232ab4e25..9d2c99356af 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -187,7 +187,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 From 752cb506c033c281064abb56093c41a7dac2735a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:03:30 -0800 Subject: [PATCH 31/80] Refactor blob views --- .../show.html.haml => blob/edit.html.haml} | 13 +++++++++---- .../{new_tree/show.html.haml => blob/new.html.haml} | 2 +- .../projects/{edit_tree => blob}/preview.html.haml | 0 app/views/projects/empty.html.haml | 2 +- app/views/projects/tree/_tree.html.haml | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) rename app/views/projects/{edit_tree/show.html.haml => blob/edit.html.haml} (84%) rename app/views/projects/{new_tree/show.html.haml => blob/new.html.haml} (92%) rename app/views/projects/{edit_tree => blob}/preview.html.haml (100%) diff --git a/app/views/projects/edit_tree/show.html.haml b/app/views/projects/blob/edit.html.haml similarity index 84% rename from app/views/projects/edit_tree/show.html.haml rename to 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' - %li - = link_to editing_preview_title(@blob.name), '#preview', 'data-preview-url' => preview_project_edit_tree_path(@project, @id) + = link_to '#editor' do + %i.fa.fa-edit + Edit file - = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do + %li + = 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_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 similarity index 92% rename from app/views/projects/new_tree/show.html.haml rename to 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 similarity index 100% rename from app/views/projects/edit_tree/preview.html.haml rename to app/views/projects/blob/preview.html.haml diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 3a42fce43e9..776a7327bc2 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -8,7 +8,7 @@ The repository for this project is empty %p.lead You can - = link_to '#', class: 'btn btn-new btn-lg' do + = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do add a file  or push it via command line. 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 From ed9137862773c8cd242e16a7945cf18a0b2e1ff9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:12:13 -0800 Subject: [PATCH 32/80] Fix blob controller rendering in case of errors --- app/controllers/projects/blob_controller.rb | 4 ++-- features/steps/shared/paths.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 00b82ff1df3..b471d57f698 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -28,7 +28,7 @@ class Projects::BlobController < Projects::ApplicationController redirect_to project_blob_path(@project, File.join(@ref, file_path)) else flash[:alert] = result[:message] - render :show + render :new end end @@ -53,7 +53,7 @@ class Projects::BlobController < Projects::ApplicationController redirect_to after_edit_path else flash[:alert] = result[:message] - render :show + render :edit end end 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 From 2b8b060236535d3abe27d705be97523b0816da67 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 15:15:51 -0800 Subject: [PATCH 33/80] Make code font size a bit bigger so its easier to read it --- app/assets/stylesheets/generic/highlight.scss | 8 ++++---- app/assets/stylesheets/main/variables.scss | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/generic/highlight.scss index 83dc7ab491a..839551ca8da 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: 1.4 !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: 1.4 !important; white-space: nowrap; i { diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss index 6bbce70a782..f2402a4fc30 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -59,3 +59,4 @@ $list-font-size: 15px; $sidebar_width: 230px; $avatar_radius: 50%; +$code_font_size: 13px; From 4641514cbfdcc56a0cbc5ad3444a92284df9a665 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 15:59:40 -0800 Subject: [PATCH 34/80] Update rspec tests to the new external issue logic. --- app/assets/javascripts/dispatcher.js.coffee | 1 - app/assets/javascripts/project_new.js.coffee | 14 ------------- spec/factories/projects.rb | 16 +++++++++++++-- spec/helpers/gitlab_markdown_helper_spec.rb | 11 ++++++---- spec/helpers/issues_helper_spec.rb | 21 ++++++++++---------- spec/helpers/projects_helper_spec.rb | 21 -------------------- 6 files changed, 31 insertions(+), 53 deletions(-) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index ef86c2781c9..9457f88817f 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -99,7 +99,6 @@ class Dispatcher switch path[1] when 'edit' shortcut_handler = new ShortcutsNavigation() - new ProjectNew() when 'new' new ProjectNew() when 'show' diff --git a/app/assets/javascripts/project_new.js.coffee b/app/assets/javascripts/project_new.js.coffee index f4a2ca813d2..836269c44f9 100644 --- a/app/assets/javascripts/project_new.js.coffee +++ b/app/assets/javascripts/project_new.js.coffee @@ -9,17 +9,3 @@ class @ProjectNew initEvents: -> disableButtonIfEmptyField '#project_name', '.project-submit' - - $('#project_issues_enabled').change -> - if ($(this).is(':checked') == true) - $('#project_issues_tracker').removeAttr('disabled') - else - $('#project_issues_tracker').attr('disabled', 'disabled') - - $('#project_issues_tracker').change() - - $('#project_issues_tracker').change -> - if ($(this).val() == gon.default_issues_tracker || $(this).is(':disabled')) - $('#project_issues_tracker_id').attr('disabled', 'disabled') - else - $('#project_issues_tracker_id').removeAttr('disabled') diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 1738b20fab2..499139089d9 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -76,7 +76,19 @@ FactoryGirl.define do end factory :redmine_project, parent: :project do - issues_tracker { "redmine" } - issues_tracker_id { "project_name_in_redmine" } + after :create do |project| + project.create_redmine_service( + active: true, + properties: { + project_url: 'http://redmine/projects/project_name_in_redmine', + issues_url: "http://redmine/#{project.id}/project_name_in_redmine/:id", + new_issue_url: 'http://redmine/projects/project_name_in_redmine/issues/new' + } + ) + end + after :create do |project| + project.issues_tracker = 'redmine' + project.issues_tracker_id = 'project_name_in_redmine' + end end end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 86ba801ce07..5c9eea956f3 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -296,10 +296,13 @@ describe GitlabMarkdownHelper do let(:reference) { "JIRA-#{issue.iid}" } before do - issue_tracker_config = { "jira" => { "title" => "JIRA tracker", "issues_url" => "http://jira.example/browse/:id" } } - Gitlab.config.stub(:issues_tracker).and_return(issue_tracker_config) - @project.stub(:issues_tracker).and_return("jira") - @project.stub(:issues_tracker_id).and_return("JIRA") + jira = @project.create_jira_service if @project.jira_service.nil? + properties = {"title"=>"JIRA tracker", "project_url"=>"http://jira.example/issues/?jql=project=A", "issues_url"=>"http://jira.example/browse/:id", "new_issue_url"=>"http://jira.example/secure/CreateIssue.jspa"} + jira.update_attributes(properties: properties, active: true) + end + + after do + @project.jira_service.destroy! unless @project.jira_service.nil? end it "should link using a valid id" do diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 9c95bc044f3..c82729a52e2 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -24,7 +24,7 @@ describe IssuesHelper do end describe :url_for_project_issues do - let(:project_url) { Gitlab.config.issues_tracker.redmine.project_url} + let(:project_url) { ext_project.external_issue_tracker.project_url } let(:ext_expected) do project_url.gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) @@ -54,17 +54,16 @@ describe IssuesHelper do Gitlab.config.stub(:issues_tracker).and_return(nil) end - it "should return path to internal tracker" do - url_for_project_issues.should match(polymorphic_path([@project])) + it "should return path to external tracker" do + url_for_project_issues.should match(ext_expected) end end end describe :url_for_issue do - let(:issue_id) { 3 } - let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url} + let(:issues_url) { ext_project.external_issue_tracker.issues_url} let(:ext_expected) do - issues_url.gsub(':id', issue_id.to_s) + issues_url.gsub(':id', issue.iid.to_s) .gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) end @@ -78,7 +77,7 @@ describe IssuesHelper do it "should return path to external tracker" do @project = ext_project - url_for_issue(issue_id).should match(ext_expected) + url_for_issue(issue.iid).should match(ext_expected) end it "should return empty string if project nil" do @@ -93,14 +92,14 @@ describe IssuesHelper do Gitlab.config.stub(:issues_tracker).and_return(nil) end - it "should return internal path" do - url_for_issue(issue.iid).should match(polymorphic_path([@project, issue])) + it "should return external path" do + url_for_issue(issue.iid).should match(ext_expected) end end end describe :url_for_new_issue do - let(:issues_url) { Gitlab.config.issues_tracker.redmine.new_issue_url} + let(:issues_url) { ext_project.external_issue_tracker.new_issue_url } let(:ext_expected) do issues_url.gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) @@ -131,7 +130,7 @@ describe IssuesHelper do end it "should return internal path" do - url_for_new_issue.should match(new_project_issue_path(@project)) + url_for_new_issue.should match(ext_expected) end end end diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 2146b0b1383..281d4862199 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -1,32 +1,11 @@ require 'spec_helper' describe ProjectsHelper do - describe '#project_issues_trackers' do - it "returns the correct issues trackers available" do - project_issues_trackers.should == - "\n" \ - "" - end - - it "returns the correct issues trackers available with current tracker 'gitlab' selected" do - project_issues_trackers('gitlab').should == - "\n" \ - "" - end - - it "returns the correct issues trackers available with current tracker 'redmine' selected" do - project_issues_trackers('redmine').should == - "\n" \ - "" - end - end - describe "#project_status_css_class" do it "returns appropriate class" do project_status_css_class("started").should == "active" project_status_css_class("failed").should == "danger" project_status_css_class("finished").should == "success" end - end end From 9b5b334a798233b200318ecfbff55f0284f874da Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 16:04:08 -0800 Subject: [PATCH 35/80] Remove unused feature steps. --- features/project/edit_issuetracker.feature | 18 ------------ features/steps/project/issue_tracker.rb | 31 --------------------- spec/lib/gitlab/reference_extractor_spec.rb | 1 - 3 files changed, 50 deletions(-) delete mode 100644 features/project/edit_issuetracker.feature delete mode 100644 features/steps/project/issue_tracker.rb diff --git a/features/project/edit_issuetracker.feature b/features/project/edit_issuetracker.feature deleted file mode 100644 index cc0de07ca69..00000000000 --- a/features/project/edit_issuetracker.feature +++ /dev/null @@ -1,18 +0,0 @@ -Feature: Project Issue Tracker - Background: - Given I sign in as a user - And I own project "Shop" - And project "Shop" has issues enabled - And I visit project "Shop" page - - Scenario: I set the issue tracker to "GitLab" - When I visit edit project "Shop" page - And change the issue tracker to "GitLab" - And I save project - Then I the project should have "GitLab" as issue tracker - - Scenario: I set the issue tracker to "Redmine" - When I visit edit project "Shop" page - And change the issue tracker to "Redmine" - And I save project - Then I the project should have "Redmine" as issue tracker diff --git a/features/steps/project/issue_tracker.rb b/features/steps/project/issue_tracker.rb deleted file mode 100644 index e1700292701..00000000000 --- a/features/steps/project/issue_tracker.rb +++ /dev/null @@ -1,31 +0,0 @@ -class Spinach::Features::ProjectIssueTracker < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedPaths - - step 'project "Shop" has issues enabled' do - @project = Project.find_by(name: "Shop") - @project ||= create(:project, name: "Shop", namespace: @user.namespace) - @project.issues_enabled = true - end - - step 'change the issue tracker to "GitLab"' do - select 'GitLab', from: 'project_issues_tracker' - end - - step 'I the project should have "GitLab" as issue tracker' do - find_field('project_issues_tracker').value.should == 'gitlab' - end - - step 'change the issue tracker to "Redmine"' do - select 'Redmine', from: 'project_issues_tracker' - end - - step 'I the project should have "Redmine" as issue tracker' do - find_field('project_issues_tracker').value.should == 'redmine' - end - - step 'I save project' do - click_button 'Save changes' - end -end diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 23867df39dd..5f45df4e8c3 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -12,7 +12,6 @@ describe Gitlab::ReferenceExtractor do end it 'extracts JIRA issue references' do - Gitlab.config.gitlab.stub(:issues_tracker).and_return('jira') subject.analyze('this one talks about issue JIRA-1234', nil) subject.issues.should == [{ project: nil, id: 'JIRA-1234' }] end From 90ba3a385cda545a58b3bb7893898bc16e982a73 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 16:08:59 -0800 Subject: [PATCH 36/80] Fix tests for blobs refactoring --- features/steps/project/source/browse_files.rb | 2 +- spec/routing/project_routing_spec.rb | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) 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/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 8191d1fb9c4..e36b266a1ff 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -430,21 +430,17 @@ describe Projects::TreeController, 'routing' do 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 From ed8c3e2d738312c09e336fb8d549eea7d9cc71b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 16:10:34 -0800 Subject: [PATCH 37/80] Remove unnecessary reload in test --- spec/services/merge_requests/update_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 0cd822bcdae..0e60baae2c4 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -48,7 +48,7 @@ describe MergeRequests::UpdateService do end it 'should create system note about merge_request reassign' do - note = @merge_request.notes.reload.last + note = @merge_request.notes.last note.note.should include "Reassigned to \@#{user2.username}" end end From 00a0d5aeeaf19ea4d72fd1890afac099026f1706 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 16:24:11 -0800 Subject: [PATCH 38/80] Move repetition to the parent. --- .../project_services/issue_tracker_service.rb | 44 +++++++++++++++ app/models/project_services/jira_service.rb | 45 ---------------- .../project_services/redmine_service.rb | 54 ++++--------------- lib/gitlab/markdown.rb | 9 ++-- 4 files changed, 58 insertions(+), 94 deletions(-) diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 664b55a5951..7ff6e0f284d 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -15,4 +15,48 @@ class IssueTrackerService < Service def new_issue_url # implement inside child end + + def fields + [ + { type: 'text', name: 'description', placeholder: description }, + { type: 'text', name: 'project_url', placeholder: 'Project url' }, + { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, + { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} + ] + end + + def initialize_properties + if properties.nil? + if enabled_in_gitlab_config + self.properties = { + title: issues_tracker['title'], + project_url: set_project_url, + issues_url: issues_tracker['issues_url'], + new_issue_url: issues_tracker['new_issue_url'] + } + end + end + end + + private + + def enabled_in_gitlab_config + Gitlab.config.issues_tracker && + Gitlab.config.issues_tracker.values.any? && + issues_tracker + end + + def issues_tracker + Gitlab.config.issues_tracker[to_param] + end + + def set_project_url + id = self.project.issues_tracker_id + + if id + issues_tracker['project_url'].gsub(":issues_tracker_id", id) + else + issues_tracker['project_url'] + end + end end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index f8b04ddeea7..b0d668948d0 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -21,49 +21,4 @@ class JiraService < IssueTrackerService def to_param 'jira' end - - def fields - [ - { type: 'text', name: 'title', placeholder: title }, - { type: 'text', name: 'description', placeholder: description }, - { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} - ] - end - - def initialize_properties - if properties.nil? - if enabled_in_gitlab_config - self.properties = { - title: issues_tracker['title'], - project_url: set_project_url, - issues_url: issues_tracker['issues_url'], - new_issue_url: issues_tracker['new_issue_url'] - } - end - end - end - - private - - def enabled_in_gitlab_config - Gitlab.config.issues_tracker && - Gitlab.config.issues_tracker.values.any? && - issues_tracker - end - - def issues_tracker - Gitlab.config.issues_tracker['jira'] - end - - def set_project_url - id = self.project.issues_tracker_id - - if id - issues_tracker['project_url'].gsub(":issues_tracker_id", id) - else - issues_tracker['project_url'] - end - end end diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb index 71286d74b58..11cce3e0561 100644 --- a/app/models/project_services/redmine_service.rb +++ b/app/models/project_services/redmine_service.rb @@ -3,56 +3,22 @@ class RedmineService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url def title - 'Redmine' + if self.properties && self.properties['title'].present? + self.properties['title'] + else + 'Redmine' + end end def description - 'Redmine issue tracker' + if self.properties && self.properties['description'].present? + self.properties['description'] + else + 'Redmine issue tracker' + end end def to_param 'redmine' end - - def fields - [ - { type: 'text', name: 'project_url', placeholder: 'Project url' }, - { type: 'text', name: 'issues_url', placeholder: 'Issue url'}, - { type: 'text', name: 'new_issue_url', placeholder: 'New Issue url'} - ] - end - - def initialize_properties - if properties.nil? - if enabled_in_gitlab_config - self.properties = { - title: issues_tracker['title'], - project_url: set_project_url, - issues_url: issues_tracker['issues_url'], - new_issue_url: issues_tracker['new_issue_url'] - } - end - end - end - - private - - def enabled_in_gitlab_config - Gitlab.config.issues_tracker && - Gitlab.config.issues_tracker.values.any? && - issues_tracker - end - - def issues_tracker - Gitlab.config.issues_tracker['redmine'] - end - - def set_project_url - id = self.project.issues_tracker_id - if id - issues_tracker['project_url'].gsub(":issues_tracker_id", id) - else - issues_tracker['project_url'] - end - end end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 2f041336471..c0e83fb3078 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -220,9 +220,8 @@ module Gitlab link_to("#{prefix_text}##{identifier}", url, options) end else - external_issue_tracker = project.external_issue_tracker - if external_issue_tracker.present? - reference_external_issue(identifier, external_issue_tracker, project, + if project.external_issue_tracker.present? + reference_external_issue(identifier, project, prefix_text) end end @@ -266,10 +265,10 @@ module Gitlab end end - def reference_external_issue(identifier, issue_tracker, project = @project, + def reference_external_issue(identifier, project = @project, prefix_text = nil) url = url_for_issue(identifier, project) - title = issue_tracker.title + title = project.external_issue_tracker.title options = html_options.merge( title: "Issue in #{title}", From e6b97d09470b01b5b65e87dab339c500f1bac45f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 18:56:56 -0800 Subject: [PATCH 39/80] Improve font sizes for code and diff --- CHANGELOG | 4 ++-- app/assets/stylesheets/generic/highlight.scss | 4 ++-- app/assets/stylesheets/main/variables.scss | 1 + app/assets/stylesheets/sections/diff.scss | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 72ca2b529d5..91409707c87 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,8 +17,8 @@ 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 diff --git a/app/assets/stylesheets/generic/highlight.scss b/app/assets/stylesheets/generic/highlight.scss index 839551ca8da..e1ca86af816 100644 --- a/app/assets/stylesheets/generic/highlight.scss +++ b/app/assets/stylesheets/generic/highlight.scss @@ -11,7 +11,7 @@ border-radius: 0; font-family: $monospace_font; font-size: $code_font_size !important; - line-height: 1.4 !important; + line-height: $code_line_height !important; margin: 0; overflow: auto; overflow-y: hidden; @@ -39,7 +39,7 @@ font-family: $monospace_font; display: block; font-size: $code_font_size !important; - line-height: 1.4 !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 f2402a4fc30..acbf5be94a3 100644 --- a/app/assets/stylesheets/main/variables.scss +++ b/app/assets/stylesheets/main/variables.scss @@ -60,3 +60,4 @@ $sidebar_width: 230px; $avatar_radius: 50%; $code_font_size: 13px; +$code_line_height: 1.5; 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; } } From aac36b120ef86469feb05ae5db39205493f851ed Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 19:28:11 -0800 Subject: [PATCH 40/80] Fix app title when browse blob --- app/helpers/projects_helper.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9d2c99356af..db4bb303d0f 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -189,6 +189,8 @@ module ProjectsHelper elsif current_controller?(:blob) if current_action?(:new) || current_action?(:create) "New file at #{@ref}" + elsif current_action?(:show) + "#{@blob.path} at #{@ref}" elsif @blob "Edit file #{@blob.path} at #{@ref}" end From a3d879d427c1236d26832dcd0312b3e0d6158bbe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 20:57:42 -0800 Subject: [PATCH 41/80] Refactor web editor --- .../javascripts/{ => blob}/blob.js.coffee | 0 .../javascripts/blob/edit_blob.js.coffee | 40 ++++++++++++++++++ .../javascripts/blob/new_blob.js.coffee | 17 ++++++++ app/assets/stylesheets/sections/editor.scss | 22 ++++++++++ app/views/projects/_blob_editor.html.haml | 15 ------- app/views/projects/blob/_editor.html.haml | 25 +++++++++++ app/views/projects/blob/edit.html.haml | 42 +------------------ app/views/projects/blob/new.html.haml | 30 +------------ lib/gitlab/satellite/files/new_file_action.rb | 8 ++-- 9 files changed, 112 insertions(+), 87 deletions(-) rename app/assets/javascripts/{ => blob}/blob.js.coffee (100%) create mode 100644 app/assets/javascripts/blob/edit_blob.js.coffee create mode 100644 app/assets/javascripts/blob/new_blob.js.coffee delete mode 100644 app/views/projects/_blob_editor.html.haml create mode 100644 app/views/projects/blob/_editor.html.haml diff --git a/app/assets/javascripts/blob.js.coffee b/app/assets/javascripts/blob/blob.js.coffee similarity index 100% rename from app/assets/javascripts/blob.js.coffee rename to app/assets/javascripts/blob/blob.js.coffee diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee new file mode 100644 index 00000000000..79433dab505 --- /dev/null +++ b/app/assets/javascripts/blob/edit_blob.js.coffee @@ -0,0 +1,40 @@ +class @EditBlob + constructor: (assets_path, mode)-> + ace.config.set "modePath", assets_path + '/ace' + ace.config.loadModule "ace/ext/searchbox" + if mode + ace_mode = mode + editor = ace.edit("editor") + editor.focus() + + if ace_mode + editor.getSession().setMode "ace/mode/" + ace_mode + + disableButtonIfEmptyField "#commit_message", ".js-commit-button" + $(".js-commit-button").click -> + $("#file-content").val editor.getValue() + $(".file-editor form").submit() + return + + editModePanes = $(".js-edit-mode-pane") + editModeLinks = $(".js-edit-mode a") + editModeLinks.click (event) -> + event.preventDefault() + currentLink = $(this) + paneId = currentLink.attr("href") + currentPane = editModePanes.filter(paneId) + editModeLinks.parent().removeClass "active hover" + currentLink.parent().addClass "active hover" + editModePanes.hide() + if paneId is "#preview" + currentPane.fadeIn 200 + $.post currentLink.data("preview-url"), + content: editor.getValue() + , (response) -> + currentPane.empty().append response + return + + else + currentPane.fadeIn 200 + editor.focus() + return diff --git a/app/assets/javascripts/blob/new_blob.js.coffee b/app/assets/javascripts/blob/new_blob.js.coffee new file mode 100644 index 00000000000..ed4b7c47936 --- /dev/null +++ b/app/assets/javascripts/blob/new_blob.js.coffee @@ -0,0 +1,17 @@ +class @NewBlob + constructor: (assets_path, mode)-> + ace.config.set "modePath", assets_path + '/ace' + ace.config.loadModule "ace/ext/searchbox" + if mode + ace_mode = mode + editor = ace.edit("editor") + editor.focus() + + if ace_mode + editor.getSession().setMode "ace/mode/" + ace_mode + + disableButtonIfEmptyField "#commit_message", ".js-commit-button" + $(".js-commit-button").click -> + $("#file-content").val editor.getValue() + $(".file-editor form").submit() + return diff --git a/app/assets/stylesheets/sections/editor.scss b/app/assets/stylesheets/sections/editor.scss index f62f46ee168..becd593331f 100644 --- a/app/assets/stylesheets/sections/editor.scss +++ b/app/assets/stylesheets/sections/editor.scss @@ -31,4 +31,26 @@ margin: 5px 8px 0 8px; } } + + .file-title { + @extend .monospace; + font-size: 14px; + } + + .editor-ref { + background: #fafafa; + padding: 18px 15px; + padding-left: 25px; + border-right: 1px solid #CCC; + display: inline-block; + margin: -10px -15px; + margin-right: 10px; + } + + .editor-file-name { + .new-file-name { + display: inline-block; + width: 200px; + } + } } diff --git a/app/views/projects/_blob_editor.html.haml b/app/views/projects/_blob_editor.html.haml deleted file mode 100644 index 1fb74b55c41..00000000000 --- a/app/views/projects/_blob_editor.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -.file-holder.file - .file-title - %i.icon-file - %span.file_name - %span.monospace.light #{ref} - - if local_assigns[:path] - = ': ' + local_assigns[:path] - .file-content.code - %pre.js-edit-mode-pane#editor - = params[:content] || local_assigns[:blob_data] - - if local_assigns[:path] - .js-edit-mode-pane#preview.hide - .center - %h2 - %i.icon-spinner.icon-spin diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml new file mode 100644 index 00000000000..a0d9ea57b1c --- /dev/null +++ b/app/views/projects/blob/_editor.html.haml @@ -0,0 +1,25 @@ +.file-holder.file + .file-title + .editor-ref + %i.fa.fa-code-fork + = ref + %span.editor-file-name + - if @path + %span.monospace + = @path + + - if current_action?(:new) || current_action?(:create) + \/ + = text_field_tag 'file_name', params[:file_name], placeholder: "sample.rb", + required: true, class: 'form-control new-file-name' + .pull-right + = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control' + + .file-content.code + %pre.js-edit-mode-pane#editor + = params[:content] || local_assigns[:blob_data] + - if local_assigns[:path] + .js-edit-mode-pane#preview.hide + .center + %h2 + %i.icon-spinner.icon-spin diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 883845c03f5..c0734d9f476 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -11,7 +11,7 @@ = editing_preview_title(@blob.name) = 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 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data = render 'shared/commit_message_container', params: params, placeholder: "Update #{@blob.name}" = hidden_field_tag 'last_commit', @last_commit @@ -21,42 +21,4 @@ cancel_path: @after_edit_path :javascript - ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace") - ace.config.loadModule("ace/ext/searchbox"); - var ace_mode = "#{@blob.language.try(:ace_mode)}"; - var editor = ace.edit("editor"); - if (ace_mode) { - editor.getSession().setMode('ace/mode/' + ace_mode); - } - - disableButtonIfEmptyField("#commit_message", ".js-commit-button"); - - $(".js-commit-button").click(function(){ - $("#file-content").val(editor.getValue()); - $(".file-editor form").submit(); - }); - - var editModePanes = $('.js-edit-mode-pane'), - editModeLinks = $('.js-edit-mode a'); - - editModeLinks.click(function(event) { - event.preventDefault(); - - var currentLink = $(this), - paneId = currentLink.attr('href'), - currentPane = editModePanes.filter(paneId); - - editModeLinks.parent().removeClass('active hover'); - currentLink.parent().addClass('active hover'); - editModePanes.hide(); - - if (paneId == '#preview') { - currentPane.fadeIn(200); - $.post(currentLink.data('preview-url'), { content: editor.getValue() }, function(response) { - currentPane.empty().append(response); - }) - } else { - currentPane.fadeIn(200); - editor.focus() - } - }) + new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}") diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 57e830d5c56..70f52332cc7 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,25 +1,7 @@ %h3.page-title New file -%hr .file-editor = 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 - .col-sm-10 - .input-group - %span.input-group-addon - = @path[-1] == "/" ? @path : @path + "/" - = text_field_tag 'file_name', params[:file_name], placeholder: "sample.rb", required: true, class: 'form-control' - %span.input-group-addon - on - %span= @ref - - .form-group.commit_message-group - = label_tag :encoding, class: "control-label" do - Encoding - .col-sm-10 - = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control' - = render 'projects/blob_editor', ref: @ref + = render 'projects/blob/editor', ref: @ref = render 'shared/commit_message_container', params: params, placeholder: 'Add new file' = hidden_field_tag 'content', '', id: 'file-content' @@ -27,12 +9,4 @@ cancel_path: project_tree_path(@project, @id) :javascript - ace.config.set("modePath", gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}/ace-src-noconflict") - var editor = ace.edit("editor"); - - disableButtonIfAnyEmptyField($('.form-new-file'), '.form-control', '.btn-create') - - $(".js-commit-button").click(function(){ - $("#file-content").val(editor.getValue()); - $(".file-editor form").submit(); - }); + new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null) diff --git a/lib/gitlab/satellite/files/new_file_action.rb b/lib/gitlab/satellite/files/new_file_action.rb index c230239d390..5b657c7aba2 100644 --- a/lib/gitlab/satellite/files/new_file_action.rb +++ b/lib/gitlab/satellite/files/new_file_action.rb @@ -15,12 +15,12 @@ module Gitlab # create target branch in satellite at the corresponding commit from bare repo current_ref = - if repo.commits.any? - repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") - ref - else + if @project.empty_repo? # skip this step if we want to add first file to empty repo Satellite::PARKING_BRANCH + else + repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}") + ref end file_path_in_satellite = File.join(repo.working_dir, file_path) From 8ecf7d3207ca52d694f6d8ebd9bed96041c49a8c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 20:58:38 -0800 Subject: [PATCH 42/80] Improve web editor filename placeholder --- app/views/projects/blob/_editor.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index a0d9ea57b1c..96f188e4aa7 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -10,7 +10,7 @@ - if current_action?(:new) || current_action?(:create) \/ - = text_field_tag 'file_name', params[:file_name], placeholder: "sample.rb", + = text_field_tag 'file_name', params[:file_name], placeholder: "File name", required: true, class: 'form-control new-file-name' .pull-right = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control' From 33913f9b8fef1f8df45dc26239faf8fa4cffc982 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 22:08:27 -0800 Subject: [PATCH 43/80] Make issue tracker service fields required. --- app/models/project.rb | 2 +- .../project_services/issue_tracker_service.rb | 4 + spec/factories/projects.rb | 6 +- spec/models/jira_service_spec.rb | 83 +++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 spec/models/jira_service_spec.rb diff --git a/app/models/project.rb b/app/models/project.rb index de31f14b98e..43b61897a3c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -319,7 +319,7 @@ class Project < ActiveRecord::Base end def external_issues_trackers - services.select { |service| service.category == :issue_tracker } + services.select { |service| service.issue_tracker? } end def external_issue_tracker diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 7ff6e0f284d..fc7b2fe5acd 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -1,5 +1,7 @@ class IssueTrackerService < Service + validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? + def category :issue_tracker end @@ -34,6 +36,8 @@ class IssueTrackerService < Service issues_url: issues_tracker['issues_url'], new_issue_url: issues_tracker['new_issue_url'] } + else + self.properties = {} end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 499139089d9..5ae57718c1a 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -80,9 +80,9 @@ FactoryGirl.define do project.create_redmine_service( active: true, properties: { - project_url: 'http://redmine/projects/project_name_in_redmine', - issues_url: "http://redmine/#{project.id}/project_name_in_redmine/:id", - new_issue_url: 'http://redmine/projects/project_name_in_redmine/issues/new' + 'project_url' => 'http://redmine/projects/project_name_in_redmine', + 'issues_url' => "http://redmine/#{project.id}/project_name_in_redmine/:id", + 'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new' } ) end diff --git a/spec/models/jira_service_spec.rb b/spec/models/jira_service_spec.rb new file mode 100644 index 00000000000..0c73a68c924 --- /dev/null +++ b/spec/models/jira_service_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +describe JiraService do + describe "Associations" do + it { should belong_to :project } + it { should have_one :service_hook } + end + + describe "Validations" do + context "active" do + before do + subject.active = true + end + + it { should validate_presence_of :project_url } + it { should validate_presence_of :issues_url } + it { should validate_presence_of :new_issue_url } + end + end + + describe 'description and title' do + let(:project) { create(:project) } + + context 'when it is not set' do + before do + @service = project.create_jira_service(active: true) + end + + after do + @service.destroy! + end + + it 'should be initialized' do + expect(@service.title).to eq('JIRA') + expect(@service.description).to eq("Jira issue tracker") + end + end + + context 'when it is set' do + before do + properties = { 'title' => 'Jira One', 'description' => 'Jira One issue tracker' } + @service = project.create_jira_service(active: true, properties: properties) + end + + after do + @service.destroy! + end + + it "should be correct" do + expect(@service.title).to eq('Jira One') + expect(@service.description).to eq('Jira One issue tracker') + end + end + end + + describe 'project and issue urls' do + let(:project) { create(:project) } + + context 'when gitlab.yml was initialized' do + before do + settings = { "jira" => { + "title" => "Jira", + "project_url" => "http://jira.sample/projects/project_a", + "issues_url" => "http://jira.sample/issues/:id", + "new_issue_url" => "http://jira.sample/projects/project_a/issues/new" + } + } + Gitlab.config.stub(:issues_tracker).and_return(settings) + @service = project.create_jira_service(active: true) + end + + after do + @service.destroy! + end + + it 'should be prepopulated with the settings' do + expect(@service.properties[:project_url]).to eq('http://jira.sample/projects/project_a') + expect(@service.properties[:issues_url]).to eq("http://jira.sample/issues/:id") + expect(@service.properties[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new") + end + end + end +end From 65e88f1e1aa247c9a89af82717aae791786ad276 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 26 Jan 2015 22:39:48 -0800 Subject: [PATCH 44/80] Fixed few tests and improved css style --- app/assets/javascripts/blob/edit_blob.js.coffee | 4 ++++ app/assets/javascripts/blob/new_blob.js.coffee | 4 ++++ app/assets/stylesheets/sections/editor.scss | 8 ++++---- app/views/projects/blob/edit.html.haml | 2 +- app/views/projects/blob/new.html.haml | 2 +- features/steps/project/source/browse_files.rb | 5 ++--- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee index 79433dab505..6914ca759f6 100644 --- a/app/assets/javascripts/blob/edit_blob.js.coffee +++ b/app/assets/javascripts/blob/edit_blob.js.coffee @@ -6,6 +6,7 @@ class @EditBlob ace_mode = mode editor = ace.edit("editor") editor.focus() + @editor = editor if ace_mode editor.getSession().setMode "ace/mode/" + ace_mode @@ -38,3 +39,6 @@ class @EditBlob currentPane.fadeIn 200 editor.focus() return + + editor: -> + return @editor diff --git a/app/assets/javascripts/blob/new_blob.js.coffee b/app/assets/javascripts/blob/new_blob.js.coffee index ed4b7c47936..a6e27116b40 100644 --- a/app/assets/javascripts/blob/new_blob.js.coffee +++ b/app/assets/javascripts/blob/new_blob.js.coffee @@ -6,6 +6,7 @@ class @NewBlob ace_mode = mode editor = ace.edit("editor") editor.focus() + @editor = editor if ace_mode editor.getSession().setMode "ace/mode/" + ace_mode @@ -15,3 +16,6 @@ class @NewBlob $("#file-content").val editor.getValue() $(".file-editor form").submit() return + + editor: -> + return @editor diff --git a/app/assets/stylesheets/sections/editor.scss b/app/assets/stylesheets/sections/editor.scss index becd593331f..88aa256e56e 100644 --- a/app/assets/stylesheets/sections/editor.scss +++ b/app/assets/stylesheets/sections/editor.scss @@ -35,15 +35,15 @@ .file-title { @extend .monospace; font-size: 14px; + padding: 5px; } .editor-ref { - background: #fafafa; - padding: 18px 15px; - padding-left: 25px; + background: #f5f5f5; + padding: 11px 15px; border-right: 1px solid #CCC; display: inline-block; - margin: -10px -15px; + margin: -5px -5px; margin-right: 10px; } diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index c0734d9f476..b150b639888 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -21,4 +21,4 @@ cancel_path: @after_edit_path :javascript - new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}") + blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}") diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index 70f52332cc7..df6aedbe17d 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -9,4 +9,4 @@ cancel_path: project_tree_path(@project, @id) :javascript - new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null) + blob = new NewBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", null) diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index 1caad73654b..bd1ca55a20a 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -58,7 +58,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I can edit code' do set_new_content - evaluate_script('editor.getValue()').should == new_gitignore_content + evaluate_script('blob.editor.getValue()').should == new_gitignore_content end step 'I edit code' do @@ -103,7 +103,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps step 'I can see new file page' do page.should have_content "New file" - page.should have_content "File name" page.should have_content "Commit message" end @@ -170,7 +169,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps private def set_new_content - execute_script("editor.setValue('#{new_gitignore_content}')") + execute_script("blob.editor.setValue('#{new_gitignore_content}')") end # Content of the gitignore file on the seed repository. From ededa98995208591c5792c0ece1a5ec0ef302127 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Mon, 26 Jan 2015 22:46:54 -0800 Subject: [PATCH 45/80] Shorter check in services controller. --- app/controllers/projects/services_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index c7cc38b9c67..09bccb4bf8f 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -17,7 +17,7 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.update_attributes(service_params) - if @service.activated? && @service.category == :issue_tracker + if @service.activated? && @service.issue_tracker? @project.update_attributes(issues_tracker: @service.to_param) end redirect_to edit_project_service_path(@project, @service.to_param), From 93bc2d5202e5802bd31419d05232b62355516a53 Mon Sep 17 00:00:00 2001 From: Boyan Tabakov Date: Thu, 21 Aug 2014 13:53:32 +0300 Subject: [PATCH 46/80] Added support for firing system hooks on group create/destroy and adding/removing users to group. Added tests and updated docs. Also adding 'user_id' field in the hooks for adding/removing user from team. --- CHANGELOG | 1 + app/models/group.rb | 15 ++++++ app/models/members/group_member.rb | 14 ++++- app/services/system_hooks_service.rb | 23 ++++++++ doc/system_hooks/system_hooks.md | 63 +++++++++++++++++++++- spec/models/system_hook_spec.rb | 35 ++++++++++++ spec/services/system_hooks_service_spec.rb | 31 +++++++++++ 7 files changed, 179 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dd9b13ceac2..975cb0af8c9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -59,6 +59,7 @@ v 7.8.0 - - - + - Added support for firing system hooks on group create/destroy and adding/removing users to group (Boyan Tabakov) v 7.7.1 - Improve mention autocomplete performance diff --git a/app/models/group.rb b/app/models/group.rb index 733afa2fc07..e098dfb3cdf 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -25,6 +25,9 @@ class Group < Namespace mount_uploader :avatar, AttachmentUploader + after_create :post_create_hook + after_destroy :post_destroy_hook + def human_name name end @@ -74,6 +77,18 @@ class Group < Namespace projects.public_only.any? end + def post_create_hook + system_hook_service.execute_hooks_for(self, :create) + end + + def post_destroy_hook + system_hook_service.execute_hooks_for(self, :destroy) + end + + def system_hook_service + SystemHooksService.new + end + class << self def search(query) where("LOWER(namespaces.name) LIKE :query", query: "%#{query.downcase}%") diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb index b7f296b13fb..28d0b4483b4 100644 --- a/app/models/members/group_member.rb +++ b/app/models/members/group_member.rb @@ -27,8 +27,9 @@ class GroupMember < Member scope :with_group, ->(group) { where(source_id: group.id) } scope :with_user, ->(user) { where(user_id: user.id) } - after_create :notify_create + after_create :post_create_hook after_update :notify_update + after_destroy :post_destroy_hook def self.access_level_roles Gitlab::Access.options_with_owner @@ -42,8 +43,9 @@ class GroupMember < Member access_level end - def notify_create + def post_create_hook notification_service.new_group_member(self) + system_hook_service.execute_hooks_for(self, :create) end def notify_update @@ -52,6 +54,14 @@ class GroupMember < Member end end + def post_destroy_hook + system_hook_service.execute_hooks_for(self, :destroy) + end + + def system_hook_service + SystemHooksService.new + end + def notification_service NotificationService.new end diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 44e494525b3..46f6e91e808 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -60,6 +60,26 @@ class SystemHooksService access_level: model.human_access, project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase }) + when Group + owner = model.owner + + data.merge!( + name: model.name, + path: model.path, + group_id: model.id, + owner_name: owner.respond_to?(:name) ? owner.name : nil, + owner_email: owner.respond_to?(:email) ? owner.email : nil, + ) + when GroupMember + data.merge!( + group_name: model.group.name, + group_path: model.group.path, + group_id: model.group.id, + user_name: model.user.name, + user_email: model.user.email, + user_id: model.user.id, + group_access: model.human_access, + ) end end @@ -68,6 +88,9 @@ class SystemHooksService when ProjectMember return "user_add_to_team" if event == :create return "user_remove_from_team" if event == :destroy + when GroupMember + return 'user_add_to_group' if event == :create + return 'user_remove_from_group' if event == :destroy else "#{model.class.name.downcase}_#{event.to_s}" end diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 54e6e3a9e3f..41c2732ef77 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -1,6 +1,6 @@ # System hooks -Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create` and `key_destroy`. +Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`. System hooks can be used, e.g. for logging or changing information in a LDAP server. @@ -50,6 +50,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser "project_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", + "user_id": 41, "project_visibility": "private", } ``` @@ -66,6 +67,7 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser "project_path": "storecloud", "user_email": "johnsmith@gmail.com", "user_name": "John Smith", + "user_id": 41, "project_visibility": "private", } ``` @@ -117,3 +119,62 @@ System hooks can be used, e.g. for logging or changing information in a LDAP ser "id": 4 } ``` + +**Group created:** + +```json +{ + "created_at": "2012-07-21T07:30:54Z", + "event_name": "group_create", + "name": "StormCloud", + "owner_email": "johnsmith@gmail.com", + "owner_name": "John Smith", + "path": "stormcloud", + "group_id": 78 +} +``` + +**Group removed:** + +```json +{ + "created_at": "2012-07-21T07:30:54Z", + "event_name": "group_destroy", + "name": "StoreCloud", + "owner_email": "johnsmith@gmail.com", + "owner_name": "John Smith", + "path": "storecloud", + "group_id": 78 +} +``` + +**New Group Member:** + +```json +{ + "created_at": "2012-07-21T07:30:56Z", + "event_name": "user_add_to_group", + "group_access": "Master", + "group_id": 78, + "group_name": "StoreCloud", + "group_path": "storecloud", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", + "user_id": 41 +} +``` +**Group Member Removed:** + +```json +{ + "created_at": "2012-07-21T07:30:56Z", + "event_name": "user_remove_from_group", + "group_access": "Master", + "group_id": 78, + "group_name": "StoreCloud", + "group_path": "storecloud", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", + "user_id": 41 +} +``` diff --git a/spec/models/system_hook_spec.rb b/spec/models/system_hook_spec.rb index 4ab5261dc9d..8deb732de9c 100644 --- a/spec/models/system_hook_spec.rb +++ b/spec/models/system_hook_spec.rb @@ -61,5 +61,40 @@ describe SystemHook do project.project_members.destroy_all WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once end + + it 'group create hook' do + create(:group) + WebMock.should have_requested(:post, @system_hook.url).with( + body: /group_create/ + ).once + end + + it 'group destroy hook' do + group = create(:group) + group.destroy + WebMock.should have_requested(:post, @system_hook.url).with( + body: /group_destroy/ + ).once + end + + it 'group member create hook' do + group = create(:group) + user = create(:user) + group.add_user(user, Gitlab::Access::MASTER) + WebMock.should have_requested(:post, @system_hook.url).with( + body: /user_add_to_group/ + ).once + end + + it 'group member destroy hook' do + group = create(:group) + user = create(:user) + group.add_user(user, Gitlab::Access::MASTER) + group.group_members.destroy_all + WebMock.should have_requested(:post, @system_hook.url).with( + body: /user_remove_from_group/ + ).once + end + end end diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb index 573446d3a19..a45e9d0575c 100644 --- a/spec/services/system_hooks_service_spec.rb +++ b/spec/services/system_hooks_service_spec.rb @@ -5,6 +5,8 @@ describe SystemHooksService do let (:project) { create :project } let (:project_member) { create :project_member } let (:key) { create(:key, user: user) } + let (:group) { create(:group) } + let (:group_member) { create(:group_member) } context 'event data' do it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) } @@ -15,6 +17,31 @@ describe SystemHooksService do it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } it { event_data(key, :create).should include(:username, :key, :id) } it { event_data(key, :destroy).should include(:username, :key, :id) } + + it do + event_data(group, :create).should include( + :event_name, :name, :created_at, :path, :group_id, :owner_name, + :owner_email + ) + end + it do + event_data(group, :destroy).should include( + :event_name, :name, :created_at, :path, :group_id, :owner_name, + :owner_email + ) + end + it do + event_data(group_member, :create).should include( + :event_name, :created_at, :group_name, :group_path, :group_id, :user_id, + :user_name, :user_email, :group_access + ) + end + it do + event_data(group_member, :destroy).should include( + :event_name, :created_at, :group_name, :group_path, :group_id, :user_id, + :user_name, :user_email, :group_access + ) + end end context 'event names' do @@ -26,6 +53,10 @@ describe SystemHooksService do it { event_name(project_member, :destroy).should eq "user_remove_from_team" } it { event_name(key, :create).should eq 'key_create' } it { event_name(key, :destroy).should eq 'key_destroy' } + it { event_name(group, :create).should eq 'group_create' } + it { event_name(group, :destroy).should eq 'group_destroy' } + it { event_name(group_member, :create).should eq 'user_add_to_group' } + it { event_name(group_member, :destroy).should eq 'user_remove_from_group' } end def event_data(*args) From 4fefd353d86a0b7b223b44c5f2e355b09231f79d Mon Sep 17 00:00:00 2001 From: yglukhov Date: Tue, 27 Jan 2015 15:14:52 +0200 Subject: [PATCH 47/80] Update semantic-ui-sass to 1.8 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 96a1097d6d8..a49e6912986 100644 --- a/Gemfile +++ b/Gemfile @@ -170,7 +170,7 @@ gem 'ace-rails-ap' gem 'mousetrap-rails' # Semantic UI Sass for Sidebar -gem 'semantic-ui-sass', '~> 0.16.1.0' +gem 'semantic-ui-sass', '~> 1.8.0' gem "sass-rails", '~> 4.0.2' gem "coffee-rails" diff --git a/Gemfile.lock b/Gemfile.lock index 18fae9b7001..69ed6af2c63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -490,7 +490,7 @@ GEM activesupport (>= 3.1, < 4.2) select2-rails (3.5.2) thor (~> 0.14) - semantic-ui-sass (0.16.1.0) + semantic-ui-sass (1.8.0.0) sass (~> 3.2) settingslogic (2.0.9) sexp_processor (4.4.0) @@ -715,7 +715,7 @@ DEPENDENCIES sdoc seed-fu select2-rails - semantic-ui-sass (~> 0.16.1.0) + semantic-ui-sass (~> 1.8.0) settingslogic shoulda-matchers (~> 2.1.0) sidekiq (~> 3.3) From 7e6fa0afd63b75d2653ff75fcde26164f832a094 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 09:30:16 -0800 Subject: [PATCH 48/80] Update CHANGELOG with new stuff --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 91409707c87..56d3ac092e8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,8 +5,8 @@ v 7.8.0 - 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 - - - - + - Better UI for project services page + - Cleaner UI for web editor - Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger) - - From 233f9f0766f4316661f9464698d971069ea30e37 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Tue, 27 Jan 2015 09:35:46 -0800 Subject: [PATCH 49/80] Prevent confusion between active users and 30 day users. --- app/views/admin/dashboard/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index dd95af426c4..32e0e4a6848 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -32,7 +32,7 @@ %span.light.pull-right = Milestone.count %p - Active users last 30 days + Users who signed in during last 30 days %span.light.pull-right = User.where("current_sign_in_at > ?", 30.days.ago).count .col-md-4 From 6182f1cabf08e75b01146198cbd09fdea0bfdb67 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 09:48:42 -0800 Subject: [PATCH 50/80] Use larger avatar on application header --- app/assets/stylesheets/sections/header.scss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/sections/header.scss b/app/assets/stylesheets/sections/header.scss index 047617e54ba..e255cbcada8 100644 --- a/app/assets/stylesheets/sections/header.scss +++ b/app/assets/stylesheets/sections/header.scss @@ -138,9 +138,10 @@ header { top: -1px; padding-right: 0px !important; img { - width: 26px; - height: 26px; - @include border-radius($avatar_radius); + width: 50px; + height: 50px; + margin: -15px; + margin-left: 5px; } } From 2fa36ddd9c9efcc4f0d40755f535867573a0483c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 11:32:28 -0800 Subject: [PATCH 51/80] Replace p with h4 for empty repo text --- app/views/projects/empty.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 776a7327bc2..36628195b4e 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -6,7 +6,7 @@ .center.well %h3 The repository for this project is empty - %p.lead + %h4 You can = link_to project_new_blob_path(@project, 'master'), class: 'btn btn-new btn-lg' do add a file From 95db00c3e9b7658b1a2a38f62006371988eabe5c Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Tue, 27 Jan 2015 12:19:32 -0800 Subject: [PATCH 52/80] Still need the javascript on the project edit page. --- app/assets/javascripts/dispatcher.js.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index acce4ad5096..1643ca941ff 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -100,6 +100,7 @@ class Dispatcher switch path[1] when 'edit' shortcut_handler = new ShortcutsNavigation() + new ProjectNew() when 'new' new ProjectNew() when 'show' From e956066d4a9c3f556a52f80acfb5c761aede7c6c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 12:19:32 -0800 Subject: [PATCH 53/80] Add tests for initializing bare repo and creating new file in it --- features/project/source/browse_files.feature | 13 +++++++++++++ features/steps/project/source/browse_files.rb | 11 +++++++++++ features/steps/shared/project.rb | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature index 6ea64f70092..ccb29293a89 100644 --- a/features/project/source/browse_files.feature +++ b/features/project/source/browse_files.feature @@ -34,6 +34,19 @@ Feature: Project Source Browse Files Then I am redirected to the new file And I should see its new content + @javascript + Scenario: I can create file in empty repo + Given I own an empty project + And I visit my empty project page + And I create bare repo + When I click on "add a file" link + And I edit code + And I fill the new file name + And I fill the commit message + And I click on "Commit Changes" + Then I am redirected to the new file + And I should see its new content + @javascript Scenario: If I enter an illegal file name I see an error message Given I click on "new file" link in repo diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb index bd1ca55a20a..770e8162497 100644 --- a/features/steps/project/source/browse_files.rb +++ b/features/steps/project/source/browse_files.rb @@ -166,6 +166,17 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps expect(page).to have_content('Your changes could not be committed') end + step 'I create bare repo' do + click_link 'Create empty bare repository' + end + + step 'I click on "add a file" link' do + click_link 'add a file' + + # Remove pre-receive hook so we can push without auth + FileUtils.rm(File.join(Project.last.repository.path, 'hooks', 'pre-receive')) + end + private def set_new_content diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 0bd5653538c..cf0be256231 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -28,6 +28,10 @@ module SharedProject @project.team << [@user, :master] end + step 'I visit my empty project page' do + visit project_path(Project.find_by(name: 'Empty Project')) + end + step 'project "Shop" has push event' do @project = Project.find_by(name: "Shop") From b35f1d1c2f8741e777a670e06785b6ff47e7e764 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 12:45:31 -0800 Subject: [PATCH 54/80] Increase font size for issue/mr titles --- app/assets/stylesheets/sections/issues.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss index fbfd9c8cd9b..7a9d3334d96 100644 --- a/app/assets/stylesheets/sections/issues.scss +++ b/app/assets/stylesheets/sections/issues.scss @@ -163,8 +163,9 @@ form.edit-issue { } } -.issue-title { +h3.issue-title { margin-top: 0; + font-size: 2em; } .context .select2-container { From 8cc111bd038e4c4d67b835de4a1996c04c6674d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 13:40:23 -0800 Subject: [PATCH 55/80] Fix random failing test --- spec/features/atom/dashboard_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb index a7f87906b2d..52ade3e2d31 100644 --- a/spec/features/atom/dashboard_spec.rb +++ b/spec/features/atom/dashboard_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe "Dashboard Feed", feature: true do describe "GET /" do - let!(:user) { create(:user) } + let!(:user) { create(:user, name: "Jonh") } context "projects atom feed via private token" do it "should render projects atom feed" do From 35d6d1ce4669d1f3850862f3c144abaaf5b841d3 Mon Sep 17 00:00:00 2001 From: Visay Keo Date: Mon, 26 Jan 2015 12:12:16 +0700 Subject: [PATCH 56/80] Fix broadcast message to show up properly with new UI With the new UI, the broadcast message is the first level child element of the body tag and then render full width without respecting the width of the left sidebar. This makes the message goes under the left sidebar in smaller screen. This commit fixes the issue by moving the message element into the "page-with-sidebar" div so it will always render together with the main content area with same look as before. The rendering for the search, login and other view without left sidebar remains untouched. Releases: master, 7-7-stable Fixes: #1019 --- CHANGELOG | 2 +- app/views/layouts/_page.html.haml | 1 + app/views/layouts/admin.html.haml | 1 - app/views/layouts/application.html.haml | 1 - app/views/layouts/group.html.haml | 1 - app/views/layouts/profile.html.haml | 1 - app/views/layouts/project_settings.html.haml | 1 - app/views/layouts/projects.html.haml | 1 - app/views/layouts/public_group.html.haml | 1 - app/views/layouts/public_projects.html.haml | 1 - app/views/layouts/public_users.html.haml | 1 - 11 files changed, 2 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b05f0e760b8..999b21f758a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -33,7 +33,7 @@ v 7.8.0 - - - - - + - Fix long broadcast message cut-off on left sidebar (Visay Keo) - Add Project Avatars (Steven Thonus and Hannes Rosenögger) - - diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 621365fa6aa..1263f44eca9 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,5 +1,6 @@ - if defined?(sidebar) .page-with-sidebar + = render "layouts/broadcast" .sidebar-wrapper = render(sidebar) .content-wrapper diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index fb62d5fea0a..dc8652cb145 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Admin area" %body{class: "#{app_theme} #{theme_type} admin", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/head_panel", title: "Admin area" = render 'layouts/page', sidebar: 'layouts/nav/admin' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index d40c9753b10..e5420a13605 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Dashboard" %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page } - = render "layouts/broadcast" = render "layouts/head_panel", title: "Dashboard" = render 'layouts/page', sidebar: 'layouts/nav/dashboard' diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index 72b0d03908d..98edcf3a140 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: group_head_title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/head_panel", title: @group.name = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 941084cc4ad..89d816061e2 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: "Profile" %body{class: "#{app_theme} #{theme_type} profile", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/head_panel", title: "Profile" = render 'layouts/page', sidebar: 'layouts/nav/profile' diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index 0f20bf38bfd..d2c9c2a991c 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -2,7 +2,6 @@ %html{ lang: "en"} = render "layouts/head", title: @project.name_with_namespace %body{class: "#{app_theme} #{theme_type} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/broadcast" = render "layouts/head_panel", title: project_title(@project) = render "layouts/init_auto_complete" - @project_settings_nav = true diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml index d4ee53db55c..c44a40c9c12 100644 --- a/app/views/layouts/projects.html.haml +++ b/app/views/layouts/projects.html.haml @@ -2,7 +2,6 @@ %html{ lang: "en"} = render "layouts/head", title: project_head_title %body{class: "#{app_theme} #{theme_type} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/broadcast" = render "layouts/head_panel", title: project_title(@project) = render "layouts/init_auto_complete" = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_group.html.haml b/app/views/layouts/public_group.html.haml index 64794104ac5..ae3d2bd8a89 100644 --- a/app/views/layouts/public_group.html.haml +++ b/app/views/layouts/public_group.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: group_head_title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/public_head_panel", title: "group: #{@group.name}" = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml index 5964a29d522..027e9a53139 100644 --- a/app/views/layouts/public_projects.html.haml +++ b/app/views/layouts/public_projects.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: @project.name_with_namespace %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/public_head_panel", title: project_title(@project) = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml index 0510ce34a7f..37767df33d2 100644 --- a/app/views/layouts/public_users.html.haml +++ b/app/views/layouts/public_users.html.haml @@ -2,6 +2,5 @@ %html{ lang: "en"} = render "layouts/head", title: @title %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page} - = render "layouts/broadcast" = render "layouts/public_head_panel", title: @title = render 'layouts/page' From 50297f7134e878fba84168785ae461d14e08c572 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 22:51:11 -0800 Subject: [PATCH 57/80] Fix gravatar size for head panel icon --- app/views/layouts/_head_panel.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index bdf27562c26..77bfe4f996e 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -43,6 +43,6 @@ %i.fa.fa-sign-out %li.hidden-xs = link_to current_user, class: "profile-pic", id: 'profile-pic' do - = image_tag avatar_icon(current_user.email, 26), alt: 'User activity' + = image_tag avatar_icon(current_user.email, 60), alt: 'User activity' = render 'shared/outdated_browser' From 8eb365c0a04b912d2e10eb16adeeb4216563be2c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 27 Jan 2015 22:54:46 -0800 Subject: [PATCH 58/80] Separate admin settings from other links --- app/views/layouts/nav/_admin.html.haml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/views/layouts/nav/_admin.html.haml b/app/views/layouts/nav/_admin.html.haml index 66770adb5a5..4813a4f16f5 100644 --- a/app/views/layouts/nav/_admin.html.haml +++ b/app/views/layouts/nav/_admin.html.haml @@ -40,14 +40,15 @@ %span Background Jobs - = nav_link(controller: :application_settings) do - = link_to admin_application_settings_path, title: 'Settings' do - %i.fa.fa-cogs - %span - Settings - = nav_link(controller: :applications) do = link_to admin_applications_path, title: 'Applications' do %i.fa.fa-cloud %span Applications + + = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do + = link_to admin_application_settings_path, title: 'Settings' do + %i.fa.fa-cogs + %span + Settings + From 43da3f0929521615fe77d1dcb85318a8128bb7e8 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 28 Jan 2015 11:09:11 +0100 Subject: [PATCH 59/80] Point out common LDAP port/method combinations --- doc/integration/ldap.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index 56b0d826adb..6172a61d005 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -76,6 +76,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server EOS ``` +If you are getting 'Connection Refused' errors when trying to connect to the LDAP server please double-check the LDAP `port` and `method` settings used by GitLab. +Common combinations are `method: 'plain'` and `port: 389`, OR `method: 'ssl'` and `port: 636`. + If you are using a GitLab installation from source you can find the LDAP settings in `/home/git/gitlab/config/gitlab.yml`: ``` From 087c4cbc3cba2cce1c25773af304833d217976fc Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 28 Jan 2015 11:08:44 +0100 Subject: [PATCH 60/80] Make 'plain', port 389 the default for LDAP --- config/gitlab.yml.example | 4 ++-- doc/integration/ldap.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index e5780cabb63..59af49c0180 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -153,9 +153,9 @@ production: &base label: 'LDAP' host: '_your_ldap_server' - port: 636 + port: 389 uid: 'sAMAccountName' - method: 'ssl' # "tls" or "ssl" or "plain" + method: 'plain' # "tls" or "ssl" or "plain" bind_dn: '_the_full_dn_of_the_user_you_will_bind_with' password: '_the_password_of_the_bind_user' diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index 6172a61d005..125ce31b521 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -29,9 +29,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server label: 'LDAP' host: '_your_ldap_server' - port: 636 + port: 389 uid: 'sAMAccountName' - method: 'ssl' # "tls" or "ssl" or "plain" + method: 'plain' # "tls" or "ssl" or "plain" bind_dn: '_the_full_dn_of_the_user_you_will_bind_with' password: '_the_password_of_the_bind_user' From 537cd66d7e4237f0df6db88b3225327c8e4140c5 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 Jan 2015 09:28:17 -0800 Subject: [PATCH 61/80] Add gitlab internal issue tracker service. --- app/controllers/application_controller.rb | 2 +- .../projects/services_controller.rb | 5 +--- app/models/project.rb | 24 ++++++++++++++----- .../gitlab_issue_tracker_service.rb | 13 ++++++++++ .../project_services/issue_tracker_service.rb | 4 ++++ 5 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 app/models/project_services/gitlab_issue_tracker_service.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ad13a0ac3e4..36e13706768 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -181,7 +181,7 @@ class ApplicationController < ActionController::Base end def add_gon_variables - gon.default_issues_tracker = Project.issues_tracker.default_value + gon.default_issues_tracker = Project.new.default_issue_tracker.to_param gon.api_version = API::API.version gon.relative_url_root = Gitlab.config.gitlab.relative_url_root gon.default_avatar_url = URI::join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 09bccb4bf8f..5dda869a154 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -9,7 +9,7 @@ class Projects::ServicesController < Projects::ApplicationController def index @project.build_missing_services - @services = @project.services.reload + @services = @project.services.where.not(type: 'GitlabIssueTrackerService').reload end def edit @@ -17,9 +17,6 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.update_attributes(service_params) - if @service.activated? && @service.issue_tracker? - @project.update_attributes(issues_tracker: @service.to_param) - end redirect_to edit_project_service_path(@project, @service.to_param), notice: 'Successfully updated.' else diff --git a/app/models/project.rb b/app/models/project.rb index 12751bb77e6..9e31c019fd3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -77,6 +77,7 @@ class Project < ActiveRecord::Base has_one :jira_service, dependent: :destroy has_one :redmine_service, dependent: :destroy has_one :custom_issue_tracker_service, dependent: :destroy + has_one :gitlab_issue_tracker_service, dependent: :destroy has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" @@ -149,8 +150,6 @@ class Project < ActiveRecord::Base scope :public_and_internal_only, -> { where(visibility_level: Project.public_and_internal_levels) } scope :non_archived, -> { where(archived: false) } - enumerize :issues_tracker, in: (Service.issue_tracker_service_list).append(:gitlab), default: :gitlab - state_machine :import_status, initial: :none do event :import_start do transition [:none, :finished] => :started @@ -317,19 +316,32 @@ class Project < ActiveRecord::Base end end + def default_issue_tracker + unless gitlab_issue_tracker_service + create_gitlab_issue_tracker_service + end + + gitlab_issue_tracker_service + end + + def issues_tracker + if external_issue_tracker + external_issue_tracker + else + default_issue_tracker + end + end + def default_issues_tracker? if external_issue_tracker false else - unless self.issues_tracker == Project.issues_tracker.default_value - self.update_attributes(issues_tracker: Project.issues_tracker.default_value) - end true end end def external_issues_trackers - services.select { |service| service.issue_tracker? } + services.select(&:issue_tracker?).reject(&:default?) end def external_issue_tracker diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb new file mode 100644 index 00000000000..46649a74751 --- /dev/null +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -0,0 +1,13 @@ +class GitlabIssueTrackerService < IssueTrackerService + + prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url + + + def default? + true + end + + def to_param + 'gitlab' + end +end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index fc7b2fe5acd..810ecbe46fc 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -6,6 +6,10 @@ class IssueTrackerService < Service :issue_tracker end + def default? + false + end + def project_url # implement inside child end From 965cec68accf9e9c2137e433ab00283f2ae6987f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 10:53:28 -0800 Subject: [PATCH 62/80] Project/Group access dropdown should contain link to permissions help page --- app/views/groups/_new_group_member.html.haml | 6 +++++- app/views/projects/team_members/_form.html.haml | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/views/groups/_new_group_member.html.haml b/app/views/groups/_new_group_member.html.haml index e590ddbf931..ed00153de7e 100644 --- a/app/views/groups/_new_group_member.html.haml +++ b/app/views/groups/_new_group_member.html.haml @@ -5,7 +5,11 @@ .form-group = f.label :access_level, "Group Access", class: 'control-label' - .col-sm-10= select_tag :access_level, options_for_select(GroupMember.access_level_roles, @users_group.access_level), class: "project-access-select select2" + .col-sm-10 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles, @users_group.access_level), class: "project-access-select select2" + .help-block + Read more about role permissions + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" .form-actions = f.submit 'Add users into group', class: "btn btn-create" diff --git a/app/views/projects/team_members/_form.html.haml b/app/views/projects/team_members/_form.html.haml index 2bf61fa12bb..ddf8cb76f78 100644 --- a/app/views/projects/team_members/_form.html.haml +++ b/app/views/projects/team_members/_form.html.haml @@ -17,7 +17,12 @@ %p 2. Set access level for them .form-group = f.label :access_level, "Project Access", class: 'control-label' - .col-sm-10= select_tag :access_level, options_for_select(Gitlab::Access.options, @user_project_relation.access_level), class: "project-access-select select2" + .col-sm-10 + = select_tag :access_level, options_for_select(Gitlab::Access.options, @user_project_relation.access_level), class: "project-access-select select2" + .help-block + Read more about role permissions + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" + .form-actions = f.submit 'Add users', class: "btn btn-create" From b40809d73135ada0e82c826f96e6cb1dd6fbaa7c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 11:25:13 -0800 Subject: [PATCH 63/80] Improve UX for widget if merge request can not be merged --- app/assets/stylesheets/sections/merge_requests.scss | 1 + .../projects/merge_requests/show/_mr_accept.html.haml | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss index 8bd32f41e2c..0e27c389387 100644 --- a/app/assets/stylesheets/sections/merge_requests.scss +++ b/app/assets/stylesheets/sections/merge_requests.scss @@ -122,6 +122,7 @@ background: $box_bg; margin-bottom: 20px; color: #666; + border: 1px solid #EEE; @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); .ci_widget { diff --git a/app/views/projects/merge_requests/show/_mr_accept.html.haml b/app/views/projects/merge_requests/show/_mr_accept.html.haml index 11a111e5faa..f8ee6973637 100644 --- a/app/views/projects/merge_requests/show/_mr_accept.html.haml +++ b/app/views/projects/merge_requests/show/_mr_accept.html.haml @@ -45,10 +45,17 @@ .automerge_widget.cannot_be_merged.hide %h4 This request can't be merged with GitLab. - %p You should do it manually with %strong - = link_to "command line", "#modal_merge_info", class: "how_to_merge_link", title: "How To Merge", "data-toggle" => "modal" + = link_to "#modal_merge_info", class: "underlined-link how_to_merge_link", title: "How To Merge", "data-toggle" => "modal" do + command line + + %p + %button.btn.disabled + %i.fa.fa-warning + Accept Merge Request +   + This usually happens when git can not resolve conflicts between branches automatically. .automerge_widget.unchecked %p From c6c7552e41cba12ca84238bd466d522aa1712220 Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 Jan 2015 13:19:32 -0800 Subject: [PATCH 64/80] Build the urls inside of the service. --- app/helpers/issues_helper.rb | 19 +++---------------- .../gitlab_issue_tracker_service.rb | 14 +++++++++++++- .../project_services/issue_tracker_service.rb | 4 ++++ spec/helpers/gitlab_markdown_helper_spec.rb | 1 + 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 2bf430f9142..9fe183e6e2f 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -16,32 +16,19 @@ module IssuesHelper def url_for_project_issues(project = @project) return '' if project.nil? - if project.default_issues_tracker? - project_issues_path(project) - else - project.external_issue_tracker.project_url - end + project.issues_tracker.project_url end def url_for_new_issue(project = @project) return '' if project.nil? - if project.default_issues_tracker? - url = new_project_issue_path project_id: project - else - project.external_issue_tracker.new_issue_url - end + project.issues_tracker.new_issue_url end def url_for_issue(issue_iid, project = @project) return '' if project.nil? - if project.default_issues_tracker? - url = project_issue_url project_id: project, id: issue_iid - else - url = project.external_issue_tracker.issues_url - url.gsub(':id', issue_iid.to_s) - end + project.issues_tracker.issue_url(issue_iid) end def title_for_issue(issue_iid, project = @project) diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 46649a74751..8e548a6d636 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -1,5 +1,5 @@ class GitlabIssueTrackerService < IssueTrackerService - + include Rails.application.routes.url_helpers prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url @@ -10,4 +10,16 @@ class GitlabIssueTrackerService < IssueTrackerService def to_param 'gitlab' end + + def project_url + project_issues_path(project) + end + + def new_issue_url + new_project_issue_path project_id: project + end + + def issue_url(iid) + "#{Gitlab.config.gitlab.url}#{project_issue_path project_id: project, id: iid}" + end end diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index 810ecbe46fc..632f053d17b 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -22,6 +22,10 @@ class IssueTrackerService < Service # implement inside child end + def issue_url(iid) + self.issues_url.gsub(':id', iid.to_s) + end + def fields [ { type: 'text', name: 'description', placeholder: description }, diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index 5c9eea956f3..d633287b2a9 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -23,6 +23,7 @@ describe GitlabMarkdownHelper do @project = project @ref = 'markdown' @repository = project.repository + @request.host = Gitlab.config.gitlab.host end describe "#gfm" do From 34b7472b33986db8894939b59116784f706d4759 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 14:20:00 -0800 Subject: [PATCH 65/80] Improve wording for fork project page --- app/views/projects/forks/new.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index 54f2cef023b..13f3a4b2e85 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -1,5 +1,6 @@ %h3.page-title Fork project -%p.lead Select namespace where to fork this project +%p.lead + Click on icon with user or group to fork project there %hr .fork-namespaces From 68f7302474768351abf12767c7741823f56f35cd Mon Sep 17 00:00:00 2001 From: Marin Jankovski Date: Wed, 28 Jan 2015 14:25:55 -0800 Subject: [PATCH 66/80] Add a scope for visible services, code styling changes for easier readability. --- app/controllers/projects/services_controller.rb | 2 +- app/models/project.rb | 6 +----- app/models/project_services/gitlab_issue_tracker_service.rb | 2 +- app/models/service.rb | 2 ++ 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 5dda869a154..5b35cc90413 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -9,7 +9,7 @@ class Projects::ServicesController < Projects::ApplicationController def index @project.build_missing_services - @services = @project.services.where.not(type: 'GitlabIssueTrackerService').reload + @services = @project.services.visible.reload end def edit diff --git a/app/models/project.rb b/app/models/project.rb index 9e31c019fd3..b26c697a7b7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -317,11 +317,7 @@ class Project < ActiveRecord::Base end def default_issue_tracker - unless gitlab_issue_tracker_service - create_gitlab_issue_tracker_service - end - - gitlab_issue_tracker_service + gitlab_issue_tracker_service ||= create_gitlab_issue_tracker_service end def issues_tracker diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 8e548a6d636..25f5f23bdf9 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -20,6 +20,6 @@ class GitlabIssueTrackerService < IssueTrackerService end def issue_url(iid) - "#{Gitlab.config.gitlab.url}#{project_issue_path project_id: project, id: iid}" + "#{Gitlab.config.gitlab.url}#{project_issue_path(project_id: project, id: iid)}" end end diff --git a/app/models/service.rb b/app/models/service.rb index 42419475349..15948e63e41 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -26,6 +26,8 @@ class Service < ActiveRecord::Base validates :project_id, presence: true + scope :visible, -> { where.not(type: 'GitlabIssueTrackerService') } + def activated? active end From b076d8cddb37ea7ae24cd035967cba885cdc429d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 15:36:12 -0800 Subject: [PATCH 67/80] Fix test for merge request --- features/steps/project/merge_requests.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index 071ef75dc62..6f421de1aba 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -173,7 +173,9 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps merge!: true, ) - click_button "Accept Merge Request" + within '.can_be_merged' do + click_button "Accept Merge Request" + end end step 'I should see merged request' do From f2f7b5a18e91005deda8ea36d95fd159568d93a4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 15:37:20 -0800 Subject: [PATCH 68/80] Better wording --- app/views/projects/forks/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index 13f3a4b2e85..959d5f08d47 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -1,6 +1,6 @@ %h3.page-title Fork project %p.lead - Click on icon with user or group to fork project there + Click to fork the project to a user or group %hr .fork-namespaces From 54f6d8c7b5a1c67a222011c35ad70909da0e686d Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 27 Jan 2015 15:37:19 -0800 Subject: [PATCH 69/80] an ability to clone project with oauth2 token --- ...150116234545_add_gitlab_access_token_to_user.rb | 5 +++++ db/schema.rb | 3 ++- lib/gitlab/backend/grack_auth.rb | 14 +++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20150116234545_add_gitlab_access_token_to_user.rb diff --git a/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb new file mode 100644 index 00000000000..c28ba3197ac --- /dev/null +++ b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb @@ -0,0 +1,5 @@ +class AddGitlabAccessTokenToUser < ActiveRecord::Migration + def change + add_column :users, :gitlab_access_token, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 29466f048eb..3f9ceb84e5d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150116234544) do +ActiveRecord::Schema.define(version: 20150116234545) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -434,6 +434,7 @@ ActiveRecord::Schema.define(version: 20150116234544) do t.string "website_url", default: "", null: false t.datetime "last_credential_check_at" t.string "github_access_token" + t.string "gitlab_access_token" end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb index 1f71906bc8e..2e393f753e8 100644 --- a/lib/gitlab/backend/grack_auth.rb +++ b/lib/gitlab/backend/grack_auth.rb @@ -34,7 +34,7 @@ module Grack def auth! if @auth.provided? return bad_request unless @auth.basic? - + # Authentication with username and password login, password = @auth.credentials @@ -71,8 +71,20 @@ module Grack false end + def oauth_access_token_check(login, password) + if login == "oauth2" && git_cmd == 'git-upload-pack' && password.present? + token = Doorkeeper::AccessToken.by_token(password) + token && token.accessible? && User.find_by(id: token.resource_owner_id) + end + end + def authenticate_user(login, password) user = Gitlab::Auth.new.find(login, password) + + unless user + user = oauth_access_token_check(login, password) + end + return user if user.present? # At this point, we know the credentials were wrong. We let Rack::Attack From d74e732299dc2c896a64350ddfdbdb2bb55a5fc6 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 28 Jan 2015 23:53:16 +0000 Subject: [PATCH 70/80] update changelog --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 999b21f758a..023d2f5449a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,8 @@ v 7.8.0 - Increate font size when browse source files and diffs - Create new file in empty repository using GitLab UI - + - Ability to clone project using oauth2 token + - - 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 From 792ced2f4190226c3335967a8e5a30d3b72bd4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Rosen=C3=B6gger?= <123haynes@gmail.com> Date: Wed, 28 Jan 2015 22:18:22 +0100 Subject: [PATCH 71/80] Add a commit calendar to the user profile --- CHANGELOG | 2 +- Gemfile | 3 + Gemfile.lock | 2 + app/assets/javascripts/application.js.coffee | 1 + app/assets/javascripts/calendar.js.coffee | 71 +++++++++++++++ app/assets/stylesheets/application.scss | 1 + app/assets/stylesheets/generic/calendar.scss | 95 ++++++++++++++++++++ app/controllers/users_controller.rb | 25 +++++- app/models/repository.rb | 35 ++++++-- app/views/events/_event.html.haml | 3 +- app/views/users/_calendar.html.haml | 9 ++ app/views/users/_calendar_onclick.html.haml | 25 ++++++ app/views/users/show.html.haml | 2 + config/routes.rb | 4 + lib/gitlab/commits_calendar.rb | 79 ++++++++++++++++ spec/controllers/users_controller_spec.rb | 27 ++++++ 16 files changed, 374 insertions(+), 10 deletions(-) create mode 100644 app/assets/javascripts/calendar.js.coffee create mode 100644 app/assets/stylesheets/generic/calendar.scss create mode 100644 app/views/users/_calendar.html.haml create mode 100644 app/views/users/_calendar_onclick.html.haml create mode 100644 lib/gitlab/commits_calendar.rb create mode 100644 spec/controllers/users_controller_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 999b21f758a..8914068570e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,7 +29,7 @@ v 7.8.0 - - - - - + - Add a commit calendar to the user profile (Hannes Rosenögger) - - - diff --git a/Gemfile b/Gemfile index 96a1097d6d8..6e4e20f5e1f 100644 --- a/Gemfile +++ b/Gemfile @@ -154,6 +154,9 @@ gem "slack-notifier", "~> 1.0.0" # d3 gem "d3_rails", "~> 3.1.4" +#cal-heatmap +gem "cal-heatmap-rails", "~> 0.0.1" + # underscore-rails gem "underscore-rails", "~> 1.4.4" diff --git a/Gemfile.lock b/Gemfile.lock index 18fae9b7001..5c70541a735 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -52,6 +52,7 @@ GEM sass (~> 3.2) browser (0.7.2) builder (3.2.2) + cal-heatmap-rails (0.0.1) capybara (2.2.1) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -627,6 +628,7 @@ DEPENDENCIES binding_of_caller bootstrap-sass (~> 3.0) browser + cal-heatmap-rails (~> 0.0.1) capybara (~> 2.2.1) carrierwave coffee-rails diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 337170605dc..4912c534b0e 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -39,6 +39,7 @@ #= require shortcuts_dashboard_navigation #= require shortcuts_issueable #= require shortcuts_network +#= require cal-heatmap #= require_tree . window.slugify = (text) -> diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee new file mode 100644 index 00000000000..e3bb420a278 --- /dev/null +++ b/app/assets/javascripts/calendar.js.coffee @@ -0,0 +1,71 @@ +class @calendar + options = + month: "short" + day: "numeric" + year: "numeric" + + constructor: (timestamps,starting_year,starting_month,activities_path) -> + cal = new CalHeatMap() + cal.init + itemName: ["commit"] + data: timestamps + start: new Date(starting_year, starting_month) + domainLabelFormat: "%b" + id: "cal-heatmap" + domain: "month" + subDomain: "day" + range: 12 + tooltip: true + domainDynamicDimension: false + colLimit: 4 + label: + position: "top" + domainMargin: 1 + legend: [ + 0 + 1 + 4 + 7 + ] + legendCellPadding: 3 + onClick: (date, count) -> + $.ajax + url: activities_path + data: + date: date + + dataType: "json" + success: (data) -> + $("#loading_commits").fadeIn() + calendar.calendarOnClick data, date, count + setTimeout (-> + $("#calendar_onclick_placeholder").fadeIn 500 + return + ), 400 + setTimeout (-> + $("#loading_commits").hide() + return + ), 400 + return + return + return + + @calendarOnClick: (data, date, nb)-> + $("#calendar_onclick_placeholder").hide() + $("#calendar_onclick_placeholder").html -> + "" + + ((if nb is null then "no" else nb)) + + " commit" + + ((if (nb isnt 1) then "s" else "")) + " " + + date.toLocaleDateString("en-US", options) + + "
" + $.each data, (key, data) -> + $.each data, (index, data) -> + $("#calendar_onclick_placeholder").append -> + "Pushed " + ((if data is null then "no" else data)) + " commit" + + ((if (data isnt 1) then "s" else "")) + + " to " + + index + "
" + return + return + return diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 3cf08782c3c..8f63a7fee64 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -8,6 +8,7 @@ *= require select2 *= require_self *= require dropzone/basic + *= require cal-heatmap */ @import "main/*"; diff --git a/app/assets/stylesheets/generic/calendar.scss b/app/assets/stylesheets/generic/calendar.scss new file mode 100644 index 00000000000..9483b26164e --- /dev/null +++ b/app/assets/stylesheets/generic/calendar.scss @@ -0,0 +1,95 @@ +.calendar_onclick_placeholder { + padding: 0 0 2px 0; +} + +.calendar_commit_activity { + padding: 5px 0 0; +} + +.calendar_onclick_second { + font-size: 14px; + display: block; +} + +.calendar_onclick_hr { + padding: 0; + margin: 10px 0; +} + +.calendar_commit_date { + color: #999; +} + +.calendar_activity_summary { + font-size: 14px; +} + +/** +* This overwrites the default values of the cal-heatmap gem +*/ +.calendar { + .qi { + background-color: #999; + fill: #fff; + } + + .q1 { + background-color: #dae289; + fill: #ededed; + } + + .q2 { + background-color: #cedb9c; + fill: #ACD5F2; + } + + .q3 { + background-color: #b5cf6b; + fill: #7FA8D1; + } + + .q4 { + background-color: #637939; + fill: #49729B; + } + + .q5 { + background-color: #3b6427; + fill: #254E77; + } + + .domain-background { + fill: none; + shape-rendering: crispedges; + } + + .ch-tooltip { + position: absolute; + display: none; + margin-top: 22px; + margin-left: 1px; + font-size: 13px; + padding: 3px; + font-weight: 550; + background-color: #222; + span { + position: absolute; + width: 200px; + text-align: center; + visibility: hidden; + border-radius: 10px; + &:after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + margin-left: -8px; + width: 0; + height: 0; + border-top: 8px solid #000000; + border-right: 8px solid transparent; + border-left: 8px solid transparent; + } + } + } +} diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 67af1801bda..a5e80f7e008 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - skip_before_filter :authenticate_user!, only: [:show] + skip_before_filter :authenticate_user!, only: [:show, :activities] layout :determine_layout def show @@ -10,7 +10,8 @@ class UsersController < ApplicationController end # Projects user can view - authorized_projects_ids = ProjectsFinder.new.execute(current_user).pluck(:id) + visible_projects = ProjectsFinder.new.execute(current_user) + authorized_projects_ids = visible_projects.pluck(:id) @projects = @user.personal_projects. where(id: authorized_projects_ids) @@ -24,12 +25,32 @@ class UsersController < ApplicationController @title = @user.name + user_repositories = visible_projects.map(&:repository) + @timestamps = Gitlab::CommitsCalendar.create_timestamp(user_repositories, + @user, false) + @starting_year = Gitlab::CommitsCalendar.starting_year(@timestamps) + @starting_month = Gitlab::CommitsCalendar.starting_month(@timestamps) + @last_commit_date = Gitlab::CommitsCalendar.last_commit_date(@timestamps) + respond_to do |format| format.html format.atom { render layout: false } end end + def activities + user = User.find_by_username!(params[:username]) + # Projects user can view + visible_projects = ProjectsFinder.new.execute(current_user) + + user_repositories = visible_projects.map(&:repository) + user_activities = Gitlab::CommitsCalendar.create_timestamp(user_repositories, + user, true) + user_activities = Gitlab::CommitsCalendar.commit_activity_match( + user_activities, params[:date]) + render json: user_activities.to_json + end + def determine_layout if current_user 'navless' diff --git a/app/models/repository.rb b/app/models/repository.rb index e93c76790c7..e44ecca865c 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -139,21 +139,46 @@ class Repository def graph_log Rails.cache.fetch(cache_key(:graph_log)) do - commits = raw_repository.log(limit: 6000, skip_merges: true, - ref: root_ref) - commits.map do |rugged_commit| - commit = Gitlab::Git::Commit.new(rugged_commit) + # handle empty repos that don't have a root_ref set yet + unless raw_repository.root_ref.present? + raw_repository.root_ref = 'refs/heads/master' + end + + commits = raw_repository.log(limit: 6000, skip_merges: true, + ref: raw_repository.root_ref) + + commits.map do |rugged_commit| + + commit = Gitlab::Git::Commit.new(rugged_commit) { author_name: commit.author_name.force_encoding('UTF-8'), author_email: commit.author_email.force_encoding('UTF-8'), additions: commit.stats.additions, - deletions: commit.stats.deletions + deletions: commit.stats.deletions, + date: commit.committed_date } end end end + def graph_logs_by_user_email(user) + graph_log.select { |u_email| u_email[:author_email] == user.email } + end + + def timestamps_by_user_from_graph_log(user) + graph_logs_by_user_email(user).map { |graph_log| graph_log[:date].to_time.to_i } + end + + def commits_log_of_user_by_date(user) + timestamps_by_user_from_graph_log(user). + group_by { |commit_date| commit_date }. + inject({}) do |hash, (timestamp_date, commits)| + hash[timestamp_date] = commits.count + hash + end + end + def cache_key(type) "#{type}:#{path_with_namespace}" end diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 61383315373..c7976ba564f 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -11,5 +11,4 @@ - elsif event.note? = render "events/event/note", event: event - else - = render "events/event/common", event: event - + = render "events/event/common", event: event \ No newline at end of file diff --git a/app/views/users/_calendar.html.haml b/app/views/users/_calendar.html.haml new file mode 100644 index 00000000000..70d5cca854d --- /dev/null +++ b/app/views/users/_calendar.html.haml @@ -0,0 +1,9 @@ +#cal-heatmap.calendar + :javascript + new calendar( + #{@timestamps.to_json}, + #{@starting_year}, + #{@starting_month}, + '#{user_activities_path}' + ); += render "calendar_onclick" diff --git a/app/views/users/_calendar_onclick.html.haml b/app/views/users/_calendar_onclick.html.haml new file mode 100644 index 00000000000..1514b56bb23 --- /dev/null +++ b/app/views/users/_calendar_onclick.html.haml @@ -0,0 +1,25 @@ +#calendar_commit_activity.calendar_commit_activity + %h4.activity_title Commit Activity: + + #loading_commits + %section.text-center + %h3 + %i.icon-spinner.icon-spin + + #calendar_onclick_placeholder.calendar_onclick_placeholder + %span.calendar_onclick_second.calendar_onclick_second + - if @timestamps.empty? + %span.calendar_activity_summary + %strong> #{@user.username} +   has no activity + - else + %span.calendar_activity_summary + %strong> #{@user.username} + 's last commit was on + %span.commit_date #{@last_commit_date} + + %hr.calendar_onclick_hr + +:javascript + $("#loading_commits").hide(); + diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 54f2666ce5d..0d214d31607 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -18,6 +18,8 @@ %h4 Groups: = render 'groups', groups: @groups %hr + %h4 Calendar: + = render 'calendar' %h4 User Activity: diff --git a/config/routes.rb b/config/routes.rb index f29b620e079..5d61de29b9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -157,6 +157,10 @@ Gitlab::Application.routes.draw do end end + # route for commits used by the cal-heatmap + get 'u/:username/activities' => 'users#activities', as: :user_activities, + constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, + via: :get get '/u/:username' => 'users#show', as: :user, constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb new file mode 100644 index 00000000000..a862e67a598 --- /dev/null +++ b/lib/gitlab/commits_calendar.rb @@ -0,0 +1,79 @@ +module Gitlab + class CommitsCalendar + def self.create_timestamp(repositories, user, show_activity) + timestamps = {} + repositories.each do |raw_repository| + if raw_repository.exists? + commits_log = raw_repository.commits_log_of_user_by_date(user) + + populated_timestamps = + if show_activity + populate_timestamps_by_project( + commits_log, + timestamps, + raw_repository + ) + else + populate_timestamps(commits_log, timestamps) + end + timestamps.merge!(populated_timestamps) + end + end + timestamps + end + + def self.populate_timestamps(commits_log, timestamps) + commits_log.each do |timestamp_date, commits_count| + hash = { "#{timestamp_date}" => commits_count } + if timestamps.has_key?("#{timestamp_date}") + timestamps.merge!(hash) do |timestamp_date, commits_count, + new_commits_count| commits_count = commits_count.to_i + + new_commits_count + end + else + timestamps.merge!(hash) + end + end + timestamps + end + + def self.populate_timestamps_by_project(commits_log, timestamps, + project) + commits_log.each do |timestamp_date, commits_count| + if timestamps.has_key?("#{timestamp_date}") + timestamps["#{timestamp_date}"]. + merge!(project.path_with_namespace => commits_count) + else + hash = { "#{timestamp_date}" => { project.path_with_namespace => + commits_count } } + timestamps.merge!(hash) + end + end + timestamps + end + + def self.latest_commit_date(timestamps) + if timestamps.nil? || timestamps.empty? + DateTime.now.to_date + else + Time.at(timestamps.keys.first.to_i).to_date + end + end + + def self.starting_year(timestamps) + DateTime.now.to_date - 1 + end + + def self.starting_month(timestamps) + Date.today.strftime("%m").to_i + end + + def self.last_commit_date(timestamps) + latest_commit_date(timestamps).to_formatted_s(:long).to_s + end + + def self.commit_activity_match(user_activities, date) + user_activities.select { |x| Time.at(x.to_i) == Time.parse(date) } + end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb new file mode 100644 index 00000000000..bfbe5254bbe --- /dev/null +++ b/spec/controllers/users_controller_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe UsersController do + let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") } + + before do + sign_in(user) + end + + describe "GET #show" do + render_views + before do + get :show, username: user.username + end + + it "renders the show template" do + expect(response.status).to eq(200) + expect(response).to render_template("show") + end + + it "renders calendar" do + controller.prepend_view_path 'app/views/users' + expect(response).to render_template("_calendar") + end + end +end + From ef315dda5f6b252151feb320af0abdea12690df4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 16:59:25 -0800 Subject: [PATCH 72/80] Add light border to bootstrap panels --- app/assets/stylesheets/gl_bootstrap.scss | 3 --- app/assets/stylesheets/main/mixins.scss | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/assets/stylesheets/gl_bootstrap.scss b/app/assets/stylesheets/gl_bootstrap.scss index 2a68d922bb7..6efa56544a5 100644 --- a/app/assets/stylesheets/gl_bootstrap.scss +++ b/app/assets/stylesheets/gl_bootstrap.scss @@ -1,9 +1,6 @@ /* * Twitter bootstrap with GitLab customizations/additions * - * Some unused bootstrap compontents like panels are not included. - * Other components like tabs are modified to GitLab style. - * */ $font-size-base: 13px !default; diff --git a/app/assets/stylesheets/main/mixins.scss b/app/assets/stylesheets/main/mixins.scss index 8435d1dae79..e54482d14c3 100644 --- a/app/assets/stylesheets/main/mixins.scss +++ b/app/assets/stylesheets/main/mixins.scss @@ -139,7 +139,7 @@ } @mixin panel-colored { - border: none; + border: 1px solid #EEE; background: $box_bg; @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); From 953c1fff8f242f09f3f16998112931d48d6a5ecc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 17:00:40 -0800 Subject: [PATCH 73/80] Be more careful with parsing changes from gitlab-shell --- lib/gitlab/git_access.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index c7bf2efc628..ea96d04c5ab 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -73,7 +73,7 @@ module Gitlab changes = changes.lines if changes.kind_of?(String) # Iterate over all changes to find if user allowed all of them to be applied - changes.each do |change| + changes.map(&:strip).reject(&:blank?).each do |change| status = change_access_check(user, project, change) unless status.allowed? # If user does not have access to make at least one change - cancel all push From c39f80bdb412bc9cc7646de0929efe8cb5b870d4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 28 Jan 2015 23:00:41 -0800 Subject: [PATCH 74/80] Refactor commit calendar a bit. Fixed dates --- app/assets/javascripts/calendar.js.coffee | 16 ++++++++-------- app/controllers/users_controller.rb | 4 ++-- lib/gitlab/commits_calendar.rb | 8 -------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index e3bb420a278..c5465f92076 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -4,7 +4,7 @@ class @calendar day: "numeric" year: "numeric" - constructor: (timestamps,starting_year,starting_month,activities_path) -> + constructor: (timestamps, starting_year, starting_month, activities_path) -> cal = new CalHeatMap() cal.init itemName: ["commit"] @@ -46,7 +46,7 @@ class @calendar $("#loading_commits").hide() return ), 400 - return + return return return @@ -54,17 +54,17 @@ class @calendar $("#calendar_onclick_placeholder").hide() $("#calendar_onclick_placeholder").html -> "" + - ((if nb is null then "no" else nb)) + - " commit" + - ((if (nb isnt 1) then "s" else "")) + " " + - date.toLocaleDateString("en-US", options) + + ((if nb is null then "no" else nb)) + + " commit" + + ((if (nb isnt 1) then "s" else "")) + " " + + date.toLocaleDateString("en-US", options) + "
" $.each data, (key, data) -> $.each data, (index, data) -> $("#calendar_onclick_placeholder").append -> "Pushed " + ((if data is null then "no" else data)) + " commit" + - ((if (data isnt 1) then "s" else "")) + - " to " + + ((if (data isnt 1) then "s" else "")) + + " to " + index + "
" return return diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a5e80f7e008..28de2707778 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -28,8 +28,8 @@ class UsersController < ApplicationController user_repositories = visible_projects.map(&:repository) @timestamps = Gitlab::CommitsCalendar.create_timestamp(user_repositories, @user, false) - @starting_year = Gitlab::CommitsCalendar.starting_year(@timestamps) - @starting_month = Gitlab::CommitsCalendar.starting_month(@timestamps) + @starting_year = (Time.now - 1.year).strftime("%Y") + @starting_month = Date.today.strftime("%m").to_i @last_commit_date = Gitlab::CommitsCalendar.last_commit_date(@timestamps) respond_to do |format| diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb index a862e67a598..93256187fd2 100644 --- a/lib/gitlab/commits_calendar.rb +++ b/lib/gitlab/commits_calendar.rb @@ -60,14 +60,6 @@ module Gitlab end end - def self.starting_year(timestamps) - DateTime.now.to_date - 1 - end - - def self.starting_month(timestamps) - Date.today.strftime("%m").to_i - end - def self.last_commit_date(timestamps) latest_commit_date(timestamps).to_formatted_s(:long).to_s end From a9288e554e55e843b95ab6f8109a4c610af64c83 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 00:53:43 -0800 Subject: [PATCH 75/80] Cleanup and make contribution calendar faster --- app/assets/javascripts/calendar.js.coffee | 42 +----------- app/controllers/users_controller.rb | 19 +----- app/models/repository.rb | 33 +++++---- app/views/users/_calendar.html.haml | 6 +- app/views/users/_calendar_onclick.html.haml | 25 ------- app/views/users/show.html.haml | 4 +- lib/gitlab/commits_calendar.rb | 74 ++++----------------- spec/controllers/users_controller_spec.rb | 4 +- 8 files changed, 42 insertions(+), 165 deletions(-) delete mode 100644 app/views/users/_calendar_onclick.html.haml diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index c5465f92076..6a0d5e43567 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -4,11 +4,13 @@ class @calendar day: "numeric" year: "numeric" - constructor: (timestamps, starting_year, starting_month, activities_path) -> + constructor: (timestamps, starting_year, starting_month) -> cal = new CalHeatMap() cal.init itemName: ["commit"] data: timestamps + domain: "year" + subDomain: "month" start: new Date(starting_year, starting_month) domainLabelFormat: "%b" id: "cal-heatmap" @@ -29,43 +31,5 @@ class @calendar ] legendCellPadding: 3 onClick: (date, count) -> - $.ajax - url: activities_path - data: - date: date - - dataType: "json" - success: (data) -> - $("#loading_commits").fadeIn() - calendar.calendarOnClick data, date, count - setTimeout (-> - $("#calendar_onclick_placeholder").fadeIn 500 - return - ), 400 - setTimeout (-> - $("#loading_commits").hide() - return - ), 400 - return return return - - @calendarOnClick: (data, date, nb)-> - $("#calendar_onclick_placeholder").hide() - $("#calendar_onclick_placeholder").html -> - "" + - ((if nb is null then "no" else nb)) + - " commit" + - ((if (nb isnt 1) then "s" else "")) + " " + - date.toLocaleDateString("en-US", options) + - "
" - $.each data, (key, data) -> - $.each data, (index, data) -> - $("#calendar_onclick_placeholder").append -> - "Pushed " + ((if data is null then "no" else data)) + " commit" + - ((if (data isnt 1) then "s" else "")) + - " to " + - index + "
" - return - return - return diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 28de2707778..9e5ea6cfa45 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -25,12 +25,12 @@ class UsersController < ApplicationController @title = @user.name + # Get user repositories and collect timestamps for commits user_repositories = visible_projects.map(&:repository) - @timestamps = Gitlab::CommitsCalendar.create_timestamp(user_repositories, - @user, false) + calendar = Gitlab::CommitsCalendar.new(user_repositories, @user) + @timestamps = calendar.timestamps @starting_year = (Time.now - 1.year).strftime("%Y") @starting_month = Date.today.strftime("%m").to_i - @last_commit_date = Gitlab::CommitsCalendar.last_commit_date(@timestamps) respond_to do |format| format.html @@ -38,19 +38,6 @@ class UsersController < ApplicationController end end - def activities - user = User.find_by_username!(params[:username]) - # Projects user can view - visible_projects = ProjectsFinder.new.execute(current_user) - - user_repositories = visible_projects.map(&:repository) - user_activities = Gitlab::CommitsCalendar.create_timestamp(user_repositories, - user, true) - user_activities = Gitlab::CommitsCalendar.commit_activity_match( - user_activities, params[:date]) - render json: user_activities.to_json - end - def determine_layout if current_user 'navless' diff --git a/app/models/repository.rb b/app/models/repository.rb index e44ecca865c..f6400f7aff1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -139,39 +139,36 @@ class Repository def graph_log Rails.cache.fetch(cache_key(:graph_log)) do - - # handle empty repos that don't have a root_ref set yet - unless raw_repository.root_ref.present? - raw_repository.root_ref = 'refs/heads/master' - end - - commits = raw_repository.log(limit: 6000, skip_merges: true, - ref: raw_repository.root_ref) + commits = raw_repository.log(limit: 6000, + skip_merges: true, + ref: root_ref) commits.map do |rugged_commit| - commit = Gitlab::Git::Commit.new(rugged_commit) + { author_name: commit.author_name.force_encoding('UTF-8'), author_email: commit.author_email.force_encoding('UTF-8'), additions: commit.stats.additions, deletions: commit.stats.deletions, - date: commit.committed_date } end end end - def graph_logs_by_user_email(user) - graph_log.select { |u_email| u_email[:author_email] == user.email } + def timestamps_by_user_log(user) + args = %W(git log --author=#{user.email} --since=#{(Date.today - 1.year).to_s} --pretty=format:%cd --date=short) + dates = Gitlab::Popen.popen(args, path_to_repo).first.split("\n") + + if dates.present? + dates + else + [] + end end - def timestamps_by_user_from_graph_log(user) - graph_logs_by_user_email(user).map { |graph_log| graph_log[:date].to_time.to_i } - end - - def commits_log_of_user_by_date(user) - timestamps_by_user_from_graph_log(user). + def commits_per_day_for_user(user) + timestamps_by_user_log(user). group_by { |commit_date| commit_date }. inject({}) do |hash, (timestamp_date, commits)| hash[timestamp_date] = commits.count diff --git a/app/views/users/_calendar.html.haml b/app/views/users/_calendar.html.haml index 70d5cca854d..b16a7305a32 100644 --- a/app/views/users/_calendar.html.haml +++ b/app/views/users/_calendar.html.haml @@ -1,9 +1,7 @@ #cal-heatmap.calendar - :javascript + :javascript new calendar( #{@timestamps.to_json}, #{@starting_year}, - #{@starting_month}, - '#{user_activities_path}' + #{@starting_month} ); -= render "calendar_onclick" diff --git a/app/views/users/_calendar_onclick.html.haml b/app/views/users/_calendar_onclick.html.haml deleted file mode 100644 index 1514b56bb23..00000000000 --- a/app/views/users/_calendar_onclick.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -#calendar_commit_activity.calendar_commit_activity - %h4.activity_title Commit Activity: - - #loading_commits - %section.text-center - %h3 - %i.icon-spinner.icon-spin - - #calendar_onclick_placeholder.calendar_onclick_placeholder - %span.calendar_onclick_second.calendar_onclick_second - - if @timestamps.empty? - %span.calendar_activity_summary - %strong> #{@user.username} -   has no activity - - else - %span.calendar_activity_summary - %strong> #{@user.username} - 's last commit was on - %span.commit_date #{@last_commit_date} - - %hr.calendar_onclick_hr - -:javascript - $("#loading_commits").hide(); - diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 0d214d31607..c248a280475 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -18,8 +18,10 @@ %h4 Groups: = render 'groups', groups: @groups %hr + %h4 Calendar: - = render 'calendar' + %div= render 'calendar' + %hr %h4 User Activity: diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb index 93256187fd2..b6699c585f6 100644 --- a/lib/gitlab/commits_calendar.rb +++ b/lib/gitlab/commits_calendar.rb @@ -1,71 +1,25 @@ module Gitlab class CommitsCalendar - def self.create_timestamp(repositories, user, show_activity) - timestamps = {} - repositories.each do |raw_repository| - if raw_repository.exists? - commits_log = raw_repository.commits_log_of_user_by_date(user) + attr_reader :timestamps - populated_timestamps = - if show_activity - populate_timestamps_by_project( - commits_log, - timestamps, - raw_repository - ) - else - populate_timestamps(commits_log, timestamps) - end - timestamps.merge!(populated_timestamps) - end + def initialize(repositories, user) + @timestamps = {} + date_timestamps = [] + + repositories.select(&:exists?).reject(&:empty?).each do |raw_repository| + commits_log = raw_repository.commits_per_day_for_user(user) + date_timestamps << commits_log end - timestamps - end - def self.populate_timestamps(commits_log, timestamps) - commits_log.each do |timestamp_date, commits_count| - hash = { "#{timestamp_date}" => commits_count } - if timestamps.has_key?("#{timestamp_date}") - timestamps.merge!(hash) do |timestamp_date, commits_count, - new_commits_count| commits_count = commits_count.to_i + - new_commits_count - end - else - timestamps.merge!(hash) - end + date_timestamps = date_timestamps.inject do |collection, date| + collection.merge(date) { |k, old_v, new_v| old_v + new_v } end - timestamps - end - def self.populate_timestamps_by_project(commits_log, timestamps, - project) - commits_log.each do |timestamp_date, commits_count| - if timestamps.has_key?("#{timestamp_date}") - timestamps["#{timestamp_date}"]. - merge!(project.path_with_namespace => commits_count) - else - hash = { "#{timestamp_date}" => { project.path_with_namespace => - commits_count } } - timestamps.merge!(hash) - end + date_timestamps ||= [] + date_timestamps.each do |date, commits| + timestamp = Date.parse(date).to_time.to_i.to_s + @timestamps[timestamp] = commits end - timestamps - end - - def self.latest_commit_date(timestamps) - if timestamps.nil? || timestamps.empty? - DateTime.now.to_date - else - Time.at(timestamps.keys.first.to_i).to_date - end - end - - def self.last_commit_date(timestamps) - latest_commit_date(timestamps).to_formatted_s(:long).to_s - end - - def self.commit_activity_match(user_activities, date) - user_activities.select { |x| Time.at(x.to_i) == Time.parse(date) } end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index bfbe5254bbe..0c537a552c2 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' describe UsersController do let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") } - + before do sign_in(user) end - describe "GET #show" do + describe "GET #show" do render_views before do get :show, username: user.username From c9f18d4587f16eb16b8b902d69576520c08b7f5a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 01:03:20 -0800 Subject: [PATCH 76/80] Make sure we dont have exception on date parsing --- lib/gitlab/commits_calendar.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb index b6699c585f6..ccc80d080af 100644 --- a/lib/gitlab/commits_calendar.rb +++ b/lib/gitlab/commits_calendar.rb @@ -17,8 +17,8 @@ module Gitlab date_timestamps ||= [] date_timestamps.each do |date, commits| - timestamp = Date.parse(date).to_time.to_i.to_s - @timestamps[timestamp] = commits + timestamp = Date.parse(date).to_time.to_i.to_s rescue nil + @timestamps[timestamp] = commits if timestamp end end end From 1f0e16569f1924ed967bff9f4f78bbee874251db Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 01:20:17 -0800 Subject: [PATCH 77/80] Load contribution calendar via AJAX --- app/controllers/users_controller.rb | 31 ++++++++++++------- ..._calendar.html.haml => calendar.html.haml} | 1 + app/views/users/show.html.haml | 10 ++++-- config/routes.rb | 7 ++--- 4 files changed, 32 insertions(+), 17 deletions(-) rename app/views/users/{_calendar.html.haml => calendar.html.haml} (90%) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9e5ea6cfa45..8c96f67a2a4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,14 +1,7 @@ class UsersController < ApplicationController - skip_before_filter :authenticate_user!, only: [:show, :activities] layout :determine_layout def show - @user = User.find_by_username!(params[:username]) - - unless current_user || @user.public_profile? - return authenticate_user! - end - # Projects user can view visible_projects = ProjectsFinder.new.execute(current_user) authorized_projects_ids = visible_projects.pluck(:id) @@ -25,6 +18,15 @@ class UsersController < ApplicationController @title = @user.name + respond_to do |format| + format.html + format.atom { render layout: false } + end + end + + def calendar + visible_projects = ProjectsFinder.new.execute(current_user) + # Get user repositories and collect timestamps for commits user_repositories = visible_projects.map(&:repository) calendar = Gitlab::CommitsCalendar.new(user_repositories, @user) @@ -32,10 +34,7 @@ class UsersController < ApplicationController @starting_year = (Time.now - 1.year).strftime("%Y") @starting_month = Date.today.strftime("%m").to_i - respond_to do |format| - format.html - format.atom { render layout: false } - end + render 'calendar', layout: false end def determine_layout @@ -45,4 +44,14 @@ class UsersController < ApplicationController 'public_users' end end + + private + + def authenticate_user! + @user = User.find_by_username!(params[:username]) + + unless current_user || @user.public_profile? + return authenticate_user! + end + end end diff --git a/app/views/users/_calendar.html.haml b/app/views/users/calendar.html.haml similarity index 90% rename from app/views/users/_calendar.html.haml rename to app/views/users/calendar.html.haml index b16a7305a32..727faf23679 100644 --- a/app/views/users/_calendar.html.haml +++ b/app/views/users/calendar.html.haml @@ -1,3 +1,4 @@ +%h4 Calendar: #cal-heatmap.calendar :javascript new calendar( diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index c248a280475..445f43cd500 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -19,8 +19,9 @@ = render 'groups', groups: @groups %hr - %h4 Calendar: - %div= render 'calendar' + .user-calendar + %h4.center.light + %i.fa.fa-spinner.fa-spin %hr %h4 User Activity: @@ -36,3 +37,8 @@ = render 'profile', user: @user - if @projects.present? = render 'projects', projects: @projects + + +:coffeescript + $ -> + $(".user-calendar").load("#{user_calendar_path}") diff --git a/config/routes.rb b/config/routes.rb index 5d61de29b9a..e122777314a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -157,10 +157,9 @@ Gitlab::Application.routes.draw do end end - # route for commits used by the cal-heatmap - get 'u/:username/activities' => 'users#activities', as: :user_activities, - constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ }, - via: :get + get 'u/:username/calendar' => 'users#calendar', as: :user_calendar, + constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } + get '/u/:username' => 'users#show', as: :user, constraints: { username: /(?:[^.]|\.(?!atom$))+/, format: /atom/ } From 35bf471a13abe0ec68ca8ceb19f896be5ce63c46 Mon Sep 17 00:00:00 2001 From: Vincent Robert Date: Thu, 29 Jan 2015 16:34:01 +0100 Subject: [PATCH 78/80] Bump Gitlab for Docker to 7.7.1 --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 445fdd6d063..70d6c721f1c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update -q \ # If the Omnibus package version below is outdated please contribute a merge request to update it. # If you run GitLab Enterprise Edition point it to a location where you have downloaded it. RUN TMP_FILE=$(mktemp); \ - wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.6.2-omnibus.5.3.0.ci.1-1_amd64.deb \ + wget -q -O $TMP_FILE https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.7.1-omnibus.5.4.1.ci-1_amd64.deb \ && dpkg -i $TMP_FILE \ && rm -f $TMP_FILE From 08582f153249d91d361977d7968126a420739a8b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 08:55:57 -0800 Subject: [PATCH 79/80] Improve user calendar authentification and tests --- app/controllers/users_controller.rb | 4 +++- spec/controllers/users_controller_spec.rb | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8c96f67a2a4..ff5e31067fb 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,6 @@ class UsersController < ApplicationController + skip_before_filter :authenticate_user! + before_filter :set_user layout :determine_layout def show @@ -47,7 +49,7 @@ class UsersController < ApplicationController private - def authenticate_user! + def set_user @user = User.find_by_username!(params[:username]) unless current_user || @user.public_profile? diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 0c537a552c2..44225c054f2 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -9,18 +9,18 @@ describe UsersController do describe "GET #show" do render_views - before do - get :show, username: user.username - end it "renders the show template" do + get :show, username: user.username expect(response.status).to eq(200) expect(response).to render_template("show") end + end + describe "GET #calendar" do it "renders calendar" do - controller.prepend_view_path 'app/views/users' - expect(response).to render_template("_calendar") + get :calendar, username: user.username + expect(response).to render_template("calendar") end end end From ca701a964971a3291270e60669757c9853e3cf66 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 13:28:41 -0800 Subject: [PATCH 80/80] Improvements to LDAP::User model * method #changed? also tracks changes of identites (fixes issue with email mapping) * find ldap identity before initialize one --- lib/gitlab/ldap/user.rb | 8 ++++++-- spec/lib/gitlab/ldap/user_spec.rb | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 3ef494ba137..cfa8692659d 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -40,12 +40,16 @@ module Gitlab def update_user_attributes gl_user.email = auth_hash.email - gl_user.identities.build(provider: auth_hash.provider, extern_uid: auth_hash.uid) + + # Build new identity only if we dont have have same one + gl_user.identities.find_or_initialize_by(provider: auth_hash.provider, + extern_uid: auth_hash.uid) + gl_user end def changed? - gl_user.changed? + gl_user.changed? || gl_user.identities.any?(&:changed?) end def needs_blocking? diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index f73884e6441..63ffc21ba3b 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -13,6 +13,23 @@ describe Gitlab::LDAP::User do double(uid: 'my-uid', provider: 'ldapmain', info: double(info)) end + describe :changed? do + it "marks existing ldap user as changed" do + existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_true + end + + it "marks existing non-ldap user if the email matches as changed" do + existing_user = create(:user, email: 'john@example.com') + expect(gl_user.changed?).to be_true + end + + it "dont marks existing ldap user as changed" do + existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_false + end + end + describe :find_or_create do it "finds the user if already existing" do existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')