summaryrefslogtreecommitdiff
path: root/lib/gitlab/checks/changes_access.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/checks/changes_access.rb')
-rw-r--r--lib/gitlab/checks/changes_access.rb35
1 files changed, 28 insertions, 7 deletions
diff --git a/lib/gitlab/checks/changes_access.rb b/lib/gitlab/checks/changes_access.rb
index 3ce2e50c548..84c01cf4baf 100644
--- a/lib/gitlab/checks/changes_access.rb
+++ b/lib/gitlab/checks/changes_access.rb
@@ -33,18 +33,33 @@ module Gitlab
# changes. This set may also contain commits which are not referenced by
# any of the new revisions.
def commits
+ allow_quarantine = true
+
newrevs = @changes.map do |change|
+ oldrev = change[:oldrev]
newrev = change[:newrev]
- newrev unless newrev.blank? || Gitlab::Git.blank_ref?(newrev)
+
+ next if blank_rev?(newrev)
+
+ # In case any of the old revisions is blank, then we cannot reliably
+ # detect which commits are new for a given change when enumerating
+ # objects via the object quarantine directory given that the client
+ # may have pushed too many commits, and we don't know when to
+ # terminate the walk. We thus fall back to using `git rev-list --not
+ # --all`, which is a lot less efficient but at least can only ever
+ # returns commits which really are new.
+ allow_quarantine = false if allow_quarantine && blank_rev?(oldrev)
+
+ newrev
end.compact
return [] if newrevs.empty?
- @commits ||= project.repository.new_commits(newrevs, allow_quarantine: true)
+ @commits ||= project.repository.new_commits(newrevs, allow_quarantine: allow_quarantine)
end
# All commits which have been newly introduced via the given revision.
- def commits_for(newrev)
+ def commits_for(oldrev, newrev)
commits_by_id = commits.index_by(&:id)
result = []
@@ -65,9 +80,11 @@ module Gitlab
# Only add the parent ID to the pending set if we actually know its
# commit to guards us against readding an ID which we have already
- # queued up before.
+ # queued up before. Furthermore, we stop walking as soon as we hit
+ # `oldrev` such that we do not include any commits in our checks
+ # which have been "over-pushed" by the client.
commit.parent_ids.each do |parent_id|
- pending.add(parent_id) if commits_by_id.has_key?(parent_id)
+ pending.add(parent_id) if commits_by_id.has_key?(parent_id) && parent_id != oldrev
end
result << commit
@@ -80,10 +97,10 @@ module Gitlab
@single_changes_accesses ||=
changes.map do |change|
commits =
- if change[:newrev].blank? || Gitlab::Git.blank_ref?(change[:newrev])
+ if blank_rev?(change[:newrev])
[]
else
- Gitlab::Lazy.new { commits_for(change[:newrev]) }
+ Gitlab::Lazy.new { commits_for(change[:oldrev], change[:newrev]) }
end
Checks::SingleChangeAccess.new(
@@ -109,6 +126,10 @@ module Gitlab
def bulk_access_checks!
Gitlab::Checks::LfsCheck.new(self).validate!
end
+
+ def blank_rev?(rev)
+ rev.blank? || Gitlab::Git.blank_ref?(rev)
+ end
end
end
end