From bb50b7fcd0161a7b9f0f87cb395e355a87a9dd17 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Mon, 6 Jul 2015 18:43:17 +0200 Subject: Allow custom backup archive permissions This change helps system administrators who want to replicate GitLab backup files without needing root permissions. --- CHANGELOG | 1 + config/gitlab.yml.example | 1 + config/initializers/1_settings.rb | 1 + doc/raketasks/backup_restore.md | 17 +++++++++++++++++ lib/backup/manager.rb | 6 +++--- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d538bb42992..1c2155c0f9c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,6 +37,7 @@ v 7.13.0 (unreleased) - Correctly show anonymous authorized applications under Profile > Applications. - Query Optimization in MySQL. - Allow users to be blocked and unblocked via the API + - Allow custom backup archive permissions v 7.12.2 - Correctly show anonymous authorized applications under Profile > Applications. diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index c32ac2042d0..542106e86dd 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -247,6 +247,7 @@ production: &base ## Backup settings backup: path: "tmp/backups" # Relative paths are relative to Rails.root (default: tmp/backups/) + # archive_permissions: 0640 # Permissions for the resulting backup.tar file (default: 0600) # keep_time: 604800 # default: 0 (forever) (in seconds) # upload: # # Fog storage connection settings, see http://fog.io/storage/ . diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index 7b5d488f59e..bd76c918485 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -170,6 +170,7 @@ Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_s Settings['backup'] ||= Settingslogic.new({}) Settings.backup['keep_time'] ||= 0 Settings.backup['path'] = File.expand_path(Settings.backup['path'] || "tmp/backups/", Rails.root) +Settings.backup['archive_permissions'] ||= 0600 Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil }) # Convert upload connection settings to use symbol keys, to make Fog happy if Settings.backup['upload']['connection'] diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 39a13b14fba..4a2e2df357a 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -141,6 +141,23 @@ with the name of your bucket: } ``` +## Backup archive permissions + +The backup archives created by GitLab (123456_gitlab_backup.tar) will have owner/group git:git and 0600 permissions by default. +This is meant to avoid other system users reading GitLab's data. +If you need the backup archives to have different permissions you can use the 'archive_permissions' setting. + +``` +# In /etc/gitlab/gitlab.rb, for omnibus packages +gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable +``` + +``` +# In gitlab.yml, for installations from source: + backup: + archive_permissions: 0644 # Makes the backup archives world-readable +``` + ## Storing configuration files Please be informed that a backup does not store your configuration files. diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 6fa2079d1a8..5103b265ed4 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -20,14 +20,14 @@ module Backup # create archive $progress.print "Creating backup archive: #{tar_file} ... " - orig_umask = File.umask(0077) - if Kernel.system('tar', '-cf', tar_file, *backup_contents) + # Set file permissions on open to prevent chmod races. + tar_system_options = {out: [tar_file, 'w', Gitlab.config.backup.archive_permissions]} + if Kernel.system('tar', '-cf', '-', *backup_contents, tar_system_options) $progress.puts "done".green else puts "creating archive #{tar_file} failed".red abort 'Backup failed' end - File.umask(orig_umask) upload(tar_file) end -- cgit v1.2.1 From 0194dd4182778b6bbf6b02f5d57e995ecbb43066 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 7 Jul 2015 19:03:29 +0200 Subject: Add tests for custom backup archive file permissions --- spec/tasks/gitlab/backup_rake_spec.rb | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index cdcfeba8d1f..e1f4a887dcc 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -60,7 +60,7 @@ describe 'gitlab:app namespace rake task' do Dir.glob(File.join(Gitlab.config.backup.path, '*_gitlab_backup.tar')) end - before :all do + def create_backup # Record the existing backup tars so we don't touch them existing_tars = tars_glob @@ -73,13 +73,36 @@ describe 'gitlab:app namespace rake task' do @backup_tar = (tars_glob - existing_tars).first end + before :all do + create_backup + end + after :all do FileUtils.rm(@backup_tar) end - it 'should set correct permissions on the tar file' do - expect(File.exist?(@backup_tar)).to be_truthy - expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + context 'archive file permissions' do + it 'should set correct permissions on the tar file' do + expect(File.exist?(@backup_tar)).to be_truthy + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100600') + end + + context 'with custom archive_permissions' do + before do + allow(Gitlab.config.backup).to receive(:archive_permissions).and_return(0651) + # We created a backup in a before(:all) so it got the default permissions. + # We now need to do some work to create a _new_ backup file using our stub. + FileUtils.rm(@backup_tar) + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable + create_backup + end + + it 'uses the custom permissions' do + expect(File::Stat.new(@backup_tar).mode.to_s(8)).to eq('100651') + end + end end it 'should set correct permissions on the tar contents' do -- cgit v1.2.1 From 64f60340918d3f4aa3c1d33b89d8dc90bcd96de7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 8 Jul 2015 20:07:56 +0200 Subject: More hacks to get the specs working again --- spec/tasks/gitlab/backup_rake_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index e1f4a887dcc..7f0396795b8 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -97,6 +97,9 @@ describe 'gitlab:app namespace rake task' do Rake::Task["gitlab:backup:repo:create"].reenable Rake::Task["gitlab:backup:uploads:create"].reenable create_backup + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable end it 'uses the custom permissions' do -- cgit v1.2.1 From 4612599e5eb94e09f539a3fbbc3a1eaeaa96a3c7 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 9 Jul 2015 12:11:35 +0200 Subject: Remove rake task re-enabling into a method --- spec/tasks/gitlab/backup_rake_spec.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 7f0396795b8..ec06670ba19 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -73,6 +73,12 @@ describe 'gitlab:app namespace rake task' do @backup_tar = (tars_glob - existing_tars).first end + def reenable_backup_sub_tasks + Rake::Task["gitlab:backup:db:create"].reenable + Rake::Task["gitlab:backup:repo:create"].reenable + Rake::Task["gitlab:backup:uploads:create"].reenable + end + before :all do create_backup end @@ -93,13 +99,9 @@ describe 'gitlab:app namespace rake task' do # We created a backup in a before(:all) so it got the default permissions. # We now need to do some work to create a _new_ backup file using our stub. FileUtils.rm(@backup_tar) - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks create_backup - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks end it 'uses the custom permissions' do -- cgit v1.2.1 From 810ffab4b135024a76b2b68f0edbbbf76036d027 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 10 Jul 2015 14:44:07 +0200 Subject: Use a loop when enabling subtasks --- spec/tasks/gitlab/backup_rake_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index ec06670ba19..476e22b8802 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -74,9 +74,9 @@ describe 'gitlab:app namespace rake task' do end def reenable_backup_sub_tasks - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + %w{db repo uploads}.each do |subtask| + Rake::Task["gitlab:backup:#{subtask}:create"].reenable + end end before :all do -- cgit v1.2.1 From 277f311f20739bd97f4059b51dfa1dbc38aa38e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 15:27:14 +0200 Subject: Fetch reference from fork repo when create merge request --- app/models/repository.rb | 5 +++++ app/services/merge_requests/create_service.rb | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/app/models/repository.rb b/app/models/repository.rb index 6262b5c4c92..70d416159a7 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -465,6 +465,11 @@ class Repository ) end + def fetch_ref(source_path, source_ref, target_ref) + args = %W(git fetch #{source_path} #{source_ref}:#{target_ref}) + Gitlab::Popen.popen(args, path_to_repo) + end + private def cache diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index f431c5d5534..8389f29a53a 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -9,6 +9,15 @@ module MergeRequests merge_request.author = current_user if merge_request.save + # Fetch fork branch into hidden ref of target repository + if merge_request.for_fork? + merge_request.target_project.repository.fetch_ref( + merge_request.source_project.repository.path_to_repo, + "refs/heads/#{merge_request.source_branch}", + "refs/merge-requests/#{merge_request.id}/head" + ) + end + merge_request.update_attributes(label_ids: label_params) event_service.open_mr(merge_request, current_user) notification_service.new_merge_request(merge_request, current_user) -- cgit v1.2.1 From a87989fb7d0c4f05658ba29dec48ecefedf32334 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 15:45:57 +0200 Subject: Remove satellites --- Gemfile.lock | 3 - .../projects/merge_requests_controller.rb | 2 - app/models/merge_request.rb | 6 +- app/models/namespace.rb | 5 +- app/models/project.rb | 14 +- app/services/compare_service.rb | 11 +- app/services/git_push_service.rb | 10 +- app/services/merge_requests/auto_merge_service.rb | 5 +- app/services/merge_requests/build_service.rb | 4 - app/services/projects/destroy_service.rb | 1 - app/services/projects/transfer_service.rb | 6 - .../projects/merge_requests/_new_compare.html.haml | 2 +- .../projects/merge_requests/widget/_open.html.haml | 2 - .../widget/open/_no_satellite.html.haml | 3 - app/workers/repository_import_worker.rb | 1 - doc/development/architecture.md | 2 +- doc/install/installation.md | 4 - doc/install/structure.md | 4 +- doc/logs/logs.md | 12 +- doc/raketasks/maintenance.md | 13 -- features/steps/project/forked_merge_requests.rb | 1 - features/steps/project/merge_requests.rb | 5 - lib/gitlab.rb | 5 - lib/gitlab/backend/shell.rb | 14 -- lib/gitlab/satellite/action.rb | 58 -------- lib/gitlab/satellite/compare_action.rb | 44 ------ lib/gitlab/satellite/logger.rb | 13 -- lib/gitlab/satellite/merge_action.rb | 146 -------------------- lib/gitlab/satellite/satellite.rb | 148 --------------------- lib/tasks/gitlab/check.rake | 56 -------- lib/tasks/gitlab/enable_automerge.rake | 39 ------ spec/lib/gitlab/satellite/action_spec.rb | 116 ---------------- spec/lib/gitlab/satellite/merge_action_spec.rb | 104 --------------- spec/models/project_spec.rb | 1 - spec/requests/api/files_spec.rb | 2 +- 35 files changed, 18 insertions(+), 844 deletions(-) delete mode 100644 app/views/projects/merge_requests/widget/open/_no_satellite.html.haml delete mode 100644 lib/gitlab.rb delete mode 100644 lib/gitlab/satellite/action.rb delete mode 100644 lib/gitlab/satellite/compare_action.rb delete mode 100644 lib/gitlab/satellite/logger.rb delete mode 100644 lib/gitlab/satellite/merge_action.rb delete mode 100644 lib/gitlab/satellite/satellite.rb delete mode 100644 lib/tasks/gitlab/enable_automerge.rake delete mode 100644 spec/lib/gitlab/satellite/action_spec.rb delete mode 100644 spec/lib/gitlab/satellite/merge_action_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index 6e571072a4c..12ba2fa295a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -875,6 +875,3 @@ DEPENDENCIES virtus webmock (~> 1.21.0) wikicloth (= 0.8.1) - -BUNDLED WITH - 1.10.5 diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d1265198318..0ef9e99123d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -1,5 +1,3 @@ -require 'gitlab/satellite/satellite' - class Projects::MergeRequestsController < Projects::ApplicationController before_action :module_enabled before_action :merge_request, only: [ diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 53b3fc10ccb..aa2137e7469 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -207,7 +207,7 @@ class MergeRequest < ActiveRecord::Base def check_if_can_be_merged can_be_merged = if for_fork? - Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged? + raise 'Implement me' else project.repository.can_be_merged?(source_branch, target_branch) end @@ -274,14 +274,14 @@ class MergeRequest < ActiveRecord::Base # # see "git diff" def to_diff(current_user) - Gitlab::Satellite::MergeAction.new(current_user, self).diff_in_satellite + raise 'Implement me' end # Returns the commit as a series of email patches. # # see "git format-patch" def to_patch(current_user) - Gitlab::Satellite::MergeAction.new(current_user, self).format_patch + raise 'Implement me' end def hook_attrs diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 03d2ab165ea..815672a1bf7 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -115,12 +115,11 @@ class Namespace < ActiveRecord::Base def move_dir if gitlab_shell.mv_namespace(path_was, path) - # If repositories moved successfully we need to remove old satellites - # and send update instructions to users. + # If repositories moved successfully we need to + # send update instructions to users. # However we cannot allow rollback since we moved namespace dir # So we basically we mute exceptions in next actions begin - gitlab_shell.rm_satellites(path_was) send_update_instructions rescue # Returning false does not rollback after_* transaction but gives diff --git a/app/models/project.rb b/app/models/project.rb index b161cbe86b9..8481a149e21 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -520,14 +520,6 @@ class Project < ActiveRecord::Base !repository.exists? || repository.empty? end - def ensure_satellite_exists - self.satellite.create unless self.satellite.exists? - end - - def satellite - @satellite ||= Gitlab::Satellite::Satellite.new(self) - end - def repo repository.raw end @@ -597,14 +589,11 @@ class Project < ActiveRecord::Base new_path_with_namespace = File.join(namespace_dir, path) if gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace) - # If repository moved successfully we need to remove old satellite - # and send update instructions to users. + # If repository moved successfully we need to send update instructions to users. # However we cannot allow rollback since we moved repository # So we basically we mute exceptions in next actions begin gitlab_shell.mv_repository("#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki") - gitlab_shell.rm_satellites(old_path_with_namespace) - ensure_satellite_exists send_move_instructions reset_events_cache rescue @@ -698,7 +687,6 @@ class Project < ActiveRecord::Base def create_repository if forked? if gitlab_shell.fork_repository(forked_from_project.path_with_namespace, self.namespace.path) - ensure_satellite_exists true else errors.add(:base, 'Failed to fork repository') diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb index 6aa9df4b194..48ad7fab4e6 100644 --- a/app/services/compare_service.rb +++ b/app/services/compare_service.rb @@ -3,9 +3,6 @@ class CompareService def execute(current_user, source_project, source_branch, target_project, target_branch) # Try to compare branches to get commits list and diffs - # - # Note: Use satellite only when need to compare between two repos - # because satellites are slower than operations on bare repo if target_project == source_project Gitlab::CompareResult.new( Gitlab::Git::Compare.new( @@ -15,13 +12,7 @@ class CompareService ) ) else - Gitlab::Satellite::CompareAction.new( - current_user, - target_project, - target_branch, - source_project, - source_branch - ).result + raise 'Implement me' end end end diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index 6135ae65007..3a5a52e6f55 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -10,16 +10,14 @@ class GitPushService # # Next, this method: # 1. Creates the push event - # 2. Ensures that the project satellite exists - # 3. Updates merge requests - # 4. Recognizes cross-references from commit messages - # 5. Executes the project's web hooks - # 6. Executes the project's services + # 2. Updates merge requests + # 3. Recognizes cross-references from commit messages + # 4. Executes the project's web hooks + # 5. Executes the project's services # def execute(project, user, oldrev, newrev, ref) @project, @user = project, user - project.ensure_satellite_exists project.repository.expire_cache project.update_repository_size diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb index df793fc997d..1c41148d41d 100644 --- a/app/services/merge_requests/auto_merge_service.rb +++ b/app/services/merge_requests/auto_merge_service.rb @@ -1,7 +1,7 @@ module MergeRequests # AutoMergeService class # - # Do git merge in satellite and in case of success + # Do git merge and in case of success # mark merge request as merged and execute all hooks and notifications # Called when you do merge via GitLab UI class AutoMergeService < BaseMergeService @@ -32,9 +32,8 @@ module MergeRequests def merge! if merge_request.for_fork? - Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message) + raise 'Implement me' else - # Merge local branches using rugged instead of satellites if sha = commit after_commit(sha, merge_request.target_branch) end diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 956480938c3..5ef1cd2caa0 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -40,7 +40,6 @@ module MergeRequests merge_request.compare_diffs = diffs elsif diffs == false - # satellite timeout return false merge_request.can_be_created = false merge_request.compare_failed = true end @@ -59,9 +58,6 @@ module MergeRequests end merge_request - - rescue Gitlab::Satellite::BranchesWithoutParent - return build_failed(merge_request, "Selected branches have no common commit so they cannot be merged.") end def build_failed(merge_request, message) diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 403f419ec50..28872c89259 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -27,7 +27,6 @@ module Projects end end - project.satellite.destroy log_info("Project \"#{project.name}\" was removed") system_hook_service.execute_hooks_for(project, :destroy) true diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index f43c0ef70e9..550ed6897dd 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -33,9 +33,6 @@ module Projects raise TransferError.new("Project with same path in target namespace already exists") end - # Remove old satellite - project.satellite.destroy - # Apply new namespace id project.namespace = new_namespace project.save! @@ -51,9 +48,6 @@ module Projects # Move wiki repo also if present gitlab_shell.mv_repository("#{old_path}.wiki", "#{new_path}.wiki") - # Create a new satellite (reload project from DB) - Project.find(project.id).ensure_satellite_exists - # clear project cached events project.reset_events_cache diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml index ff9c0cdb283..7709330611a 100644 --- a/app/views/projects/merge_requests/_new_compare.html.haml +++ b/app/views/projects/merge_requests/_new_compare.html.haml @@ -35,7 +35,7 @@ - if @merge_request.compare_failed .alert.alert-danger %h4 Compare failed - %p We can't compare selected branches. It may be because of huge diff or satellite timeout. Please try again or select different branches. + %p We can't compare selected branches. It may be because of huge diff. Please try again or select different branches. - else .light-well .center diff --git a/app/views/projects/merge_requests/widget/_open.html.haml b/app/views/projects/merge_requests/widget/_open.html.haml index bb794912f8f..f420cdcab49 100644 --- a/app/views/projects/merge_requests/widget/_open.html.haml +++ b/app/views/projects/merge_requests/widget/_open.html.haml @@ -3,8 +3,6 @@ .mr-widget-body - if @project.archived? = render 'projects/merge_requests/widget/open/archived' - - elsif !@project.satellite.exists? - = render 'projects/merge_requests/widget/open/no_satellite' - elsif @merge_request.commits.blank? = render 'projects/merge_requests/widget/open/nothing' - elsif @merge_request.branch_missing? diff --git a/app/views/projects/merge_requests/widget/open/_no_satellite.html.haml b/app/views/projects/merge_requests/widget/open/_no_satellite.html.haml deleted file mode 100644 index 3718cfd8333..00000000000 --- a/app/views/projects/merge_requests/widget/open/_no_satellite.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%p - %span - %strong This repository does not have a satellite. Please ask an administrator to fix this issue! diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index e6a50afedb1..4e14e4883bb 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -27,7 +27,6 @@ class RepositoryImportWorker project.import_finish project.save - project.satellite.create unless project.satellite.exists? project.update_repository_size Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket' end diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 541af487bb1..99f56016120 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -58,7 +58,7 @@ A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a w The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. `/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc. -The satellite repository is used by the web interface for editing repositories and the wiki which is also a git repository. When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. +[DEPRECATED] The satellite repository is used by the web interface for editing repositories and the wiki which is also a git repository. When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access. diff --git a/doc/install/installation.md b/doc/install/installation.md index 8b918cba133..5bd68ab6a35 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -216,10 +216,6 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da sudo chmod -R u+rwX,go-w log/ sudo chmod -R u+rwX tmp/ - # Create directory for satellites - sudo -u git -H mkdir /home/git/gitlab-satellites - sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites - # Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories sudo chmod -R u+rwX tmp/pids/ sudo chmod -R u+rwX tmp/sockets/ diff --git a/doc/install/structure.md b/doc/install/structure.md index 5c03f073c18..d58b0040eef 100644 --- a/doc/install/structure.md +++ b/doc/install/structure.md @@ -6,16 +6,14 @@ This is the directory structure you will end up with following the instructions | |-- git | |-- .ssh | |-- gitlab - | |-- gitlab-satellites | |-- gitlab-shell | |-- repositories * `/home/git/.ssh` - contains openssh settings. Specifically the `authorized_keys` file managed by gitlab-shell. * `/home/git/gitlab` - GitLab core software. -* `/home/git/gitlab-satellites` - checked out repositories for merge requests and file editing from web UI. This can be treated as a temporary files directory. * `/home/git/gitlab-shell` - Core add-on component of GitLab. Maintains SSH cloning and other functionality. * `/home/git/repositories` - bare repositories for all projects organized by namespace. This is where the git repositories which are pushed/pulled are maintained for all projects. **This area is critical data for projects. [Keep a backup](../raketasks/backup_restore.md)** -*Note: the default locations for gitlab-satellites and repositories can be configured in `config/gitlab.yml` of GitLab and `config.yml` of gitlab-shell.* +*Note: the default locations for repositories can be configured in `config/gitlab.yml` of GitLab and `config.yml` of gitlab-shell.* To see a more in-depth overview see the [GitLab architecture doc](../development/architecture.md). diff --git a/doc/logs/logs.md b/doc/logs/logs.md index 83c32b09253..27937e51764 100644 --- a/doc/logs/logs.md +++ b/doc/logs/logs.md @@ -51,16 +51,6 @@ December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/ error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git' ``` -#### satellites.log -This file lives in `/var/log/gitlab/gitlab-rails/satellites.log` for omnibus package or in `/home/git/gitlab/log/satellites.log` for installations from the source. - -In some cases GitLab should perform write actions to git repository, for example when it is needed to merge the merge request or edit a file with online editor. If something went wrong you can look into this file to find out what exactly happened. -``` -October 07, 2014 11:36: Failed to create satellite for Chesley Weimann III / project1817 -October 07, 2014 11:36: PID: 1872: git clone /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git /Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/gitlab-satellites/conrad6841/gitlabhq -October 07, 2014 11:36: PID: 1872: -> fatal: repository '/Users/vsizov/gitlab-development-kit/gitlab/tmp/tests/repositories/conrad6841/gitlabhq.git' does not exist -``` - #### sidekiq.log This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for omnibus package or in `/home/git/gitlab/log/sidekiq.log` for installations from the source. @@ -99,4 +89,4 @@ W, [2015-02-13T07:16:01.313000 #9094] WARN -- : Unicorn::WorkerKiller send SIGQ I, [2015-02-13T07:16:01.530733 #9047] INFO -- : reaped # worker=1 I, [2015-02-13T07:16:01.534501 #13379] INFO -- : worker=1 spawned pid=13379 I, [2015-02-13T07:16:01.534848 #13379] INFO -- : worker=1 ready -``` \ No newline at end of file +``` diff --git a/doc/raketasks/maintenance.md b/doc/raketasks/maintenance.md index 69171cd1765..d9dce2af480 100644 --- a/doc/raketasks/maintenance.md +++ b/doc/raketasks/maintenance.md @@ -105,24 +105,11 @@ Log directory writable? ... yes Tmp directory writable? ... yes Init script exists? ... yes Init script up-to-date? ... yes -Projects have satellites? ... yes Redis version >= 2.0.0? ... yes Checking GitLab ... Finished ``` -## (Re-)Create satellite repositories - -This will create satellite repositories for all your projects. - -If necessary, remove the `repo_satellites` directory and rerun the commands below. - -``` -sudo -u git -H mkdir -p /home/git/gitlab-satellites -sudo -u git -H bundle exec rake gitlab:satellites:create RAILS_ENV=production -sudo chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites -``` - ## Rebuild authorized_keys file In some case it is necessary to rebuild the `authorized_keys` file. diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb index 58c16d59d05..3e6beb20e78 100644 --- a/features/steps/project/forked_merge_requests.rb +++ b/features/steps/project/forked_merge_requests.rb @@ -9,7 +9,6 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps @project = Project.find_by(name: "Shop") @project ||= create(:project, name: "Shop") @project.team << [@user, :reporter] - @project.ensure_satellite_exists end step 'I have a project forked off of "Shop" called "Forked Shop"' do diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index a1a26abd8ca..f2198f58c13 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -198,15 +198,10 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'merge request "Bug NS-05" is mergeable' do - merge_request.project.satellite.create merge_request.mark_as_mergeable end step 'I accept this merge request' do - Gitlab::Satellite::MergeAction.any_instance.stub( - merge!: true, - ) - page.within '.mr-state-widget' do click_button "Accept Merge Request" end diff --git a/lib/gitlab.rb b/lib/gitlab.rb deleted file mode 100644 index 5fc1862c3e9..00000000000 --- a/lib/gitlab.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'gitlab/git' - -module Gitlab - autoload :Satellite, 'gitlab/satellite/satellite' -end diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb index 172d4902add..14ee4701e7b 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/backend/shell.rb @@ -217,20 +217,6 @@ module Gitlab FileUtils.mv(full_path(old_name), full_path(new_name)) end - # Remove GitLab Satellites for provided path (namespace or repo dir) - # - # Ex. - # rm_satellites("gitlab") - # - # rm_satellites("gitlab/gitlab-ci.git") - # - def rm_satellites(path) - raise ArgumentError.new("Path can't be blank") if path.blank? - - satellites_path = File.join(Gitlab.config.satellites.path, path) - FileUtils.rm_r(satellites_path, force: true) - end - def url_to_repo(path) Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git" end diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb deleted file mode 100644 index 489070f1a3f..00000000000 --- a/lib/gitlab/satellite/action.rb +++ /dev/null @@ -1,58 +0,0 @@ -module Gitlab - module Satellite - class Action - DEFAULT_OPTIONS = { git_timeout: Gitlab.config.satellites.timeout.seconds } - - attr_accessor :options, :project, :user - - def initialize(user, project, options = {}) - @options = DEFAULT_OPTIONS.merge(options) - @project = project - @user = user - end - - protected - - # * Sets a 30s timeout for Git - # * Locks the satellite repo - # * Yields the prepared satellite repo - def in_locked_and_timed_satellite - Gitlab::ShellEnv.set_env(user) - - Grit::Git.with_timeout(options[:git_timeout]) do - project.satellite.lock do - return yield project.satellite.repo - end - end - rescue Errno::ENOMEM => ex - return handle_exception(ex) - rescue Grit::Git::GitTimeout => ex - return handle_exception(ex) - ensure - Gitlab::ShellEnv.reset_env - end - - # * Recreates the satellite - # * Sets up Git variables for the user - # - # Note: use this within #in_locked_and_timed_satellite - def prepare_satellite!(repo) - project.satellite.clear_and_update! - - if user - repo.config['user.name'] = user.name - repo.config['user.email'] = user.email - end - end - - def default_options(options = {}) - { raise: true, timeout: true }.merge(options) - end - - def handle_exception(exception) - Gitlab::GitLogger.error(exception.message) - false - end - end - end -end diff --git a/lib/gitlab/satellite/compare_action.rb b/lib/gitlab/satellite/compare_action.rb deleted file mode 100644 index 46c98a8f4ca..00000000000 --- a/lib/gitlab/satellite/compare_action.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Gitlab - module Satellite - class BranchesWithoutParent < StandardError; end - - class CompareAction < Action - def initialize(user, target_project, target_branch, source_project, source_branch) - super user, target_project - - @target_project, @target_branch = target_project, target_branch - @source_project, @source_branch = source_project, source_branch - end - - # Compare 2 repositories and return Gitlab::CompareResult object - def result - in_locked_and_timed_satellite do |target_repo| - prepare_satellite!(target_repo) - update_satellite_source_and_target!(target_repo) - - Gitlab::CompareResult.new(compare(target_repo)) - end - rescue Grit::Git::CommandFailed => ex - raise BranchesWithoutParent - end - - private - - # Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for diffs - def update_satellite_source_and_target!(target_repo) - target_repo.remote_add('source', @source_project.repository.path_to_repo) - target_repo.remote_fetch('source') - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - def compare(repo) - @compare ||= Gitlab::Git::Compare.new( - Gitlab::Git::Repository.new(repo.path), - "origin/#{@target_branch}", - "source/#{@source_branch}" - ) - end - end - end -end diff --git a/lib/gitlab/satellite/logger.rb b/lib/gitlab/satellite/logger.rb deleted file mode 100644 index 6f3f8255aca..00000000000 --- a/lib/gitlab/satellite/logger.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Gitlab - module Satellite - class Logger < Gitlab::Logger - def self.file_name - 'satellites.log' - end - - def format_message(severity, timestamp, progname, msg) - "#{timestamp.to_s(:long)}: #{msg}\n" - end - end - end -end diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb deleted file mode 100644 index 1f2e5f82dd5..00000000000 --- a/lib/gitlab/satellite/merge_action.rb +++ /dev/null @@ -1,146 +0,0 @@ -module Gitlab - module Satellite - # GitLab server-side merge - class MergeAction < Action - attr_accessor :merge_request - - def initialize(user, merge_request) - super user, merge_request.target_project - @merge_request = merge_request - end - - # Checks if a merge request can be executed without user interaction - def can_be_merged? - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - merge_in_satellite!(merge_repo) - end - end - - # Merges the source branch into the target branch in the satellite and - # pushes it back to the repository. - # It also removes the source branch if requested in the merge request (and this is permitted by the merge request). - # - # Returns false if the merge produced conflicts - # Returns false if pushing from the satellite to the repository failed or was rejected - # Returns true otherwise - def merge!(merge_commit_message = nil) - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - if merge_in_satellite!(merge_repo, merge_commit_message) - # push merge back to bare repo - # will raise CommandFailed when push fails - merge_repo.git.push(default_options, :origin, merge_request.target_branch) - - # remove source branch - if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch) && !merge_request.for_fork? - # will raise CommandFailed when push fails - merge_repo.git.push(default_options, :origin, ":#{merge_request.source_branch}") - end - # merge, push and branch removal successful - true - end - end - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - def diff_in_satellite - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - update_satellite_source_and_target!(merge_repo) - - # Only show what is new in the source branch compared to the target branch, not the other way around. - # The line below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" - common_commit = merge_repo.git.native(:merge_base, default_options, ["origin/#{merge_request.target_branch}", "source/#{merge_request.source_branch}"]).strip - merge_repo.git.native(:diff, default_options, common_commit, "source/#{merge_request.source_branch}") - end - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - def diffs_between_satellite - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - update_satellite_source_and_target!(merge_repo) - if merge_request.for_fork? - repository = Gitlab::Git::Repository.new(merge_repo.path) - diffs = Gitlab::Git::Diff.between( - repository, - "source/#{merge_request.source_branch}", - "origin/#{merge_request.target_branch}" - ) - else - raise "Attempt to determine diffs between for a non forked merge request in satellite MergeRequest.id:[#{merge_request.id}]" - end - - return diffs - end - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - # Get commit as an email patch - def format_patch - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - update_satellite_source_and_target!(merge_repo) - patch = merge_repo.git.format_patch(default_options({ stdout: true }), "origin/#{merge_request.target_branch}..source/#{merge_request.source_branch}") - end - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - # Retrieve an array of commits between the source and the target - def commits_between - in_locked_and_timed_satellite do |merge_repo| - prepare_satellite!(merge_repo) - update_satellite_source_and_target!(merge_repo) - if merge_request.for_fork? - repository = Gitlab::Git::Repository.new(merge_repo.path) - commits = Gitlab::Git::Commit.between( - repository, - "origin/#{merge_request.target_branch}", - "source/#{merge_request.source_branch}" - ) - else - raise "Attempt to determine commits between for a non forked merge request in satellite MergeRequest.id:[#{merge_request.id}]" - end - - return commits - end - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - private - # Merges the source_branch into the target_branch in the satellite. - # - # Note: it will clear out the satellite before doing anything - # - # Returns false if the merge produced conflicts - # Returns true otherwise - def merge_in_satellite!(repo, message = nil) - update_satellite_source_and_target!(repo) - - message ||= "Merge branch '#{merge_request.source_branch}' into '#{merge_request.target_branch}'" - - # merge the source branch into the satellite - # will raise CommandFailed when merge fails - repo.git.merge(default_options({ no_ff: true }), "-m#{message}", "source/#{merge_request.source_branch}") - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - - # Assumes a satellite exists that is a fresh clone of the projects repo, prepares satellite for merges, diffs etc - def update_satellite_source_and_target!(repo) - repo.remote_add('source', merge_request.source_project.repository.path_to_repo) - repo.remote_fetch('source') - repo.git.checkout(default_options({ b: true }), merge_request.target_branch, "origin/#{merge_request.target_branch}") - rescue Grit::Git::CommandFailed => ex - handle_exception(ex) - end - end - end -end diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb deleted file mode 100644 index 398643d68de..00000000000 --- a/lib/gitlab/satellite/satellite.rb +++ /dev/null @@ -1,148 +0,0 @@ -module Gitlab - module Satellite - autoload :DeleteFileAction, 'gitlab/satellite/files/delete_file_action' - autoload :EditFileAction, 'gitlab/satellite/files/edit_file_action' - autoload :FileAction, 'gitlab/satellite/files/file_action' - autoload :NewFileAction, 'gitlab/satellite/files/new_file_action' - - class CheckoutFailed < StandardError; end - class CommitFailed < StandardError; end - class PushFailed < StandardError; end - - class Satellite - include Gitlab::Popen - - PARKING_BRANCH = "__parking_branch" - - attr_accessor :project - - def initialize(project) - @project = project - end - - def log(message) - Gitlab::Satellite::Logger.error(message) - end - - def clear_and_update! - project.ensure_satellite_exists - - @repo = nil - clear_working_dir! - delete_heads! - remove_remotes! - update_from_source! - end - - def create - output, status = popen(%W(git clone -- #{project.repository.path_to_repo} #{path}), - Gitlab.config.satellites.path) - - log("PID: #{project.id}: git clone #{project.repository.path_to_repo} #{path}") - log("PID: #{project.id}: -> #{output}") - - if status.zero? - true - else - log("Failed to create satellite for #{project.name_with_namespace}") - false - end - end - - def exists? - File.exists? path - end - - # * Locks the satellite - # * Changes the current directory to the satellite's working dir - # * Yields - def lock - project.ensure_satellite_exists - - File.open(lock_file, "w+") do |f| - begin - f.flock File::LOCK_EX - yield - ensure - f.flock File::LOCK_UN - end - end - end - - def lock_file - create_locks_dir unless File.exists?(lock_files_dir) - File.join(lock_files_dir, "satellite_#{project.id}.lock") - end - - def path - File.join(Gitlab.config.satellites.path, project.path_with_namespace) - end - - def repo - project.ensure_satellite_exists - - @repo ||= Grit::Repo.new(path) - end - - def destroy - FileUtils.rm_rf(path) - end - - private - - # Clear the working directory - def clear_working_dir! - repo.git.reset(hard: true) - repo.git.clean(f: true, d: true, x: true) - end - - # Deletes all branches except the parking branch - # - # This ensures we have no name clashes or issues updating branches when - # working with the satellite. - def delete_heads! - heads = repo.heads.map(&:name) - - # update or create the parking branch - repo.git.checkout(default_options({ B: true }), PARKING_BRANCH) - - # remove the parking branch from the list of heads ... - heads.delete(PARKING_BRANCH) - # ... and delete all others - heads.each { |head| repo.git.branch(default_options({ D: true }), head) } - end - - # Deletes all remotes except origin - # - # This ensures we have no remote name clashes or issues updating branches when - # working with the satellite. - def remove_remotes! - remotes = repo.git.remote.split(' ') - remotes.delete('origin') - remotes.each { |name| repo.git.remote(default_options,'rm', name)} - end - - # Updates the satellite from bare repo - # - # Note: this will only update remote branches (i.e. origin/*) - def update_from_source! - repo.git.remote(default_options, 'set-url', :origin, project.repository.path_to_repo) - repo.git.fetch(default_options, :origin) - end - - def default_options(options = {}) - { raise: true, timeout: true }.merge(options) - end - - # Create directory for storing - # satellites lock files - def create_locks_dir - FileUtils.mkdir_p(lock_files_dir) - end - - def lock_files_dir - @lock_files_dir ||= File.join(Gitlab.config.satellites.path, "tmp") - end - end - end -end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index aed84226a2f..21f159e1bfe 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -25,7 +25,6 @@ namespace :gitlab do check_init_script_exists check_init_script_up_to_date check_projects_have_namespace - check_satellites_exist check_redis_version check_ruby_version check_git_version @@ -238,37 +237,6 @@ namespace :gitlab do end end - def check_satellites_exist - print "Projects have satellites? ... " - - unless Project.count > 0 - puts "can't check, you have no projects".magenta - return - end - puts "" - - Project.find_each(batch_size: 100) do |project| - print sanitized_message(project) - - if project.satellite.exists? - puts "yes".green - elsif project.empty_repo? - puts "can't create, repository is empty".magenta - else - puts "no".red - try_fixing_it( - sudo_gitlab("bundle exec rake gitlab:satellites:create RAILS_ENV=production"), - "If necessary, remove the tmp/repo_satellites directory ...", - "... and rerun the above command" - ) - for_more_information( - "doc/raketasks/maintenance.md " - ) - fix_and_rerun - end - end - end - def check_log_writable print "Log directory writable? ... " @@ -339,7 +307,6 @@ namespace :gitlab do check_repo_base_is_not_symlink check_repo_base_user_and_group check_repo_base_permissions - check_satellites_permissions check_repos_hooks_directory_is_link check_gitlab_shell_self_test @@ -417,29 +384,6 @@ namespace :gitlab do end end - def check_satellites_permissions - print "Satellites access is drwxr-x---? ... " - - satellites_path = Gitlab.config.satellites.path - unless File.exists?(satellites_path) - puts "can't check because of previous errors".magenta - return - end - - if File.stat(satellites_path).mode.to_s(8).ends_with?("0750") - puts "yes".green - else - puts "no".red - try_fixing_it( - "sudo chmod u+rwx,g=rx,o-rwx #{satellites_path}", - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - def check_repo_base_user_and_group gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user gitlab_shell_owner_group = Gitlab.config.gitlab_shell.owner_group diff --git a/lib/tasks/gitlab/enable_automerge.rake b/lib/tasks/gitlab/enable_automerge.rake deleted file mode 100644 index 3dade9d75b8..00000000000 --- a/lib/tasks/gitlab/enable_automerge.rake +++ /dev/null @@ -1,39 +0,0 @@ -namespace :gitlab do - namespace :satellites do - desc "GitLab | Create satellite repos" - task create: :environment do - create_satellites - end - end - - def create_satellites - warn_user_is_not_gitlab - - print "Creating satellites for ..." - unless Project.count > 0 - puts "skipping, because you have no projects".magenta - return - end - puts "" - - Project.find_each(batch_size: 100) do |project| - print "#{project.name_with_namespace.yellow} ... " - - unless project.repo_exists? - puts "skipping, because the repo is empty".magenta - next - end - - if project.satellite.exists? - puts "exists already".green - else - print "\n... " - if project.satellite.create - puts "created".green - else - puts "error".red - end - end - end - end -end diff --git a/spec/lib/gitlab/satellite/action_spec.rb b/spec/lib/gitlab/satellite/action_spec.rb deleted file mode 100644 index 0a93676edc3..00000000000 --- a/spec/lib/gitlab/satellite/action_spec.rb +++ /dev/null @@ -1,116 +0,0 @@ -require 'spec_helper' - -describe 'Gitlab::Satellite::Action' do - let(:project) { create(:project) } - let(:user) { create(:user) } - - describe '#prepare_satellite!' do - it 'should be able to fetch timeout from conf' do - expect(Gitlab::Satellite::Action::DEFAULT_OPTIONS[:git_timeout]).to eq(30.seconds) - end - - it 'create a repository with a parking branch and one remote: origin' do - repo = project.satellite.repo - - #now lets dirty it up - - starting_remote_count = repo.git.list_remotes.size - expect(starting_remote_count).to be >= 1 - #kind of hookey way to add a second remote - origin_uri = repo.git.remote({ v: true }).split(" ")[1] - - repo.git.remote({ raise: true }, 'add', 'another-remote', origin_uri) - repo.git.branch({ raise: true }, 'a-new-branch') - - expect(repo.heads.size).to be > (starting_remote_count) - expect(repo.git.remote().split(" ").size).to be > (starting_remote_count) - - repo.git.config({}, "user.name", "#{user.name} -- foo") - repo.git.config({}, "user.email", "#{user.email} -- foo") - expect(repo.config['user.name']).to eq("#{user.name} -- foo") - expect(repo.config['user.email']).to eq("#{user.email} -- foo") - - - #These must happen in the context of the satellite directory... - satellite_action = Gitlab::Satellite::Action.new(user, project) - project.satellite.lock do - #Now clean it up, use send to get around prepare_satellite! being protected - satellite_action.send(:prepare_satellite!, repo) - end - - #verify it's clean - heads = repo.heads.map(&:name) - expect(heads.size).to eq(1) - expect(heads.include?(Gitlab::Satellite::Satellite::PARKING_BRANCH)).to eq(true) - remotes = repo.git.remote().split(' ') - expect(remotes.size).to eq(1) - expect(remotes.include?('origin')).to eq(true) - expect(repo.config['user.name']).to eq(user.name) - expect(repo.config['user.email']).to eq(user.email) - end - end - - describe '#in_locked_and_timed_satellite' do - - it 'should make use of a lockfile' do - repo = project.satellite.repo - called = false - - #set assumptions - FileUtils.rm_f(project.satellite.lock_file) - - expect(File.exists?(project.satellite.lock_file)).to be_falsey - - satellite_action = Gitlab::Satellite::Action.new(user, project) - satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo| - expect(repo).to eq(sat_repo) - expect(File.exists? project.satellite.lock_file).to be_truthy - called = true - end - - expect(called).to be_truthy - - end - - it 'should be able to use the satellite after locking' do - repo = project.satellite.repo - called = false - - # Set base assumptions - if File.exists? project.satellite.lock_file - expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey - end - - satellite_action = Gitlab::Satellite::Action.new(user, project) - satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo| - called = true - expect(repo).to eq(sat_repo) - expect(File.exists? project.satellite.lock_file).to be_truthy - expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_truthy - end - - expect(called).to be_truthy - expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey - - end - - class FileLockStatusChecker < File - def flocked?(&block) - status = flock LOCK_EX|LOCK_NB - case status - when false - return true - when 0 - begin - block ? block.call : false - ensure - flock LOCK_UN - end - else - raise SystemCallError, status - end - end - end - - end -end diff --git a/spec/lib/gitlab/satellite/merge_action_spec.rb b/spec/lib/gitlab/satellite/merge_action_spec.rb deleted file mode 100644 index 9b1c9a34e29..00000000000 --- a/spec/lib/gitlab/satellite/merge_action_spec.rb +++ /dev/null @@ -1,104 +0,0 @@ -require 'spec_helper' - -describe 'Gitlab::Satellite::MergeAction' do - include RepoHelpers - - let(:project) { create(:project, namespace: create(:group)) } - let(:fork_project) { create(:project, namespace: create(:group), forked_from_project: project) } - let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } - let(:merge_request_fork) { create(:merge_request, source_project: fork_project, target_project: project) } - - let(:merge_request_with_conflict) { create(:merge_request, :conflict, source_project: project, target_project: project) } - let(:merge_request_fork_with_conflict) { create(:merge_request, :conflict, source_project: project, target_project: project) } - - describe '#commits_between' do - def verify_commits(commits, first_commit_sha, last_commit_sha) - commits.each { |commit| expect(commit.class).to eq(Gitlab::Git::Commit) } - expect(commits.first.id).to eq(first_commit_sha) - expect(commits.last.id).to eq(last_commit_sha) - end - - context 'on fork' do - it 'should get proper commits between' do - commits = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).commits_between - verify_commits(commits, sample_compare.commits.first, sample_compare.commits.last) - end - end - - context 'between branches' do - it 'should raise exception -- not expected to be used by non forks' do - expect { Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).commits_between }.to raise_error(RuntimeError) - end - end - end - - describe '#format_patch' do - def verify_content(patch) - sample_compare.commits.each do |commit| - expect(patch.include?(commit)).to be_truthy - end - end - - context 'on fork' do - it 'should build a format patch' do - patch = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).format_patch - verify_content(patch) - end - end - - context 'between branches' do - it 'should build a format patch' do - patch = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request).format_patch - verify_content(patch) - end - end - end - - describe '#diffs_between_satellite tested against diff_in_satellite' do - def is_a_matching_diff(diff, diffs) - diff_count = diff.scan('diff --git').size - expect(diff_count).to be >= 1 - expect(diffs.size).to eq(diff_count) - diffs.each do |a_diff| - expect(a_diff.class).to eq(Gitlab::Git::Diff) - expect(diff.include? a_diff.diff).to be_truthy - end - end - - context 'on fork' do - it 'should get proper diffs' do - diffs = Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).diffs_between_satellite - diff = Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request_fork).diff_in_satellite - is_a_matching_diff(diff, diffs) - end - end - - context 'between branches' do - it 'should get proper diffs' do - expect{ Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).diffs_between_satellite }.to raise_error(RuntimeError) - end - end - end - - describe '#can_be_merged?' do - context 'on fork' do - it do - expect(Gitlab::Satellite::MergeAction.new(merge_request_fork.author, merge_request_fork).can_be_merged?).to be_truthy - end - - it do - expect(Gitlab::Satellite::MergeAction.new(merge_request_fork_with_conflict.author, merge_request_fork_with_conflict).can_be_merged?).to be_falsey - end - end - - context 'between branches' do - it do - expect(Gitlab::Satellite::MergeAction.new(merge_request.author, merge_request).can_be_merged?).to be_truthy - end - - it do - expect(Gitlab::Satellite::MergeAction.new(merge_request_with_conflict.author, merge_request_with_conflict).can_be_merged?).to be_falsey - end - end - end -end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 63091e913ff..721ae88c120 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -90,7 +90,6 @@ describe Project do describe 'Respond to' do it { is_expected.to respond_to(:url_to_repo) } it { is_expected.to respond_to(:repo_exists?) } - it { is_expected.to respond_to(:satellite) } it { is_expected.to respond_to(:update_merge_requests) } it { is_expected.to respond_to(:execute_hooks) } it { is_expected.to respond_to(:name_with_namespace) } diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index 6c7860511e8..8cb8790c339 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -110,7 +110,7 @@ describe API::API, api: true do expect(response.status).to eq(400) end - it "should return a 400 if satellite fails to create file" do + it "should return a 400 if fails to create file" do allow_any_instance_of(Repository).to receive(:remove_file).and_return(false) delete api("/projects/#{project.id}/repository/files", user), valid_params -- cgit v1.2.1 From 2be3c949258e45850d55c36b67fc4d5306a626ff Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 15:59:38 +0200 Subject: Fix application initialize --- features/steps/dashboard/help.rb | 2 +- lib/gitlab.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab.rb diff --git a/features/steps/dashboard/help.rb b/features/steps/dashboard/help.rb index 86ab31a58ab..800e869533e 100644 --- a/features/steps/dashboard/help.rb +++ b/features/steps/dashboard/help.rb @@ -16,6 +16,6 @@ class Spinach::Features::DashboardHelp < Spinach::FeatureSteps end step 'Header "Rebuild project satellites" should have correct ids and links' do - header_should_have_correct_id_and_link(2, '(Re-)Create satellite repositories', 're-create-satellite-repositories', '.documentation') + header_should_have_correct_id_and_link(2, 'Check GitLab configuration', 'check-gitlab-configuration', '.documentation') end end diff --git a/lib/gitlab.rb b/lib/gitlab.rb new file mode 100644 index 00000000000..6108697bc20 --- /dev/null +++ b/lib/gitlab.rb @@ -0,0 +1,4 @@ +require 'gitlab/git' + +module Gitlab +end -- cgit v1.2.1 From 2a6f522cac52ead493aa9f69017e2d7780c342a1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 16:45:38 +0200 Subject: Implement merge from forks without satellites --- .../projects/merge_requests_controller.rb | 3 ++- app/models/merge_request.rb | 19 +++++++++++------- app/models/merge_request_diff.rb | 6 ++++-- app/models/repository.rb | 23 ++++++++++++++++++++-- app/services/compare_service.rb | 19 +++++++++++++++++- app/services/merge_requests/auto_merge_service.rb | 10 +++------- .../projects/merge_requests/_new_submit.html.haml | 4 ++-- 7 files changed, 62 insertions(+), 22 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 0ef9e99123d..fbf2d8fa3ee 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -149,7 +149,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController return access_denied! unless @merge_request.can_be_merged_by?(current_user) if @merge_request.automergeable? - AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) + #AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) + @merge_request.automerge!(current_user, params[:commit_message]) @status = true else @status = false diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index aa2137e7469..e32b224eb77 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -206,11 +206,7 @@ class MergeRequest < ActiveRecord::Base def check_if_can_be_merged can_be_merged = - if for_fork? - raise 'Implement me' - else - project.repository.can_be_merged?(source_branch, target_branch) - end + project.repository.can_be_merged?(source_sha, target_branch) if can_be_merged mark_as_mergeable @@ -274,14 +270,14 @@ class MergeRequest < ActiveRecord::Base # # see "git diff" def to_diff(current_user) - raise 'Implement me' + target_project.repository.diff_text(target_branch, source_sha) end # Returns the commit as a series of email patches. # # see "git format-patch" def to_patch(current_user) - raise 'Implement me' + target_project.repository.format_patch(target_branch, source_sha) end def hook_attrs @@ -432,4 +428,13 @@ class MergeRequest < ActiveRecord::Base "Open" end end + + def target_sha + @target_sha ||= target_project. + repository.commit(target_branch).sha + end + + def source_sha + commits.first.sha + end end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index df1c2b78758..f3a1c91e75c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -160,10 +160,12 @@ class MergeRequestDiff < ActiveRecord::Base private def compare_result + source_sha = merge_request.source_project.commit(source_branch).sha + @compare_result ||= CompareService.new.execute( merge_request.author, - merge_request.source_project, - merge_request.source_branch, + merge_request.target_project, + source_sha, merge_request.target_project, merge_request.target_branch, ) diff --git a/app/models/repository.rb b/app/models/repository.rb index 70d416159a7..1924e7ee072 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -422,15 +422,34 @@ class Repository } end - def can_be_merged?(source_branch, target_branch) + def can_be_merged?(source_sha, target_branch) our_commit = rugged.branches[target_branch].target - their_commit = rugged.branches[source_branch].target + their_commit = rugged.lookup(source_sha) if our_commit && their_commit !rugged.merge_commits(our_commit, their_commit).conflicts? end end + def merge(source_sha, target_branch, options = {}) + our_commit = rugged.branches[target_branch].target + their_commit = rugged.lookup(source_sha) + + raise "Invalid merge target" if our_commit.nil? + raise "Invalid merge source" if their_commit.nil? + + merge_index = rugged.merge_commits(our_commit, their_commit) + return false if merge_index.conflicts? + + actual_options = options.merge( + parents: [our_commit, their_commit], + tree: merge_index.write_tree(rugged), + update_ref: "refs/heads/#{target_branch}" + ) + + Rugged::Commit.create(rugged, actual_options) + end + def search_files(query, ref) offset = 2 args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref}) diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb index 48ad7fab4e6..4c8b35edff8 100644 --- a/app/services/compare_service.rb +++ b/app/services/compare_service.rb @@ -1,3 +1,5 @@ +require 'securerandom' + # Compare 2 branches for one repo or between repositories # and return Gitlab::CompareResult object that responds to commits and diffs class CompareService @@ -12,7 +14,22 @@ class CompareService ) ) else - raise 'Implement me' + random_string = SecureRandom.hex + target_project.repository.fetch_ref( + source_project.repository.path_to_repo, + "refs/heads/#{source_branch}", + "refs/tmp/#{random_string}/head" + ) + + source_sha = source_project.commit(source_branch).sha + + Gitlab::CompareResult.new( + Gitlab::Git::Compare.new( + target_project.repository.raw_repository, + target_branch, + source_sha, + ) + ) end end end diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb index 1c41148d41d..3db498acfcd 100644 --- a/app/services/merge_requests/auto_merge_service.rb +++ b/app/services/merge_requests/auto_merge_service.rb @@ -31,12 +31,8 @@ module MergeRequests end def merge! - if merge_request.for_fork? - raise 'Implement me' - else - if sha = commit - after_commit(sha, merge_request.target_branch) - end + if sha = commit + after_commit(sha, merge_request.target_branch) end end @@ -49,7 +45,7 @@ module MergeRequests committer: committer } - repository.merge(merge_request.source_branch, merge_request.target_branch, options) + repository.merge(merge_request.source_sha, merge_request.target_branch, options) end def after_commit(sha, branch) diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 633a54f3620..76f44211dac 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -24,7 +24,7 @@ = icon('history') Commits %span.badge= @commits.size - %li.diffs-tab + %li.diffs-tab.active = link_to url_for(params), data: {target: '#diffs', action: 'diffs', toggle: 'tab'} do = icon('list-alt') Changes @@ -33,7 +33,7 @@ .tab-content #commits.commits.tab-pane = render "projects/commits/commits", project: @project - #diffs.diffs.tab-pane + #diffs.diffs.tab-pane.active - if @diffs.present? = render "projects/diffs/diffs", diffs: @diffs, project: @project - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE -- cgit v1.2.1 From cb6f34e367a58d277c58d7861343af6e08d5508a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 16:52:50 +0200 Subject: Implement update of ref when merge request code is reloaded --- app/models/merge_request_diff.rb | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index f3a1c91e75c..8a48f78dbd4 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -160,14 +160,23 @@ class MergeRequestDiff < ActiveRecord::Base private def compare_result - source_sha = merge_request.source_project.commit(source_branch).sha - - @compare_result ||= CompareService.new.execute( - merge_request.author, - merge_request.target_project, - source_sha, - merge_request.target_project, - merge_request.target_branch, - ) + @compare_result ||= + begin + source_sha = merge_request.source_project.commit(source_branch).sha + + merge_request.target_project.repository.fetch_ref( + merge_request.source_project.repository.path_to_repo, + "refs/heads/#{merge_request.source_branch}", + "refs/merge-requests/#{merge_request.id}/head" + ) + + CompareService.new.execute( + merge_request.author, + merge_request.target_project, + source_sha, + merge_request.target_project, + merge_request.target_branch, + ) + end end end -- cgit v1.2.1 From 26f5d6047d6e21a5c65a4276266648f1e69aac4a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 15 Jul 2015 17:28:09 +0200 Subject: Refactor compare and fetch logic --- app/controllers/projects/compare_controller.rb | 9 ++---- .../projects/merge_requests_controller.rb | 3 +- app/models/merge_request.rb | 8 ++++++ app/models/merge_request_diff.rb | 22 +++++++-------- app/models/repository.rb | 2 ++ app/services/compare_service.rb | 33 +++++++++------------- app/services/merge_requests/build_service.rb | 1 - app/services/merge_requests/create_service.rb | 9 ------ 8 files changed, 36 insertions(+), 51 deletions(-) diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index c5f085c236f..d9b3adae95b 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -13,13 +13,8 @@ class Projects::CompareController < Projects::ApplicationController base_ref = Addressable::URI.unescape(params[:from]) @ref = head_ref = Addressable::URI.unescape(params[:to]) - compare_result = CompareService.new.execute( - current_user, - @project, - head_ref, - @project, - base_ref - ) + compare_result = CompareService.new. + execute(@project, head_ref, @project, base_ref) @commits = compare_result.commits @diffs = compare_result.diffs diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index fbf2d8fa3ee..0ef9e99123d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -149,8 +149,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController return access_denied! unless @merge_request.can_be_merged_by?(current_user) if @merge_request.automergeable? - #AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) - @merge_request.automerge!(current_user, params[:commit_message]) + AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) @status = true else @status = false diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index e32b224eb77..4dcde029efa 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -437,4 +437,12 @@ class MergeRequest < ActiveRecord::Base def source_sha commits.first.sha end + + def fetch_ref + target_project.repository.fetch_ref( + source_project.repository.path_to_repo, + "refs/heads/#{source_branch}", + "refs/merge-requests/#{id}/head" + ) + end end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 8a48f78dbd4..6f01a589d1c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -162,20 +162,18 @@ class MergeRequestDiff < ActiveRecord::Base def compare_result @compare_result ||= begin - source_sha = merge_request.source_project.commit(source_branch).sha + # Update ref if merge request is from fork + merge_request.fetch_ref if merge_request.for_fork? - merge_request.target_project.repository.fetch_ref( - merge_request.source_project.repository.path_to_repo, - "refs/heads/#{merge_request.source_branch}", - "refs/merge-requests/#{merge_request.id}/head" - ) + # Get latest sha of branch from source project + source_sha = merge_request.source_project.commit(source_branch).sha - CompareService.new.execute( - merge_request.author, - merge_request.target_project, - source_sha, - merge_request.target_project, - merge_request.target_branch, + Gitlab::CompareResult.new( + Gitlab::Git::Compare.new( + merge_request.target_project.repository.raw_repository, + merge_request.target_branch, + source_sha, + ) ) end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 1924e7ee072..41666bd6e38 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -428,6 +428,8 @@ class Repository if our_commit && their_commit !rugged.merge_commits(our_commit, their_commit).conflicts? + else + false end end diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb index 4c8b35edff8..70f642baaaa 100644 --- a/app/services/compare_service.rb +++ b/app/services/compare_service.rb @@ -3,33 +3,26 @@ require 'securerandom' # Compare 2 branches for one repo or between repositories # and return Gitlab::CompareResult object that responds to commits and diffs class CompareService - def execute(current_user, source_project, source_branch, target_project, target_branch) - # Try to compare branches to get commits list and diffs - if target_project == source_project - Gitlab::CompareResult.new( - Gitlab::Git::Compare.new( - target_project.repository.raw_repository, - target_branch, - source_branch, - ) - ) - else + def execute(source_project, source_branch, target_project, target_branch) + source_sha = source_project.commit(source_branch).sha + + # If compare with other project we need to fetch ref first + unless target_project == source_project random_string = SecureRandom.hex + target_project.repository.fetch_ref( source_project.repository.path_to_repo, "refs/heads/#{source_branch}", "refs/tmp/#{random_string}/head" ) + end - source_sha = source_project.commit(source_branch).sha - - Gitlab::CompareResult.new( - Gitlab::Git::Compare.new( - target_project.repository.raw_repository, - target_branch, - source_sha, - ) + Gitlab::CompareResult.new( + Gitlab::Git::Compare.new( + target_project.repository.raw_repository, + target_branch, + source_sha, ) - end + ) end end diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 5ef1cd2caa0..3ff5374b353 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -17,7 +17,6 @@ module MergeRequests end compare_result = CompareService.new.execute( - current_user, merge_request.source_project, merge_request.source_branch, merge_request.target_project, diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 8389f29a53a..f431c5d5534 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -9,15 +9,6 @@ module MergeRequests merge_request.author = current_user if merge_request.save - # Fetch fork branch into hidden ref of target repository - if merge_request.for_fork? - merge_request.target_project.repository.fetch_ref( - merge_request.source_project.repository.path_to_repo, - "refs/heads/#{merge_request.source_branch}", - "refs/merge-requests/#{merge_request.id}/head" - ) - end - merge_request.update_attributes(label_ids: label_params) event_service.open_mr(merge_request, current_user) notification_service.new_merge_request(merge_request, current_user) -- cgit v1.2.1 From a7fded9b9529cfc08463afd4f6cf12478262e951 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 16:03:07 +0200 Subject: Huge refactoring for accepting merge requests Signed-off-by: Dmitriy Zaporozhets --- Gemfile.lock | 3 ++ .../javascripts/merge_request_widget.js.coffee | 2 +- .../projects/merge_requests_controller.rb | 10 ++-- app/models/merge_request.rb | 25 +++++---- app/models/project_services/gitlab_ci_service.rb | 4 ++ app/services/base_service.rb | 4 ++ app/services/files/base_service.rb | 9 +--- app/services/merge_requests/auto_merge_service.rb | 62 ---------------------- app/services/merge_requests/base_merge_service.rb | 10 ---- app/services/merge_requests/merge_service.rb | 61 ++++++++++++++++----- app/services/merge_requests/post_merge_service.rb | 22 ++++++++ app/services/merge_requests/refresh_service.rb | 4 +- app/services/post_commit_service.rb | 8 +++ .../projects/merge_requests/automerge.js.haml | 6 --- app/views/projects/merge_requests/merge.js.haml | 6 +++ .../projects/merge_requests/widget/_show.html.haml | 4 +- .../merge_requests/widget/open/_accept.html.haml | 2 +- app/workers/auto_merge_worker.rb | 13 ----- app/workers/merge_worker.rb | 19 +++++++ config/routes.rb | 4 +- lib/api/merge_requests.rb | 6 ++- 21 files changed, 145 insertions(+), 139 deletions(-) delete mode 100644 app/services/merge_requests/auto_merge_service.rb delete mode 100644 app/services/merge_requests/base_merge_service.rb create mode 100644 app/services/merge_requests/post_merge_service.rb create mode 100644 app/services/post_commit_service.rb delete mode 100644 app/views/projects/merge_requests/automerge.js.haml create mode 100644 app/views/projects/merge_requests/merge.js.haml delete mode 100644 app/workers/auto_merge_worker.rb create mode 100644 app/workers/merge_worker.rb diff --git a/Gemfile.lock b/Gemfile.lock index 12ba2fa295a..9830f3c77dc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -875,3 +875,6 @@ DEPENDENCIES virtus webmock (~> 1.21.0) wikicloth (= 0.8.1) + +BUNDLED WITH + 1.10.4 diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index e4d815bb4e4..e0ddc82eb36 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -19,7 +19,7 @@ class @MergeRequestWidget when 'merged' location.reload() else - setTimeout(merge_request_widget.mergeInProgress, 3000) + setTimeout(merge_request_widget.mergeInProgress, 2000) dataType: 'json' getMergeStatus: -> diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 0ef9e99123d..f3054881daf 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -1,7 +1,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController before_action :module_enabled before_action :merge_request, only: [ - :edit, :update, :show, :diffs, :commits, :automerge, :automerge_check, + :edit, :update, :show, :diffs, :commits, :merge, :merge_check, :ci_status, :toggle_subscription ] before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits] @@ -135,7 +135,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end end - def automerge_check + def merge_check if @merge_request.unchecked? @merge_request.check_if_can_be_merged end @@ -145,11 +145,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController render partial: "projects/merge_requests/widget/show.html.haml", layout: false end - def automerge + def merge return access_denied! unless @merge_request.can_be_merged_by?(current_user) - if @merge_request.automergeable? - AutoMergeWorker.perform_async(@merge_request.id, current_user.id, params) + if @merge_request.mergeable? + MergeWorker.perform_async(@merge_request.id, current_user.id, params) @status = true else @status = false diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 4dcde029efa..631a2d887cc 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -41,8 +41,6 @@ class MergeRequest < ActiveRecord::Base delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil - attr_accessor :should_remove_source_branch - # When this attribute is true some MR validation is ignored # It allows us to close or modify broken merge requests attr_accessor :allow_broken @@ -57,7 +55,7 @@ class MergeRequest < ActiveRecord::Base transition [:reopened, :opened] => :closed end - event :merge do + event :mark_as_merged do transition [:reopened, :opened, :locked] => :merged end @@ -223,14 +221,6 @@ class MergeRequest < ActiveRecord::Base self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last end - def automerge!(current_user, commit_message = nil) - return unless automergeable? - - MergeRequests::AutoMergeService. - new(target_project, current_user). - execute(self, commit_message) - end - def open? opened? || reopened? end @@ -239,11 +229,11 @@ class MergeRequest < ActiveRecord::Base title =~ /\A\[?WIP\]?:? /i end - def automergeable? + def mergeable? open? && !work_in_progress? && can_be_merged? end - def automerge_status + def gitlab_merge_status if work_in_progress? "work_in_progress" else @@ -445,4 +435,13 @@ class MergeRequest < ActiveRecord::Base "refs/merge-requests/#{id}/head" ) end + + def in_locked_state + begin + lock_mr + yield + ensure + unlock_mr if locked? + end + end end diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index c284e19fe50..0ea866fdb4a 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -70,6 +70,8 @@ class GitlabCiService < CiService else :error end + rescue Errno::ECONNREFUSED + :error end def fork_registration(new_project, private_token) @@ -99,6 +101,8 @@ class GitlabCiService < CiService if response.code == 200 and response["coverage"] response["coverage"] end + rescue Errno::ECONNREFUSED + nil end def build_page(sha, ref) diff --git a/app/services/base_service.rb b/app/services/base_service.rb index 6d9ed345914..f00ec7408b6 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -31,6 +31,10 @@ class BaseService SystemHooksService.new end + def repository + project.repository + end + # Add an error to the specified model for restricted visibility levels def deny_visibility_level(model, denied_visibility_level = nil) denied_visibility_level ||= model.visibility_level diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb index f587ee266da..d7b40ee8906 100644 --- a/app/services/files/base_service.rb +++ b/app/services/files/base_service.rb @@ -33,15 +33,8 @@ module Files private - def repository - project.repository - end - def after_commit(sha, branch) - commit = repository.commit(sha) - full_ref = 'refs/heads/' + branch - old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA - GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) + PostCommitService.new(project, current_user).execute(sha, branch) end def current_branch diff --git a/app/services/merge_requests/auto_merge_service.rb b/app/services/merge_requests/auto_merge_service.rb deleted file mode 100644 index 3db498acfcd..00000000000 --- a/app/services/merge_requests/auto_merge_service.rb +++ /dev/null @@ -1,62 +0,0 @@ -module MergeRequests - # AutoMergeService class - # - # Do git merge and in case of success - # mark merge request as merged and execute all hooks and notifications - # Called when you do merge via GitLab UI - class AutoMergeService < BaseMergeService - attr_reader :merge_request, :commit_message - - def execute(merge_request, commit_message) - @commit_message = commit_message - @merge_request = merge_request - - merge_request.lock_mr - - if merge! - merge_request.merge - 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 - else - merge_request.unlock_mr - false - end - rescue - merge_request.unlock_mr if merge_request.locked? - merge_request.mark_as_unmergeable - false - end - - def merge! - if sha = commit - after_commit(sha, merge_request.target_branch) - end - end - - def commit - committer = repository.user_to_comitter(current_user) - - options = { - message: commit_message, - author: committer, - committer: committer - } - - repository.merge(merge_request.source_sha, merge_request.target_branch, options) - end - - def after_commit(sha, branch) - commit = repository.commit(sha) - full_ref = 'refs/heads/' + branch - old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA - GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) - end - - def repository - project.repository - end - end -end diff --git a/app/services/merge_requests/base_merge_service.rb b/app/services/merge_requests/base_merge_service.rb deleted file mode 100644 index 9579573adf9..00000000000 --- a/app/services/merge_requests/base_merge_service.rb +++ /dev/null @@ -1,10 +0,0 @@ -module MergeRequests - class BaseMergeService < MergeRequests::BaseService - - private - - def create_merge_event(merge_request, current_user) - EventCreateService.new.merge_mr(merge_request, current_user) - end - end -end diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 327ead4ff3f..2107529a21a 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -1,22 +1,57 @@ module MergeRequests # MergeService class # - # Mark existing merge request as merged - # and execute all hooks and notifications - # Called when you do merge via command line and push code - # to target branch - class MergeService < BaseMergeService + # Do git merge and in case of success + # mark merge request as merged and execute all hooks and notifications + # Executed when you do merge via GitLab UI + # + class MergeService < MergeRequests::BaseService + attr_reader :merge_request, :commit_message + def execute(merge_request, commit_message) - merge_request.merge + @commit_message = commit_message + @merge_request = merge_request - create_merge_event(merge_request, current_user) - create_note(merge_request) - notification_service.merge_mr(merge_request, current_user) - execute_hooks(merge_request, 'merge') + unless @merge_request.mergeable? + return error('Merge request is not mergeable') + end + + merge_request.in_locked_state do + if merge_changes + after_merge + success + else + error('Can not merge changes') + end + end + end + + private + + def merge_changes + if sha = commit + after_commit(sha, merge_request.target_branch) + end + end + + def commit + committer = repository.user_to_comitter(current_user) + + options = { + message: commit_message, + author: committer, + committer: committer + } + + repository.merge(merge_request.source_sha, merge_request.target_branch, options) + end + + def after_commit(sha, branch) + PostCommitService.new(project, current_user).execute(sha, branch) + end - true - rescue - false + def after_merge + MergeRequests::PostMergeService.new(project, current_user).execute(merge_request) end end end diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb new file mode 100644 index 00000000000..aceb8cb9021 --- /dev/null +++ b/app/services/merge_requests/post_merge_service.rb @@ -0,0 +1,22 @@ +module MergeRequests + # PostMergeService class + # + # Mark existing merge request as merged + # and execute all hooks and notifications + # + class PostMergeService < MergeRequests::BaseService + def execute(merge_request) + merge_request.mark_as_merged + create_merge_event(merge_request, current_user) + create_note(merge_request) + notification_service.merge_mr(merge_request, current_user) + execute_hooks(merge_request, 'merge') + end + + private + + def create_merge_event(merge_request, current_user) + EventCreateService.new.merge_mr(merge_request, current_user) + end + end +end diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index d0648da049b..8286beaba63 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -33,9 +33,9 @@ module MergeRequests merge_requests.uniq.select(&:source_project).each do |merge_request| - MergeRequests::MergeService. + MergeRequests::PostMergeService new(merge_request.target_project, @current_user). - execute(merge_request, nil) + execute(merge_request) end end diff --git a/app/services/post_commit_service.rb b/app/services/post_commit_service.rb new file mode 100644 index 00000000000..7d7e5fbc32e --- /dev/null +++ b/app/services/post_commit_service.rb @@ -0,0 +1,8 @@ +class PostCommitService < BaseService + def execute(sha, branch) + commit = repository.commit(sha) + full_ref = 'refs/heads/' + branch + old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA + GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) + end +end diff --git a/app/views/projects/merge_requests/automerge.js.haml b/app/views/projects/merge_requests/automerge.js.haml deleted file mode 100644 index 33321651e32..00000000000 --- a/app/views/projects/merge_requests/automerge.js.haml +++ /dev/null @@ -1,6 +0,0 @@ -- if @status - :plain - merge_request_widget.mergeInProgress(); -- else - :plain - $('.mr-widget-body').html("#{escape_javascript(render('projects/merge_requests/widget/open/reload'))}"); diff --git a/app/views/projects/merge_requests/merge.js.haml b/app/views/projects/merge_requests/merge.js.haml new file mode 100644 index 00000000000..33321651e32 --- /dev/null +++ b/app/views/projects/merge_requests/merge.js.haml @@ -0,0 +1,6 @@ +- if @status + :plain + merge_request_widget.mergeInProgress(); +- else + :plain + $('.mr-widget-body').html("#{escape_javascript(render('projects/merge_requests/widget/open/reload'))}"); diff --git a/app/views/projects/merge_requests/widget/_show.html.haml b/app/views/projects/merge_requests/widget/_show.html.haml index 263cab7a9e8..a489d4f9b24 100644 --- a/app/views/projects/merge_requests/widget/_show.html.haml +++ b/app/views/projects/merge_requests/widget/_show.html.haml @@ -11,10 +11,10 @@ var merge_request_widget; merge_request_widget = new MergeRequestWidget({ - url_to_automerge_check: "#{automerge_check_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", + url_to_automerge_check: "#{merge_check_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", check_enable: #{@merge_request.unchecked? ? "true" : "false"}, url_to_ci_check: "#{ci_status_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}", ci_enable: #{@project.ci_service ? "true" : "false"}, - current_status: "#{@merge_request.automerge_status}", + current_status: "#{@merge_request.gitlab_merge_status}", }); diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml index f5bacaf280a..3c0cd25ba07 100644 --- a/app/views/projects/merge_requests/widget/open/_accept.html.haml +++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml @@ -1,4 +1,4 @@ -= form_for [:automerge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f| += form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f| = hidden_field_tag :authenticity_token, form_authenticity_token .accept-merge-holder.clearfix.js-toggle-container .accept-action diff --git a/app/workers/auto_merge_worker.rb b/app/workers/auto_merge_worker.rb deleted file mode 100644 index a6dd73eee5f..00000000000 --- a/app/workers/auto_merge_worker.rb +++ /dev/null @@ -1,13 +0,0 @@ -class AutoMergeWorker - include Sidekiq::Worker - - sidekiq_options queue: :default - - def perform(merge_request_id, current_user_id, params) - params = params.with_indifferent_access - current_user = User.find(current_user_id) - merge_request = MergeRequest.find(merge_request_id) - merge_request.should_remove_source_branch = params[:should_remove_source_branch] - merge_request.automerge!(current_user, params[:commit_message]) - end -end diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb new file mode 100644 index 00000000000..6a8665c179a --- /dev/null +++ b/app/workers/merge_worker.rb @@ -0,0 +1,19 @@ +class MergeWorker + include Sidekiq::Worker + + sidekiq_options queue: :default + + def perform(merge_request_id, current_user_id, params) + params = params.with_indifferent_access + current_user = User.find(current_user_id) + merge_request = MergeRequest.find(merge_request_id) + + result = MergeRequests::MergeService.new(merge_request.target_project, current_user). + execute(merge_request, params[:commit_message]) + + if result[:status] == :success && params[:should_remove_source_branch].present? + DeleteBranchService.new(merge_request.source_project, current_user). + execute(merge_request.source_branch) + end + end +end diff --git a/config/routes.rb b/config/routes.rb index 055d59a0c93..704cf705870 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -458,8 +458,8 @@ Gitlab::Application.routes.draw do member do get :diffs get :commits - post :automerge - get :automerge_check + post :merge + get :merge_check get :ci_status post :toggle_subscription end diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index aa43e1dffd9..a956c960a2e 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -198,7 +198,11 @@ module API if merge_request.open? && !merge_request.work_in_progress? if merge_request.can_be_merged? - merge_request.automerge!(current_user, params[:merge_commit_message] || merge_request.merge_commit_message) + commit_message = params[:merge_commit_message] || merge_request.merge_commit_message + + MergeRequests::MergeService.new(merge_request.target_project, current_user). + execute(merge_request, commit_message) + present merge_request, with: Entities::MergeRequest else render_api_error!('Branch cannot be merged', 405) -- cgit v1.2.1 From 971e47520f176625efe9c6c0dace7c6325ad89e5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 16:32:43 +0200 Subject: Increase COMMITS_SAFE_SIZE to reasonable size in compare to diff limits. Fix reload with full diff link Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 9 ++++----- app/views/projects/diffs/_warning.html.haml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 6f01a589d1c..2177f972ca3 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -16,9 +16,8 @@ require Rails.root.join("app/models/commit") class MergeRequestDiff < ActiveRecord::Base include Sortable - # Prevent store of diff - # if commits amount more then 200 - COMMITS_SAFE_SIZE = 200 + # Prevent store of diff if commits amount more then 500 + COMMITS_SAFE_SIZE = 500 attr_reader :commits, :diffs @@ -124,12 +123,12 @@ class MergeRequestDiff < ActiveRecord::Base if new_diffs.any? if new_diffs.size > Commit::DIFF_HARD_LIMIT_FILES self.state = :overflow_diff_files_limit - new_diffs = [] + new_diffs = new_diffs.first[Commit::DIFF_HARD_LIMIT_LINES] end if new_diffs.sum { |diff| diff.diff.lines.count } > Commit::DIFF_HARD_LIMIT_LINES self.state = :overflow_diff_lines_limit - new_diffs = [] + new_diffs = new_diffs.first[Commit::DIFF_HARD_LIMIT_LINES] end end diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index da3d4be84ba..f99bc9a85eb 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -3,7 +3,7 @@ Too many changes to show. .pull-right - unless diff_hard_limit_enabled? - = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true)), class: "btn btn-sm btn-warning" + = link_to "Reload with full diff", url_for(params.merge(force_show_diff: true, format: nil)), class: "btn btn-sm btn-warning" - if current_controller?(:commit) or current_controller?(:merge_requests) - if current_controller?(:commit) -- cgit v1.2.1 From 989329c9d9fb28092d8250a86a2dd6f4afc3a445 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 16:34:58 +0200 Subject: Fix refresh service Signed-off-by: Dmitriy Zaporozhets --- app/services/merge_requests/refresh_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 8286beaba63..e903e48e3cd 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -33,7 +33,7 @@ module MergeRequests merge_requests.uniq.select(&:source_project).each do |merge_request| - MergeRequests::PostMergeService + MergeRequests::PostMergeService. new(merge_request.target_project, @current_user). execute(merge_request) end -- cgit v1.2.1 From abd2bc00f92d6c516e1b1922355fb187b134f873 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 17:04:49 +0200 Subject: Fix some of tests Signed-off-by: Dmitriy Zaporozhets --- spec/models/project_services/slack_service_spec.rb | 2 +- spec/models/repository_spec.rb | 4 ++-- spec/support/mentionable_shared_examples.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb index 69466b11f09..97b60e19e40 100644 --- a/spec/models/project_services/slack_service_spec.rb +++ b/spec/models/project_services/slack_service_spec.rb @@ -67,7 +67,7 @@ describe SlackService do opts = { title: 'Awesome merge_request', description: 'please fix', - source_branch: 'stable', + source_branch: 'feature', target_branch: 'master' } merge_service = MergeRequests::CreateService.new(project, diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index d25351b0f0e..d96244f23e0 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -36,13 +36,13 @@ describe Repository do describe :can_be_merged? do context 'mergeable branches' do - subject { repository.can_be_merged?('feature', 'master') } + subject { repository.can_be_merged?('0b4bc9a49b562e85de7cc9e834518ea6828729b9', 'master') } it { is_expected.to be_truthy } end context 'non-mergeable branches' do - subject { repository.can_be_merged?('feature_conflict', 'feature') } + subject { repository.can_be_merged?('bb5206fee213d983da88c47f9cf4cc6caf9c66dc', 'feature') } it { is_expected.to be_falsey } end diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb index f0717e61781..e3de0afb448 100644 --- a/spec/support/mentionable_shared_examples.rb +++ b/spec/support/mentionable_shared_examples.rb @@ -9,7 +9,7 @@ def common_mentionable_setup let(:author) { subject.author } let(:mentioned_issue) { create(:issue, project: project) } - let(:mentioned_mr) { create(:merge_request, :simple, source_project: project) } + let!(:mentioned_mr) { create(:merge_request, :simple, source_project: project) } let(:mentioned_commit) { project.commit } let(:ext_proj) { create(:project, :public) } -- cgit v1.2.1 From fa88f2c084a3d99419f91159b35bdd3aaad3b39a Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 17:09:20 +0200 Subject: Use real branches from test repo Signed-off-by: Dmitriy Zaporozhets --- features/steps/dashboard/merge_requests.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb index cec8d06adee..28c8c6b6015 100644 --- a/features/steps/dashboard/merge_requests.rb +++ b/features/steps/dashboard/merge_requests.rb @@ -66,7 +66,7 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps def authored_merge_request @authored_merge_request ||= create :merge_request, - source_branch: 'simple_merge_request', + source_branch: 'markdown', author: current_user, target_project: project, source_project: project @@ -74,14 +74,14 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps def other_merge_request @other_merge_request ||= create :merge_request, - source_branch: '2_3_notes_fix', + source_branch: 'fix', target_project: project, source_project: project end def authored_merge_request_from_fork @authored_merge_request_from_fork ||= create :merge_request, - source_branch: 'basic_page', + source_branch: 'feature_conflict', author: current_user, target_project: public_project, source_project: forked_project @@ -89,7 +89,7 @@ class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps def assigned_merge_request_from_fork @assigned_merge_request_from_fork ||= create :merge_request, - source_branch: 'basic_page_fix', + source_branch: 'markdown', assignee: current_user, target_project: public_project, source_project: forked_project -- cgit v1.2.1 From 66bdbdb35d5930bb458ddf381c45f80548aa7235 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 16 Jul 2015 17:57:46 +0200 Subject: Remove satellites mention from architecture doc Signed-off-by: Dmitriy Zaporozhets --- doc/development/architecture.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 99f56016120..c00d290371e 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -56,9 +56,9 @@ To serve repositories over SSH there's an add-on application called gitlab-shell A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs. -The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. `/home/git/gitlab-satellites` keeps checked out repositories when performing actions such as a merge request, editing files in the web interface, etc. +The GitLab web app uses MySQL or PostgreSQL for persistent database information (e.g. users, permissions, issues, other meta data). GitLab stores the bare git repositories it serves in `/home/git/repositories` by default. It also keeps default branch and hook information with the bare repository. -[DEPRECATED] The satellite repository is used by the web interface for editing repositories and the wiki which is also a git repository. When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. +When serving repositories over HTTP/HTTPS GitLab utilizes the GitLab API to resolve authorization and access as well as serving git objects. The add-on component gitlab-shell serves repositories over SSH. It manages the SSH keys within `/home/git/.ssh/authorized_keys` which should not be manually edited. gitlab-shell accesses the bare repositories directly to serve git objects and communicates with redis to submit jobs to Sidekiq for GitLab to process. gitlab-shell queries the GitLab API to determine authorization and access. @@ -129,7 +129,7 @@ Note: `/home/git/` is shorthand for `/home/git`. gitlabhq (includes Unicorn and Sidekiq logs) -- `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `githost.log`, `satellites.log`, and `unicorn.stderr.log` normally. +- `/home/git/gitlab/log/` contains `application.log`, `production.log`, `sidekiq.log`, `unicorn.stdout.log`, `githost.log` and `unicorn.stderr.log` normally. gitlab-shell -- cgit v1.2.1 From 8279d936804659bbf8f161384eef4ac2649ff6a9 Mon Sep 17 00:00:00 2001 From: mchristof Date: Thu, 23 Jul 2015 09:47:32 +0100 Subject: updated restore docs wrt backup location [ci skip] Made sure to point out that the restore location can be overwritten by an entry in the config. --- doc/raketasks/backup_restore.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 36ab2b91959..996a642e2f1 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -232,7 +232,7 @@ Deleting tmp directories...[DONE] We will assume that you have installed GitLab from an omnibus package and run `sudo gitlab-ctl reconfigure` at least once. -First make sure your backup tar file is in `/var/opt/gitlab/backups`. +First make sure your backup tar file is in `/var/opt/gitlab/backups` (or whereever `gitlab_rails['backup_path']` points to). ```shell sudo cp 1393513186_gitlab_backup.tar /var/opt/gitlab/backups/ -- cgit v1.2.1 From db0fce322a19e20e755abca772ceb2918d815ea0 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:34:00 +0200 Subject: Create more backups during backup tests I hope this makes the backup tests more reliable. --- spec/tasks/gitlab/backup_rake_spec.rb | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 476e22b8802..48d08031d29 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -15,6 +15,12 @@ describe 'gitlab:app namespace rake task' do Rake.application.invoke_task task_name end + def reenable_backup_sub_tasks + %w{db repo uploads}.each do |subtask| + Rake::Task["gitlab:backup:#{subtask}:create"].reenable + end + end + describe 'backup_restore' do before do # avoid writing task output to spec progress @@ -67,23 +73,19 @@ describe 'gitlab:app namespace rake task' do # Redirect STDOUT and run the rake task orig_stdout = $stdout $stdout = StringIO.new + reenable_backup_sub_tasks run_rake_task('gitlab:backup:create') + reenable_backup_sub_tasks $stdout = orig_stdout @backup_tar = (tars_glob - existing_tars).first end - def reenable_backup_sub_tasks - %w{db repo uploads}.each do |subtask| - Rake::Task["gitlab:backup:#{subtask}:create"].reenable - end - end - - before :all do + before do create_backup end - after :all do + after do FileUtils.rm(@backup_tar) end @@ -99,9 +101,7 @@ describe 'gitlab:app namespace rake task' do # We created a backup in a before(:all) so it got the default permissions. # We now need to do some work to create a _new_ backup file using our stub. FileUtils.rm(@backup_tar) - reenable_backup_sub_tasks create_backup - reenable_backup_sub_tasks end it 'uses the custom permissions' do @@ -138,9 +138,7 @@ describe 'gitlab:app namespace rake task' do before :all do @origin_cd = Dir.pwd - Rake::Task["gitlab:backup:db:create"].reenable - Rake::Task["gitlab:backup:repo:create"].reenable - Rake::Task["gitlab:backup:uploads:create"].reenable + reenable_backup_sub_tasks # Record the existing backup tars so we don't touch them existing_tars = tars_glob -- cgit v1.2.1 From 39a7e210a3484fb84683d53c2cf5e0f7ef0c3a80 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:54:06 +0200 Subject: Use a separate backup test directory and nuke its contents --- config/gitlab.yml.example | 2 ++ spec/support/test_env.rb | 5 +++++ spec/tasks/gitlab/backup_rake_spec.rb | 10 ++++------ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 542106e86dd..456fb3d636e 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -339,6 +339,8 @@ test: # user: YOUR_USERNAME satellites: path: tmp/tests/gitlab-satellites/ + backup: + path: tmp/tests/backups gitlab_shell: path: tmp/tests/gitlab-shell/ repos_path: tmp/tests/repositories/ diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 8bdd6b43cdd..2bdb64ff314 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -29,6 +29,7 @@ module TestEnv clean_test_path FileUtils.mkdir_p(repos_path) + FileUtils.mkdir_p(backup_path) # Setup GitLab shell for test instance setup_gitlab_shell @@ -121,6 +122,10 @@ module TestEnv Gitlab.config.gitlab_shell.repos_path end + def backup_path + Gitlab.config.backup.path + end + def copy_forked_repo_with_submodules(project) base_repo_path = File.expand_path(forked_repo_path_bare) target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 48d08031d29..23f322e0a62 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -67,8 +67,7 @@ describe 'gitlab:app namespace rake task' do end def create_backup - # Record the existing backup tars so we don't touch them - existing_tars = tars_glob + FileUtils.rm tars_glob # Redirect STDOUT and run the rake task orig_stdout = $stdout @@ -78,7 +77,7 @@ describe 'gitlab:app namespace rake task' do reenable_backup_sub_tasks $stdout = orig_stdout - @backup_tar = (tars_glob - existing_tars).first + @backup_tar = tars_glob.first end before do @@ -140,8 +139,7 @@ describe 'gitlab:app namespace rake task' do reenable_backup_sub_tasks - # Record the existing backup tars so we don't touch them - existing_tars = tars_glob + FileUtils.rm tars_glob # Redirect STDOUT and run the rake task orig_stdout = $stdout @@ -150,7 +148,7 @@ describe 'gitlab:app namespace rake task' do run_rake_task('gitlab:backup:create') $stdout = orig_stdout - @backup_tar = (tars_glob - existing_tars).first + @backup_tar = tars_glob.first end after :all do -- cgit v1.2.1 From d371331a65070ce5b3ab9c210eac697062170c91 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 24 Jul 2015 18:55:50 +0200 Subject: Remove weird trailing characters --- config/gitlab.yml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 456fb3d636e..6dc0d170826 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -339,7 +339,7 @@ test: # user: YOUR_USERNAME satellites: path: tmp/tests/gitlab-satellites/ - backup: + backup: path: tmp/tests/backups gitlab_shell: path: tmp/tests/gitlab-shell/ -- cgit v1.2.1 From 1cd28600652e23c8605b9344e269c34e83edccd1 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Mon, 27 Jul 2015 15:29:10 +0900 Subject: Fix the image file that contains non-ascii character is not displayed --- CHANGELOG | 1 + lib/gitlab/markdown/relative_link_filter.rb | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e198b48e86e..808f66b9483 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix the image file that contains non-ascii character is not displayed(Hiroyuki Sato) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix Error 500 when browsing projects with no HEAD (Stan Hu) - Fix full screen mode for snippet comments (Daniel Gerhardt) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index 9de2b24a9da..3eaceba5323 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -98,9 +98,10 @@ module Gitlab # # Returns a String def path_type(path) - if repository.tree(current_sha, path).entries.any? + unescaped_path = Addressable::URI.unescape(path) + if repository.tree(current_sha, unescaped_path).entries.any? 'tree' - elsif repository.blob_at(current_sha, path).try(:image?) + elsif repository.blob_at(current_sha, unescaped_path).try(:image?) 'raw' else 'blob' -- cgit v1.2.1 From a784b996b3071cfe1807b1108316143dbc64492f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 15:49:44 +0200 Subject: Add project star and fork count, group avatar URL and user/group web URL attributes to API --- CHANGELOG | 1 + app/models/group.rb | 11 +++++++++++ app/models/user.rb | 4 ++++ lib/api/entities.rb | 4 +++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index cf0fa36bd47..eef3c3e7c01 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page + - Add project star and fork count, group avatar URL and user/group web URL attributes to API v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list diff --git a/app/models/group.rb b/app/models/group.rb index 051c672cb33..adcbbec465e 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,6 +17,7 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace + include Gitlab::ConfigHelper include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -56,6 +57,16 @@ class Group < Namespace name end + def avatar_url(size = nil) + if avatar.present? + [gitlab_config.url, avatar.url].join + end + end + + def web_url + [gitlab_config.url, "groups", self.path].join('/') + end + def owners @owners ||= group_members.owners.map(&:user) end diff --git a/app/models/user.rb b/app/models/user.rb index 4a10520b209..00a37cd9135 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -637,6 +637,10 @@ class User < ActiveRecord::Base end end + def web_url + [gitlab_config.url, "u", self.username].join('/') + end + def all_emails [self.email, *self.emails.map(&:email)] end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ecf1412dee5..c1b0cece344 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -5,7 +5,7 @@ module API end class UserBasic < UserSafe - expose :id, :state, :avatar_url + expose :id, :state, :avatar_url, :web_url end class User < UserBasic @@ -59,6 +59,7 @@ module API expose :namespace expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? } expose :avatar_url + expose :star_count, :forks_count end class ProjectMember < UserBasic @@ -69,6 +70,7 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description + expose :avatar_url, :web_url end class GroupDetail < Group -- cgit v1.2.1 From f9bcb9632c1f7f5c5c72d50a90289baa2af762f5 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 16:32:15 +0200 Subject: Add specific ability for managing group members --- app/controllers/groups/group_members_controller.rb | 7 +++++++ app/models/ability.rb | 5 +++-- app/views/dashboard/groups/index.html.haml | 7 ++++--- app/views/groups/group_members/_group_member.html.haml | 2 +- app/views/groups/group_members/index.html.haml | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 040255f08e6..b9c428a964f 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -21,6 +21,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end def create + return render_403 unless can?(current_user, :admin_group_member, @group) + @group.add_users(params[:user_ids].split(','), params[:access_level], current_user) redirect_to group_group_members_path(@group), notice: 'Users were successfully added.' @@ -28,6 +30,9 @@ class Groups::GroupMembersController < Groups::ApplicationController def update @member = @group.group_members.find(params[:id]) + + return render_403 unless can?(current_user, :update_group_member, @member) + @member.update_attributes(member_params) end @@ -46,6 +51,8 @@ class Groups::GroupMembersController < Groups::ApplicationController end def resend_invite + return render_403 unless can?(current_user, :admin_group_member, @group) + redirect_path = group_group_members_path(@group) @group_member = @group.group_members.find(params[:id]) diff --git a/app/models/ability.rb b/app/models/ability.rb index 6a8f683bc89..f8e5afa9b01 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -233,7 +233,8 @@ class Ability if group.has_owner?(user) || user.admin? rules.push(*[ :admin_group, - :admin_namespace + :admin_namespace, + :admin_group_member ]) end @@ -295,7 +296,7 @@ class Ability rules = [] target_user = subject.user group = subject.group - can_manage = group_abilities(user, group).include?(:admin_group) + can_manage = group_abilities(user, group).include?(:admin_group_member) if can_manage && (user != target_user) rules << :update_group_member diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 0a354373b9b..b75c11795bd 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,9 +23,10 @@ %i.fa.fa-cogs Settings - = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do - %i.fa.fa-sign-out - Leave + - if can?(current_user, :destroy_group_member, group_member) + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do + %i.fa.fa-sign-out + Leave = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" = link_to group, class: 'group-name' do diff --git a/app/views/groups/group_members/_group_member.html.haml b/app/views/groups/group_members/_group_member.html.haml index b460e0ff59e..acc7f8b28c2 100644 --- a/app/views/groups/group_members/_group_member.html.haml +++ b/app/views/groups/group_members/_group_member.html.haml @@ -24,7 +24,7 @@ = link_to member.created_by.name, user_path(member.created_by) = time_ago_with_tooltip(member.created_at) - - if show_controls && can?(current_user, :admin_group, @group) + - if show_controls && can?(current_user, :admin_group_member, member) = link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do Resend invite diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index a70d1ff0697..dba395cc8fa 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -17,7 +17,7 @@ = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' } = button_tag 'Search', class: 'btn' - - if current_user && current_user.can?(:admin_group, @group) + - if current_user && current_user.can?(:admin_group_member, @group) .pull-right = button_tag class: 'btn btn-new js-toggle-button', type: 'button' do Add members -- cgit v1.2.1 From 45acfdd32ace09b8ff4c8905cbeefb3d8001ccc3 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 16:36:48 +0200 Subject: Disable adding members from admin area when appropriate --- app/views/admin/groups/show.html.haml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 187314872de..296497a4cd4 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -51,21 +51,22 @@ = paginate @projects, param_name: 'projects_page', theme: 'gitlab' .col-md-6 - .panel.panel-default - .panel-heading - Add user(s) to the group: - .panel-body.form-holder - %p.light - Read more about project permissions - %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" + - if can?(current_user, :admin_group_member, @group) + .panel.panel-default + .panel-heading + Add user(s) to the group: + .panel-body.form-holder + %p.light + Read more about project permissions + %strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink" - = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do - %div - = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) - %div.prepend-top-10 - = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" - %hr - = button_tag 'Add users to group', class: "btn btn-create" + = form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do + %div + = users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all) + %div.prepend-top-10 + = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" + %hr + = button_tag 'Add users to group', class: "btn btn-create" .panel.panel-default .panel-heading %h3.panel-title @@ -86,7 +87,8 @@ (invited) %span.pull-right.light = member.human_access - = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do - %i.fa.fa-minus.fa-inverse + - if can?(current_user, :destroy_group_member, member) + = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, member) }, method: :delete, remote: true, class: "btn-xs btn btn-remove", title: 'Remove user from group' do + %i.fa.fa-minus.fa-inverse .panel-footer = paginate @members, param_name: 'members_page', theme: 'gitlab' -- cgit v1.2.1 From b230335090ee8fa22ab79453e24c1c3c468569df Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 28 Jul 2015 17:52:38 +0200 Subject: Show Leave button when you're the last owner, so that the error explains the reason --- app/views/dashboard/groups/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index b75c11795bd..6ef4d752ac3 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,7 +23,7 @@ %i.fa.fa-cogs Settings - - if can?(current_user, :destroy_group_member, group_member) + - if can?(current_user, :admin_group_member, group) = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do %i.fa.fa-sign-out Leave -- cgit v1.2.1 From b07ecbb5e37530e7754dc267da4ded1d7d2d736d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 19 Jul 2015 19:41:54 -0400 Subject: Simplify AutolinkFilter specs --- spec/features/markdown_spec.rb | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index b8199aa5e61..b8a846c7015 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -195,45 +195,41 @@ describe 'GitLab Markdown', feature: true do end describe 'AutolinkFilter' do - let(:list) { get_section('autolinkfilter').next_element } + def body + get_section('autolinkfilter').next_element + end - def item(index) - list.at_css("li:nth-child(#{index})") + # Override Capybara's `have_link` matcher to simplify our use case + def have_link(link) + super(link, href: link) end it 'autolinks http://' do - expect(item(1).children.first.name).to eq 'a' - expect(item(1).children.first['href']).to eq 'http://about.gitlab.com/' + expect(body).to have_link('http://about.gitlab.com/') end it 'autolinks https://' do - expect(item(2).children.first.name).to eq 'a' - expect(item(2).children.first['href']).to eq 'https://google.com/' + expect(body).to have_link('https://google.com/') end it 'autolinks ftp://' do - expect(item(3).children.first.name).to eq 'a' - expect(item(3).children.first['href']).to eq 'ftp://ftp.us.debian.org/debian/' + expect(body).to have_link('ftp://ftp.us.debian.org/debian/') end it 'autolinks smb://' do - expect(item(4).children.first.name).to eq 'a' - expect(item(4).children.first['href']).to eq 'smb://foo/bar/baz' + expect(body).to have_link('smb://foo/bar/baz') end it 'autolinks irc://' do - expect(item(5).children.first.name).to eq 'a' - expect(item(5).children.first['href']).to eq 'irc://irc.freenode.net/git' + expect(body).to have_link('irc://irc.freenode.net/git') end it 'autolinks short, invalid URLs' do - expect(item(6).children.first.name).to eq 'a' - expect(item(6).children.first['href']).to eq 'http://localhost:3000' + expect(body).to have_link('http://localhost:3000') end %w(code a kbd).each do |elem| it "ignores links inside '#{elem}' element" do - body = get_section('autolinkfilter') expect(body).not_to have_selector("#{elem} a") end end -- cgit v1.2.1 From 06478ef3ecba80625e5cff70cb3697f442e24cba Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 22:22:17 -0400 Subject: Minor Markdown feature spec reorganization --- spec/features/markdown_spec.rb | 93 +++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index b8a846c7015..f1be4e49c8a 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -33,39 +33,31 @@ require 'erb' # See the MarkdownFeature class for setup details. describe 'GitLab Markdown', feature: true do - include ActionView::Helpers::TagHelper - include ActionView::Helpers::UrlHelper include Capybara::Node::Matchers include GitlabMarkdownHelper - # `markdown` calls these two methods - def current_user - @feat.user - end - - def user_color_scheme_class - :white - end - # Let's only parse this thing once before(:all) do @feat = MarkdownFeature.new - # `markdown` expects a `@project` variable + # `gfm_with_options` depends on a `@project` variable @project = @feat.project - @md = markdown(@feat.raw_markdown) - @doc = Nokogiri::HTML::DocumentFragment.parse(@md) + @html = markdown(@feat.raw_markdown) end after(:all) do @feat.teardown end + def doc + @doc ||= Nokogiri::HTML::DocumentFragment.parse(@html) + end + # Given a header ID, goes to that element's parent (the header itself), then # its next sibling element (the body). def get_section(id) - @doc.at_css("##{id}").parent.next_element + doc.at_css("##{id}").parent.next_element end # Sometimes it can be useful to see the parsed output of the Markdown document @@ -74,11 +66,11 @@ describe 'GitLab Markdown', feature: true do # # it 'writes to a file' do # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| - # file.puts @md + # file.puts @html # end # end - describe 'Markdown' do + describe 'Redcarpet extensions' do describe 'No Intra Emphasis' do it 'does not parse emphasis inside of words' do body = get_section('no-intra-emphasis') @@ -95,21 +87,21 @@ describe 'GitLab Markdown', feature: true do end it 'allows Markdown in tables' do - expect(@doc.at_css('td:contains("Baz")').children.to_html). + expect(doc.at_css('td:contains("Baz")').children.to_html). to eq 'Baz' end end describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do - expect(@doc).to have_selector('pre.code.highlight.white.c') - expect(@doc).to have_selector('pre.code.highlight.white.python') + expect(doc).to have_selector('pre.code.highlight.white.c') + expect(doc).to have_selector('pre.code.highlight.white.python') end end describe 'Strikethrough' do it 'parses strikethroughs' do - expect(@doc).to have_selector(%{del:contains("and this text doesn't")}) + expect(doc).to have_selector(%{del:contains("and this text doesn't")}) end end @@ -125,28 +117,28 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'uses a permissive whitelist' do - expect(@doc).to have_selector('b:contains("b tag")') - expect(@doc).to have_selector('em:contains("em tag")') - expect(@doc).to have_selector('code:contains("code tag")') - expect(@doc).to have_selector('kbd:contains("s")') - expect(@doc).to have_selector('strike:contains(Emoji)') - expect(@doc).to have_selector('img[src*="smile.png"]') - expect(@doc).to have_selector('br') - expect(@doc).to have_selector('hr') + expect(doc).to have_selector('b:contains("b tag")') + expect(doc).to have_selector('em:contains("em tag")') + expect(doc).to have_selector('code:contains("code tag")') + expect(doc).to have_selector('kbd:contains("s")') + expect(doc).to have_selector('strike:contains(Emoji)') + expect(doc).to have_selector('img[src*="smile.png"]') + expect(doc).to have_selector('br') + expect(doc).to have_selector('hr') end it 'permits span elements' do - expect(@doc).to have_selector('span:contains("span tag")') + expect(doc).to have_selector('span:contains("span tag")') end it 'permits table alignment' do - expect(@doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' - expect(@doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' - expect(@doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' - expect(@doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' - expect(@doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' - expect(@doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' end it 'removes `rel` attribute from links' do @@ -155,12 +147,12 @@ describe 'GitLab Markdown', feature: true do end it "removes `href` from `a` elements if it's fishy" do - expect(@doc).not_to have_selector('a[href*="javascript"]') + expect(doc).not_to have_selector('a[href*="javascript"]') end end describe 'Escaping' do - let(:table) { @doc.css('table').last.at_css('tbody') } + let(:table) { doc.css('table').last.at_css('tbody') } it 'escapes non-tag angle brackets' do expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' @@ -169,28 +161,28 @@ describe 'GitLab Markdown', feature: true do describe 'Edge Cases' do it 'allows markup inside link elements' do - expect(@doc.at_css('a[href="#link-emphasis"]').to_html). + expect(doc.at_css('a[href="#link-emphasis"]').to_html). to eq %{text} - expect(@doc.at_css('a[href="#link-strong"]').to_html). + expect(doc.at_css('a[href="#link-strong"]').to_html). to eq %{text} - expect(@doc.at_css('a[href="#link-code"]').to_html). + expect(doc.at_css('a[href="#link-code"]').to_html). to eq %{text} end end describe 'EmojiFilter' do it 'parses Emoji' do - expect(@doc).to have_selector('img.emoji', count: 10) + expect(doc).to have_selector('img.emoji', count: 10) end end describe 'TableOfContentsFilter' do it 'creates anchors inside header elements' do - expect(@doc).to have_selector('h1 a#gitlab-markdown') - expect(@doc).to have_selector('h2 a#markdown') - expect(@doc).to have_selector('h3 a#autolinkfilter') + expect(doc).to have_selector('h1 a#gitlab-markdown') + expect(doc).to have_selector('h2 a#markdown') + expect(doc).to have_selector('h3 a#autolinkfilter') end end @@ -249,7 +241,7 @@ describe 'GitLab Markdown', feature: true do describe 'ReferenceFilter' do it 'handles references in headers' do - header = @doc.at_css('#reference-filters-eg-1').parent + header = doc.at_css('#reference-filters-eg-1').parent expect(header.css('a').size).to eq 2 end @@ -304,6 +296,15 @@ describe 'GitLab Markdown', feature: true do end end end + + # `markdown` calls these two methods + def current_user + @feat.user + end + + def user_color_scheme_class + :white + end end # This is a helper class used by the GitLab Markdown feature spec -- cgit v1.2.1 From 3cafa74387d707dac37d0e81bf2bb194e94957e4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 22:31:05 -0400 Subject: Use aggregate_failures where appropriate --- spec/features/markdown_spec.rb | 87 +++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index f1be4e49c8a..dadb1c3589f 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -81,9 +81,12 @@ describe 'GitLab Markdown', feature: true do describe 'Tables' do it 'parses table Markdown' do body = get_section('tables') - expect(body).to have_selector('th:contains("Header")') - expect(body).to have_selector('th:contains("Row")') - expect(body).to have_selector('th:contains("Example")') + + aggregate_failures do + expect(body).to have_selector('th:contains("Header")') + expect(body).to have_selector('th:contains("Row")') + expect(body).to have_selector('th:contains("Example")') + end end it 'allows Markdown in tables' do @@ -94,8 +97,10 @@ describe 'GitLab Markdown', feature: true do describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do - expect(doc).to have_selector('pre.code.highlight.white.c') - expect(doc).to have_selector('pre.code.highlight.white.python') + aggregate_failures do + expect(doc).to have_selector('pre.code.highlight.white.c') + expect(doc).to have_selector('pre.code.highlight.white.python') + end end end @@ -108,8 +113,11 @@ describe 'GitLab Markdown', feature: true do describe 'Superscript' do it 'parses superscript' do body = get_section('superscript') - expect(body.to_html).to match('1st') - expect(body.to_html).to match('2nd') + + aggregate_failures do + expect(body.to_html).to match('1st') + expect(body.to_html).to match('2nd') + end end end end @@ -117,14 +125,16 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'uses a permissive whitelist' do - expect(doc).to have_selector('b:contains("b tag")') - expect(doc).to have_selector('em:contains("em tag")') - expect(doc).to have_selector('code:contains("code tag")') - expect(doc).to have_selector('kbd:contains("s")') - expect(doc).to have_selector('strike:contains(Emoji)') - expect(doc).to have_selector('img[src*="smile.png"]') - expect(doc).to have_selector('br') - expect(doc).to have_selector('hr') + aggregate_failures do + expect(doc).to have_selector('b:contains("b tag")') + expect(doc).to have_selector('em:contains("em tag")') + expect(doc).to have_selector('code:contains("code tag")') + expect(doc).to have_selector('kbd:contains("s")') + expect(doc).to have_selector('strike:contains(Emoji)') + expect(doc).to have_selector('img[src*="smile.png"]') + expect(doc).to have_selector('br') + expect(doc).to have_selector('hr') + end end it 'permits span elements' do @@ -132,13 +142,15 @@ describe 'GitLab Markdown', feature: true do end it 'permits table alignment' do - expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' - expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' - expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' - - expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' - expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' - expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + aggregate_failures do + expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + + expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + end end it 'removes `rel` attribute from links' do @@ -161,14 +173,16 @@ describe 'GitLab Markdown', feature: true do describe 'Edge Cases' do it 'allows markup inside link elements' do - expect(doc.at_css('a[href="#link-emphasis"]').to_html). - to eq %{text} + aggregate_failures do + expect(doc.at_css('a[href="#link-emphasis"]').to_html). + to eq %{text} - expect(doc.at_css('a[href="#link-strong"]').to_html). - to eq %{text} + expect(doc.at_css('a[href="#link-strong"]').to_html). + to eq %{text} - expect(doc.at_css('a[href="#link-code"]').to_html). - to eq %{text} + expect(doc.at_css('a[href="#link-code"]').to_html). + to eq %{text} + end end end @@ -180,9 +194,11 @@ describe 'GitLab Markdown', feature: true do describe 'TableOfContentsFilter' do it 'creates anchors inside header elements' do - expect(doc).to have_selector('h1 a#gitlab-markdown') - expect(doc).to have_selector('h2 a#markdown') - expect(doc).to have_selector('h3 a#autolinkfilter') + aggregate_failures do + expect(doc).to have_selector('h1 a#gitlab-markdown') + expect(doc).to have_selector('h2 a#markdown') + expect(doc).to have_selector('h3 a#autolinkfilter') + end end end @@ -290,9 +306,12 @@ describe 'GitLab Markdown', feature: true do describe 'Task Lists' do it 'generates task lists' do body = get_section('task-lists') - expect(body).to have_selector('ul.task-list', count: 2) - expect(body).to have_selector('li.task-list-item', count: 7) - expect(body).to have_selector('input[checked]', count: 3) + + aggregate_failures do + expect(body).to have_selector('ul.task-list', count: 2) + expect(body).to have_selector('li.task-list-item', count: 7) + expect(body).to have_selector('input[checked]', count: 3) + end end end end -- cgit v1.2.1 From 97cedc5d1b023af56c035cccc5914d11bf6299de Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 20 Jul 2015 23:57:26 -0400 Subject: Break up SanitizationFilter feature specs --- spec/features/markdown_spec.rb | 53 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index dadb1c3589f..5adf19980dd 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -124,29 +124,52 @@ describe 'GitLab Markdown', feature: true do describe 'HTML::Pipeline' do describe 'SanitizationFilter' do - it 'uses a permissive whitelist' do - aggregate_failures do - expect(doc).to have_selector('b:contains("b tag")') - expect(doc).to have_selector('em:contains("em tag")') - expect(doc).to have_selector('code:contains("code tag")') - expect(doc).to have_selector('kbd:contains("s")') - expect(doc).to have_selector('strike:contains(Emoji)') - expect(doc).to have_selector('img[src*="smile.png"]') - expect(doc).to have_selector('br') - expect(doc).to have_selector('hr') - end + it 'permits b elements' do + expect(doc).to have_selector('b:contains("b tag")') + end + + it 'permits em elements' do + expect(doc).to have_selector('em:contains("em tag")') + end + + it 'permits code elements' do + expect(doc).to have_selector('code:contains("code tag")') + end + + it 'permits kbd elements' do + expect(doc).to have_selector('kbd:contains("s")') + end + + it 'permits strike elements' do + expect(doc).to have_selector('strike:contains(Emoji)') + end + + it 'permits img elements' do + expect(doc).to have_selector('img[src*="smile.png"]') + end + + it 'permits br elements' do + expect(doc).to have_selector('br') + end + + it 'permits hr elements' do + expect(doc).to have_selector('hr') end it 'permits span elements' do expect(doc).to have_selector('span:contains("span tag")') end - it 'permits table alignment' do + it 'permits style attribute in th elements' do aggregate_failures do expect(doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' expect(doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' expect(doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + end + end + it 'permits style attribute in td elements' do + aggregate_failures do expect(doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' expect(doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' expect(doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' @@ -154,8 +177,7 @@ describe 'GitLab Markdown', feature: true do end it 'removes `rel` attribute from links' do - body = get_section('sanitizationfilter') - expect(body).not_to have_selector('a[rel="bookmark"]') + expect(doc).not_to have_selector('a[rel="bookmark"]') end it "removes `href` from `a` elements if it's fishy" do @@ -164,9 +186,8 @@ describe 'GitLab Markdown', feature: true do end describe 'Escaping' do - let(:table) { doc.css('table').last.at_css('tbody') } - it 'escapes non-tag angle brackets' do + table = doc.css('table').last.at_css('tbody') expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' end end -- cgit v1.2.1 From b07df8b1b05117352bc77fd4be0227dc588255fe Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 00:21:51 -0400 Subject: Make links inside ignored elements unique This is to prevent false matches since the Autolink section uses about.gitlab.com as well. --- spec/fixtures/markdown.md.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 02ab46c905a..75f6528ccdf 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -123,9 +123,9 @@ These are all plain text that should get turned into links: But it shouldn't autolink text inside certain tags: -- http://about.gitlab.com/ -- http://about.gitlab.com/ -- http://about.gitlab.com/ +- http://code.gitlab.com/ +- http://a.gitlab.com/ +- http://kbd.gitlab.com/ ### ExternalLinkFilter -- cgit v1.2.1 From 590fca0f06c4a21dbac90480bc6622f4da97dc86 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 21 Jul 2015 00:23:27 -0400 Subject: Move MarkdownFeature to its own support file This file's about to get much bigger and this removes some of the extra noise. --- spec/features/markdown_spec.rb | 115 --------------------------------------- spec/support/markdown_feature.rb | 114 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 115 deletions(-) create mode 100644 spec/support/markdown_feature.rb diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 5adf19980dd..46814fdfb8e 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -346,118 +346,3 @@ describe 'GitLab Markdown', feature: true do :white end end - -# This is a helper class used by the GitLab Markdown feature spec -# -# Because the feature spec only cares about the output of the Markdown, and the -# test setup and teardown and parsing is fairly expensive, we only want to do it -# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` -# block, so we fake it by encapsulating all the shared setup in this class. -# -# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for -# reference to the factory-created objects. -class MarkdownFeature - include FactoryGirl::Syntax::Methods - - def initialize - DatabaseCleaner.start - end - - def teardown - DatabaseCleaner.clean - end - - def user - @user ||= create(:user) - end - - def group - unless @group - @group = create(:group) - @group.add_user(user, Gitlab::Access::DEVELOPER) - end - - @group - end - - # Direct references ---------------------------------------------------------- - - def project - @project ||= create(:project) - end - - def issue - @issue ||= create(:issue, project: project) - end - - def merge_request - @merge_request ||= create(:merge_request, :simple, source_project: project) - end - - def snippet - @snippet ||= create(:project_snippet, project: project) - end - - def commit - @commit ||= project.commit - end - - def commit_range - unless @commit_range - commit2 = project.commit('HEAD~3') - @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project) - end - - @commit_range - end - - def simple_label - @simple_label ||= create(:label, name: 'gfm', project: project) - end - - def label - @label ||= create(:label, name: 'awaiting feedback', project: project) - end - - # Cross-references ----------------------------------------------------------- - - def xproject - unless @xproject - namespace = create(:namespace, name: 'cross-reference') - @xproject = create(:project, namespace: namespace) - @xproject.team << [user, :developer] - end - - @xproject - end - - def xissue - @xissue ||= create(:issue, project: xproject) - end - - def xmerge_request - @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) - end - - def xsnippet - @xsnippet ||= create(:project_snippet, project: xproject) - end - - def xcommit - @xcommit ||= xproject.commit - end - - def xcommit_range - unless @xcommit_range - xcommit2 = xproject.commit('HEAD~2') - @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) - end - - @xcommit_range - end - - def raw_markdown - fixture = Rails.root.join('spec/fixtures/markdown.md.erb') - ERB.new(File.read(fixture)).result(binding) - end -end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb new file mode 100644 index 00000000000..5e18ffa4143 --- /dev/null +++ b/spec/support/markdown_feature.rb @@ -0,0 +1,114 @@ +# This is a helper class used by the GitLab Markdown feature spec +# +# Because the feature spec only cares about the output of the Markdown, and the +# test setup and teardown and parsing is fairly expensive, we only want to do it +# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` +# block, so we fake it by encapsulating all the shared setup in this class. +# +# The class renders `spec/fixtures/markdown.md.erb` using ERB, allowing for +# reference to the factory-created objects. +class MarkdownFeature + include FactoryGirl::Syntax::Methods + + def initialize + DatabaseCleaner.start + end + + def teardown + DatabaseCleaner.clean + end + + def user + @user ||= create(:user) + end + + def group + unless @group + @group = create(:group) + @group.add_user(user, Gitlab::Access::DEVELOPER) + end + + @group + end + + # Direct references ---------------------------------------------------------- + + def project + @project ||= create(:project) + end + + def issue + @issue ||= create(:issue, project: project) + end + + def merge_request + @merge_request ||= create(:merge_request, :simple, source_project: project) + end + + def snippet + @snippet ||= create(:project_snippet, project: project) + end + + def commit + @commit ||= project.commit + end + + def commit_range + unless @commit_range + commit2 = project.commit('HEAD~3') + @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}", project) + end + + @commit_range + end + + def simple_label + @simple_label ||= create(:label, name: 'gfm', project: project) + end + + def label + @label ||= create(:label, name: 'awaiting feedback', project: project) + end + + # Cross-references ----------------------------------------------------------- + + def xproject + unless @xproject + namespace = create(:namespace, name: 'cross-reference') + @xproject = create(:project, namespace: namespace) + @xproject.team << [user, :developer] + end + + @xproject + end + + def xissue + @xissue ||= create(:issue, project: xproject) + end + + def xmerge_request + @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) + end + + def xsnippet + @xsnippet ||= create(:project_snippet, project: xproject) + end + + def xcommit + @xcommit ||= xproject.commit + end + + def xcommit_range + unless @xcommit_range + xcommit2 = xproject.commit('HEAD~2') + @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}", xproject) + end + + @xcommit_range + end + + def raw_markdown + fixture = Rails.root.join('spec/fixtures/markdown.md.erb') + ERB.new(File.read(fixture)).result(binding) + end +end -- cgit v1.2.1 From 0673ca36812ac3f709032938b77e5ab6e1d63885 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Jul 2015 21:22:16 -0400 Subject: Add RelativeLinkFilter section to Markdown fixture --- spec/fixtures/markdown.md.erb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb index 75f6528ccdf..41d12afa9ce 100644 --- a/spec/fixtures/markdown.md.erb +++ b/spec/fixtures/markdown.md.erb @@ -100,6 +100,13 @@ Markdown should be usable inside a link. Let's try! - [**text**](#link-strong) - [`text`](#link-code) +### RelativeLinkFilter + +Linking to a file relative to this project's repository should work. + +[Relative Link](doc/README.md) +![Relative Image](app/assets/images/touch-icon-ipad.png) + ### EmojiFilter Because life would be :zzz: without Emoji, right? :rocket: -- cgit v1.2.1 From 05f9a6a9c44c094d281d3dc8d80eb30c4e7dff27 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 22 Jul 2015 21:22:57 -0400 Subject: Update Markdown feature to allow for multiple pipelines --- spec/features/markdown_spec.rb | 216 +++++++---------------------- spec/support/matchers/markdown_matchers.rb | 156 +++++++++++++++++++++ 2 files changed, 209 insertions(+), 163 deletions(-) create mode 100644 spec/support/matchers/markdown_matchers.rb diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index 46814fdfb8e..ddef2317e1c 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -17,16 +17,8 @@ require 'erb' # -> Post-process HTML # -> `gfm_with_options` helper # -> HTML::Pipeline -# -> Sanitize -# -> RelativeLink -# -> Emoji -# -> Table of Contents -# -> Autolinks -# -> Rinku (http, https, ftp) -# -> Other schemes -# -> ExternalLink -# -> References -# -> TaskList +# -> SanitizationFilter +# -> Other filters, depending on pipeline # -> `html_safe` # -> Template # @@ -35,6 +27,7 @@ require 'erb' describe 'GitLab Markdown', feature: true do include Capybara::Node::Matchers include GitlabMarkdownHelper + include MarkdownMatchers # Let's only parse this thing once before(:all) do @@ -42,50 +35,37 @@ describe 'GitLab Markdown', feature: true do # `gfm_with_options` depends on a `@project` variable @project = @feat.project - - @html = markdown(@feat.raw_markdown) end after(:all) do @feat.teardown end - def doc - @doc ||= Nokogiri::HTML::DocumentFragment.parse(@html) + def doc(html = @html) + Nokogiri::HTML::DocumentFragment.parse(html) end - # Given a header ID, goes to that element's parent (the header itself), then - # its next sibling element (the body). - def get_section(id) - doc.at_css("##{id}").parent.next_element + # Sometimes it can be useful to see the parsed output of the Markdown document + # for debugging. Call this method to write the output to + # `tmp/capybara/.html`. + def write_markdown(filename = 'markdown_spec') + File.open(Rails.root.join("tmp/capybara/#{filename}.html"), 'w') do |file| + file.puts @html + end end - # Sometimes it can be useful to see the parsed output of the Markdown document - # for debugging. Uncomment this block to write the output to - # tmp/capybara/markdown_spec.html. - # - # it 'writes to a file' do - # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| - # file.puts @html - # end - # end - - describe 'Redcarpet extensions' do - describe 'No Intra Emphasis' do + # Shared behavior that all pipelines should exhibit + shared_examples 'all pipelines' do + describe 'Redcarpet extensions' do it 'does not parse emphasis inside of words' do - body = get_section('no-intra-emphasis') - expect(body.to_html).not_to match('foobarbaz') + expect(doc.to_html).not_to match('foobarbaz') end - end - describe 'Tables' do it 'parses table Markdown' do - body = get_section('tables') - aggregate_failures do - expect(body).to have_selector('th:contains("Header")') - expect(body).to have_selector('th:contains("Row")') - expect(body).to have_selector('th:contains("Example")') + expect(doc).to have_selector('th:contains("Header")') + expect(doc).to have_selector('th:contains("Row")') + expect(doc).to have_selector('th:contains("Example")') end end @@ -93,36 +73,23 @@ describe 'GitLab Markdown', feature: true do expect(doc.at_css('td:contains("Baz")').children.to_html). to eq 'Baz' end - end - describe 'Fenced Code Blocks' do it 'parses fenced code blocks' do aggregate_failures do expect(doc).to have_selector('pre.code.highlight.white.c') expect(doc).to have_selector('pre.code.highlight.white.python') end end - end - describe 'Strikethrough' do it 'parses strikethroughs' do expect(doc).to have_selector(%{del:contains("and this text doesn't")}) end - end - describe 'Superscript' do it 'parses superscript' do - body = get_section('superscript') - - aggregate_failures do - expect(body.to_html).to match('1st') - expect(body.to_html).to match('2nd') - end + expect(doc).to have_selector('sup', count: 2) end end - end - describe 'HTML::Pipeline' do describe 'SanitizationFilter' do it 'permits b elements' do expect(doc).to have_selector('b:contains("b tag")') @@ -207,133 +174,56 @@ describe 'GitLab Markdown', feature: true do end end - describe 'EmojiFilter' do - it 'parses Emoji' do - expect(doc).to have_selector('img.emoji', count: 10) - end - end - - describe 'TableOfContentsFilter' do - it 'creates anchors inside header elements' do - aggregate_failures do - expect(doc).to have_selector('h1 a#gitlab-markdown') - expect(doc).to have_selector('h2 a#markdown') - expect(doc).to have_selector('h3 a#autolinkfilter') - end - end - end - - describe 'AutolinkFilter' do - def body - get_section('autolinkfilter').next_element - end - - # Override Capybara's `have_link` matcher to simplify our use case - def have_link(link) - super(link, href: link) - end - - it 'autolinks http://' do - expect(body).to have_link('http://about.gitlab.com/') - end - - it 'autolinks https://' do - expect(body).to have_link('https://google.com/') - end - - it 'autolinks ftp://' do - expect(body).to have_link('ftp://ftp.us.debian.org/debian/') - end - - it 'autolinks smb://' do - expect(body).to have_link('smb://foo/bar/baz') - end - - it 'autolinks irc://' do - expect(body).to have_link('irc://irc.freenode.net/git') - end - - it 'autolinks short, invalid URLs' do - expect(body).to have_link('http://localhost:3000') - end - - %w(code a kbd).each do |elem| - it "ignores links inside '#{elem}' element" do - expect(body).not_to have_selector("#{elem} a") - end - end - end - describe 'ExternalLinkFilter' do - let(:links) { get_section('externallinkfilter').next_element } - it 'adds nofollow to external link' do - expect(links.css('a').first.to_html).to match 'nofollow' + link = doc.at_css('a:contains("Google")') + expect(link.attr('rel')).to match 'nofollow' end it 'ignores internal link' do - expect(links.css('a').last.to_html).not_to match 'nofollow' + link = doc.at_css('a:contains("GitLab Root")') + expect(link.attr('rel')).not_to match 'nofollow' end end + end - describe 'ReferenceFilter' do - it 'handles references in headers' do - header = doc.at_css('#reference-filters-eg-1').parent - - expect(header.css('a').size).to eq 2 - end - - it "handles references in Markdown" do - body = get_section('reference-filters-eg-1') - expect(body).to have_selector('em a.gfm-merge_request', count: 1) - end - - it 'parses user references' do - body = get_section('userreferencefilter') - expect(body).to have_selector('a.gfm.gfm-project_member', count: 3) - end + context 'default pipeline' do + before(:all) do + @html = markdown(@feat.raw_markdown) + end - it 'parses issue references' do - body = get_section('issuereferencefilter') - expect(body).to have_selector('a.gfm.gfm-issue', count: 2) - end + it_behaves_like 'all pipelines' - it 'parses merge request references' do - body = get_section('mergerequestreferencefilter') - expect(body).to have_selector('a.gfm.gfm-merge_request', count: 2) - end + it 'includes RelativeLinkFilter' do + expect(doc).to parse_relative_links + end - it 'parses snippet references' do - body = get_section('snippetreferencefilter') - expect(body).to have_selector('a.gfm.gfm-snippet', count: 2) - end + it 'includes EmojiFilter' do + expect(doc).to parse_emoji + end - it 'parses commit range references' do - body = get_section('commitrangereferencefilter') - expect(body).to have_selector('a.gfm.gfm-commit_range', count: 2) - end + it 'includes TableOfContentsFilter' do + expect(doc).to create_header_links + end - it 'parses commit references' do - body = get_section('commitreferencefilter') - expect(body).to have_selector('a.gfm.gfm-commit', count: 2) - end + it 'includes AutolinkFilter' do + expect(doc).to create_autolinks + end - it 'parses label references' do - body = get_section('labelreferencefilter') - expect(body).to have_selector('a.gfm.gfm-label', count: 3) + it 'includes all reference filters' do + aggregate_failures do + expect(doc).to reference_users + expect(doc).to reference_issues + expect(doc).to reference_merge_requests + expect(doc).to reference_snippets + expect(doc).to reference_commit_ranges + expect(doc).to reference_commits + expect(doc).to reference_labels end end - describe 'Task Lists' do - it 'generates task lists' do - body = get_section('task-lists') - - aggregate_failures do - expect(body).to have_selector('ul.task-list', count: 2) - expect(body).to have_selector('li.task-list-item', count: 7) - expect(body).to have_selector('input[checked]', count: 3) - end - end + it 'includes TaskListFilter' do + expect(doc).to parse_task_lists end end diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb new file mode 100644 index 00000000000..9df226c3af8 --- /dev/null +++ b/spec/support/matchers/markdown_matchers.rb @@ -0,0 +1,156 @@ +# MarkdownMatchers +# +# Custom matchers for our custom HTML::Pipeline filters. These are used to test +# that specific filters are or are not used by our defined pipelines. +# +# Must be included manually. +module MarkdownMatchers + extend RSpec::Matchers::DSL + include Capybara::Node::Matchers + + # RelativeLinkFilter + matcher :parse_relative_links do + set_default_markdown_messages + + match do |actual| + link = actual.at_css('a:contains("Relative Link")') + image = actual.at_css('img[alt="Relative Image"]') + + expect(link['href']).to end_with('master/doc/README.md') + expect(image['src']).to end_with('master/app/assets/images/touch-icon-ipad.png') + end + end + + # EmojiFilter + matcher :parse_emoji do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('img.emoji', count: 10) + end + end + + # TableOfContentsFilter + matcher :create_header_links do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('h1 a#gitlab-markdown') + expect(actual).to have_selector('h2 a#markdown') + expect(actual).to have_selector('h3 a#autolinkfilter') + end + end + + # AutolinkFilter + matcher :create_autolinks do + def have_autolink(link) + have_link(link, href: link) + end + + set_default_markdown_messages + + match do |actual| + expect(actual).to have_autolink('http://about.gitlab.com/') + expect(actual).to have_autolink('https://google.com/') + expect(actual).to have_autolink('ftp://ftp.us.debian.org/debian/') + expect(actual).to have_autolink('smb://foo/bar/baz') + expect(actual).to have_autolink('irc://irc.freenode.net/git') + expect(actual).to have_autolink('http://localhost:3000') + + %w(code a kbd).each do |elem| + expect(body).not_to have_selector("#{elem} a") + end + end + end + + # UserReferenceFilter + matcher :reference_users do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-project_member', count: 3) + end + end + + # IssueReferenceFilter + matcher :reference_issues do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-issue', count: 3) + end + end + + # MergeRequestReferenceFilter + matcher :reference_merge_requests do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-merge_request', count: 3) + expect(actual).to have_selector('em a.gfm-merge_request') + end + end + + # SnippetReferenceFilter + matcher :reference_snippets do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-snippet', count: 2) + end + end + + # CommitRangeReferenceFilter + matcher :reference_commit_ranges do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-commit_range', count: 2) + end + end + + # CommitReferenceFilter + matcher :reference_commits do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-commit', count: 2) + end + end + + # LabelReferenceFilter + matcher :reference_labels do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('a.gfm.gfm-label', count: 3) + end + end + + # TaskListFilter + matcher :parse_task_lists do + set_default_markdown_messages + + match do |actual| + expect(actual).to have_selector('ul.task-list', count: 2) + expect(actual).to have_selector('li.task-list-item', count: 7) + expect(actual).to have_selector('input[checked]', count: 3) + end + end +end + +# Monkeypatch the matcher DSL so that we can reduce some noisy duplication for +# setting the failure messages for these matchers +module RSpec::Matchers::DSL::Macros + def set_default_markdown_messages + failure_message do + # expected to parse emoji, but didn't + "expected to #{description}, but didn't" + end + + failure_message_when_negated do + # expected not to parse task lists, but did + "expected not to #{description}, but did" + end + end +end -- cgit v1.2.1 From 8c957b54f5a70d07a0c70f15c84cdf9fc7eb0f23 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 28 Jul 2015 23:27:08 -0400 Subject: Fix setup/teardown for Markdown feature spec Prior, CI seemed to be freezing after running these specs. --- spec/features/markdown_spec.rb | 25 +++++++++---------------- spec/support/markdown_feature.rb | 8 -------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb index ddef2317e1c..859a62f740f 100644 --- a/spec/features/markdown_spec.rb +++ b/spec/features/markdown_spec.rb @@ -29,22 +29,6 @@ describe 'GitLab Markdown', feature: true do include GitlabMarkdownHelper include MarkdownMatchers - # Let's only parse this thing once - before(:all) do - @feat = MarkdownFeature.new - - # `gfm_with_options` depends on a `@project` variable - @project = @feat.project - end - - after(:all) do - @feat.teardown - end - - def doc(html = @html) - Nokogiri::HTML::DocumentFragment.parse(html) - end - # Sometimes it can be useful to see the parsed output of the Markdown document # for debugging. Call this method to write the output to # `tmp/capybara/.html`. @@ -54,6 +38,10 @@ describe 'GitLab Markdown', feature: true do end end + def doc(html = @html) + Nokogiri::HTML::DocumentFragment.parse(html) + end + # Shared behavior that all pipelines should exhibit shared_examples 'all pipelines' do describe 'Redcarpet extensions' do @@ -189,6 +177,11 @@ describe 'GitLab Markdown', feature: true do context 'default pipeline' do before(:all) do + @feat = MarkdownFeature.new + + # `gfm_with_options` depends on a `@project` variable + @project = @feat.project + @html = markdown(@feat.raw_markdown) end diff --git a/spec/support/markdown_feature.rb b/spec/support/markdown_feature.rb index 5e18ffa4143..2a868aed73b 100644 --- a/spec/support/markdown_feature.rb +++ b/spec/support/markdown_feature.rb @@ -10,14 +10,6 @@ class MarkdownFeature include FactoryGirl::Syntax::Methods - def initialize - DatabaseCleaner.start - end - - def teardown - DatabaseCleaner.clean - end - def user @user ||= create(:user) end -- cgit v1.2.1 From c5aae3077335ab0eaafb73f51548d4c85413a1d1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 11:18:55 +0200 Subject: Set internal backup directory modes on create This sidesteps problems with running 'chmod' on some CIFS mounts. --- lib/backup/database.rb | 2 +- lib/backup/manager.rb | 2 -- lib/backup/repository.rb | 2 +- lib/backup/uploads.rb | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index c5a5396cbbf..8450019980f 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -7,7 +7,7 @@ module Backup def initialize @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] @db_dir = File.join(Gitlab.config.backup.path, 'db') - FileUtils.mkdir_p(@db_dir) unless Dir.exists?(@db_dir) + FileUtils.mkdir_p(@db_dir, mode: 0700)unless Dir.exists?(@db_dir) end def dump diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 6fa2079d1a8..9ae4b346436 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -16,8 +16,6 @@ module Backup file << s.to_yaml.gsub(/^---\n/,'') end - FileUtils.chmod(0700, folders_to_backup) - # create archive $progress.print "Creating backup archive: #{tar_file} ... " orig_umask = File.umask(0077) diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index dfb2da9f84e..36d43d62982 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -130,7 +130,7 @@ module Backup def prepare FileUtils.rm_rf(backup_repos_path) - FileUtils.mkdir_p(backup_repos_path) + FileUtils.mkdir_p(backup_repos_path, mode: 0700) end def silent diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb index bf43610acf6..ed445f79084 100644 --- a/lib/backup/uploads.rb +++ b/lib/backup/uploads.rb @@ -10,7 +10,7 @@ module Backup # Copy uploads from public/uploads to backup/uploads def dump - FileUtils.mkdir_p(backup_uploads_dir) + FileUtils.mkdir_p(backup_uploads_dir, mode: 0700) FileUtils.cp_r(app_uploads_dir, backup_dir) end -- cgit v1.2.1 From 05cca9342b3cff4e9f2785a062822cd3af9fcdd4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 12:03:53 +0200 Subject: Use URL helpers --- app/models/group.rb | 4 ++-- app/models/project.rb | 2 +- app/models/user.rb | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/models/group.rb b/app/models/group.rb index adcbbec465e..885d3b1e5ab 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,7 +17,7 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace - include Gitlab::ConfigHelper + include Rails.application.routes.url_helpers include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -64,7 +64,7 @@ class Group < Namespace end def web_url - [gitlab_config.url, "groups", self.path].join('/') + group_url(self) end def owners diff --git a/app/models/project.rb b/app/models/project.rb index ff372ea9aa5..0608133b2cb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -316,7 +316,7 @@ class Project < ActiveRecord::Base end def web_url - [gitlab_config.url, path_with_namespace].join('/') + namespace_project_url(self.namespace, self) end def web_url_without_protocol diff --git a/app/models/user.rb b/app/models/user.rb index 00a37cd9135..6dd2271abe2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,6 +67,7 @@ class User < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::CurrentSettings + include Rails.application.routes.url_helpers include Referable include Sortable include TokenAuthenticatable @@ -638,7 +639,7 @@ class User < ActiveRecord::Base end def web_url - [gitlab_config.url, "u", self.username].join('/') + user_url(self) end def all_emails -- cgit v1.2.1 From d953f6927cfa605d0bc336b09a25bde2a483b3ba Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 12:15:21 +0200 Subject: Restore Leave button on dashboard groups page --- app/views/dashboard/groups/index.html.haml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 6ef4d752ac3..0a354373b9b 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -23,10 +23,9 @@ %i.fa.fa-cogs Settings - - if can?(current_user, :admin_group_member, group) - = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do - %i.fa.fa-sign-out - Leave + = link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do + %i.fa.fa-sign-out + Leave = image_tag group_icon(group), class: "avatar s40 avatar-tile hidden-xs" = link_to group, class: 'group-name' do -- cgit v1.2.1 From 72c552c2d4ea985a9ab1470ba2e44fc7e52673d9 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 13:23:28 +0200 Subject: Fix specs --- app/models/project.rb | 2 +- spec/models/project_spec.rb | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 0608133b2cb..2d029962557 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -571,7 +571,7 @@ class Project < ActiveRecord::Base end def http_url_to_repo - [gitlab_config.url, '/', path_with_namespace, '.git'].join('') + "#{web_url}.git" end # Check if current branch name is marked as protected in the system diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 63091e913ff..1ffd92b9bd9 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -111,14 +111,20 @@ describe Project do expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') end - it 'returns the full web URL for this repo' do - project = Project.new(path: 'somewhere') - expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere") + describe "#web_url" do + let(:project) { create(:empty_project, path: "somewhere") } + + it 'returns the full web URL for this repo' do + expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.path}/somewhere") + end end - it 'returns the web URL without the protocol for this repo' do - project = Project.new(path: 'somewhere') - expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere") + describe "#web_url_without_protocol" do + let(:project) { create(:empty_project, path: "somewhere") } + + it 'returns the web URL without the protocol for this repo' do + expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/#{project.namespace.path}/somewhere") + end end describe 'last_activity methods' do -- cgit v1.2.1 From 4fb6ddfe06164c211f22e69fdec0b248bc61f6b4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 29 Jul 2015 15:40:08 +0200 Subject: Add ability to manage user email addresses via the API. --- CHANGELOG | 1 + doc/api/users.md | 132 +++++++++++++++++++++++++++++++ lib/api/entities.rb | 4 + lib/api/users.rb | 111 ++++++++++++++++++++++++++ spec/requests/api/users_spec.rb | 171 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 419 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7ca450d423c..ab46ef3b169 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Add ability to manage user email addresses via the API. v 7.13.2 - Fix randomly failed spec diff --git a/doc/api/users.md b/doc/api/users.md index 5dca77b5c7b..9ac55d3f09e 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -397,6 +397,138 @@ Parameters: Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. +## List emails + +Get a list of currently authenticated user's emails. + +``` +GET /user/emails +``` + +```json +[ + { + "id": 1, + "email": "email@example.com" + }, + { + "id": 3, + "email": "email2@example.com" + } +] +``` + +Parameters: + +- **none** + +## List emails for user + +Get a list of a specified user's emails. Available only for admin + +``` +GET /users/:uid/emails +``` + +Parameters: + +- `uid` (required) - id of specified user + +## Single SSH key + +Get a single key. + +``` +GET /user/emails/:id +``` + +Parameters: + +- `id` (required) - The ID of an SSH key + +```json +{ + "id": 1, + "email": "email@example.com" +} +``` + +## Add email + +Creates a new email owned by the currently authenticated user. + +``` +POST /user/emails +``` + +Parameters: + +- `email` (required) - email address + +```json +{ + "id": 4, + "email": "email@example.com" +} +``` + +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": { + "email": [ + "has already been taken" + ] + } +} +``` + +## Add email for user + +Create new email owned by specified user. Available only for admin + +``` +POST /users/:id/emails +``` + +Parameters: + +- `id` (required) - id of specified user +- `email` (required) - email address + +Will return created key with status `201 Created` on success, or `404 Not found` on fail. + +## Delete email for current user + +Deletes email owned by currently authenticated user. +This is an idempotent function and calling it on a email that is already deleted +or not available results in `200 OK`. + +``` +DELETE /user/emails/:id +``` + +Parameters: + +- `id` (required) - email ID + +## Delete email for given user + +Deletes email owned by a specified user. Available only for admin. + +``` +DELETE /users/:uid/emails/:id +``` + +Parameters: + +- `uid` (required) - id of specified user +- `id` (required) - email ID + +Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. + ## Block user Blocks the specified user. Available only for admin. diff --git a/lib/api/entities.rb b/lib/api/entities.rb index ecf1412dee5..ce3d09a32cd 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -31,6 +31,10 @@ module API expose :private_token end + class Email < Grape::Entity + expose :id, :email + end + class Hook < Grape::Entity expose :id, :url, :created_at end diff --git a/lib/api/users.rb b/lib/api/users.rb index c468371d3d4..bd8cc9f16a8 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -185,6 +185,65 @@ module API end end + # Add email to a specified user. Only available to admin users. + # + # Parameters: + # id (required) - The ID of a user + # email (required) - Email address + # Example Request: + # POST /users/:id/emails + post ":id/emails" do + authenticated_as_admin! + required_attributes! [:email] + + user = User.find(params[:id]) + attrs = attributes_for_keys [:email] + email = user.emails.new attrs + if email.save + NotificationService.new.new_email(email) + present email, with: Entities::Email + else + render_validation_error!(email) + end + end + + # Get emails of a specified user. Only available to admin users. + # + # Parameters: + # uid (required) - The ID of a user + # Example Request: + # GET /users/:uid/emails + get ':uid/emails' do + authenticated_as_admin! + user = User.find_by(id: params[:uid]) + not_found!('User') unless user + + present user.emails, with: Entities::Email + end + + # Delete existing email of a specified user. Only available to admin + # users. + # + # Parameters: + # uid (required) - The ID of a user + # id (required) - Email ID + # Example Request: + # DELETE /users/:uid/emails/:id + delete ':uid/emails/:id' do + authenticated_as_admin! + user = User.find_by(id: params[:uid]) + not_found!('User') unless user + + begin + email = user.emails.find params[:id] + email.destroy + + user.update_secondary_emails! + rescue ActiveRecord::RecordNotFound + not_found!('Email') + end + end + # Delete user. Available only for admin # # Example Request: @@ -289,6 +348,58 @@ module API rescue end end + + # Get currently authenticated user's emails + # + # Example Request: + # GET /user/emails + get "emails" do + present current_user.emails, with: Entities::Email + end + + # Get single email owned by currently authenticated user + # + # Example Request: + # GET /user/emails/:id + get "emails/:id" do + email = current_user.emails.find params[:id] + present email, with: Entities::Email + end + + # Add new email to currently authenticated user + # + # Parameters: + # email (required) - Email address + # Example Request: + # POST /user/emails + post "emails" do + required_attributes! [:email] + + attrs = attributes_for_keys [:email] + email = current_user.emails.new attrs + if email.save + NotificationService.new.new_email(email) + present email, with: Entities::Email + else + render_validation_error!(email) + end + end + + # Delete existing email of currently authenticated user + # + # Parameters: + # id (required) - EMail ID + # Example Request: + # DELETE /user/emails/:id + delete "emails/:id" do + begin + email = current_user.emails.find params[:id] + email.destroy + + current_user.update_secondary_emails! + rescue + end + end end end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index c4dd1f76cf2..7fa6aebca0b 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -6,6 +6,7 @@ describe API::API, api: true do let(:user) { create(:user) } let(:admin) { create(:admin) } let(:key) { create(:key, user: user) } + let(:email) { create(:email, user: user) } describe "GET /users" do context "when unauthenticated" do @@ -384,6 +385,87 @@ describe API::API, api: true do end end + describe "POST /users/:id/emails" do + before { admin } + + it "should not create invalid email" do + post api("/users/#{user.id}/emails", admin), { } + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "email" not given') + end + + it "should create email" do + email_attrs = attributes_for :email + expect do + post api("/users/#{user.id}/emails", admin), email_attrs + end.to change{ user.emails.count }.by(1) + end + end + + describe 'GET /user/:uid/emails' do + before { admin } + + context 'when unauthenticated' do + it 'should return authentication error' do + get api("/users/#{user.id}/emails") + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'should return 404 for non-existing user' do + get api('/users/999999/emails', admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') + end + + it 'should return array of emails' do + user.emails << email + user.save + get api("/users/#{user.id}/emails", admin) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['email']).to eq(email.email) + end + end + end + + describe 'DELETE /user/:uid/emails/:id' do + before { admin } + + context 'when unauthenticated' do + it 'should return authentication error' do + delete api("/users/#{user.id}/emails/42") + expect(response.status).to eq(401) + end + end + + context 'when authenticated' do + it 'should delete existing email' do + user.emails << email + user.save + expect do + delete api("/users/#{user.id}/emails/#{email.id}", admin) + end.to change { user.emails.count }.by(-1) + expect(response.status).to eq(200) + end + + it 'should return 404 error if user not found' do + user.emails << email + user.save + delete api("/users/999999/emails/#{email.id}", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') + end + + it 'should return 404 error if email not foud' do + delete api("/users/#{user.id}/emails/42", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Email Not Found') + end + end + end + describe "DELETE /users/:id" do before { admin } @@ -528,6 +610,95 @@ describe API::API, api: true do end end + describe "GET /user/emails" do + context "when unauthenticated" do + it "should return authentication error" do + get api("/user/emails") + expect(response.status).to eq(401) + end + end + + context "when authenticated" do + it "should return array of emails" do + user.emails << email + user.save + get api("/user/emails", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first["email"]).to eq(email.email) + end + end + end + + describe "GET /user/emails/:id" do + it "should return single email" do + user.emails << email + user.save + get api("/user/emails/#{email.id}", user) + expect(response.status).to eq(200) + expect(json_response["email"]).to eq(email.email) + end + + it "should return 404 Not Found within invalid ID" do + get api("/user/emails/42", user) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') + end + + it "should return 404 error if admin accesses user's email" do + user.emails << email + user.save + admin + get api("/user/emails/#{email.id}", admin) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') + end + end + + describe "POST /user/emails" do + it "should create email" do + email_attrs = attributes_for :email + expect do + post api("/user/emails", user), email_attrs + end.to change{ user.emails.count }.by(1) + expect(response.status).to eq(201) + end + + it "should return a 401 error if unauthorized" do + post api("/user/emails"), email: 'some email' + expect(response.status).to eq(401) + end + + it "should not create email with invalid email" do + post api("/user/emails", user), {} + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "email" not given') + end + end + + describe "DELETE /user/emails/:id" do + it "should delete existed email" do + user.emails << email + user.save + expect do + delete api("/user/emails/#{email.id}", user) + end.to change{user.emails.count}.by(-1) + expect(response.status).to eq(200) + end + + it "should return success if email ID not found" do + delete api("/user/emails/42", user) + expect(response.status).to eq(200) + end + + it "should return 401 error if unauthorized" do + user.emails << email + user.save + delete api("/user/emails/#{email.id}") + expect(response.status).to eq(401) + end + end + describe 'PUT /user/:id/block' do before { admin } it 'should block existing user' do -- cgit v1.2.1 From 097a8952d0991b42752a84aedd472aa8291717cf Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 15:42:18 +0200 Subject: Move CHANGELOG entry to 7.14 --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d0f7f775916..3570bb6df51 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,7 @@ v 7.14.0 (unreleased) - Expire Rails cache entries after two weeks to prevent endless Redis growth - Add support for destroying project milestones (Stan Hu) - Add fetch command to the MR page. + - Allow custom backup archive permissions v 7.13.0 (unreleased) - Remove repository graph log to fix slow cache updates after push event (Stan Hu) @@ -52,7 +53,6 @@ v 7.13.0 (unreleased) - Correctly show anonymous authorized applications under Profile > Applications. - Query Optimization in MySQL. - Allow users to be blocked and unblocked via the API - - Allow custom backup archive permissions - Use native Postgres database cleaning during backup restore - Redesign project page. Show README as default instead of activity. Move project activity to separate page - Make left menu more hierarchical and less contextual by adding back item at top -- cgit v1.2.1 From e361dc3a1d78d77b40f865280e125926a901a200 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 29 Jul 2015 15:46:28 +0200 Subject: Manually fix automatic CHANGELOG merge --- CHANGELOG | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6e3a7e8669b..3cd18479bd8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,10 +19,6 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page. - Allow custom backup archive permissions -v 7.13.0 (unreleased) - - Add fetch command to the MR page - - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list - Fix: Label not shown in the Issue list, although it's set through web interface -- cgit v1.2.1 From 0fac66f84d85eb072f2d96a54820ac805799c5f3 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 30 Jul 2015 01:06:16 +0300 Subject: Mention group and project name in flash messages upon create, update and delete. --- CHANGELOG | 1 + app/controllers/groups_controller.rb | 6 +++--- app/controllers/projects_controller.rb | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 01c59299ece..0cebe2519e3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) v 7.13.2 - Fix randomly failed spec diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 901c1cdddcb..784cb0f8f7e 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -24,7 +24,7 @@ class GroupsController < Groups::ApplicationController if @group.save @group.add_owner(current_user) - redirect_to @group, notice: 'Group was successfully created.' + redirect_to @group, notice: "Group '#{@group.name}' was successfully created." else render action: "new" end @@ -75,7 +75,7 @@ class GroupsController < Groups::ApplicationController def update if @group.update_attributes(group_params) - redirect_to edit_group_path(@group), notice: 'Group was successfully updated.' + redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated." else render action: "edit" end @@ -84,7 +84,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, notice: 'Group was removed.' + redirect_to root_path, notice: "Group '#{@group.name} was deleted." end protected diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 586359f3080..dafc11d0707 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -24,7 +24,7 @@ class ProjectsController < ApplicationController if @project.saved? redirect_to( project_path(@project), - notice: 'Project was successfully created.' + notice: "Project '#{@project.name}' was successfully created." ) else render 'new' @@ -36,11 +36,11 @@ class ProjectsController < ApplicationController respond_to do |format| if status - flash[:notice] = 'Project was successfully updated.' + flash[:notice] = "Project '#{@project.name}' was successfully updated." format.html do redirect_to( edit_project_path(@project), - notice: 'Project was successfully updated.' + notice: "Project '#{@project.name}' was successfully updated." ) end format.js @@ -100,7 +100,7 @@ class ProjectsController < ApplicationController return access_denied! unless can?(current_user, :remove_project, @project) ::Projects::DestroyService.new(@project, current_user, {}).execute - flash[:alert] = 'Project deleted.' + flash[:alert] = "Project '#{@project.name}' was deleted." if request.referer.include?('/admin') redirect_to admin_namespaces_projects_path -- cgit v1.2.1 From baa157926d432f404a41c31ad6514ff8d5366269 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 30 Jul 2015 10:17:34 +0200 Subject: Stricter mkdir's in 'rake gitlab:backup:create' --- lib/backup/database.rb | 7 +++++-- lib/backup/repository.rb | 5 ++++- lib/backup/uploads.rb | 6 +++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/backup/database.rb b/lib/backup/database.rb index 8450019980f..bbb230a10f0 100644 --- a/lib/backup/database.rb +++ b/lib/backup/database.rb @@ -7,7 +7,11 @@ module Backup def initialize @config = YAML.load_file(File.join(Rails.root,'config','database.yml'))[Rails.env] @db_dir = File.join(Gitlab.config.backup.path, 'db') - FileUtils.mkdir_p(@db_dir, mode: 0700)unless Dir.exists?(@db_dir) + FileUtils.rm_rf(@db_dir) + # Ensure the parent dir of @db_dir exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create @db_dir before us + FileUtils.mkdir(@db_dir, mode: 0700) end def dump @@ -25,7 +29,6 @@ module Backup abort 'Backup failed' unless success $progress.print 'Compressing database ... ' - FileUtils.rm_f db_file_name_gz success = system('gzip', db_file_name) report_success(success) abort 'Backup failed: compress error' unless success diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 36d43d62982..4d70f7883dd 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -130,7 +130,10 @@ module Backup def prepare FileUtils.rm_rf(backup_repos_path) - FileUtils.mkdir_p(backup_repos_path, mode: 0700) + # Ensure the parent dir of backup_repos_path exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create backup_repos_path before us + FileUtils.mkdir(backup_repos_path, mode: 0700) end def silent diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb index ed445f79084..1f9626644e6 100644 --- a/lib/backup/uploads.rb +++ b/lib/backup/uploads.rb @@ -10,7 +10,11 @@ module Backup # Copy uploads from public/uploads to backup/uploads def dump - FileUtils.mkdir_p(backup_uploads_dir, mode: 0700) + FileUtils.rm_rf(backup_uploads_dir) + # Ensure the parent dir of backup_uploads_dir exists + FileUtils.mkdir_p(Gitlab.config.backup.path) + # Fail if somebody raced to create backup_uploads_dir before us + FileUtils.mkdir(backup_uploads_dir, mode: 0700) FileUtils.cp_r(app_uploads_dir, backup_dir) end -- cgit v1.2.1 From 70410fb6bc7ae475461361a7fe526d8c76601ec2 Mon Sep 17 00:00:00 2001 From: Mike C Date: Thu, 30 Jul 2015 08:23:11 +0000 Subject: fixed typo in backup_restore.md --- doc/raketasks/backup_restore.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 996a642e2f1..fbaeb3ff549 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -232,7 +232,7 @@ Deleting tmp directories...[DONE] We will assume that you have installed GitLab from an omnibus package and run `sudo gitlab-ctl reconfigure` at least once. -First make sure your backup tar file is in `/var/opt/gitlab/backups` (or whereever `gitlab_rails['backup_path']` points to). +First make sure your backup tar file is in `/var/opt/gitlab/backups` (or wherever `gitlab_rails['backup_path']` points to). ```shell sudo cp 1393513186_gitlab_backup.tar /var/opt/gitlab/backups/ @@ -352,4 +352,4 @@ For more information see similar questions on postgresql issue tracker[here](htt ## Note This documentation is for GitLab CE. -We backup GitLab.com and make sure your data is secure, but you can't use these methods to export / backup your data yourself from GitLab.com. +We backup GitLab.com and make sure your data is secure, but you can't use these methods to export / backup your data yourself from GitLab.com. \ No newline at end of file -- cgit v1.2.1 From 1c7a8b8c27398250983bf4329007f6971df65f34 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 11:41:59 +0200 Subject: Fix docs --- doc/api/users.md | 12 ++++++------ spec/requests/api/users_spec.rb | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/api/users.md b/doc/api/users.md index 9ac55d3f09e..7ba2db248ff 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -434,9 +434,9 @@ Parameters: - `uid` (required) - id of specified user -## Single SSH key +## Single email -Get a single key. +Get a single email. ``` GET /user/emails/:id @@ -444,7 +444,7 @@ GET /user/emails/:id Parameters: -- `id` (required) - The ID of an SSH key +- `id` (required) - email ID ```json { @@ -472,7 +472,7 @@ Parameters: } ``` -Will return created key with status `201 Created` on success. If an +Will return created email with status `201 Created` on success. If an error occurs a `400 Bad Request` is returned with a message explaining the error: ```json @@ -498,7 +498,7 @@ Parameters: - `id` (required) - id of specified user - `email` (required) - email address -Will return created key with status `201 Created` on success, or `404 Not found` on fail. +Will return created email with status `201 Created` on success, or `404 Not found` on fail. ## Delete email for current user @@ -527,7 +527,7 @@ Parameters: - `uid` (required) - id of specified user - `id` (required) - email ID -Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found. +Will return `200 OK` on success, or `404 Not found` if either user or email cannot be found. ## Block user diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 7fa6aebca0b..f2aa369985e 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -389,7 +389,7 @@ describe API::API, api: true do before { admin } it "should not create invalid email" do - post api("/users/#{user.id}/emails", admin), { } + post api("/users/#{user.id}/emails", admin), {} expect(response.status).to eq(400) expect(json_response['message']).to eq('400 (Bad request) "email" not given') end -- cgit v1.2.1 From b8066e2cd0c8ae8384b68c81ea3a6c071cd44c51 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 11:56:15 +0200 Subject: No more web url --- app/models/group.rb | 5 ----- app/models/project.rb | 3 +-- app/models/user.rb | 5 ----- lib/api/entities.rb | 12 ++++++++++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/app/models/group.rb b/app/models/group.rb index 885d3b1e5ab..cfb8faa1491 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -17,7 +17,6 @@ require 'carrierwave/orm/activerecord' require 'file_size_validator' class Group < Namespace - include Rails.application.routes.url_helpers include Referable has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember' @@ -63,10 +62,6 @@ class Group < Namespace end end - def web_url - group_url(self) - end - def owners @owners ||= group_members.owners.map(&:user) end diff --git a/app/models/project.rb b/app/models/project.rb index 2d029962557..99be170731b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -36,7 +36,6 @@ class Project < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::ShellAdapter include Gitlab::VisibilityLevel - include Rails.application.routes.url_helpers include Referable include Sortable @@ -316,7 +315,7 @@ class Project < ActiveRecord::Base end def web_url - namespace_project_url(self.namespace, self) + Rails.application.routes.url_helpers.namespace_project_url(self.namespace, self) end def web_url_without_protocol diff --git a/app/models/user.rb b/app/models/user.rb index 6dd2271abe2..4a10520b209 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -67,7 +67,6 @@ class User < ActiveRecord::Base include Gitlab::ConfigHelper include Gitlab::CurrentSettings - include Rails.application.routes.url_helpers include Referable include Sortable include TokenAuthenticatable @@ -638,10 +637,6 @@ class User < ActiveRecord::Base end end - def web_url - user_url(self) - end - def all_emails [self.email, *self.emails.map(&:email)] end diff --git a/lib/api/entities.rb b/lib/api/entities.rb index c1b0cece344..dcfd7a8e1a7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -5,7 +5,11 @@ module API end class UserBasic < UserSafe - expose :id, :state, :avatar_url, :web_url + expose :id, :state, :avatar_url + + expose :web_url do |user, options| + Rails.application.routes.url_helpers.user_url(user) + end end class User < UserBasic @@ -70,7 +74,11 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description - expose :avatar_url, :web_url + expose :avatar_url + + expose :web_url do |group, options| + Rails.application.routes.url_helpers.group_url(group) + end end class GroupDetail < Group -- cgit v1.2.1 From 2a60b8006b1374aec998370f9cfe5b574255712f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 12:35:09 +0200 Subject: Fix Project --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 99be170731b..cc2b936ba2a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -432,7 +432,7 @@ class Project < ActiveRecord::Base if avatar.present? [gitlab_config.url, avatar.url].join elsif avatar_in_git - [gitlab_config.url, namespace_project_avatar_path(namespace, self)].join + Rails.application.routes.url_helpers.namespace_project_avatar_url(namespace, self) end end -- cgit v1.2.1 From feb2865fba15524c7dd1ae03274c63ae02edd152 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 30 Jul 2015 14:11:26 +0300 Subject: Raise alert when group is deleted. This change was made to match the project deletion. --- app/controllers/groups_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 784cb0f8f7e..279c6ef0f4d 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -84,7 +84,7 @@ class GroupsController < Groups::ApplicationController def destroy DestroyGroupService.new(@group, current_user).execute - redirect_to root_path, notice: "Group '#{@group.name} was deleted." + redirect_to root_path, alert: "Group '#{@group.name} was deleted." end protected -- cgit v1.2.1 From 0b5acdd88fb745821cd49f539e7e6cd4874a58ab Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 15:12:57 +0200 Subject: Show buttons to add license, changelog and contribution guide if they're missing. --- CHANGELOG | 1 + app/assets/stylesheets/pages/projects.scss | 9 ++++++ app/helpers/projects_helper.rb | 44 +++++++++++++++++++++++++++--- app/views/projects/show.html.haml | 21 ++++++++++++-- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c03e5053d17..3b1d8dc7b61 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Show buttons to add license, changelog and contribution guide if they're missing. v 7.13.2 - Fix randomly failed spec diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 5f415f2d78f..21d958db80c 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -297,6 +297,15 @@ table.table.protected-branches-list tr.no-border { ul.nav-pills { display:inline-block; } li { display:inline; } a { float:left; } + + li.missing a { + color: #bbb; + border: 1px dashed #ccc; + + &:hover { + background-color: #FAFAFA; + } + } } pre.light-well { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index a675a292432..f5b78533896 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -184,7 +184,43 @@ module ProjectsHelper end end - def contribution_guide_url(project) + def add_contribution_guide_path(project) + if project && !project.repository.contribution_guide + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "CONTRIBUTING.md", + commit_message: "Add contribution guide" + ) + end + end + + def add_changelog_path(project) + if project && !project.repository.changelog + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "CHANGELOG", + commit_message: "Add changelog" + ) + end + end + + def add_license_path(project) + if project && !project.repository.license + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch, + file_name: "LICENSE", + commit_message: "Add license" + ) + end + end + + def contribution_guide_path(project) if project && contribution_guide = project.repository.contribution_guide namespace_project_blob_path( project.namespace, @@ -195,7 +231,7 @@ module ProjectsHelper end end - def changelog_url(project) + def changelog_path(project) if project && changelog = project.repository.changelog namespace_project_blob_path( project.namespace, @@ -206,7 +242,7 @@ module ProjectsHelper end end - def license_url(project) + def license_path(project) if project && license = project.repository.license namespace_project_blob_path( project.namespace, @@ -217,7 +253,7 @@ module ProjectsHelper end end - def version_url(project) + def version_path(project) if project && version = project.repository.version namespace_project_blob_path( project.namespace, diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 769dd68f089..4577b84ab89 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -22,19 +22,34 @@ %li = link_to namespace_project_tags_path(@project.namespace, @project) do = pluralize(number_with_delimiter(@repository.tag_names.count), 'tag') + - if @repository.changelog %li - = link_to changelog_url(@project) do + = link_to changelog_path(@project) do Changelog - if @repository.license %li - = link_to license_url(@project) do + = link_to license_path(@project) do License - if @repository.contribution_guide %li - = link_to contribution_guide_url(@project) do + = link_to contribution_guide_path(@project) do Contribution guide + - if current_user && can_push_branch?(@project, @project.default_branch) + - unless @repository.changelog + %li.missing + = link_to add_changelog_path(@project) do + Add Changelog + - unless @repository.license + %li.missing + = link_to add_license_path(@project) do + Add License + - unless @repository.contribution_guide + %li.missing + = link_to add_contribution_guide_path(@project) do + Add Contribution guide + - if @project.archived? .text-warning.center.prepend-top-20 %p -- cgit v1.2.1 From 66cc712fa516d758ab09f22ffe78b85cb4415740 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 30 Jul 2015 15:31:34 +0200 Subject: Fix method name. --- app/views/shared/issuable/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 8cc0b517cd2..ac8c1936c9e 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -100,7 +100,7 @@ = link_to 'Change branches', mr_change_branches_path(@merge_request) .form-actions - - if !issuable.project.empty_repo? && (guide_url = contribution_guide_url(issuable.project)) && !issuable.persisted? + - if !issuable.project.empty_repo? && (guide_url = contribution_guide_path(issuable.project)) && !issuable.persisted? %p Please review the %strong #{link_to 'guidelines for contribution', guide_url} -- cgit v1.2.1 From ee1710284883d4cf61fc89d5197beef63646a220 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 29 Jul 2015 09:03:15 -0700 Subject: Check that hooks directory exists before attempting to call realpath Closes #2121 --- lib/tasks/gitlab/check.rake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index aed84226a2f..badb47c6779 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -485,7 +485,8 @@ namespace :gitlab do if project.empty_repo? puts "repository is empty".magenta - elsif File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path) + elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) && + (File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path)) puts 'ok'.green else puts "wrong or missing hooks".red @@ -754,7 +755,7 @@ namespace :gitlab do print "Ruby version >= #{required_version} ? ... " if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".green + puts "yes (#{current_version})".green else puts "no".red try_fixing_it( @@ -772,7 +773,7 @@ namespace :gitlab do print "Git version >= #{required_version} ? ... " if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".green + puts "yes (#{current_version})".green else puts "no".red try_fixing_it( @@ -806,4 +807,3 @@ namespace :gitlab do end end end - -- cgit v1.2.1 From 168f10febaab7ec1590ed8a1ba2771b534ae9c22 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:20:10 -0700 Subject: added new doc about adding users and members --- doc/permissions/permissions.md | 3 +++ doc/workflow/README.md | 1 + doc/workflow/add-user/add-user.md | 25 ++++++++++++++++++++++++ doc/workflow/add-user/images/add-members.png | Bin 0 -> 2361 bytes doc/workflow/add-user/images/members.png | Bin 0 -> 8295 bytes doc/workflow/add-user/images/new-member.png | Bin 0 -> 12038 bytes doc/workflow/add-user/images/select-project.png | Bin 0 -> 4042 bytes 7 files changed, 29 insertions(+) create mode 100644 doc/workflow/add-user/add-user.md create mode 100644 doc/workflow/add-user/images/add-members.png create mode 100644 doc/workflow/add-user/images/members.png create mode 100644 doc/workflow/add-user/images/new-member.png create mode 100644 doc/workflow/add-user/images/select-project.png diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index e81432c600f..e6185472dab 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,6 +6,9 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. +To add or import a user or member, you can follow the [Project users and members +documentation](workflow/add-user/add-user.md). + ## Project | Action | Guest | Reporter | Developer | Master | Owner | diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 1f39d02bdf3..139f4db7d57 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -10,6 +10,7 @@ - [Notification emails](notifications.md) - [Project Features](project_features.md) - [Project forking workflow](forking_workflow.md) +- [Project users and members](add-user/add-user.md) - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md new file mode 100644 index 00000000000..1693dd6e527 --- /dev/null +++ b/doc/workflow/add-user/add-user.md @@ -0,0 +1,25 @@ +# Project Users and Members + +You can add or import members to your projects. You can also give them different access +levels. + +You should have 'master' or 'owner' permissions to add or import a new member to your +project. + +To add or import a new member, go to your project and click on "Members" on the left side +of your screen: + +![Members](images/members.png) + +Select "Add members" or "Import members" on the right side of your screen: + +![Add or Import](images/add-members.png) + +If you are adding a member, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to +give the member: + +![Add or Import](images/new-member.png) + +If you are importing a member, follow the steps to select the project where you'd like to import the user from. + +![Add or Import](images/select-project.png) diff --git a/doc/workflow/add-user/images/add-members.png b/doc/workflow/add-user/images/add-members.png new file mode 100644 index 00000000000..2805c5764a5 Binary files /dev/null and b/doc/workflow/add-user/images/add-members.png differ diff --git a/doc/workflow/add-user/images/members.png b/doc/workflow/add-user/images/members.png new file mode 100644 index 00000000000..f1797b95f67 Binary files /dev/null and b/doc/workflow/add-user/images/members.png differ diff --git a/doc/workflow/add-user/images/new-member.png b/doc/workflow/add-user/images/new-member.png new file mode 100644 index 00000000000..d500daea56e Binary files /dev/null and b/doc/workflow/add-user/images/new-member.png differ diff --git a/doc/workflow/add-user/images/select-project.png b/doc/workflow/add-user/images/select-project.png new file mode 100644 index 00000000000..dd3844edff8 Binary files /dev/null and b/doc/workflow/add-user/images/select-project.png differ -- cgit v1.2.1 From e70901abe76b07d7d08c6687ec746ac0491ddf26 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:26:10 -0700 Subject: typo --- doc/permissions/permissions.md | 4 ++-- doc/workflow/add-user/add-user.md | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index e6185472dab..029d446640d 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,8 +6,8 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. -To add or import a user or member, you can follow the [Project users and members -documentation](workflow/add-user/add-user.md). +To add or import a user or member, you can follow the [project users and members +documentation](doc/workflow/add-user/add-user.md). ## Project diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md index 1693dd6e527..58f7bd0a5ce 100644 --- a/doc/workflow/add-user/add-user.md +++ b/doc/workflow/add-user/add-user.md @@ -1,12 +1,12 @@ -# Project Users and Members +# Project users and members -You can add or import members to your projects. You can also give them different access +You can add or import users to your projects. You can also give them different access levels. -You should have 'master' or 'owner' permissions to add or import a new member to your +You should have 'master' or 'owner' permissions to add or import a new user to your project. -To add or import a new member, go to your project and click on "Members" on the left side +To add or import a user, go to your project and click on "Members" on the left side of your screen: ![Members](images/members.png) @@ -15,11 +15,11 @@ Select "Add members" or "Import members" on the right side of your screen: ![Add or Import](images/add-members.png) -If you are adding a member, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to -give the member: +If you are adding a user, select the user and the [permission level](doc/permissions/permissions.md) that you'd like to +give the user: ![Add or Import](images/new-member.png) -If you are importing a member, follow the steps to select the project where you'd like to import the user from. +If you are importing a user, follow the steps to select the project where you'd like to import the user from: ![Add or Import](images/select-project.png) -- cgit v1.2.1 From bd72b5bd32c64606a498066cadf9f765be059b9d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 30 Jul 2015 13:40:30 -0700 Subject: Fix version for CHANGELOG entry --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index c03e5053d17..a3b1b82e0eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Disabled autocapitalize and autocorrect on login field (Daryl Chan) v 7.13.2 - Fix randomly failed spec @@ -29,7 +30,6 @@ v 7.13.2 - Show the first tab automatically on MergeRequests#new - Add rake task 'gitlab:update_commit_count' (Daniel Gerhardt) - Fix Gmail Actions - - Disabled autocapitalize and autocorrect on login field (Daryl Chan) v 7.13.1 - Fix: Label modifications are not reflected in existing notes and in the issue list -- cgit v1.2.1 From 2911b71e821daf90642d2a60b62b14c4380832ad Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:50:15 -0700 Subject: added new doc about creating MR --- doc/gitlab-basics/README.md | 2 ++ doc/gitlab-basics/add-merge-request.md | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 doc/gitlab-basics/add-merge-request.md diff --git a/doc/gitlab-basics/README.md b/doc/gitlab-basics/README.md index 538894f5848..9491f8c91fe 100644 --- a/doc/gitlab-basics/README.md +++ b/doc/gitlab-basics/README.md @@ -19,3 +19,5 @@ Step-by-step guides on the basics of working with Git and GitLab. * [Fork a project](fork-project.md) * [Add a file](add-file.md) + +* [Create a Merge Request](add-merge-request.md) diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md new file mode 100644 index 00000000000..a02b3f05205 --- /dev/null +++ b/doc/gitlab-basics/add-merge-request.md @@ -0,0 +1,41 @@ +# How to create a merge request + +Merge Requests are useful to integrate separate changes that you've made to a project, on different branches. + +To create a new Merge Request, sign in to [GitLab.com](https://gitlab.com). + +Select a project on the right side of your screen: + +![Select a project](basicsimages/select_project.png) + +Click on "Merge Requests" on the left side of your screen: + +![Merge requests](basicsimages/merge_requests.png) + +Click on "+ new Merge Request" on the right side of the screen: + +![New Merge Request](basicsimages/new_merge_request.png) + +Select a source branch or branch: + +![Select a branch](basicsimages/select_branch.png) + +Click on the "compare branches" button: + +![Compare branches](basicsimages/compare_branches.png) + +Add a title and a description to your Merge Request: + +![Add a title and description](basicsimages/title_description_mr.png) + +Select a user to review your Merge Request and to accept or close it. You may also select milestones and labels (they are optional). Then click on the "submit new Merge Request" button: + +![Add a new merge request](basicsimages/add_new_merge_request.png) + +Your Merge Request will be ready to be approved and published. + +### Note + +After you created a new branch, you'll be able to find a "create a Merge Request" button at the top of your screen. +You may automatically create a Merge Request from your recently created branch when clicking on this button: + -- cgit v1.2.1 From 89fc87122fead708671180c88652d3a9bd032613 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Thu, 30 Jul 2015 13:54:37 -0700 Subject: added image --- doc/gitlab-basics/add-merge-request.md | 5 +++-- doc/gitlab-basics/basicsimages/button-create-mr.png | Bin 0 -> 6154 bytes 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 doc/gitlab-basics/basicsimages/button-create-mr.png diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md index a02b3f05205..d829faf097f 100644 --- a/doc/gitlab-basics/add-merge-request.md +++ b/doc/gitlab-basics/add-merge-request.md @@ -36,6 +36,7 @@ Your Merge Request will be ready to be approved and published. ### Note -After you created a new branch, you'll be able to find a "create a Merge Request" button at the top of your screen. +After you created a new branch, you'll immediately find a "create a Merge Request" button at the top of your screen. You may automatically create a Merge Request from your recently created branch when clicking on this button: - + +![Automatic MR button](basicsimages/button-create-mr.png) diff --git a/doc/gitlab-basics/basicsimages/button-create-mr.png b/doc/gitlab-basics/basicsimages/button-create-mr.png new file mode 100644 index 00000000000..457af459bb9 Binary files /dev/null and b/doc/gitlab-basics/basicsimages/button-create-mr.png differ -- cgit v1.2.1 From 4e22dcb6a34f43e5b3b2700ec72b32354315adc0 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Jul 2015 17:25:07 -0400 Subject: Add spec to RelativeLinkFilter for Unicode filenames --- lib/gitlab/markdown/relative_link_filter.rb | 13 +++++++++++-- spec/lib/gitlab/markdown/relative_link_filter_spec.rb | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index 3eaceba5323..30f50b82996 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -99,15 +99,24 @@ module Gitlab # Returns a String def path_type(path) unescaped_path = Addressable::URI.unescape(path) - if repository.tree(current_sha, unescaped_path).entries.any? + + if tree?(unescaped_path) 'tree' - elsif repository.blob_at(current_sha, unescaped_path).try(:image?) + elsif image?(unescaped_path) 'raw' else 'blob' end end + def tree?(path) + repository.tree(current_sha, path).entries.any? + end + + def image?(path) + repository.blob_at(current_sha, path).try(:image?) + end + def current_sha context[:commit].try(:id) || ref ? repository.commit(ref).try(:sha) : repository.head_commit.sha diff --git a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb index 5ee5310825d..7f4d67e403f 100644 --- a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb +++ b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb @@ -1,3 +1,5 @@ +# encoding: UTF-8 + require 'spec_helper' module Gitlab::Markdown @@ -101,6 +103,20 @@ module Gitlab::Markdown expect(doc.at_css('a')['href']).to eq 'http://example.com' end + it 'supports Unicode filenames' do + path = 'files/images/한글.png' + escaped = Addressable::URI.escape(path) + + # Stub these methods so the file doesn't actually need to be in the repo + allow_any_instance_of(described_class).to receive(:file_exists?). + and_return(true) + allow_any_instance_of(described_class). + to receive(:image?).with(path).and_return(true) + + doc = filter(image(escaped)) + expect(doc.at_css('img')['src']).to match '/raw/' + end + context 'when requested path is a file in the repo' do let(:requested_path) { 'doc/api/README.md' } include_examples :relative_to_requested -- cgit v1.2.1 From 7ca7770e984d802f9f35579d6b5c08ad63a3052a Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 30 Jul 2015 17:27:25 -0400 Subject: Fix CHANGELOG entry --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 86927eae79f..c1f7da82f5e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,7 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - - Fix the image file that contains non-ascii character is not displayed(Hiroyuki Sato) + - Add support for Unicode filenames in relative links (Hiroyuki Sato) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) - Fix commit data retrieval when branch name has single quotes (Stan Hu) - Check that project was actually created rather than just validated in import:repos task (Stan Hu) -- cgit v1.2.1 From 0abe98f0497b667ef85ad4e078ea5c10b5b26ede Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 30 Jul 2015 22:31:53 -0700 Subject: Fix multi-line syntax highlighting HTML span elements only apply to a single line, and in the case of multi-line comments, the highlighting was dropped as a result. Ensure that each line has the proper styling to fix this. Closes #1577 --- CHANGELOG | 1 + lib/rouge/formatters/html_gitlab.rb | 12 ++++++++++-- spec/helpers/blob_helper_spec.rb | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bfff6a56777..27cf89b5938 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix multi-line syntax highlighting (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Add support for Unicode filenames in relative links (Hiroyuki Sato) diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb index 485af6832d7..092a920a0c4 100644 --- a/lib/rouge/formatters/html_gitlab.rb +++ b/lib/rouge/formatters/html_gitlab.rb @@ -148,6 +148,12 @@ module Rouge end end + def wrap_values(val, element) + lines = val.split("\n") + lines = lines.map{ |x| "#{x}" } + lines.join("\n") + end + def span(tok, val) # http://stackoverflow.com/a/1600584/2587286 val = CGI.escapeHTML(val) @@ -155,11 +161,13 @@ module Rouge if tok.shortname.empty? val else + # In the case of multi-line values (e.g. comments), we need to apply + # styling to each line since span elements are inline. if @inline_theme rules = @inline_theme.style_for(tok).rendered_rules - "#{val}" + wrap_values(val, "style=\"#{rules.to_a.join(';')}\"") else - "#{val}" + wrap_values(val, "class=\"#{tok.shortname}\"") end end end diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb index e49e4e6d5d8..76009c36099 100644 --- a/spec/helpers/blob_helper_spec.rb +++ b/spec/helpers/blob_helper_spec.rb @@ -6,6 +6,14 @@ describe BlobHelper do let(:no_context_content) { ":type \"assem\"))" } let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" } let(:split_content) { blob_content.split("\n") } + let(:multiline_content) do + %q( + def test(input): + """This is line 1 of a multi-line comment. + This is line 2. + """ + ) + end it 'should return plaintext for unknown lexer context' do result = highlight(blob_name, no_context_content, nowrap: true, continue: false) @@ -29,5 +37,15 @@ describe BlobHelper do result = split_content.map{ |content| highlight(blob_name, content, nowrap: true, continue: true) } expect(result).to eq(expected) end + + it 'should highlight multi-line comments' do + result = highlight(blob_name, multiline_content, nowrap: true, continue: false) + html = Nokogiri::HTML(result) + lines = html.search('.s') + expect(lines.count).to eq(3) + expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.') + expect(lines[1].text).to eq(' This is line 2.') + expect(lines[2].text).to eq(' """') + end end end -- cgit v1.2.1 From 7ba765201939bafb1d433cfa315779ab5b6d92b1 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 31 Jul 2015 13:56:15 +0200 Subject: Tweak project page buttons. --- CHANGELOG | 1 + app/assets/javascripts/project.js.coffee | 15 ++++++++----- app/assets/stylesheets/pages/projects.scss | 3 +-- app/views/projects/_home_panel.html.haml | 8 ++++++- app/views/projects/buttons/_dropdown.html.haml | 29 +++++++++++++------------- app/views/projects/buttons/_fork.html.haml | 4 ++-- app/views/projects/buttons/_star.html.haml | 4 ++-- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c03e5053d17..0ae37ea6cd6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page - Fix bug causing Bitbucket importer to crash when OAuth application had been removed. - Add fetch command to the MR page. + - Tweak project page buttons. v 7.13.2 - Fix randomly failed spec diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index eb8c1fa1426..cb44e1abe97 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -1,12 +1,12 @@ class @Project constructor: -> # Git clone panel switcher - scope = $ '.git-clone-holder' - if scope.length > 0 - $('a, button', scope).click -> - $('a, button', scope).removeClass 'active' + cloneHolder = $ '.git-clone-holder' + if cloneHolder.length > 0 + $('a, button', cloneHolder).click -> + $('a, button', cloneHolder).removeClass 'active' $(@).addClass 'active' - $('#project_clone', scope).val $(@).data 'clone' + $('#project_clone', cloneHolder).val $(@).data 'clone' $(".clone").text("").append $(@).data 'clone' # Ref switcher @@ -24,3 +24,8 @@ class @Project $.cookie('hide_no_password_message', 'false', { path: path }) $(@).parents('.no-password-message').remove() e.preventDefault() + + $('.js-toggle-clone-holder').on 'click', (e) -> + cloneHolder.toggle() + + cloneHolder.hide() diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 5f415f2d78f..c9627972279 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -16,7 +16,6 @@ .project-home-panel { text-align: center; - margin-bottom: 20px; .project-identicon-holder { margin-bottom: 15px; @@ -39,7 +38,7 @@ .git-clone-holder { max-width: 600px; - margin: 0 auto; + margin: 20px auto; } .visibility-level-label { diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 7b6b4b35c8d..159ce1ecf3f 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -19,9 +19,15 @@ Forked from = forked_from_project.namespace.try(:name) + - if can? current_user, :download_code, @project + = link_to "#", class: 'btn js-toggle-clone-holder' do + = icon('cloud-download fw') + Clone + - if can? current_user, :download_code, @project = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn', rel: 'nofollow' do - %i.fa.fa-download + = icon('download fw') + Download = render 'projects/buttons/dropdown' diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index 99c2ed62545..cade930c8cc 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -1,31 +1,32 @@ - if current_user %span.dropdown %a.dropdown-toggle.btn.btn-new{href: '#', "data-toggle" => "dropdown"} - %i.fa.fa-plus + = icon('plus') %ul.dropdown-menu - - if @project.issues_enabled && can?(current_user, :create_issue, @project) + - if can?(current_user, :create_issue, @project) %li - = link_to url_for_new_issue, title: "New Issue" do + = link_to url_for_new_issue do + = icon('exclamation-circle fw') New issue - - if @project.merge_requests_enabled && can?(current_user, :create_merge_request, @project) + - if can?(current_user, :create_merge_request, @project) %li - = link_to new_namespace_project_merge_request_path(@project.namespace, @project), title: "New Merge Request" do + = link_to new_namespace_project_merge_request_path(@project.namespace, @project) do + = icon('tasks fw') New merge request - - if @project.snippets_enabled && can?(current_user, :create_snippet, @project) + - if can?(current_user, :create_snippet, @project) %li - = link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do + = link_to new_namespace_project_snippet_path(@project.namespace, @project) do + = icon('file-text-o fw') New snippet - - if can?(current_user, :admin_project_member, @project) - %li - = link_to namespace_project_project_members_path(@project.namespace, @project), title: "New project member" do - New project member - - if can? current_user, :push_code, @project + - if can?(current_user, :push_code, @project) %li.divider %li = link_to new_namespace_project_branch_path(@project.namespace, @project) do - New git branch + = icon('code-fork fw') + New branch %li = link_to new_namespace_project_tag_path(@project.namespace, @project) do - New git tag + = icon('tags fw') + New tag diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index f0483c79edc..854c154824d 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,13 +1,13 @@ - if current_user && can?(current_user, :fork_project, @project) - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn' do - = icon('code-fork') + = icon('code-fork fw') Fork %span.count = @project.forks_count - else = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn' do - = icon('code-fork') + = icon('code-fork fw') Fork %span.count = @project.forks_count diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml index b5f14b43bfd..5d7df5ae099 100644 --- a/app/views/projects/buttons/_star.html.haml +++ b/app/views/projects/buttons/_star.html.haml @@ -1,6 +1,6 @@ - if current_user = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star', method: :post, remote: true do - = icon('star') + = icon('star fw') - if current_user.starred?(@project) Unstar - else @@ -16,7 +16,7 @@ - else = link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do - = icon('star') + = icon('star fw') Star %span.count = @project.star_count -- cgit v1.2.1 From 0736f348a6953e6417d3857b78ea5c7eb5954e51 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 31 Jul 2015 14:15:49 +0200 Subject: Use before_actions --- app/controllers/groups/application_controller.rb | 6 ++++++ app/controllers/groups/group_members_controller.rb | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 4df9d1b7533..6878d4bc07e 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -18,4 +18,10 @@ class Groups::ApplicationController < ApplicationController return render_404 end end + + def authorize_admin_group_member! + unless can?(current_user, :admin_group_member, group) + return render_403 + end + end end diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index b9c428a964f..91518c44a98 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -5,6 +5,7 @@ class Groups::GroupMembersController < Groups::ApplicationController # Authorize before_action :authorize_read_group! before_action :authorize_admin_group!, except: [:index, :leave] + before_action :authorize_admin_group_member!, only: [:create, :resend_invite] def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @@ -21,8 +22,6 @@ class Groups::GroupMembersController < Groups::ApplicationController end def create - return render_403 unless can?(current_user, :admin_group_member, @group) - @group.add_users(params[:user_ids].split(','), params[:access_level], current_user) redirect_to group_group_members_path(@group), notice: 'Users were successfully added.' @@ -51,8 +50,6 @@ class Groups::GroupMembersController < Groups::ApplicationController end def resend_invite - return render_403 unless can?(current_user, :admin_group_member, @group) - redirect_path = group_group_members_path(@group) @group_member = @group.group_members.find(params[:id]) -- cgit v1.2.1 From 87df06171ebfdcab01f377e4e040f72b4ba3b013 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 31 Jul 2015 15:48:23 +0200 Subject: Bump redis-store to 1.1.6 and remove redid-store-fix-expiry --- CHANGELOG | 1 + Gemfile.lock | 4 +-- config/initializers/redis-store-fix-expiry.rb | 44 --------------------------- 3 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 config/initializers/redis-store-fix-expiry.rb diff --git a/CHANGELOG b/CHANGELOG index 8dc23cf175f..5716afa227c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -24,6 +24,7 @@ v 7.14.0 (unreleased) - Add fetch command to the MR page. - Disabled autocapitalize and autocorrect on login field (Daryl Chan) - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) + - Remove redis-store TTL monkey patch v 7.13.2 - Fix randomly failed spec diff --git a/Gemfile.lock b/Gemfile.lock index 44365017edc..58622f2ac10 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -508,7 +508,7 @@ GEM rdoc (3.12.2) json (~> 1.4) redcarpet (3.3.2) - redis (3.1.0) + redis (3.2.1) redis-actionpack (4.0.0) actionpack (~> 4) redis-rack (~> 1.5.0) @@ -525,7 +525,7 @@ GEM redis-actionpack (~> 4) redis-activesupport (~> 4) redis-store (~> 1.1.0) - redis-store (1.1.4) + redis-store (1.1.6) redis (>= 2.2) request_store (1.0.5) rerun (0.10.0) diff --git a/config/initializers/redis-store-fix-expiry.rb b/config/initializers/redis-store-fix-expiry.rb deleted file mode 100644 index fce0a135330..00000000000 --- a/config/initializers/redis-store-fix-expiry.rb +++ /dev/null @@ -1,44 +0,0 @@ -# Monkey-patch Redis::Store to make 'setex' and 'expire' work with namespacing - -module Gitlab - class Redis - class Store - module Namespace - # Redis::Store#setex in redis-store 1.1.4 does not respect namespaces; - # this new method does. - def setex(key, expires_in, value, options=nil) - namespace(key) { |key| super(key, expires_in, value) } - end - - # Redis::Store#expire in redis-store 1.1.4 does not respect namespaces; - # this new method does. - def expire(key, expires_in) - namespace(key) { |key| super(key, expires_in) } - end - - private - - # Our new definitions of #setex and #expire above assume that the - # #namespace method exists. Because we cannot be sure of that, we - # re-implement the #namespace method from Redis::Store::Namespace so - # that it is available for all Redis::Store instances, whether they use - # namespacing or not. - # - # Based on lib/redis/store/namespace.rb L49-51 (redis-store 1.1.4) - def namespace(key) - if @namespace - yield interpolate(key) - else - # This Redis::Store instance does not use a namespace so we should - # just pass through the key. - yield key - end - end - end - end - end -end - -Redis::Store.class_eval do - include Gitlab::Redis::Store::Namespace -end -- cgit v1.2.1 From e72e721f0453abdd383aacebf0aebc8f5f7f4b3c Mon Sep 17 00:00:00 2001 From: karen Carias Date: Fri, 31 Jul 2015 08:21:53 -0700 Subject: small changes --- doc/gitlab-basics/add-file.md | 2 +- doc/gitlab-basics/add-merge-request.md | 4 ++-- doc/gitlab-basics/command-line-commands.md | 2 +- doc/gitlab-basics/create-group.md | 2 +- doc/gitlab-basics/create-project.md | 2 +- doc/gitlab-basics/create-your-ssh-keys.md | 2 +- doc/gitlab-basics/fork-project.md | 2 +- doc/gitlab-basics/start-using-git.md | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/gitlab-basics/add-file.md b/doc/gitlab-basics/add-file.md index e7c441e7698..57136ac5c39 100644 --- a/doc/gitlab-basics/add-file.md +++ b/doc/gitlab-basics/add-file.md @@ -2,7 +2,7 @@ You can create a file in your [shell](command-line-commands.md) or in GitLab. -To create a file in GitLab, sign in to [GitLab.com](https://gitlab.com). +To create a file in GitLab, sign in to GitLab. Select a project on the right side of your screen: diff --git a/doc/gitlab-basics/add-merge-request.md b/doc/gitlab-basics/add-merge-request.md index d829faf097f..236b4248ea2 100644 --- a/doc/gitlab-basics/add-merge-request.md +++ b/doc/gitlab-basics/add-merge-request.md @@ -2,9 +2,9 @@ Merge Requests are useful to integrate separate changes that you've made to a project, on different branches. -To create a new Merge Request, sign in to [GitLab.com](https://gitlab.com). +To create a new Merge Request, sign in to GitLab. -Select a project on the right side of your screen: +Go to the project where you'd like to merge your changes: ![Select a project](basicsimages/select_project.png) diff --git a/doc/gitlab-basics/command-line-commands.md b/doc/gitlab-basics/command-line-commands.md index a8223a9b161..b03cca4029c 100644 --- a/doc/gitlab-basics/command-line-commands.md +++ b/doc/gitlab-basics/command-line-commands.md @@ -2,7 +2,7 @@ ## Start working on your project -In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to [GitLab.com](https://gitlab.com). +In Git, when you copy a project you say you "clone" it. To work on a git project locally (from your own computer), you will need to clone it. To do this, sign in to GitLab. When you are on your Dashboard, click on the project that you'd like to clone, which you'll find at the right side of your screen. diff --git a/doc/gitlab-basics/create-group.md b/doc/gitlab-basics/create-group.md index 8e168395ff7..f80ae62e442 100644 --- a/doc/gitlab-basics/create-group.md +++ b/doc/gitlab-basics/create-group.md @@ -2,7 +2,7 @@ ## Create a group -Your projects in [GitLab.com](https://gitlab.com) can be organized in 2 different ways: +Your projects in GitLab can be organized in 2 different ways: under your own namespace for single projects, such as ´your-name/project-1'; or under groups. If you organize your projects under a group, it works like a folder. You can manage your group members' permissions and access to the projects. diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index 90d40cb6c51..b545d62549d 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -1,6 +1,6 @@ # How to create a project in GitLab -To create a new project, sign in to [GitLab.com](https://gitlab.com). +To create a new project, sign in to GitLab. Go to your Dashboard and click on "new project" on the right side of your screen. diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md index dcd3e6ffb31..c8a73feb028 100644 --- a/doc/gitlab-basics/create-your-ssh-keys.md +++ b/doc/gitlab-basics/create-your-ssh-keys.md @@ -6,7 +6,7 @@ You need to connect your computer to your GitLab account through SSH Keys. They Create an account on GitLab. Sign up and check your email for your confirmation link. -After you confirm, go to [GitLab.com](https://about.gitlab.com/) and sign in to your account. +After you confirm, go to GitLab and sign in to your account. ## Add your SSH Key diff --git a/doc/gitlab-basics/fork-project.md b/doc/gitlab-basics/fork-project.md index 5173aae2c0f..5f8b81ea919 100644 --- a/doc/gitlab-basics/fork-project.md +++ b/doc/gitlab-basics/fork-project.md @@ -6,7 +6,7 @@ publishing or not, without affecting your original project. It takes just a few steps to fork a project in GitLab. -Sign in to [gitlab.com](https://gitlab.com). +Sign in to GitLab. Select a project on the right side of your screen: diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index 5b1c6c1cd46..b2ceda025c0 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -1,6 +1,6 @@ # Start using Git on the command line -If you want to start using a Git and GitLab, make sure that you have created an account on [GitLab.com](https://about.gitlab.com/). +If you want to start using a Git and GitLab, make sure that you have created an account on GitLab. ## Open a shell -- cgit v1.2.1 From 8802846565f382f4bf21ff7e08a4e9c459bb10d6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 31 Jul 2015 14:35:32 +0200 Subject: Fix indentation --- lib/api/users.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/api/users.rb b/lib/api/users.rb index bd8cc9f16a8..ee29f952246 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -131,11 +131,11 @@ module API # Add ssh key to a specified user. Only available to admin users. # # Parameters: - # id (required) - The ID of a user - # key (required) - New SSH Key - # title (required) - New SSH Key's title + # id (required) - The ID of a user + # key (required) - New SSH Key + # title (required) - New SSH Key's title # Example Request: - # POST /users/:id/keys + # POST /users/:id/keys post ":id/keys" do authenticated_as_admin! required_attributes! [:title, :key] @@ -153,9 +153,9 @@ module API # Get ssh keys of a specified user. Only available to admin users. # # Parameters: - # uid (required) - The ID of a user + # uid (required) - The ID of a user # Example Request: - # GET /users/:uid/keys + # GET /users/:uid/keys get ':uid/keys' do authenticated_as_admin! user = User.find_by(id: params[:uid]) @@ -188,10 +188,10 @@ module API # Add email to a specified user. Only available to admin users. # # Parameters: - # id (required) - The ID of a user - # email (required) - Email address + # id (required) - The ID of a user + # email (required) - Email address # Example Request: - # POST /users/:id/emails + # POST /users/:id/emails post ":id/emails" do authenticated_as_admin! required_attributes! [:email] @@ -210,9 +210,9 @@ module API # Get emails of a specified user. Only available to admin users. # # Parameters: - # uid (required) - The ID of a user + # uid (required) - The ID of a user # Example Request: - # GET /users/:uid/emails + # GET /users/:uid/emails get ':uid/emails' do authenticated_as_admin! user = User.find_by(id: params[:uid]) -- cgit v1.2.1 From 1aa1f392482ac721e2fabf17e4b4a0cbc6493b0e Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 31 Jul 2015 17:44:16 -0400 Subject: Make `code` elements in links display as such Also adds some minor padding to inline `code` elements. --- app/assets/stylesheets/base/mixins.scss | 2 +- app/assets/stylesheets/generic/typography.scss | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/base/mixins.scss b/app/assets/stylesheets/base/mixins.scss index d64e79170b9..7beef1845ef 100644 --- a/app/assets/stylesheets/base/mixins.scss +++ b/app/assets/stylesheets/base/mixins.scss @@ -70,7 +70,7 @@ font-family: $monospace_font; white-space: pre; word-wrap: normal; - padding: 0; + padding: 1px 2px; } kbd { diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 2db4213159a..34b4ee3e17e 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -38,6 +38,10 @@ code { } } +a > code { + color: $link-color; +} + /** * Wiki typography * -- cgit v1.2.1 From fa5efea7f315d6eda05fa8215070979906cd1f02 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sat, 1 Aug 2015 19:10:14 -0400 Subject: Fix the `inline_theme` option for the Rouge formatter --- lib/rouge/formatters/html_gitlab.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb index 092a920a0c4..3f92212243d 100644 --- a/lib/rouge/formatters/html_gitlab.rb +++ b/lib/rouge/formatters/html_gitlab.rb @@ -47,7 +47,7 @@ module Rouge @lineanchors = lineanchors @lineanchorsid = lineanchorsid @anchorlinenos = anchorlinenos - @inline_theme = Theme.find(@inline_theme).new if @inline_theme.is_a?(String) + @inline_theme = Theme.find(inline_theme).new if inline_theme.is_a?(String) end def render(tokens) -- cgit v1.2.1 From 208e07fe6f4f5954f01462be6d5b595ec8d2fedf Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 1 Aug 2015 23:33:33 -0700 Subject: Fix errors deleting and creating branches with encoded slashes Closes #1804 --- CHANGELOG | 1 + app/controllers/projects/branches_controller.rb | 7 ++++--- spec/controllers/branches_controller_spec.rb | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8dc23cf175f..493d6122b99 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix errors deleting and creating branches with encoded slashes (Stan Hu) - Fix multi-line syntax highlighting (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb index 117ae3aaa3d..3ac0a75fa70 100644 --- a/app/controllers/projects/branches_controller.rb +++ b/app/controllers/projects/branches_controller.rb @@ -17,7 +17,9 @@ class Projects::BranchesController < Projects::ApplicationController def create branch_name = sanitize(strip_tags(params[:branch_name])) + branch_name = Addressable::URI.unescape(branch_name) ref = sanitize(strip_tags(params[:ref])) + ref = Addressable::URI.unescape(ref) result = CreateBranchService.new(project, current_user). execute(branch_name, ref) @@ -32,9 +34,8 @@ class Projects::BranchesController < Projects::ApplicationController end def destroy - status = DeleteBranchService.new(project, current_user).execute(params[:id]) - @branch_name = params[:id] - + @branch_name = Addressable::URI.unescape(params[:id]) + status = DeleteBranchService.new(project, current_user).execute(@branch_name) respond_to do |format| format.html do redirect_to namespace_project_branches_path(@project.namespace, diff --git a/spec/controllers/branches_controller_spec.rb b/spec/controllers/branches_controller_spec.rb index bd4c946b64b..8e06d4bdc77 100644 --- a/spec/controllers/branches_controller_spec.rb +++ b/spec/controllers/branches_controller_spec.rb @@ -54,6 +54,13 @@ describe Projects::BranchesController do let(:ref) { "" } it { is_expected.to render_template('new') } end + + context "valid branch name with encoded slashes" do + let(:branch) { "feature%2Ftest" } + let(:ref) { "" } + it { is_expected.to render_template('new') } + it { project.repository.branch_names.include?('feature/test')} + end end describe "POST destroy" do @@ -74,6 +81,19 @@ describe Projects::BranchesController do it { expect(subject).to render_template('destroy') } end + context "valid branch name with unencoded slashes" do + let(:branch) { "improve/awesome" } + + it { expect(response.status).to eq(200) } + it { expect(subject).to render_template('destroy') } + end + + context "valid branch name with encoded slashes" do + let(:branch) { "improve%2Fawesome" } + + it { expect(response.status).to eq(200) } + it { expect(subject).to render_template('destroy') } + end context "invalid branch name, valid ref" do let(:branch) { "no-branch" } -- cgit v1.2.1 From ecbe119af13dfef707694fc7a271d60f3af8f779 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 2 Aug 2015 00:07:23 -0700 Subject: Fix "Network" and "Graphs" pages for branches with encoded slashes Closes #1359 --- CHANGELOG | 1 + lib/extracts_path.rb | 2 +- spec/lib/extracts_path_spec.rb | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 493d6122b99..007961b2576 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) + - Fix "Network" and "Graphs" pages for branches with encoded slashes (Stan Hu) - Fix errors deleting and creating branches with encoded slashes (Stan Hu) - Fix multi-line syntax highlighting (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu) diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index 3f420553d42..322aed5e27c 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -94,7 +94,7 @@ module ExtractsPath @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? } @options = HashWithIndifferentAccess.new(@options) - @id = get_id + @id = Addressable::URI.unescape(get_id) @ref, @path = extract_ref(@id) @repo = @project.repository if @options[:extended_sha1].blank? diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index 4439775f612..9c115bbfc6a 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -29,6 +29,16 @@ describe ExtractsPath do assign_ref_vars expect(@logs_path).to eq("/#{@project.path_with_namespace}/refs/#{ref}/logs_tree/files/ruby/popen.rb") end + + context 'escaped sequences in ref' do + let(:ref) { "improve%2Fawesome" } + + it "id should have no escape sequences" do + assign_ref_vars + expect(@ref).to eq('improve/awesome') + expect(@logs_path).to eq("/#{@project.path_with_namespace}/refs/#{ref}/logs_tree/files/ruby/popen.rb") + end + end end describe '#extract_ref' do -- cgit v1.2.1 From f33898ecfb7c5c15c8a3355dabe07cdff296fc75 Mon Sep 17 00:00:00 2001 From: Atsushi Ishida Date: Mon, 3 Aug 2015 01:52:54 +0900 Subject: Re-annotate models --- app/models/application_setting.rb | 5 +++-- app/models/audit_event.rb | 14 ++++++++++++++ app/models/project.rb | 3 ++- app/models/security_event.rb | 14 ++++++++++++++ app/models/user.rb | 1 + spec/factories/projects.rb | 3 ++- spec/models/application_setting_spec.rb | 5 ++++- spec/models/project_spec.rb | 3 ++- spec/models/user_spec.rb | 1 + 9 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index fee52694099..6d1ad82a262 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -14,13 +14,14 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text +# version_check_enabled :boolean default(TRUE) # max_attachment_size :integer default(10), not null -# session_expire_delay :integer default(10080), not null # default_project_visibility :integer # default_snippet_visibility :integer # restricted_signup_domains :text -# user_oauth_applications :bool default(TRUE) +# user_oauth_applications :boolean default(TRUE) # after_sign_out_path :string(255) +# session_expire_delay :integer default(10080), not null # class ApplicationSetting < ActiveRecord::Base diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb index 967ffd46db0..0ed0dd98a59 100644 --- a/app/models/audit_event.rb +++ b/app/models/audit_event.rb @@ -1,3 +1,17 @@ +# == Schema Information +# +# Table name: audit_events +# +# id :integer not null, primary key +# author_id :integer not null +# type :string(255) not null +# entity_id :integer not null +# entity_type :string(255) not null +# details :text +# created_at :datetime +# updated_at :datetime +# + class AuditEvent < ActiveRecord::Base serialize :details, Hash diff --git a/app/models/project.rb b/app/models/project.rb index 0921fdfe9b4..3dc1729e812 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # require 'carrierwave/orm/activerecord' diff --git a/app/models/security_event.rb b/app/models/security_event.rb index d131c11cb6c..68c00adad59 100644 --- a/app/models/security_event.rb +++ b/app/models/security_event.rb @@ -1,2 +1,16 @@ +# == Schema Information +# +# Table name: audit_events +# +# id :integer not null, primary key +# author_id :integer not null +# type :string(255) not null +# entity_id :integer not null +# entity_type :string(255) not null +# details :text +# created_at :datetime +# updated_at :datetime +# + class SecurityEvent < AuditEvent end diff --git a/app/models/user.rb b/app/models/user.rb index 4a10520b209..2beefb1d614 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -57,6 +57,7 @@ # otp_backup_codes :text # public_email :string(255) default(""), not null # dashboard :integer default(0) +# project_view :integer default(0) # require 'carrierwave/orm/activerecord' diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 102678a1d74..1d500a11ad7 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # FactoryGirl.define do diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index d648f4078be..bc14ff98fd8 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -14,11 +14,14 @@ # default_branch_protection :integer default(2) # twitter_sharing_enabled :boolean default(TRUE) # restricted_visibility_levels :text +# version_check_enabled :boolean default(TRUE) # max_attachment_size :integer default(10), not null -# session_expire_delay :integer default(10080), not null # default_project_visibility :integer # default_snippet_visibility :integer # restricted_signup_domains :text +# user_oauth_applications :boolean default(TRUE) +# after_sign_out_path :string(255) +# session_expire_delay :integer default(10080), not null # require 'spec_helper' diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1ffd92b9bd9..5d40754d59d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -21,12 +21,13 @@ # import_url :string(255) # visibility_level :integer default(0), not null # archived :boolean default(FALSE), not null +# avatar :string(255) # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null # import_type :string(255) # import_source :string(255) -# avatar :string(255) +# commit_count :integer default(0) # require 'spec_helper' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 76f16323e2f..922e9ebf844 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -57,6 +57,7 @@ # otp_backup_codes :text # public_email :string(255) default(""), not null # dashboard :integer default(0) +# project_view :integer default(0) # require 'spec_helper' -- cgit v1.2.1 From 8ec7025a5d49548c1876440c1bd9b767828a5f56 Mon Sep 17 00:00:00 2001 From: Sytse Sijbrandij Date: Mon, 3 Aug 2015 11:33:48 +0000 Subject: Link to admin raketask --- doc/raketasks/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 770b7a70fe0..a8dc5c24df2 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -7,3 +7,4 @@ - [User management](user_management.md) - [Web hooks](web_hooks.md) - [Import](import.md) of git repositories in bulk +- [Rebuild authorized_keys file](http://doc.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators \ No newline at end of file -- cgit v1.2.1 From 8221236df1acd1d38f36e79f248bc4fff3474839 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sun, 2 Aug 2015 22:36:34 -0700 Subject: Update merge request text to reflect editability of source/target branch Closes #2134 --- .../projects/merge_requests/widget/open/_missing_branch.html.haml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml b/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml index 423fcd48e25..1c565bae80a 100644 --- a/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml +++ b/app/views/projects/merge_requests/widget/open/_missing_branch.html.haml @@ -6,9 +6,11 @@ %span.label.label-inverse= @merge_request.source_branch does not exist in %span.label.label-info= @merge_request.source_project_path + %br + %strong Please close this merge request and open a new merge request to change source branches. - else %span.label.label-inverse= @merge_request.target_branch does not exist in %span.label.label-info= @merge_request.target_project_path - %br - %strong Please close this merge request or change branches with existing one + %br + %strong Please close this merge request or change to another target branch. -- cgit v1.2.1 From 28cc6d9b9860fb38fc68d05c40d552d3a46e7ac8 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 3 Aug 2015 15:51:09 -0700 Subject: text fixed --- doc/permissions/permissions.md | 2 +- doc/workflow/add-user/add-user.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md index 029d446640d..7a6a1958445 100644 --- a/doc/permissions/permissions.md +++ b/doc/permissions/permissions.md @@ -6,7 +6,7 @@ If a user is both in a project group and in the project itself, the highest perm If a user is a GitLab administrator they receive all permissions. -To add or import a user or member, you can follow the [project users and members +To add or import a user, you can follow the [project users and members documentation](doc/workflow/add-user/add-user.md). ## Project diff --git a/doc/workflow/add-user/add-user.md b/doc/workflow/add-user/add-user.md index 58f7bd0a5ce..8c9b4f72631 100644 --- a/doc/workflow/add-user/add-user.md +++ b/doc/workflow/add-user/add-user.md @@ -1,13 +1,13 @@ -# Project users and members +# Project users -You can add or import users to your projects. You can also give them different access -levels. +You can manage the groups and users and their access levels in all of your projects. You can also personalize the access level you give each user, per project. -You should have 'master' or 'owner' permissions to add or import a new user to your -project. +Here's how to add or import users to your projects. -To add or import a user, go to your project and click on "Members" on the left side -of your screen: +You should have 'master' or 'owner' permissions to add or import a new user +to your project. + +To add or import a user, go to your project and click on "Members" on the left side of your screen: ![Members](images/members.png) -- cgit v1.2.1 From c5a6c16dba66318ea7f36b368217a275f1dd24e8 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Mon, 3 Aug 2015 15:55:02 -0700 Subject: typo --- doc/workflow/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 139f4db7d57..3915198ad2a 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -10,7 +10,7 @@ - [Notification emails](notifications.md) - [Project Features](project_features.md) - [Project forking workflow](forking_workflow.md) -- [Project users and members](add-user/add-user.md) +- [Project users](add-user/add-user.md) - [Protected branches](protected_branches.md) - [Web Editor](web_editor.md) - ["Work In Progress" Merge Requests](wip_merge_requests.md) -- cgit v1.2.1 From 4ccd767abf45df909c43e93d8898096236c99e3d Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Fri, 19 Jun 2015 19:17:34 +0200 Subject: Only publish ssh key-type and key --- CHANGELOG | 13 ++++++++----- app/models/key.rb | 5 +++++ app/models/user.rb | 2 +- spec/controllers/profile_keys_controller_spec.rb | 11 +++++++++++ spec/factories.rb | 2 +- spec/models/key_spec.rb | 7 +++++++ 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8a24bf412d2..09a74cda9a9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,7 @@ v 7.14.0 (unreleased) - Disabled autocapitalize and autocorrect on login field (Daryl Chan) - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) - Remove redis-store TTL monkey patch + - Remove comments and email addresses when publicly exposing ssh keys (Zeger-Jan van de Weg) v 7.13.2 - Fix randomly failed spec @@ -54,6 +55,8 @@ v 7.13.1 v 7.13.0 - Remove repository graph log to fix slow cache updates after push event (Stan Hu) - Return comments in created order in merge request API (Stan Hu) + +v 7.13.0 (unreleased) - Only enable HSTS header for HTTPS and port 443 (Stan Hu) - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu) - Fix redirection to home page URL for unauthorized users (Daniel Gerhardt) @@ -80,15 +83,15 @@ v 7.13.0 - Update ssl_ciphers in Nginx example to remove DHE settings. This will deny forward secrecy for Android 2.3.7, Java 6 and OpenSSL 0.9.8 - Admin can edit and remove user identities - Convert CRLF newlines to LF when committing using the web editor. - - API request /projects/:project_id/merge_requests?state=closed will return only closed merge requests without merged one. If you need ones that were merged - use state=merged. + - API request /projects/:project_id/merge_requests?state=closed will return only closed merge requests without merged one. If you need ones that were merged - use state=merged. - Allow Administrators to filter the user list by those with or without Two-factor Authentication enabled. - Show a user's Two-factor Authentication status in the administration area. - Explicit error when commit not found in the CI - - Improve performance for issue and merge request pages + - Improve performance for issue and merge request pages - Users with guest access level can not set assignee, labels or milestones for issue and merge request - Reporter role can manage issue tracker now: edit any issue, set assignee or milestone and manage labels - Better performance for pages with events list, issues list and commits list - - Faster automerge check and merge itself when source and target branches are in same repository + - Faster automerge check and merge itself when source and target branches are in same repository - Correctly show anonymous authorized applications under Profile > Applications. - Query Optimization in MySQL. - Allow users to be blocked and unblocked via the API @@ -96,7 +99,7 @@ v 7.13.0 - Redesign project page. Show README as default instead of activity. Move project activity to separate page - Make left menu more hierarchical and less contextual by adding back item at top - A fork can’t have a visibility level that is greater than the original project. - - Faster code search in repository and wiki. Fixes search page timeout for big repositories + - Faster code search in repository and wiki. Fixes search page timeout for big repositories - Allow administrators to disable 2FA for a specific user - Add error message for SSH key linebreaks - Store commits count in database (will populate with valid values only after first push) @@ -115,7 +118,7 @@ v 7.12.1 - Add SAML to list of social_provider (Matt Firtion) - Fix merge requests API scope to keep compatibility in 7.12.x patch release (Dmitriy Zaporozhets) - Fix closed merge request scope at milestone page (Dmitriy Zaporozhets) - - Revert merge request states renaming + - Revert merge request states renaming - Fix hooks for web based events with external issue references (Daniel Gerhardt) - Improve performance for issue and merge request pages - Compress database dumps to reduce backup size diff --git a/app/models/key.rb b/app/models/key.rb index 2dcae059c0e..406a1257b5d 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -39,6 +39,11 @@ class Key < ActiveRecord::Base self.key = key.strip unless key.blank? end + def publishable_key + #Removes anything beyond the keytype and key itself + self.key.split[0..1].join(' ') + end + # projects that has this key def projects user.authorized_projects diff --git a/app/models/user.rb b/app/models/user.rb index 2beefb1d614..57145cc6b6e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -619,7 +619,7 @@ class User < ActiveRecord::Base end def all_ssh_keys - keys.map(&:key) + keys.map(&:publishable_key) end def temp_oauth_email? diff --git a/spec/controllers/profile_keys_controller_spec.rb b/spec/controllers/profile_keys_controller_spec.rb index 593d3e9eb56..b6573f105dc 100644 --- a/spec/controllers/profile_keys_controller_spec.rb +++ b/spec/controllers/profile_keys_controller_spec.rb @@ -48,6 +48,17 @@ describe Profiles::KeysController do expect(response.body).not_to eq("") expect(response.body).to eq(user.all_ssh_keys.join("\n")) + + # Unique part of key 1 + expect(response.body).to match(/PWx6WM4lhHNedGfBpPJNPpZ/) + # Key 2 + expect(response.body).to match(/AQDmTillFzNTrrGgwaCKaSj/) + end + + it "should not render the comment of the key" do + get :get_keys, username: user.username + + expect(response.body).not_to match(/dummy@gitlab.com/) end it "should respond with text/plain content type" do diff --git a/spec/factories.rb b/spec/factories.rb index 05e3211d551..200f18f660d 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -100,7 +100,7 @@ FactoryGirl.define do factory :key do title key do - "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" + "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0= dummy@gitlab.com" end factory :deploy_key, class: 'DeployKey' do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 456bf221d62..2f819f60cbb 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -32,6 +32,13 @@ describe Key do describe "Methods" do it { is_expected.to respond_to :projects } + it { is_expected.to respond_to :publishable_key } + + describe "#publishable_keys" do + it 'strips all personal information' do + expect(build(:key).publishable_key).not_to match(/dummy@gitlab/) + end + end end context "validation of uniqueness" do -- cgit v1.2.1 From c17f5d06aa4a55a8446928ea6b690ae8e09ce237 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 4 Aug 2015 16:33:53 +0200 Subject: Fix merge api and spec Signed-off-by: Dmitriy Zaporozhets --- lib/api/merge_requests.rb | 2 +- spec/requests/api/merge_requests_spec.rb | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index a956c960a2e..e8b49fb7cba 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -200,7 +200,7 @@ module API if merge_request.can_be_merged? commit_message = params[:merge_commit_message] || merge_request.merge_commit_message - MergeRequests::MergeService.new(merge_request.target_project, current_user). + ::MergeRequests::MergeService.new(merge_request.target_project, current_user). execute(merge_request, commit_message) present merge_request, with: Entities::MergeRequest diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 7030c105b58..780ff93a232 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -147,7 +147,7 @@ describe API::API, api: true do it "should return merge_request" do post api("/projects/#{project.id}/merge_requests", user), title: 'Test merge_request', - source_branch: 'stable', + source_branch: 'feature_conflict', target_branch: 'master', author: user, labels: 'label, label2' @@ -170,20 +170,20 @@ describe API::API, api: true do it "should return 400 when target_branch is missing" do post api("/projects/#{project.id}/merge_requests", user), - title: "Test merge_request", source_branch: "stable", author: user + title: "Test merge_request", source_branch: "markdown", author: user expect(response.status).to eq(400) end it "should return 400 when title is missing" do post api("/projects/#{project.id}/merge_requests", user), - target_branch: 'master', source_branch: 'stable' + target_branch: 'master', source_branch: 'markdown' expect(response.status).to eq(400) end it 'should return 400 on invalid label names' do post api("/projects/#{project.id}/merge_requests", user), title: 'Test merge_request', - source_branch: 'stable', + source_branch: 'markdown', target_branch: 'master', author: user, labels: 'label, ?' @@ -197,7 +197,7 @@ describe API::API, api: true do before do post api("/projects/#{project.id}/merge_requests", user), title: 'Test merge_request', - source_branch: 'stable', + source_branch: 'feature_conflict', target_branch: 'master', author: user @mr = MergeRequest.all.last @@ -207,7 +207,7 @@ describe API::API, api: true do expect do post api("/projects/#{project.id}/merge_requests", user), title: 'New test merge_request', - source_branch: 'stable', + source_branch: 'feature_conflict', target_branch: 'master', author: user end.to change { MergeRequest.count }.by(0) @@ -227,7 +227,8 @@ describe API::API, api: true do it "should return merge_request" do post api("/projects/#{fork_project.id}/merge_requests", user2), - title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user2, target_project_id: project.id, description: 'Test description for Test merge_request' + title: 'Test merge_request', source_branch: "feature_conflict", target_branch: "master", + author: user2, target_project_id: project.id, description: 'Test description for Test merge_request' expect(response.status).to eq(201) expect(json_response['title']).to eq('Test merge_request') expect(json_response['description']).to eq('Test description for Test merge_request') @@ -257,7 +258,7 @@ describe API::API, api: true do it "should return 400 when title is missing" do post api("/projects/#{fork_project.id}/merge_requests", user2), - target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: project.id + target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: project.id expect(response.status).to eq(400) end @@ -266,7 +267,7 @@ describe API::API, api: true do post api("/projects/#{project.id}/merge_requests", user), title: 'Test merge_request', target_branch: 'master', - source_branch: 'stable', + source_branch: 'markdown', author: user, target_project_id: fork_project.id expect(response.status).to eq(422) @@ -276,7 +277,7 @@ describe API::API, api: true do post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', target_branch: 'master', - source_branch: 'stable', + source_branch: 'markdown', author: user2, target_project_id: unrelated_project.id expect(response.status).to eq(422) @@ -285,7 +286,7 @@ describe API::API, api: true do it "should return 201 when target_branch is specified and for the same project" do post api("/projects/#{fork_project.id}/merge_requests", user2), - title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: fork_project.id + title: 'Test merge_request', target_branch: 'master', source_branch: 'markdown', author: user2, target_project_id: fork_project.id expect(response.status).to eq(201) end end @@ -301,9 +302,6 @@ describe API::API, api: true do describe "PUT /projects/:id/merge_request/:merge_request_id/merge" do it "should return merge_request in case of success" do - allow_any_instance_of(MergeRequest). - to receive_messages(can_be_merged?: true, automerge!: true) - put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) expect(response.status).to eq(200) -- cgit v1.2.1 From 427b5df260cffdfcae5caa4662c7fc38631b48a3 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 30 Jul 2015 13:58:47 +0200 Subject: Added support for CI skipped status --- CHANGELOG | 1 + app/assets/javascripts/merge_request_widget.js.coffee | 2 +- app/assets/stylesheets/pages/merge_requests.scss | 5 +++++ app/models/project_services/ci_service.rb | 2 +- app/views/projects/merge_requests/widget/_heading.html.haml | 6 ++++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8a24bf412d2..cec3f98a460 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,7 @@ v 7.14.0 (unreleased) - Disabled autocapitalize and autocorrect on login field (Daryl Chan) - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) - Remove redis-store TTL monkey patch + - Add support for CI skipped status v 7.13.2 - Fix randomly failed spec diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee index e4d815bb4e4..762eec63dee 100644 --- a/app/assets/javascripts/merge_request_widget.js.coffee +++ b/app/assets/javascripts/merge_request_widget.js.coffee @@ -36,7 +36,7 @@ class @MergeRequestWidget showCiState: (state) -> $('.ci_widget').hide() - allowed_states = ["failed", "canceled", "running", "pending", "success", "not_found"] + allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"] if state in allowed_states $('.ci_widget.ci-' + state).show() switch state diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 61071320973..6185dabd39b 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -139,6 +139,11 @@ color: $gl-success; } + &.ci-skipped { + background-color: #eee; + color: #888; + } + &.ci-pending, &.ci-running { color: $gl-warning; diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 77d48d4af5e..803402c83ee 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -41,7 +41,7 @@ class CiService < Service # Return string with build status or :error symbol # - # Allowed states: 'success', 'failed', 'running', 'pending' + # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped' # # # Ex. diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml index 4cc9c652b61..f04eac0e3bb 100644 --- a/app/views/projects/merge_requests/widget/_heading.html.haml +++ b/app/views/projects/merge_requests/widget/_heading.html.haml @@ -6,6 +6,12 @@ for #{@merge_request.last_commit_short_sha}. = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" + .ci_widget.ci-skipped{style: "display:none"} + = icon("check") + %span CI build skipped + for #{@merge_request.last_commit_short_sha}. + = link_to "View build page", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink" + .ci_widget.ci-failed{style: "display:none"} = icon("times") %span CI build failed -- cgit v1.2.1 From 44ac823e59619877fb2e3fd192c35f6e827fe665 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 4 Aug 2015 17:20:26 +0200 Subject: Improve tests to use real branches in merge requests Signed-off-by: Dmitriy Zaporozhets --- spec/lib/gitlab/reference_extractor_spec.rb | 8 ++++---- spec/models/merge_request_spec.rb | 2 +- spec/routing/project_routing_spec.rb | 14 +++++++------- spec/services/merge_requests/create_service_spec.rb | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index f921dd9cc09..088e34f050c 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -25,7 +25,7 @@ describe Gitlab::ReferenceExtractor do project.team << [@u_bar, :guest] subject.analyze(%Q{ - Inline code: `@foo` + Inline code: `@foo` Code block: @@ -33,7 +33,7 @@ describe Gitlab::ReferenceExtractor do @bar ``` - Quote: + Quote: > @offteam }) @@ -49,8 +49,8 @@ describe Gitlab::ReferenceExtractor do end it 'accesses valid merge requests' do - @m0 = create(:merge_request, source_project: project, target_project: project, source_branch: 'aaa') - @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb') + @m0 = create(:merge_request, source_project: project, target_project: project, source_branch: 'markdown') + @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'feature_conflict') subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.") expect(subject.merge_requests).to eq([@m1, @m0]) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 76f6d8c54c4..b91687bc09f 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -165,7 +165,7 @@ describe MergeRequest do end it_behaves_like 'an editable mentionable' do - subject { create(:merge_request, source_project: project) } + subject { create(:merge_request) } let(:backref_text) { "merge request #{subject.to_reference}" } let(:set_mentionable_text) { ->(txt){ subject.description = txt } } diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 0040718d9be..82f62a8709c 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -210,8 +210,8 @@ end # diffs_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/diffs(.:format) projects/merge_requests#diffs # commits_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/commits(.:format) projects/merge_requests#commits -# automerge_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/automerge(.:format) projects/merge_requests#automerge -# automerge_check_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/automerge_check(.:format) projects/merge_requests#automerge_check +# merge_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/merge(.:format) projects/merge_requests#merge +# merge_check_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/merge_check(.:format) projects/merge_requests#merge_check # ci_status_namespace_project_merge_request GET /:namespace_id/:project_id/merge_requests/:id/ci_status(.:format) projects/merge_requests#ci_status # toggle_subscription_namespace_project_merge_request POST /:namespace_id/:project_id/merge_requests/:id/toggle_subscription(.:format) projects/merge_requests#toggle_subscription # branch_from_namespace_project_merge_requests GET /:namespace_id/:project_id/merge_requests/branch_from(.:format) projects/merge_requests#branch_from @@ -233,15 +233,15 @@ describe Projects::MergeRequestsController, 'routing' do expect(get('/gitlab/gitlabhq/merge_requests/1/commits')).to route_to('projects/merge_requests#commits', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it 'to #automerge' do - expect(post('/gitlab/gitlabhq/merge_requests/1/automerge')).to route_to( - 'projects/merge_requests#automerge', + it 'to #merge' do + expect(post('/gitlab/gitlabhq/merge_requests/1/merge')).to route_to( + 'projects/merge_requests#merge', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1' ) end - it 'to #automerge_check' do - expect(get('/gitlab/gitlabhq/merge_requests/1/automerge_check')).to route_to('projects/merge_requests#automerge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') + it 'to #merge_check' do + expect(get('/gitlab/gitlabhq/merge_requests/1/merge_check')).to route_to('projects/merge_requests#merge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end it 'to #branch_from' do diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index d9bfdf64308..cc64d69361e 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -10,7 +10,7 @@ describe MergeRequests::CreateService do { title: 'Awesome merge_request', description: 'please fix', - source_branch: 'stable', + source_branch: 'feature', target_branch: 'master' } end -- cgit v1.2.1 From e9bbea704855de86dd45b13550e3aba41b9747be Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 4 Aug 2015 16:58:14 -0400 Subject: Don't hide the clone holder for an empty project --- app/assets/javascripts/project.js.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee index cb44e1abe97..87c1b67a772 100644 --- a/app/assets/javascripts/project.js.coffee +++ b/app/assets/javascripts/project.js.coffee @@ -1,8 +1,8 @@ class @Project constructor: -> # Git clone panel switcher - cloneHolder = $ '.git-clone-holder' - if cloneHolder.length > 0 + cloneHolder = $('.git-clone-holder') + if cloneHolder.length $('a, button', cloneHolder).click -> $('a, button', cloneHolder).removeClass 'active' $(@).addClass 'active' @@ -28,4 +28,4 @@ class @Project $('.js-toggle-clone-holder').on 'click', (e) -> cloneHolder.toggle() - cloneHolder.hide() + cloneHolder.hide() unless $('.empty-project').length -- cgit v1.2.1 From f9d71c4b911284bcb9577c23b8a2a5f61a9ffd71 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 4 Aug 2015 17:07:12 -0400 Subject: Update docs for Ruby MRI 2.1 requirement --- README.md | 4 ++-- doc/install/requirements.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bd663b30f3e..d6b661532ef 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Instructions on how to start GitLab and how to run the tests can be found in the GitLab is a Ruby on Rails application that runs on the following software: - Ubuntu/Debian/CentOS/RHEL -- Ruby (MRI) 2.0 or 2.1 +- Ruby (MRI) 2.1 - Git 1.7.10+ - Redis 2.0+ - MySQL or PostgreSQL @@ -103,4 +103,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on ## Is it awesome? Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua. -[These people](https://twitter.com/gitlab/favorites) seem to like it. \ No newline at end of file +[These people](https://twitter.com/gitlab/favorites) seem to like it. diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 1efc1f7bddf..605977097b4 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -32,7 +32,7 @@ Please consider using a virtual machine to run GitLab. ## Ruby versions -GitLab requires Ruby (MRI) 2.0 or 2.1 +GitLab requires Ruby (MRI) 2.1 You will have to use the standard MRI implementation of Ruby. We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab needs several Gems that have native extensions. @@ -113,4 +113,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o ### Common UI problems with IE -If you experience UI issues with Internet Explorer, please make sure that you have the `Compatibility View` mode disabled. \ No newline at end of file +If you experience UI issues with Internet Explorer, please make sure that you have the `Compatibility View` mode disabled. -- cgit v1.2.1 From b83b3332171f7de1046b5e27a1351daf84fac583 Mon Sep 17 00:00:00 2001 From: karen Carias Date: Tue, 4 Aug 2015 14:51:08 -0700 Subject: added note about changing servers --- doc/raketasks/backup_restore.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 05324b33022..d704d93fdef 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -7,7 +7,7 @@ A backup creates an archive file that contains the database, all repositories and all attachments. This archive will be saved in backup_path (see `config/gitlab.yml`). The filename will be `[TIMESTAMP]_gitlab_backup.tar`. This timestamp can be used to restore an specific backup. -You can only restore a backup to exactly the same version of GitLab that you created it on, for example 7.2.1. +You can only restore a backup to exactly the same version of GitLab that you created it on, for example 7.2.1. The best way to migrate your repositories from one server to another is through backup restore. You need to keep a separate copy of `/etc/gitlab/gitlab-secrets.json` (for omnibus packages) or `/home/git/gitlab/.secret` (for installations -- cgit v1.2.1 From ee0fc2c3ad9608db91175e082fe1f6da19a3aec7 Mon Sep 17 00:00:00 2001 From: Sven Strickroth Date: Sun, 26 Apr 2015 20:01:43 +0200 Subject: Put author name at the end of a tree row Signed-off-by: Sven Strickroth --- app/assets/stylesheets/pages/tree.scss | 6 +----- app/views/projects/tree/_tree_commit_column.html.haml | 5 ++++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 34ee4d7b31e..642bcd943aa 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -60,11 +60,7 @@ } .tree_author { - padding-right: 8px; - - .commit-author-name { - color: gray; - } + padding-left: 8px; } .tree_commit { diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml index 50521264a61..86a80703072 100644 --- a/app/views/projects/tree/_tree_commit_column.html.haml +++ b/app/views/projects/tree/_tree_commit_column.html.haml @@ -1,3 +1,6 @@ %span.str-truncated - %span.tree_author= commit_author_link(commit, avatar: true, size: 16) = link_to_gfm commit.title, namespace_project_commit_path(@project.namespace, @project, commit.id), class: "tree-commit-link" + %span.tree_author + [ + commit_author_link(commit, avatar: false) + ] -- cgit v1.2.1 From c90e592e91137c6fe5f9e4fb2e07443f5fb9f854 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 5 Aug 2015 08:32:09 +0300 Subject: Replace relative url with full path, remove old reference for indexes Closes #2176 (gitlab.com) --- doc/update/mysql_to_postgresql.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md index 26605c7c3a3..a596ea38456 100644 --- a/doc/update/mysql_to_postgresql.md +++ b/doc/update/mysql_to_postgresql.md @@ -1,5 +1,5 @@ # Migrating GitLab from MySQL to Postgres -*Make sure you view this [guide from the `master` branch](../../../master/doc/update/mysql_to_postgresql.md) for the most up to date instructions.* +*Make sure you view this [guide from the `master` branch](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/mysql_to_postgresql.md#migrating-gitlab-from-mysql-to-postgres) for the most up to date instructions.* If you are replacing MySQL with Postgres while keeping GitLab on the same server all you need to do is to export from MySQL, convert the resulting SQL file, and import it into Postgres. If you are also moving GitLab to another server, or if you are switching to omnibus-gitlab, you may want to use a GitLab backup file. The second part of this documents explains the procedure to do this. @@ -70,5 +70,5 @@ sudo -u git -H gzip db/database.sql sudo -u git -H tar rf TIMESTAMP_gitlab_backup.tar db/database.sql.gz # Done! TIMESTAMP_gitlab_backup.tar can now be restored into a Postgres GitLab -# installation. Remember to recreate the indexes after the import. +# installation. ``` -- cgit v1.2.1 From 9076b5026b5fec92affd061f672e11ffa3dca380 Mon Sep 17 00:00:00 2001 From: Jeroen van Baarsen Date: Wed, 5 Aug 2015 08:07:35 +0200 Subject: Update the Semaphore badge to the shield badge type **Why is this needed?** It just does look better in the Readme :-) Signed-off-by: Jeroen van Baarsen --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bd663b30f3e..14dc52d30ba 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # GitLab [![build status](https://ci.gitlab.com/projects/1/status.png?ref=master)](https://ci.gitlab.com/projects/1?ref=master) -[![Build Status](https://semaphoreapp.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/243338/badge.png)](https://semaphoreapp.com/gitlabhq/gitlabhq) +[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq) [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq) [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master) @@ -103,4 +103,4 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on ## Is it awesome? Thanks for [asking this question](https://twitter.com/supersloth/status/489462789384056832) Joshua. -[These people](https://twitter.com/gitlab/favorites) seem to like it. \ No newline at end of file +[These people](https://twitter.com/gitlab/favorites) seem to like it. -- cgit v1.2.1 From 0c1ccda43fe04300a07a5f046a7c1cbae56cff32 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 29 Jul 2015 07:32:01 -0700 Subject: Add "Confirm user" button in user admin page Closes #2116 Closes https://github.com/gitlabhq/gitlabhq/issues/9502 --- CHANGELOG | 1 + app/controllers/admin/users_controller.rb | 8 ++++++++ app/views/admin/users/show.html.haml | 10 ++++++++++ config/routes.rb | 1 + spec/controllers/admin/users_controller_spec.rb | 14 ++++++++++++++ spec/models/user_spec.rb | 13 +++++++++++++ 6 files changed, 47 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 8a24bf412d2..dcd2e3203eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.14.0 (unreleased) - Fix multi-line syntax highlighting (Stan Hu) - Fix network graph when branch name has single quotes (Stan Hu) + - Add "Confirm user" button in user admin page (Stan Hu) - Upgrade gitlab_git to version 7.2.6 to fix Error 500 when creating network graphs (Stan Hu) - Add support for Unicode filenames in relative links (Hiroyuki Sato) - Fix URL used for refreshing notes if relative_url is present (Bartłomiej Święcki) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 770fe00af51..6092c79c254 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -55,6 +55,14 @@ class Admin::UsersController < Admin::ApplicationController end end + def confirm + if user.confirm! + redirect_to :back, notice: "Successfully confirmed" + else + redirect_to :back, alert: "Error occurred. User was not confirmed" + end + end + def disable_two_factor user.disable_two_factor! redirect_to admin_user_path(user), diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 33730ff05df..a383ea57384 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -105,6 +105,16 @@ .col-md-6 - unless @user == current_user + - unless @user.confirmed? + .panel.panel-info + .panel-heading + Confirm user + .panel-body + - if @user.unconfirmed_email.present? + - email = " (#{@user.unconfirmed_email})" + %p This user has an unconfirmed email address#{email}. You may force a confirmation. + %br + = link_to 'Confirm user', confirm_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' } - if @user.blocked? .panel.panel-info .panel-heading diff --git a/config/routes.rb b/config/routes.rb index 2e16c3ecb39..ef052a11bb2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,6 +159,7 @@ Gitlab::Application.routes.draw do put :block put :unblock put :unlock + put :confirm patch :disable_two_factor delete 'remove/:email_id', action: 'remove_email', as: 'remove_email' end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 6f4c8987637..c40b2c2a583 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -37,6 +37,20 @@ describe Admin::UsersController do end end + describe 'PUT confirm/:id' do + let(:user) { create(:user, confirmed_at: nil) } + + before do + request.env["HTTP_REFERER"] = "/" + end + + it 'confirms user' do + put :confirm, id: user.username + user.reload + expect(user.confirmed?).to be_truthy + end + end + describe 'PATCH disable_two_factor' do let(:user) { create(:user) } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 922e9ebf844..876cfb1204a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -184,6 +184,19 @@ describe User do it { is_expected.to respond_to(:private_token) } end + describe '#confirm' do + let(:user) { create(:user, confirmed_at: nil, unconfirmed_email: 'test@gitlab.com') } + + it 'returns unconfirmed' do + expect(user.confirmed?).to be_falsey + end + + it 'confirms a user' do + user.confirm! + expect(user.confirmed?).to be_truthy + end + end + describe '#to_reference' do let(:user) { create(:user) } -- cgit v1.2.1 From 6353ca9ae85ec42bb5f6d45d4158f50067d34cf7 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 5 Aug 2015 12:00:12 +0300 Subject: Revert "Update noteable after a new note is added" This reverts commit fbdaf0e2a517660c0e4e3960f20b2d3568c33e78. --- app/models/note.rb | 2 +- spec/lib/gitlab/note_data_builder_spec.rb | 4 ---- spec/models/note_spec.rb | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/models/note.rb b/app/models/note.rb index 62567f471dc..2362e50276e 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -31,7 +31,7 @@ class Note < ActiveRecord::Base participant :author, :mentioned_users belongs_to :project - belongs_to :noteable, polymorphic: true, touch: true + belongs_to :noteable, polymorphic: true belongs_to :author, class_name: "User" delegate :name, to: :project, prefix: true diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb index 5826144e66b..448cd0c6880 100644 --- a/spec/lib/gitlab/note_data_builder_spec.rb +++ b/spec/lib/gitlab/note_data_builder_spec.rb @@ -36,7 +36,6 @@ describe 'Gitlab::NoteDataBuilder' do let(:note) { create(:note_on_issue, noteable_id: issue.id) } it 'returns the note and issue-specific data' do - data[:issue]["updated_at"] = fixed_time expect(data).to have_key(:issue) expect(data[:issue]).to eq(issue.hook_attrs) end @@ -47,7 +46,6 @@ describe 'Gitlab::NoteDataBuilder' do let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id) } it 'returns the note and merge request data' do - data[:merge_request]["updated_at"] = fixed_time expect(data).to have_key(:merge_request) expect(data[:merge_request]).to eq(merge_request.hook_attrs) end @@ -58,7 +56,6 @@ describe 'Gitlab::NoteDataBuilder' do let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id) } it 'returns the note and merge request diff data' do - data[:merge_request]["updated_at"] = fixed_time expect(data).to have_key(:merge_request) expect(data[:merge_request]).to eq(merge_request.hook_attrs) end @@ -69,7 +66,6 @@ describe 'Gitlab::NoteDataBuilder' do let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id) } it 'returns the note and project snippet data' do - data[:snippet]["updated_at"] = fixed_time expect(data).to have_key(:snippet) expect(data[:snippet]).to eq(snippet.hook_attrs) end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index eba33dd510f..250d1e2da80 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -22,7 +22,7 @@ require 'spec_helper' describe Note do describe 'associations' do it { is_expected.to belong_to(:project) } - it { is_expected.to belong_to(:noteable).touch(true) } + it { is_expected.to belong_to(:noteable) } it { is_expected.to belong_to(:author).class_name('User') } end -- cgit v1.2.1 From ab8c71de4e57e9715d631a52d08de4e9ce87d649 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 5 Aug 2015 11:03:41 +0200 Subject: Fix merge request creation without branch selected Signed-off-by: Dmitriy Zaporozhets --- app/services/merge_requests/build_service.rb | 9 +++++++-- spec/services/merge_requests/merge_service_spec.rb | 5 ----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 3ff5374b353..a9b29f9654d 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -12,8 +12,13 @@ module MergeRequests merge_request.target_project ||= (project.forked_from_project || project) merge_request.target_branch ||= merge_request.target_project.default_branch - unless merge_request.target_branch && merge_request.source_branch - return build_failed(merge_request, nil) + if merge_request.target_branch.blank? || merge_request.source_branch.blank? + message = + if params[:source_branch] || params[:target_branch] + "You must select source and target branch" + end + + return build_failed(merge_request, message) end compare_result = CompareService.new.execute( diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index 0a25fb12f4e..7b564d34d7b 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -24,11 +24,6 @@ describe MergeRequests::MergeService do it { expect(merge_request).to be_valid } it { expect(merge_request).to be_merged } - it 'should execute hooks with merge action' do - expect(service).to have_received(:execute_hooks). - with(merge_request, 'merge') - end - it 'should send email to user2 about merge of new merge_request' do email = ActionMailer::Base.deliveries.last expect(email.to.first).to eq(user2.email) -- cgit v1.2.1 From 1cb8588c662df41a76788759737e5b9ecb2ceba6 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 5 Aug 2015 11:49:02 +0200 Subject: Remove satellites from requirements docs and add CHANGELOG Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 2 ++ doc/install/requirements.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8a24bf412d2..4b8da461a11 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,8 @@ v 7.14.0 (unreleased) - Disabled autocapitalize and autocorrect on login field (Daryl Chan) - Mention group and project name in creation, update and deletion notices (Achilleas Pipinellis) - Remove redis-store TTL monkey patch + - Fetch code from forks to refs/merge-requests/:id/head when merge request created + - Remove satellites v 7.13.2 - Fix randomly failed spec diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 1efc1f7bddf..241c951ec90 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -40,7 +40,7 @@ We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab ### Storage -The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least twice as much free space as all your repos combined take up. You need twice the storage because [GitLab satellites](structure.md) contain an extra copy of each repo. +The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least as much free space as all your repos combined take up. If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them. @@ -113,4 +113,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o ### Common UI problems with IE -If you experience UI issues with Internet Explorer, please make sure that you have the `Compatibility View` mode disabled. \ No newline at end of file +If you experience UI issues with Internet Explorer, please make sure that you have the `Compatibility View` mode disabled. -- cgit v1.2.1 From a567dd20d49fe727efbb7fad95f8755048e4fcea Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Wed, 5 Aug 2015 14:11:25 +0300 Subject: update release doc --- doc/release/monthly.md | 1 + doc/release/patch.md | 1 + 2 files changed, 2 insertions(+) diff --git a/doc/release/monthly.md b/doc/release/monthly.md index 552b24195b1..b10e7420675 100644 --- a/doc/release/monthly.md +++ b/doc/release/monthly.md @@ -81,6 +81,7 @@ workday to quickly fix any issues. - [ ] Merge CE stable into EE stable (#LINK) - [ ] Create the 'x.y.0' tag with the [release tools](https://dev.gitlab.org/gitlab/release-tools) (#LINK) +- [ ] Create the 'x.y.0' version on version.gitlab.com - [ ] Try to do before 11AM CET: Create and push omnibus tags for x.y.0 (will auto-release the packages) (#LINK) - [ ] Try to do before 12AM CET: Publish the release blog post (#LINK) - [ ] Tweet about the release (blog post) (#LINK) diff --git a/doc/release/patch.md b/doc/release/patch.md index a569bb3da8d..6aa11b283df 100644 --- a/doc/release/patch.md +++ b/doc/release/patch.md @@ -52,5 +52,6 @@ bundle exec rake release["x.x.x"] 1. Create and publish a blog post, see [patch release blog template](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/doc/patch_release_blog_template.md) 1. Send tweets about the release from `@gitlab`, tweet should include the most important feature that the release is addressing and link to the blog post 1. Note in the 'GitLab X.X regressions' issue that the patch was published (CE only) +1. Create the 'x.y.0' version on version.gitlab.com 1. [Create new AMIs](https://dev.gitlab.org/gitlab/AMI/blob/master/README.md) 1. Create a new patch release issue for the next potential release \ No newline at end of file -- cgit v1.2.1 From ce47dd4bb0c686aee13b309b07eb8f976aa5d547 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 5 Aug 2015 21:08:00 +0300 Subject: Update stable branch in installation documentation. Fixes #2191 --- doc/install/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 5bd68ab6a35..55b6f216dde 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -195,9 +195,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-12-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-13-stable gitlab -**Note:** You can change `7-12-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `7-13-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It -- cgit v1.2.1