summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-07 00:09:33 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-07 00:09:33 +0000
commitb56027c9d80ac0e297ba8a43c81e8504172dbf9f (patch)
treeb85f743277145e930ae195664655d696e6e0a7fc /lib
parent7915c41e4261719719e791602c8235574157164c (diff)
downloadgitlab-ce-b56027c9d80ac0e297ba8a43c81e8504172dbf9f.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/git_access.rb69
-rw-r--r--lib/gitlab/git_access_snippet.rb11
-rw-r--r--lib/gitlab/repository_size_checker.rb2
3 files changed, 76 insertions, 6 deletions
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index c400e1cd4fd..f1ca8900c30 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -45,6 +45,8 @@ module Gitlab
attr_reader :actor, :project, :protocol, :authentication_abilities, :namespace_path, :repository_path, :redirected_path, :auth_result_type, :changes, :logger
+ alias_method :container, :project
+
def initialize(actor, project, protocol, authentication_abilities:, namespace_path: nil, repository_path: nil, redirected_path: nil, auth_result_type: nil)
@actor = actor
@project = project
@@ -429,7 +431,72 @@ module Gitlab
end
def repository
- project.repository
+ container&.repository
+ end
+
+ def check_size_before_push!
+ if check_size_limit? && size_checker.above_size_limit?
+ raise ForbiddenError, size_checker.error_message.push_error
+ end
+ end
+
+ def check_push_size!
+ return unless check_size_limit?
+
+ # If there are worktrees with a HEAD pointing to a non-existent object,
+ # calls to `git rev-list --all` will fail in git 2.15+. This should also
+ # clear stale lock files.
+ repository.clean_stale_repository_files
+
+ # Use #check_repository_disk_size to get correct push size whenever a lot of changes
+ # gets pushed at the same time containing the same blobs. This is only
+ # doable if GIT_OBJECT_DIRECTORY_RELATIVE env var is set and happens
+ # when git push comes from CLI (not via UI and API).
+ #
+ # Fallback to determining push size using the changes_list so we can still
+ # determine the push size if env var isn't set (e.g. changes are made
+ # via UI and API).
+ if check_quarantine_size?
+ check_repository_disk_size
+ else
+ check_changes_size
+ end
+ end
+
+ def check_quarantine_size?
+ git_env = ::Gitlab::Git::HookEnv.all(repository.gl_repository)
+
+ git_env['GIT_OBJECT_DIRECTORY_RELATIVE'].present?
+ end
+
+ def check_repository_disk_size
+ check_size_against_limit(repository.object_directory_size)
+ end
+
+ def check_changes_size
+ changes_size = 0
+
+ changes_list.each do |change|
+ changes_size += repository.new_blobs(change[:newrev]).sum(&:size) # rubocop: disable CodeReuse/ActiveRecord
+
+ check_size_against_limit(changes_size)
+ end
+ end
+
+ def check_size_against_limit(size)
+ if size_checker.changes_will_exceed_size_limit?(size)
+ raise ForbiddenError, size_checker.error_message.new_changes_error
+ end
+ end
+
+ def check_size_limit?
+ strong_memoize(:check_size_limit) do
+ changes_list.any? { |change| !Gitlab::Git.blank_ref?(change[:newrev]) }
+ end
+ end
+
+ def size_checker
+ container.repository_size_checker
end
end
end
diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb
index e11c1ea527c..d05ffe9b508 100644
--- a/lib/gitlab/git_access_snippet.rb
+++ b/lib/gitlab/git_access_snippet.rb
@@ -14,6 +14,8 @@ module Gitlab
attr_reader :snippet
+ alias_method :container, :snippet
+
def initialize(actor, snippet, protocol, **kwargs)
@snippet = snippet
@@ -53,11 +55,6 @@ module Gitlab
check_change_access!
end
- override :repository
- def repository
- snippet&.repository
- end
-
def check_snippet_accessibility!
if snippet.blank?
raise NotFoundError, ERROR_MESSAGES[:snippet_not_found]
@@ -89,11 +86,15 @@ module Gitlab
raise ForbiddenError, ERROR_MESSAGES[:update_snippet]
end
+ check_size_before_push!
+
changes_list.each do |change|
# If user does not have access to make at least one change, cancel all
# push by allowing the exception to bubble up
check_single_change_access(change)
end
+
+ check_push_size!
end
def check_single_change_access(change)
diff --git a/lib/gitlab/repository_size_checker.rb b/lib/gitlab/repository_size_checker.rb
index cf1af844439..82c57f7a07d 100644
--- a/lib/gitlab/repository_size_checker.rb
+++ b/lib/gitlab/repository_size_checker.rb
@@ -5,12 +5,14 @@ module Gitlab
class RepositorySizeChecker
attr_reader :limit
+ # @param current_size_proc [Proc] returns repository size in bytes
def initialize(current_size_proc:, limit:, enabled: true)
@current_size_proc = current_size_proc
@limit = limit
@enabled = enabled && limit != 0
end
+ # @return [Integer] bytes
def current_size
@current_size ||= @current_size_proc.call
end