diff options
Diffstat (limited to 'app/models/repository.rb')
-rw-r--r-- | app/models/repository.rb | 157 |
1 files changed, 54 insertions, 103 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb index 9d1de4f4306..d725c65081d 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -8,6 +8,7 @@ class Repository RESERVED_REFS_NAMES = %W[ heads tags + replace #{REF_ENVIRONMENTS} #{REF_KEEP_AROUND} #{REF_ENVIRONMENTS} @@ -33,7 +34,10 @@ class Repository CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide changelog license_blob license_key gitignore koding_yml gitlab_ci_yml branch_names tag_names branch_count - tag_count avatar exists? empty? root_ref).freeze + tag_count avatar exists? empty? root_ref has_visible_content?).freeze + + # Methods that use cache_method but only memoize the value + MEMOIZED_CACHED_METHODS = %i(license empty_repo?).freeze # Certain method caches should be refreshed when certain types of files are # changed. This Hash maps file types (as returned by Gitlab::FileDetector) to @@ -90,12 +94,6 @@ class Repository ) end - # we need to have this method here because it is not cached in ::Git and - # the method is called multiple times for every request - def has_visible_content? - branch_count > 0 - end - def inspect "#<#{self.class.name}:#{@disk_path}>" end @@ -274,7 +272,7 @@ class Repository end def expire_branches_cache - expire_method_caches(%i(branch_names branch_count)) + expire_method_caches(%i(branch_names branch_count has_visible_content?)) @local_branches = nil @branch_exists_memo = nil end @@ -345,7 +343,7 @@ class Repository def expire_emptiness_caches return unless empty? - expire_method_caches(%i(empty?)) + expire_method_caches(%i(empty? has_visible_content?)) end def lookup_cache @@ -488,13 +486,7 @@ class Repository def exists? return false unless full_path - Gitlab::GitalyClient.migrate(:repository_exists) do |enabled| - if enabled - raw_repository.exists? - else - refs_directory_exists? - end - end + raw_repository.exists? end cache_method :exists? @@ -528,13 +520,17 @@ class Repository delegate :tag_names, to: :raw_repository cache_method :tag_names, fallback: [] - delegate :branch_count, :tag_count, to: :raw_repository + delegate :branch_count, :tag_count, :has_visible_content?, to: :raw_repository cache_method :branch_count, fallback: 0 cache_method :tag_count, fallback: 0 + cache_method :has_visible_content?, fallback: false def avatar - if tree = file_on_head(:avatar) - tree.path + # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/38327 + Gitlab::GitalyClient.allow_n_plus_1_calls do + if tree = file_on_head(:avatar) + tree.path + end end end cache_method :avatar @@ -834,10 +830,6 @@ class Repository } end - def user_to_committer(user) - Gitlab::Git.committer_hash(email: user.email, name: user.name) - end - def can_be_merged?(source_sha, target_branch) our_commit = rugged.branches[target_branch].target their_commit = rugged.lookup(source_sha) @@ -858,55 +850,54 @@ class Repository end end - def revert( - user, commit, branch_name, - start_branch_name: nil, start_project: project) - with_branch( - user, - branch_name, - start_branch_name: start_branch_name, - start_repository: start_project.repository.raw_repository) do |start_commit| - - revert_tree_id = check_revert_content(commit, start_commit.sha) - unless revert_tree_id - raise Repository::CreateTreeError.new('Failed to revert commit') + def ff_merge(user, source, target_branch, merge_request: nil) + our_commit = rugged.branches[target_branch].target + their_commit = + if source.is_a?(Gitlab::Git::Commit) + source.raw_commit + else + rugged.lookup(source) end - committer = user_to_committer(user) + raise 'Invalid merge target' if our_commit.nil? + raise 'Invalid merge source' if their_commit.nil? + + with_branch(user, target_branch) do |start_commit| + merge_request&.update(in_progress_merge_commit_sha: their_commit.oid) - create_commit(message: commit.revert_message(user), - author: committer, - committer: committer, - tree: revert_tree_id, - parents: [start_commit.sha]) + their_commit.oid end end - def cherry_pick( - user, commit, branch_name, + def revert( + user, commit, branch_name, message, start_branch_name: nil, start_project: project) - with_branch( - user, - branch_name, - start_branch_name: start_branch_name, - start_repository: start_project.repository.raw_repository) do |start_commit| - cherry_pick_tree_id = check_cherry_pick_content(commit, start_commit.sha) - unless cherry_pick_tree_id - raise Repository::CreateTreeError.new('Failed to cherry-pick commit') - end + with_cache_hooks do + raw_repository.revert( + user: user, + commit: commit.raw, + branch_name: branch_name, + message: message, + start_branch_name: start_branch_name, + start_repository: start_project.repository.raw_repository + ) + end + end - committer = user_to_committer(user) + def cherry_pick( + user, commit, branch_name, message, + start_branch_name: nil, start_project: project) - create_commit(message: commit.cherry_pick_message(user), - author: { - email: commit.author_email, - name: commit.author_name, - time: commit.authored_date - }, - committer: committer, - tree: cherry_pick_tree_id, - parents: [start_commit.sha]) + with_cache_hooks do + raw_repository.cherry_pick( + user: user, + commit: commit.raw, + branch_name: branch_name, + message: message, + start_branch_name: start_branch_name, + start_repository: start_project.repository.raw_repository + ) end end @@ -918,36 +909,6 @@ class Repository end end - def check_revert_content(target_commit, source_sha) - args = [target_commit.sha, source_sha] - args << { mainline: 1 } if target_commit.merge_commit? - - revert_index = rugged.revert_commit(*args) - return false if revert_index.conflicts? - - tree_id = revert_index.write_tree(rugged) - return false unless diff_exists?(source_sha, tree_id) - - tree_id - end - - def check_cherry_pick_content(target_commit, source_sha) - args = [target_commit.sha, source_sha] - args << 1 if target_commit.merge_commit? - - cherry_pick_index = rugged.cherrypick_commit(*args) - return false if cherry_pick_index.conflicts? - - tree_id = cherry_pick_index.write_tree(rugged) - return false unless diff_exists?(source_sha, tree_id) - - tree_id - end - - def diff_exists?(sha1, sha2) - rugged.diff(sha1, sha2).size > 0 - end - def merged_to_root_ref?(branch_name) branch_commit = commit(branch_name) root_ref_commit = commit(root_ref) @@ -1028,7 +989,7 @@ class Repository end def create_ref(ref, ref_path) - fetch_ref(path_to_repo, ref, ref_path) + raw_repository.write_ref(ref_path, ref) end def ls_files(ref) @@ -1113,12 +1074,6 @@ class Repository blob.data end - def refs_directory_exists? - circuit_breaker.perform do - File.exist?(File.join(path_to_repo, 'refs')) - end - end - def cache # TODO: should we use UUIDs here? We could move repositories without clearing this cache @cache ||= RepositoryCache.new(full_path, @project.id) @@ -1170,10 +1125,6 @@ class Repository Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, false)) end - def circuit_breaker - @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(project.repository_storage) - end - def find_commits_by_message_by_shelling_out(query, ref, path, limit, offset) ref ||= root_ref |