diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-28 13:33:23 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-28 13:33:23 +0000 |
commit | b9bf11ef5f63203c6974c4432553270f7b3d29a1 (patch) | |
tree | ddf69920d5929b68cb7097c3c586a2fdf483cd60 /lib | |
parent | 1e8ef329735f06d3b3cfe1966b79fe55eff21f30 (diff) | |
download | gitlab-ce-b9bf11ef5f63203c6974c4432553270f7b3d29a1.tar.gz |
Add latest changes from gitlab-org/security/gitlab@12-7-stable-ee
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/commit_statuses.rb | 2 | ||||
-rw-r--r-- | lib/api/commits.rb | 2 | ||||
-rw-r--r-- | lib/api/entities.rb | 12 | ||||
-rw-r--r-- | lib/gitlab/git/cross_repo_comparer.rb | 56 | ||||
-rw-r--r-- | lib/gitlab/git/repository.rb | 33 |
5 files changed, 73 insertions, 32 deletions
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 6e26ee309f0..569c4e04dc5 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -85,6 +85,8 @@ module API protected: user_project.protected_for?(ref)) end + authorize! :update_pipeline, pipeline + status = GenericCommitStatus.running_or_pending.find_or_initialize_by( project: user_project, pipeline: pipeline, diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 63a7fdfa3ab..9dcf9b015aa 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -154,7 +154,7 @@ module API not_found! 'Commit' unless commit - present commit, with: Entities::CommitDetail, stats: params[:stats] + present commit, with: Entities::CommitDetail, stats: params[:stats], current_user: current_user end desc 'Get the diff for a specific commit of a project' do diff --git a/lib/api/entities.rb b/lib/api/entities.rb index dfd0e676586..8c4d986eb34 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -491,8 +491,18 @@ module API class CommitDetail < Commit expose :stats, using: Entities::CommitStats, if: :stats expose :status - expose :last_pipeline, using: 'API::Entities::PipelineBasic' expose :project_id + + expose :last_pipeline do |commit, options| + pipeline = commit.last_pipeline if can_read_pipeline? + ::API::Entities::PipelineBasic.represent(pipeline, options) + end + + private + + def can_read_pipeline? + Ability.allowed?(options[:current_user], :read_pipeline, object.last_pipeline) + end end class CommitSignature < Grape::Entity diff --git a/lib/gitlab/git/cross_repo_comparer.rb b/lib/gitlab/git/cross_repo_comparer.rb new file mode 100644 index 00000000000..3958373f7cb --- /dev/null +++ b/lib/gitlab/git/cross_repo_comparer.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module Gitlab + module Git + class CrossRepoComparer + attr_reader :source_repo, :target_repo + + def initialize(source_repo, target_repo) + @source_repo = source_repo + @target_repo = target_repo + end + + def compare(source_ref, target_ref, straight:) + ensuring_ref_in_source(target_ref) do |target_commit_id| + Gitlab::Git::Compare.new( + source_repo, + target_commit_id, + source_ref, + straight: straight + ) + end + end + + private + + def ensuring_ref_in_source(ref, &blk) + return yield ref if source_repo == target_repo + + # If the commit doesn't exist in the target, there's nothing we can do + commit_id = target_repo.commit(ref)&.sha + return unless commit_id + + # The commit pointed to by ref may exist in the source even when they + # are different repositories. This is particularly true of close forks, + # but may also be the case if a temporary ref for this comparison has + # already been created in the past, and the result hasn't been GC'd yet. + return yield commit_id if source_repo.commit(commit_id) + + # Worst case: the commit is not in the source repo so we need to fetch + # it. Use a temporary ref and clean up afterwards + with_commit_in_source_tmp(commit_id, &blk) + end + + # Fetch the ref into source_repo from target_repo, using a temporary ref + # name that will be deleted once the method completes. This is a no-op if + # fetching the source branch fails + def with_commit_in_source_tmp(commit_id, &blk) + tmp_ref = "refs/tmp/#{SecureRandom.hex}" + + yield commit_id if source_repo.fetch_source_branch!(target_repo, commit_id, tmp_ref) + ensure + source_repo.delete_refs(tmp_ref) # best-effort + end + end + end +end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index ed3e7a1e39c..0120e3be14c 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -746,29 +746,9 @@ module Gitlab end def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:) - reachable_ref = - if source_repository == self - source_branch_name - else - # If a tmp ref was created before for a separate repo comparison (forks), - # we're able to short-circuit the tmp ref re-creation: - # 1. Take the SHA from the source repo - # 2. Read that in the current "target" repo - # 3. If that SHA is still known (readable), it means GC hasn't - # cleaned it up yet, so we can use it instead re-writing the tmp ref. - source_commit_id = source_repository.commit(source_branch_name)&.sha - commit(source_commit_id)&.sha if source_commit_id - end - - return compare(target_branch_name, reachable_ref, straight: straight) if reachable_ref - - tmp_ref = "refs/tmp/#{SecureRandom.hex}" - - return unless fetch_source_branch!(source_repository, source_branch_name, tmp_ref) - - compare(target_branch_name, tmp_ref, straight: straight) - ensure - delete_refs(tmp_ref) if tmp_ref + CrossRepoComparer + .new(source_repository, self) + .compare(source_branch_name, target_branch_name, straight: straight) end def write_ref(ref_path, ref, old_ref: nil) @@ -1046,13 +1026,6 @@ module Gitlab private - def compare(base_ref, head_ref, straight:) - Gitlab::Git::Compare.new(self, - base_ref, - head_ref, - straight: straight) - end - def empty_diff_stats Gitlab::Git::DiffStatsCollection.new([]) end |