Class: Gitlab::Git::Repository

Inherits:
Object
  • Object
show all
Includes:
EncodingHelper, RepositoryMirroring, Gitlab::Git::RuggedImpl::Repository, WrapsGitalyErrors, Utils::StrongMemoize
Defined in:
lib/gitlab/git/repository.rb

Defined Under Namespace

Classes: CreateTreeError

Constant Summary collapse

SEARCH_CONTEXT_LINES =
3
REV_LIST_COMMIT_LIMIT =
2_000
GITALY_INTERNAL_URL =
'ssh://gitaly/internal.git'
GITLAB_PROJECTS_TIMEOUT =
Gitlab.config.gitlab_shell.git_timeout
EMPTY_REPOSITORY_CHECKSUM =
'0000000000000000000000000000000000000000'
NoRepository =
Class.new(::Gitlab::Git::BaseError)
RepositoryExists =
Class.new(::Gitlab::Git::BaseError)
InvalidRepository =
Class.new(::Gitlab::Git::BaseError)
InvalidBlobName =
Class.new(::Gitlab::Git::BaseError)
InvalidRef =
Class.new(::Gitlab::Git::BaseError)
GitError =
Class.new(::Gitlab::Git::BaseError)
DeleteBranchError =
Class.new(::Gitlab::Git::BaseError)
TagExistsError =
Class.new(::Gitlab::Git::BaseError)
ChecksumError =
Class.new(::Gitlab::Git::BaseError)

Constants included from EncodingHelper

EncodingHelper::BOM_UTF8, EncodingHelper::ENCODING_CONFIDENCE_THRESHOLD, EncodingHelper::ESCAPED_CHARS, EncodingHelper::UNICODE_REPLACEMENT_CHARACTER

Constants included from Gitlab::Git::RuggedImpl::Repository

Gitlab::Git::RuggedImpl::Repository::ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES, Gitlab::Git::RuggedImpl::Repository::FEATURE_FLAGS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from EncodingHelper

#binary_io, #detect_binary?, #detect_encoding, #detect_libgit2_binary?, #encode!, #encode_binary, #encode_utf8, #encode_utf8_no_detect, #encode_utf8_with_escaping!, #encode_utf8_with_replacement_character, #strip_bom, #unquote_path

Methods included from WrapsGitalyErrors

#wrapped_gitaly_errors

Methods included from RepositoryMirroring

#remote_branches

Methods included from Gitlab::Git::RuggedImpl::Repository

#alternate_object_directories, #cleanup, #lookup, #relative_object_directories, #rev_parse_target, #rugged, #rugged_is_ancestor?, #rugged_merge_base

Methods included from Utils::Override

#extended, extensions, #included, #method_added, #override, #prepended, #queue_verification, verify!

Methods included from Gitlab::Git::RuggedImpl::UseRugged

#execute_rugged_call, #rugged_enabled_through_feature_flag?, #rugged_feature_keys, #running_puma_with_multiple_threads?, #use_rugged?

Constructor Details

#initialize(storage, relative_path, gl_repository, gl_project_path, container: nil) ⇒ Repository

Returns a new instance of Repository.



59
60
61
62
63
64
65
66
67
# File 'lib/gitlab/git/repository.rb', line 59

def initialize(storage, relative_path, gl_repository, gl_project_path, container: nil)
  @storage = storage
  @relative_path = relative_path
  @gl_repository = gl_repository
  @gl_project_path = gl_project_path
  @container = container

  @name = @relative_path.split("/").last
end

Instance Attribute Details

#containerObject (readonly)

Returns the value of attribute container.



48
49
50
# File 'lib/gitlab/git/repository.rb', line 48

def container
  @container
end

#gl_project_pathObject (readonly)

Returns the value of attribute gl_project_path.



48
49
50
# File 'lib/gitlab/git/repository.rb', line 48

def gl_project_path
  @gl_project_path
end

#gl_repositoryObject (readonly) Also known as: object_pool_remote_name

Returns the value of attribute gl_repository.



48
49
50
# File 'lib/gitlab/git/repository.rb', line 48

def gl_repository
  @gl_repository
end

#nameObject (readonly)

Directory name of repo



43
44
45
# File 'lib/gitlab/git/repository.rb', line 43

def name
  @name
end

#relative_pathObject (readonly)

Relative path of repo



46
47
48
# File 'lib/gitlab/git/repository.rb', line 46

def relative_path
  @relative_path
end

#storageObject (readonly)

Returns the value of attribute storage.



48
49
50
# File 'lib/gitlab/git/repository.rb', line 48

def storage
  @storage
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



78
79
80
# File 'lib/gitlab/git/repository.rb', line 78

def ==(other)
  other.is_a?(self.class) && [storage, relative_path] == [other.storage, other.relative_path]
end

#add_branch(branch_name, user:, target:) ⇒ Object



644
645
646
647
648
# File 'lib/gitlab/git/repository.rb', line 644

def add_branch(branch_name, user:, target:)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_create_branch(branch_name, user, target)
  end
end

#add_tag(tag_name, user:, target:, message: nil) ⇒ Object



650
651
652
653
654
# File 'lib/gitlab/git/repository.rb', line 650

def add_tag(tag_name, user:, target:, message: nil)
  wrapped_gitaly_errors do
    gitaly_operation_client.add_tag(tag_name, user, target, message)
  end
end

#ancestor?(from, to) ⇒ Boolean

Returns true is from is direct ancestor to to, otherwise false

Returns:

  • (Boolean)


500
501
502
# File 'lib/gitlab/git/repository.rb', line 500

def ancestor?(from, to)
  gitaly_commit_client.ancestor?(from, to)
end

#archive_metadata(ref, storage_path, project_path, format = "tar.gz", append_sha:, path: nil) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/gitlab/git/repository.rb', line 261

def (ref, storage_path, project_path, format = "tar.gz", append_sha:, path: nil)
  ref ||= root_ref

  if Feature.enabled?(:resolve_ambiguous_archives, container)
    commit_id = extract_commit_id_from_ref(ref)
    return {} if commit_id.nil?
  else
    commit_id = ref
  end

  commit = Gitlab::Git::Commit.find(self, commit_id)
  return {} if commit.nil?

  prefix = archive_prefix(ref, commit.id, project_path, append_sha: append_sha, path: path)

  {
    'ArchivePrefix' => prefix,
    'ArchivePath' => archive_file_path(storage_path, commit.id, prefix, format),
    'CommitId' => commit.id,
    'GitalyRepository' => gitaly_repository.to_h
  }
end

#async_delete_refs(*refs) ⇒ Object



756
757
758
759
760
761
762
763
764
# File 'lib/gitlab/git/repository.rb', line 756

def async_delete_refs(*refs)
  raise "async_delete_refs only supports project repositories" unless container.is_a?(Project)

  records = refs.map do |ref|
    BatchedGitRefUpdates::Deletion.new(project_id: container.id, ref: ref, created_at: Time.current, updated_at: Time.current)
  end

  BatchedGitRefUpdates::Deletion.bulk_insert!(records)
end

#attributes(path) ⇒ Object

Returns the Git attributes for the given file path.

See ‘Gitlab::Git::Attributes` for more information.



829
830
831
# File 'lib/gitlab/git/repository.rb', line 829

def attributes(path)
  info_attributes.attributes(path)
end

#attributes_at(ref) ⇒ Object

Returns parsed .gitattributes for a given ref

This only parses the root .gitattributes file, it does not traverse subfolders to find additional .gitattributes files

This method is around 30 times slower than ‘attributes`, which uses `$GIT_DIR/info/attributes`. Consider caching AttributesAtRefParser and reusing that for multiple calls instead of this method.



845
846
847
# File 'lib/gitlab/git/repository.rb', line 845

def attributes_at(ref)
  AttributesAtRefParser.new(self, ref)
end

#batch_blobs(items, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) ⇒ Object

Items should be of format [[commit_id, path], [commit_id1, path1]]



957
958
959
# File 'lib/gitlab/git/repository.rb', line 957

def batch_blobs(items, blob_size_limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE)
  Gitlab::Git::Blob.batch(self, items, blob_size_limit: blob_size_limit)
end

#blob_at(sha, path, limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) ⇒ Object



952
953
954
# File 'lib/gitlab/git/repository.rb', line 952

def blob_at(sha, path, limit: Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE)
  Gitlab::Git::Blob.find(self, sha, path, limit: limit) unless Gitlab::Git.blank_ref?(sha)
end

#blobs(revisions, with_paths: false, dynamic_timeout: nil) ⇒ Object

List blobs reachable via a set of revisions. Supports the pseudo-revisions ‘–not` and `–all`. Uses the minimum of GitalyClient.medium_timeout and dynamic timeout if the dynamic timeout is set, otherwise it’ll always use the medium timeout.



436
437
438
439
440
441
442
443
444
445
# File 'lib/gitlab/git/repository.rb', line 436

def blobs(revisions, with_paths: false, dynamic_timeout: nil)
  revisions = revisions.reject { |rev| rev.blank? || rev == ::Gitlab::Git::BLANK_SHA }

  return [] if revisions.blank?

  wrapped_gitaly_errors do
    gitaly_blob_client.list_blobs(revisions, limit: REV_LIST_COMMIT_LIMIT,
                                             with_paths: with_paths, dynamic_timeout: dynamic_timeout)
  end
end

#branch_countObject

Returns the number of valid branches



162
163
164
# File 'lib/gitlab/git/repository.rb', line 162

def branch_count
  branch_names.count
end

#branch_exists?(name) ⇒ Boolean

Returns true if the given branch exists

name - The name of the branch as a String.

Returns:

  • (Boolean)


244
245
246
247
248
# File 'lib/gitlab/git/repository.rb', line 244

def branch_exists?(name)
  wrapped_gitaly_errors do
    gitaly_ref_exists?("refs/heads/#{name}")
  end
end

#branch_namesObject

Returns an Array of branch names sorted by name ASC



116
117
118
119
120
# File 'lib/gitlab/git/repository.rb', line 116

def branch_names
  refs = list_refs([Gitlab::Git::BRANCH_REF_PREFIX])

  refs.map { |ref| Gitlab::Git.branch_name(ref.name) }
end

#branch_names_contains_sha(sha, limit: 0) ⇒ Object



1110
1111
1112
# File 'lib/gitlab/git/repository.rb', line 1110

def branch_names_contains_sha(sha, limit: 0)
  gitaly_ref_client.branch_names_contains_sha(sha, limit: limit)
end

#branchesObject

Returns an Array of Branches



123
124
125
126
127
# File 'lib/gitlab/git/repository.rb', line 123

def branches
  wrapped_gitaly_errors do
    gitaly_ref_client.branches
  end
end

#bundle_to_disk(save_path) ⇒ Object



1009
1010
1011
1012
1013
1014
1015
# File 'lib/gitlab/git/repository.rb', line 1009

def bundle_to_disk(save_path)
  wrapped_gitaly_errors do
    gitaly_repository_client.create_bundle(save_path)
  end

  true
end

#can_be_merged?(source_sha, target_branch) ⇒ Boolean

Returns:

  • (Boolean)


1127
1128
1129
1130
1131
1132
1133
# File 'lib/gitlab/git/repository.rb', line 1127

def can_be_merged?(source_sha, target_branch)
  if target_sha = find_branch(target_branch)&.target
    !gitaly_conflicts_client(source_sha, target_sha).conflicts?
  else
    false
  end
end

#check_objects_exist(refs) ⇒ Object



412
413
414
415
416
# File 'lib/gitlab/git/repository.rb', line 412

def check_objects_exist(refs)
  wrapped_gitaly_errors do
    gitaly_commit_client.object_existence_map(Array.wrap(refs))
  end
end

#checksumObject



1196
1197
1198
1199
1200
1201
1202
1203
# File 'lib/gitlab/git/repository.rb', line 1196

def checksum
  # The exists? RPC is much cheaper, so we perform this request first
  raise NoRepository, "Repository does not exist" unless exists?

  gitaly_repository_client.calculate_checksum
rescue GRPC::NotFound
  raise NoRepository # Guard against data races.
end

#cherry_pick(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:, dry_run: false) ⇒ Object



716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
# File 'lib/gitlab/git/repository.rb', line 716

def cherry_pick(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:, dry_run: false)
  args = {
    user: user,
    commit: commit,
    branch_name: branch_name,
    message: message,
    start_branch_name: start_branch_name,
    start_repository: start_repository,
    dry_run: dry_run
  }

  wrapped_gitaly_errors do
    gitaly_operation_client.user_cherry_pick(**args)
  end
end

#clean(options = {}) ⇒ Object

Mimic the ‘git clean` command and recursively delete untracked files. Valid keys that can be passed in the options hash are:

:d - Remove untracked directories :f - Remove untracked directories that are managed by a different

repository

:x - Remove ignored files

The value in options must evaluate to true for an option to take effect.

Examples:

repo.clean(d: true, f: true) # Enable the -d and -f options

repo.clean(d: false, x: true) # -x is enabled, -d is not


636
637
638
639
640
641
642
# File 'lib/gitlab/git/repository.rb', line 636

def clean(options = {})
  strategies = [:remove_untracked]
  strategies.push(:force) if options[:f]
  strategies.push(:remove_ignored) if options[:x]

  # TODO: implement this method
end

#commit(ref = 'HEAD') ⇒ Object

Refactoring aid; allows us to copy code from app/models/repository.rb



905
906
907
# File 'lib/gitlab/git/repository.rb', line 905

def commit(ref = 'HEAD')
  Gitlab::Git::Commit.find(self, ref)
end

#commit_count(ref) ⇒ Object

Return total commits count accessible from passed ref



607
608
609
610
611
# File 'lib/gitlab/git/repository.rb', line 607

def commit_count(ref)
  wrapped_gitaly_errors do
    gitaly_commit_client.commit_count(ref)
  end
end

#commit_files(user, branch_name:, message:, actions:, author_email: nil, author_name: nil, start_branch_name: nil, start_sha: nil, start_repository: nil, force: false) ⇒ Gitlab::Git::OperationService::BranchUpdate

Creates a commit

rubocop:disable Metrics/ParameterLists

Parameters:

  • user (User)

    The committer of the commit.

  • branch_name: (String)

    The name of the branch to be created/updated.

  • message: (String)

    The commit message.

  • actions: (Array<Hash>)

    An array of files to be added/updated/removed.

  • author_email: (String) (defaults to: nil)

    The authors email, if unspecified the committers email is used.

  • author_name: (String) (defaults to: nil)

    The authors name, if unspecified the committers name is used.

  • start_branch_name: (String) (defaults to: nil)

    The name of the branch to be used as the parent of the commit. Only used if start_sha: is unspecified.

  • start_sha: (String) (defaults to: nil)

    The sha to be used as the parent of the commit.

  • start_repository: (Gitlab::Git::Repository) (defaults to: nil)

    The repository that contains the start branch or sha. Defaults to use this repository.

  • force: (Boolean) (defaults to: false)

    Force update the branch.

Returns:



1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
# File 'lib/gitlab/git/repository.rb', line 1039

def commit_files(
  user, branch_name:, message:, actions:,
  author_email: nil, author_name: nil,
  start_branch_name: nil, start_sha: nil, start_repository: nil,
  force: false)

  wrapped_gitaly_errors do
    gitaly_operation_client.user_commit_files(user, branch_name,
        message, actions, author_email, author_name,
        start_branch_name, start_repository, force, start_sha)
  end
end

#compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:) ⇒ Object



878
879
880
881
882
883
884
885
886
887
# File 'lib/gitlab/git/repository.rb', line 878

def compare_source_branch(target_branch_name, source_repository, source_branch_name, straight:)
  CrossRepo.new(source_repository, self).execute(target_branch_name) do |target_commit_id|
    Gitlab::Git::Compare.new(
      source_repository,
      target_commit_id,
      source_branch_name,
      straight: straight
    )
  end
end

#copy_gitattributes(ref) ⇒ Object



813
814
815
816
817
# File 'lib/gitlab/git/repository.rb', line 813

def copy_gitattributes(ref)
  wrapped_gitaly_errors do
    gitaly_repository_client.apply_gitattributes(ref)
  end
end

#count_commits(options) ⇒ Object



447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/gitlab/git/repository.rb', line 447

def count_commits(options)
  options = process_count_commits_options(options.dup)

  wrapped_gitaly_errors do
    if options[:left_right]
      from = options[:from]
      to = options[:to]

      right_count = gitaly_commit_client
        .commit_count("#{from}..#{to}", options)
      left_count = gitaly_commit_client
        .commit_count("#{to}..#{from}", options)

      [left_count, right_count]
    else
      gitaly_commit_client.commit_count(options[:ref], options)
    end
  end
end

#count_commits_between(from, to, options = {}) ⇒ Object

Counts the amount of commits between ‘from` and `to`.



468
469
470
# File 'lib/gitlab/git/repository.rb', line 468

def count_commits_between(from, to, options = {})
  count_commits(from: from, to: to, **options)
end

#create_branch(ref, start_point = "HEAD") ⇒ Object

Create a new branch named **ref+ based on **stat_point+, HEAD by default Note: No Git hooks are executed for this action

Examples:

create_branch("feature")
create_branch("other-feature", "master")


792
793
794
# File 'lib/gitlab/git/repository.rb', line 792

def create_branch(ref, start_point = "HEAD")
  write_ref(ref, start_point)
end

#create_from_bundle(bundle_path) ⇒ Object



967
968
969
970
971
972
973
974
# File 'lib/gitlab/git/repository.rb', line 967

def create_from_bundle(bundle_path)
  # It's important to check that the linked-to file is actually a valid
  # .bundle file as it is passed to `git clone`, which may otherwise
  # interpret it as a pointer to another repository
  ::Gitlab::Git::BundleFile.check!(bundle_path)

  gitaly_repository_client.create_from_bundle(bundle_path)
end

#create_repository(default_branch = nil) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/gitlab/git/repository.rb', line 106

def create_repository(default_branch = nil)
  wrapped_gitaly_errors do
    gitaly_repository_client.create_repository(default_branch)
  rescue GRPC::AlreadyExists => e
    raise RepositoryExists, e.message
  end
end

#delete_all_refs_except(prefixes) ⇒ Object



255
256
257
258
259
# File 'lib/gitlab/git/repository.rb', line 255

def delete_all_refs_except(prefixes)
  wrapped_gitaly_errors do
    gitaly_ref_client.delete_refs(except_with_prefixes: prefixes)
  end
end

#delete_branch(branch_name) ⇒ Object

Delete the specified branch from the repository Note: No Git hooks are executed for this action



748
749
750
751
752
753
754
# File 'lib/gitlab/git/repository.rb', line 748

def delete_branch(branch_name)
  branch_name = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{branch_name}" unless branch_name.start_with?("refs/")

  delete_refs(branch_name)
rescue CommandError => e
  raise DeleteBranchError, e
end

#delete_refsObject



780
781
782
783
784
# File 'lib/gitlab/git/repository.rb', line 780

def delete_refs(...)
  wrapped_gitaly_errors do
    gitaly_delete_refs(...)
  end
end

#diff(from, to, options = {}, *paths) ⇒ Object

Return an array of Diff objects that represent the diff between from and to. See Diff::filter_diff_options for the allowed diff options. The options hash can also include :break_rewrites to split larger rewrites into delete/add pairs.



522
523
524
525
526
# File 'lib/gitlab/git/repository.rb', line 522

def diff(from, to, options = {}, *paths)
  iterator = gitaly_commit_client.diff(from, to, options.merge(paths: paths))

  Gitlab::Git::DiffCollection.new(iterator, options)
end

#diff_stats(left_id, right_id) ⇒ Object



528
529
530
531
532
533
534
535
536
537
538
539
540
# File 'lib/gitlab/git/repository.rb', line 528

def diff_stats(left_id, right_id)
  if [left_id, right_id].any? { |ref| ref.blank? || Gitlab::Git.blank_ref?(ref) }
    return empty_diff_stats
  end

  stats = wrapped_gitaly_errors do
    gitaly_commit_client.diff_stats(left_id, right_id)
  end

  Gitlab::Git::DiffStatsCollection.new(stats)
rescue CommandError, TypeError
  empty_diff_stats
end

#disconnect_alternatesObject



1068
1069
1070
1071
1072
# File 'lib/gitlab/git/repository.rb', line 1068

def disconnect_alternates
  wrapped_gitaly_errors do
    gitaly_repository_client.disconnect_alternates
  end
end

#diverging_commit_count(from, to, max_count: 0) ⇒ Object

Return total diverging commits count



614
615
616
617
618
# File 'lib/gitlab/git/repository.rb', line 614

def diverging_commit_count(from, to, max_count: 0)
  wrapped_gitaly_errors do
    gitaly_commit_client.diverging_commit_count(from, to, max_count: max_count)
  end
end

#empty?Boolean

Returns:

  • (Boolean)


909
910
911
# File 'lib/gitlab/git/repository.rb', line 909

def empty?
  !has_visible_content?
end

#exists?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/gitlab/git/repository.rb', line 102

def exists?
  gitaly_repository_client.exists?
end

#expire_has_local_branches_cacheObject



186
187
188
# File 'lib/gitlab/git/repository.rb', line 186

def expire_has_local_branches_cache
  clear_memoization(:has_local_branches)
end

#fetch_remote(url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true, check_tags_changed: false, http_authorization_header: "", resolved_address: "") ⇒ Object

Fetch remote for repository

remote - remote name url - URL of the remote to fetch. ‘remote` is not used in this case. refmap - if url is given, determines which references should get fetched where ssh_auth - SSH known_hosts data and a private key to use for public-key authentication forced - should we use –force flag? no_tags - should we use –no-tags flag? prune - should we use –prune flag? check_tags_changed - should we ask gitaly to calculate whether any tags changed? resolved_address - resolved IP address for provided URL



924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
# File 'lib/gitlab/git/repository.rb', line 924

def fetch_remote( # rubocop:disable Metrics/ParameterLists
  url,
  refmap: nil, ssh_auth: nil, forced: false, no_tags: false, prune: true,
  check_tags_changed: false, http_authorization_header: "", resolved_address: "")
  wrapped_gitaly_errors do
    gitaly_repository_client.fetch_remote(
      url,
      refmap: refmap,
      ssh_auth: ssh_auth,
      forced: forced,
      no_tags: no_tags,
      prune: prune,
      check_tags_changed: check_tags_changed,
      timeout: GITLAB_PROJECTS_TIMEOUT,
      http_authorization_header: http_authorization_header,
      resolved_address: resolved_address
    )
  end
end

#fetch_source_branch!(source_repository, source_branch, local_ref) ⇒ Object



872
873
874
875
876
# File 'lib/gitlab/git/repository.rb', line 872

def fetch_source_branch!(source_repository, source_branch, local_ref)
  wrapped_gitaly_errors do
    gitaly_repository_client.fetch_source_branch(source_repository, source_branch, local_ref)
  end
end

#ff_merge(user, source_sha:, target_branch:, target_sha: nil) ⇒ Object



691
692
693
694
695
696
697
698
# File 'lib/gitlab/git/repository.rb', line 691

def ff_merge(user, source_sha:, target_branch:, target_sha: nil)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_ff_branch(user,
                                           source_sha: source_sha,
                                           target_branch: target_branch,
                                           target_sha: target_sha)
  end
end

#find_branch(name) ⇒ Object

Directly find a branch with a simple name (e.g. master)



131
132
133
134
135
136
137
138
139
# File 'lib/gitlab/git/repository.rb', line 131

def find_branch(name)
  wrapped_gitaly_errors do
    gitaly_ref_client.find_branch(name)
  end
rescue Gitlab::Git::AmbiguousRef
  # Gitaly returns "reference is ambiguous" error in case when users request
  # branch "my-branch", when another branch "my-branch/branch" exists.
  # We handle this error here and return nil for this case.
end

#find_changed_paths(treeish_objects, merge_commit_diff_mode: nil) ⇒ Object



542
543
544
545
546
547
548
549
550
551
552
# File 'lib/gitlab/git/repository.rb', line 542

def find_changed_paths(treeish_objects, merge_commit_diff_mode: nil)
  processed_objects = treeish_objects.compact

  return [] if processed_objects.empty?

  wrapped_gitaly_errors do
    gitaly_commit_client.find_changed_paths(processed_objects, merge_commit_diff_mode: merge_commit_diff_mode)
  end
rescue CommandError, TypeError, NoRepository
  []
end

#find_commits_by_message(query, ref, path, limit, offset) ⇒ Object



1152
1153
1154
1155
1156
1157
1158
# File 'lib/gitlab/git/repository.rb', line 1152

def find_commits_by_message(query, ref, path, limit, offset)
  wrapped_gitaly_errors do
    gitaly_commit_client
      .commits_by_message(query, revision: ref, path: path, limit: limit, offset: offset)
      .map { |c| commit(c) }
  end
end

#find_remote_root_ref(remote_url, authorization = nil) ⇒ Object



796
797
798
799
800
801
802
# File 'lib/gitlab/git/repository.rb', line 796

def find_remote_root_ref(remote_url, authorization = nil)
  return unless remote_url.present?

  wrapped_gitaly_errors do
    gitaly_remote_client.find_remote_root_ref(remote_url, authorization)
  end
end

#find_tag(name) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/gitlab/git/repository.rb', line 141

def find_tag(name)
  wrapped_gitaly_errors do
    gitaly_ref_client.find_tag(name)
  end
rescue CommandError
  # Gitaly used to return an `Internal` error in case the tag wasn't found, which is being translated to
  # `CommandError` by the wrapper. This has been converted in v15.3.0 to instead return a structured
  # error with a `tag_not_found` error, so rescuing from `Internal` errors can be removed in v15.4.0 and
  # later.
rescue Gitlab::Git::UnknownRef
  # This is the new error returned by `find_tag`, which knows to translate the structured error returned
  # by Gitaly when the tag does not exist.
end

#flipper_idObject

Support Feature Flag Repository actor



74
75
76
# File 'lib/gitlab/git/repository.rb', line 74

def flipper_id
  "Repository:#{@relative_path}"
end

#fsckObject

Raises:



961
962
963
964
965
# File 'lib/gitlab/git/repository.rb', line 961

def fsck
  msg, status = gitaly_repository_client.fsck

  raise GitError, "Could not fsck repository: #{msg}" unless status == 0
end

#full_pathObject



1062
1063
1064
1065
1066
# File 'lib/gitlab/git/repository.rb', line 1062

def full_path
  wrapped_gitaly_errors do
    gitaly_repository_client.full_path
  end
end

#get_patch_id(old_revision, new_revision) ⇒ Object



1211
1212
1213
1214
1215
# File 'lib/gitlab/git/repository.rb', line 1211

def get_patch_id(old_revision, new_revision)
  wrapped_gitaly_errors do
    gitaly_commit_client.get_patch_id(old_revision, new_revision)
  end
end

#gitaly_blob_clientObject



1098
1099
1100
# File 'lib/gitlab/git/repository.rb', line 1098

def gitaly_blob_client
  @gitaly_blob_client ||= Gitlab::GitalyClient::BlobService.new(self)
end

#gitaly_commit_clientObject



1082
1083
1084
# File 'lib/gitlab/git/repository.rb', line 1082

def gitaly_commit_client
  @gitaly_commit_client ||= Gitlab::GitalyClient::CommitService.new(self)
end

#gitaly_conflicts_client(our_commit_oid, their_commit_oid) ⇒ Object



1102
1103
1104
# File 'lib/gitlab/git/repository.rb', line 1102

def gitaly_conflicts_client(our_commit_oid, their_commit_oid)
  Gitlab::GitalyClient::ConflictsService.new(self, our_commit_oid, their_commit_oid)
end

#gitaly_operation_clientObject



1090
1091
1092
# File 'lib/gitlab/git/repository.rb', line 1090

def gitaly_operation_client
  @gitaly_operation_client ||= Gitlab::GitalyClient::OperationService.new(self)
end

#gitaly_ref_clientObject



1078
1079
1080
# File 'lib/gitlab/git/repository.rb', line 1078

def gitaly_ref_client
  @gitaly_ref_client ||= Gitlab::GitalyClient::RefService.new(self)
end

#gitaly_remote_clientObject



1094
1095
1096
# File 'lib/gitlab/git/repository.rb', line 1094

def gitaly_remote_client
  @gitaly_remote_client ||= Gitlab::GitalyClient::RemoteService.new(self)
end

#gitaly_repositoryObject



1074
1075
1076
# File 'lib/gitlab/git/repository.rb', line 1074

def gitaly_repository
  Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository, @gl_project_path)
end

#gitaly_repository_clientObject



1086
1087
1088
# File 'lib/gitlab/git/repository.rb', line 1086

def gitaly_repository_client
  @gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self)
end

#gitattribute(path, name) ⇒ Object



833
834
835
# File 'lib/gitlab/git/repository.rb', line 833

def gitattribute(path, name)
  attributes(path)[name]
end

#has_local_branches?Boolean Also known as: has_visible_content?

Returns:

  • (Boolean)


190
191
192
193
194
# File 'lib/gitlab/git/repository.rb', line 190

def has_local_branches?
  strong_memoize(:has_local_branches) do
    uncached_has_local_branches?
  end
end

#hashObject



84
85
86
# File 'lib/gitlab/git/repository.rb', line 84

def hash
  [self.class, storage, relative_path].hash
end

#import_repository(url, http_authorization_header: '', mirror: false, resolved_address: '') ⇒ Object

Raises:

  • (ArgumentError)


944
945
946
947
948
949
950
# File 'lib/gitlab/git/repository.rb', line 944

def import_repository(url, http_authorization_header: '', mirror: false, resolved_address: '')
  raise ArgumentError, "don't use disk paths with import_repository: #{url.inspect}" if url.start_with?('.', '/')

  wrapped_gitaly_errors do
    gitaly_repository_client.import_repository(url, http_authorization_header: http_authorization_header, mirror: mirror, resolved_address: resolved_address)
  end
end

#info_attributesObject



819
820
821
822
823
824
# File 'lib/gitlab/git/repository.rb', line 819

def info_attributes
  return @info_attributes if @info_attributes

  content = gitaly_repository_client.info_attributes
  @info_attributes = AttributesParser.new(content)
end

#languages(ref = nil) ⇒ Object



849
850
851
852
853
# File 'lib/gitlab/git/repository.rb', line 849

def languages(ref = nil)
  wrapped_gitaly_errors do
    gitaly_commit_client.languages(ref)
  end
end

#last_commit_for_path(sha, path, literal_pathspec: false) ⇒ Object



1190
1191
1192
1193
1194
# File 'lib/gitlab/git/repository.rb', line 1190

def last_commit_for_path(sha, path, literal_pathspec: false)
  wrapped_gitaly_errors do
    gitaly_commit_client.last_commit_for_path(sha, path, literal_pathspec: literal_pathspec)
  end
end

#licenseObject



855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
# File 'lib/gitlab/git/repository.rb', line 855

def license
  wrapped_gitaly_errors do
    response = gitaly_repository_client.find_license

    break nil if response.license_short_name.empty?

    ::Gitlab::Git::DeclaredLicense.new(key: response.license_short_name,
                                       name: response.license_name,
                                       nickname: response.license_nickname.presence,
                                       url: response.license_url.presence,
                                       path: response.license_path)
  end
rescue Licensee::InvalidLicense => e
  Gitlab::ErrorTracking.track_exception(e)
  nil
end

#list_commits_by(query, ref, author: nil, before: nil, after: nil, limit: 1000) ⇒ Object



1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
# File 'lib/gitlab/git/repository.rb', line 1160

def list_commits_by(query, ref, author: nil, before: nil, after: nil, limit: 1000)
  params = {
    author: author,
    ignore_case: true,
    commit_message_patterns: query,
    before: before,
    after: after,
    reverse: false,
    pagination_params: { limit: limit }
  }

  wrapped_gitaly_errors do
    gitaly_commit_client
      .list_commits([ref], params)
      .map { |c| commit(c) }
  end
end

#list_commits_by_ref_name(refs) ⇒ Object



1184
1185
1186
1187
1188
# File 'lib/gitlab/git/repository.rb', line 1184

def list_commits_by_ref_name(refs)
  wrapped_gitaly_errors do
    gitaly_commit_client.list_commits_by_ref_name(refs)
  end
end

#list_last_commits_for_tree(sha, path, offset: 0, limit: 25, literal_pathspec: false) ⇒ Object



1178
1179
1180
1181
1182
# File 'lib/gitlab/git/repository.rb', line 1178

def list_last_commits_for_tree(sha, path, offset: 0, limit: 25, literal_pathspec: false)
  wrapped_gitaly_errors do
    gitaly_commit_client.list_last_commits_for_tree(sha, path, offset: offset, limit: limit, literal_pathspec: literal_pathspec)
  end
end

#list_refs(patterns = [Gitlab::Git::BRANCH_REF_PREFIX], pointing_at_oids: [], peel_tags: false) ⇒ Object

peel_tags slows down the request by a factor of 3-4



898
899
900
901
902
# File 'lib/gitlab/git/repository.rb', line 898

def list_refs(patterns = [Gitlab::Git::BRANCH_REF_PREFIX], pointing_at_oids: [], peel_tags: false)
  wrapped_gitaly_errors do
    gitaly_ref_client.list_refs(patterns, pointing_at_oids: pointing_at_oids, peel_tags: peel_tags)
  end
end

#local_branches(sort_by: nil, pagination_params: nil) ⇒ Object



155
156
157
158
159
# File 'lib/gitlab/git/repository.rb', line 155

def local_branches(sort_by: nil, pagination_params: nil)
  wrapped_gitaly_errors do
    gitaly_ref_client.local_branches(sort_by: sort_by, pagination_params: pagination_params)
  end
end

#log(options) ⇒ Object

Build an array of commits.

Usage.

repo.log(
  ref: 'master',
  path: 'app/models',
  limit: 10,
  offset: 5,
  after: Time.new(2016, 4, 21, 14, 32, 10)
)


380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/gitlab/git/repository.rb', line 380

def log(options)
  default_options = {
    limit: 10,
    offset: 0,
    path: nil,
    author: nil,
    follow: false,
    skip_merges: false,
    after: nil,
    before: nil,
    all: false
  }

  options = default_options.merge(options)
  options[:offset] ||= 0

  limit = options[:limit]
  if limit == 0 || !limit.is_a?(Integer)
    raise ArgumentError, "invalid Repository#log limit: #{limit.inspect}"
  end

  wrapped_gitaly_errors do
    gitaly_commit_client.find_commits(options)
  end
end

#ls_files(ref) ⇒ Object

Returns result like “git ls-files” , recursive and full file path

Ex.

repo.ls_files('master')


809
810
811
# File 'lib/gitlab/git/repository.rb', line 809

def ls_files(ref)
  gitaly_commit_client.ls_files(ref)
end

#merge(user, source_sha:, target_branch:, message:, target_sha: nil, &block) ⇒ Object



680
681
682
683
684
685
686
687
688
689
# File 'lib/gitlab/git/repository.rb', line 680

def merge(user, source_sha:, target_branch:, message:, target_sha: nil, &block)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_merge_branch(user,
                                              source_sha: source_sha,
                                              target_branch: target_branch,
                                              message: message,
                                              target_sha: target_sha,
                                              &block)
  end
end

#merge_baseObject

Returns the SHA of the most recent common ancestor of from and to



493
494
495
496
497
# File 'lib/gitlab/git/repository.rb', line 493

def merge_base(...)
  wrapped_gitaly_errors do
    gitaly_repository_client.find_merge_base(...)
  end
end

#merge_to_ref(user, **kwargs) ⇒ Object



674
675
676
677
678
# File 'lib/gitlab/git/repository.rb', line 674

def merge_to_ref(user, **kwargs)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_merge_to_ref(user, **kwargs)
  end
end

#merged_branch_names(branch_names = []) ⇒ Object



504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/gitlab/git/repository.rb', line 504

def merged_branch_names(branch_names = [])
  return [] unless root_ref

  root_sha = find_branch(root_ref)&.target

  return [] unless root_sha

  branches = wrapped_gitaly_errors do
    gitaly_merged_branch_names(branch_names, root_sha)
  end

  Set.new(branches)
end

#new_blobs(newrevs, dynamic_timeout: nil) ⇒ Object



418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/gitlab/git/repository.rb', line 418

def new_blobs(newrevs, dynamic_timeout: nil)
  newrevs = Array.wrap(newrevs).reject { |rev| rev.blank? || rev == ::Gitlab::Git::BLANK_SHA }
  return [] if newrevs.empty?

  newrevs = newrevs.uniq.sort

  @new_blobs ||= {}
  @new_blobs[newrevs] ||= blobs(
    ['--not', '--all', '--not'] + newrevs,
    with_paths: true,
    dynamic_timeout: dynamic_timeout
  ).to_a
end

#new_commits(newrevs) ⇒ Object



406
407
408
409
410
# File 'lib/gitlab/git/repository.rb', line 406

def new_commits(newrevs)
  wrapped_gitaly_errors do
    gitaly_commit_client.list_new_commits(Array.wrap(newrevs))
  end
end

#object_directory_sizeObject

Return git object directory size in bytes



366
367
368
# File 'lib/gitlab/git/repository.rb', line 366

def object_directory_size
  gitaly_repository_client.get_object_directory_size.to_f * 1024
end

#object_poolObject



1217
1218
1219
1220
1221
# File 'lib/gitlab/git/repository.rb', line 1217

def object_pool
  wrapped_gitaly_errors do
    gitaly_repository_client.object_pool.object_pool
  end
end

#pathObject

This method will be removed when Gitaly reaches v1.1.



89
90
91
92
93
# File 'lib/gitlab/git/repository.rb', line 89

def path
  File.join(
    Gitlab.config.repositories.storages[@storage].legacy_disk_path, @relative_path
  )
end

#praefect_info_clientObject



1106
1107
1108
# File 'lib/gitlab/git/repository.rb', line 1106

def praefect_info_client
  @praefect_info_client ||= Gitlab::GitalyClient::PraefectInfoService.new(self)
end

#raw_changes_between(old_rev, new_rev) ⇒ Object

old_rev and new_rev are commit ID’s the result of this method is an array of Gitlab::Git::RawDiffChange



474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/gitlab/git/repository.rb', line 474

def raw_changes_between(old_rev, new_rev)
  @raw_changes_between ||= {}

  @raw_changes_between[[old_rev, new_rev]] ||=
    begin
      return [] if new_rev.blank? || new_rev == Gitlab::Git::BLANK_SHA

      wrapped_gitaly_errors do
        gitaly_repository_client.raw_changes_between(old_rev, new_rev)
          .each_with_object([]) do |msg, arr|
          msg.raw_changes.each { |change| arr << ::Gitlab::Git::RawDiffChange.new(change) }
        end
      end
    end
rescue ArgumentError => e
  raise Gitlab::Git::Repository::GitError, e
end

#rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, push_options: [], &block) ⇒ Object



976
977
978
979
980
981
982
983
984
985
986
987
988
989
# File 'lib/gitlab/git/repository.rb', line 976

def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:, push_options: [], &block)
  wrapped_gitaly_errors do
    gitaly_operation_client.rebase(
      user,
      rebase_id,
      branch: branch,
      branch_sha: branch_sha,
      remote_repository: remote_repository,
      remote_branch: remote_branch,
      push_options: push_options,
      &block
    )
  end
end

#rebase_to_ref(user, source_sha:, target_ref:, first_parent_ref:, expected_old_oid: "") ⇒ Object



991
992
993
994
995
996
997
998
999
1000
1001
# File 'lib/gitlab/git/repository.rb', line 991

def rebase_to_ref(user, source_sha:, target_ref:, first_parent_ref:, expected_old_oid: "")
  wrapped_gitaly_errors do
    gitaly_operation_client.user_rebase_to_ref(
      user,
      source_sha: source_sha,
      target_ref: target_ref,
      first_parent_ref: first_parent_ref,
      expected_old_oid: expected_old_oid
    )
  end
end

#recent_objects_sizeObject

Return repository recent objects size in mebibytes

This differs from the #size method in that it does not include the size of:

  • stale objects

  • cruft packs of unreachable objects

see: gitlab.com/gitlab-org/gitaly/-/blob/257ee33ca268d48c8f99dcbfeaaf7d8b19e07f06/internal/gitaly/service/repository/repository_info.go#L41-62



357
358
359
360
361
362
363
# File 'lib/gitlab/git/repository.rb', line 357

def recent_objects_size
  wrapped_gitaly_errors do
    recent_size_in_bytes = gitaly_repository_client.repository_info.objects.recent_size

    Gitlab::Utils.bytes_to_megabytes(recent_size_in_bytes)
  end
end

#ref_exists?(ref_name) ⇒ Boolean

Returns true if the given ref name exists

Ref names must start with ‘refs/`.

Returns:

  • (Boolean)


226
227
228
229
230
# File 'lib/gitlab/git/repository.rb', line 226

def ref_exists?(ref_name)
  wrapped_gitaly_errors do
    gitaly_ref_exists?(ref_name)
  end
end

#ref_namesObject

Returns an Array of branch and tag names



251
252
253
# File 'lib/gitlab/git/repository.rb', line 251

def ref_names
  branch_names + tag_names
end

#refs_by_oid(oid:, limit: 0, ref_patterns: nil) ⇒ Object

Returns matching refs for OID

Limit of 0 means there is no limit.



574
575
576
577
578
579
580
# File 'lib/gitlab/git/repository.rb', line 574

def refs_by_oid(oid:, limit: 0, ref_patterns: nil)
  wrapped_gitaly_errors do
    gitaly_ref_client.find_refs_by_oid(oid: oid, limit: limit, ref_patterns: ref_patterns) || []
  end
rescue CommandError, TypeError, NoRepository
  []
end

#refs_hashObject

Get refs hash which key is the commit id and value is a Gitlab::Git::Tag or Gitlab::Git::Branch Note that both inherit from Gitlab::Git::Ref



557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/gitlab/git/repository.rb', line 557

def refs_hash
  return @refs_hash if @refs_hash

  @refs_hash = Hash.new { |h, k| h[k] = [] }

  (tags + branches).each do |ref|
    next unless ref.target && ref.name && ref.dereferenced_target&.id

    @refs_hash[ref.dereferenced_target.id] << ref.name
  end

  @refs_hash
end

#removeObject



172
173
174
175
176
177
178
# File 'lib/gitlab/git/repository.rb', line 172

def remove
  wrapped_gitaly_errors do
    gitaly_repository_client.remove
  end
rescue NoRepository
  nil
end

#rename(new_relative_path) ⇒ Object



166
167
168
169
170
# File 'lib/gitlab/git/repository.rb', line 166

def rename(new_relative_path)
  wrapped_gitaly_errors do
    gitaly_repository_client.rename(new_relative_path)
  end
end

#replicasObject



1205
1206
1207
1208
1209
# File 'lib/gitlab/git/repository.rb', line 1205

def replicas
  wrapped_gitaly_errors do
    praefect_info_client.replicas
  end
end

#replicate(source_repository) ⇒ Object



180
181
182
183
184
# File 'lib/gitlab/git/repository.rb', line 180

def replicate(source_repository)
  wrapped_gitaly_errors do
    gitaly_repository_client.replicate(source_repository)
  end
end

#revert(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:, dry_run: false) ⇒ Object



700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
# File 'lib/gitlab/git/repository.rb', line 700

def revert(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:, dry_run: false)
  args = {
    user: user,
    commit: commit,
    branch_name: branch_name,
    message: message,
    start_branch_name: start_branch_name,
    start_repository: start_repository,
    dry_run: dry_run
  }

  wrapped_gitaly_errors do
    gitaly_operation_client.user_revert(**args)
  end
end

#rm_branch(branch_name, user:) ⇒ Object



662
663
664
665
666
# File 'lib/gitlab/git/repository.rb', line 662

def rm_branch(branch_name, user:)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_delete_branch(branch_name, user)
  end
end

#rm_tag(tag_name, user:) ⇒ Object



668
669
670
671
672
# File 'lib/gitlab/git/repository.rb', line 668

def rm_tag(tag_name, user:)
  wrapped_gitaly_errors do
    gitaly_operation_client.rm_tag(tag_name, user)
  end
end

#root_ref(head_only: false) ⇒ Object

Default branch in the repository



96
97
98
99
100
# File 'lib/gitlab/git/repository.rb', line 96

def root_ref(head_only: false)
  wrapped_gitaly_errors do
    gitaly_ref_client.default_branch_name(head_only: head_only)
  end
end

#search_files_by_content(query, ref, options = {}) ⇒ Object



1118
1119
1120
1121
1122
1123
1124
1125
# File 'lib/gitlab/git/repository.rb', line 1118

def search_files_by_content(query, ref, options = {})
  return [] if empty? || query.blank?

  safe_query = Regexp.escape(query)
  ref ||= root_ref

  gitaly_repository_client.search_files_by_content(ref, safe_query, options)
end

#search_files_by_name(query, ref, limit: 0, offset: 0) ⇒ Object



1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
# File 'lib/gitlab/git/repository.rb', line 1135

def search_files_by_name(query, ref, limit: 0, offset: 0)
  safe_query = query.sub(%r{^/*}, "")
  ref ||= root_ref

  return [] if empty? || safe_query.blank?

  gitaly_repository_client.search_files_by_name(ref, safe_query, limit: limit, offset: offset).map do |file|
    Gitlab::EncodingHelper.encode_utf8(file)
  end
end

#search_files_by_regexp(filter, ref = 'HEAD', limit: 0, offset: 0) ⇒ Object



1146
1147
1148
1149
1150
# File 'lib/gitlab/git/repository.rb', line 1146

def search_files_by_regexp(filter, ref = 'HEAD', limit: 0, offset: 0)
  gitaly_repository_client.search_files_by_regexp(ref, filter, limit: limit, offset: offset).map do |file|
    Gitlab::EncodingHelper.encode_utf8(file)
  end
end

#set_full_path(full_path:) ⇒ Object

rubocop:enable Metrics/ParameterLists

Raises:



1053
1054
1055
1056
1057
1058
1059
1060
# File 'lib/gitlab/git/repository.rb', line 1053

def set_full_path(full_path:)
  return unless full_path.present?

  # This guard avoids Gitaly log/error spam
  raise NoRepository, 'repository does not exist' unless exists?

  gitaly_repository_client.set_full_path(full_path)
end

#sizeObject

Return repo size in megabytes



341
342
343
344
345
346
347
348
# File 'lib/gitlab/git/repository.rb', line 341

def size
  if Feature.enabled?(:use_repository_info_for_repository_size)
    repository_info_size_megabytes
  else
    kilobytes = gitaly_repository_client.repository_size
    (kilobytes.to_f / 1024).round(2)
  end
end

#squash(user, start_sha:, end_sha:, author:, message:) ⇒ Object



1003
1004
1005
1006
1007
# File 'lib/gitlab/git/repository.rb', line 1003

def squash(user, start_sha:, end_sha:, author:, message:)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_squash(user, start_sha, end_sha, author, message)
  end
end

#submodule_url_for(ref, path) ⇒ Object

Returns url for submodule

Ex.

@repository.submodule_url_for('master', 'rack')
# => git@localhost:rack.git


588
589
590
591
592
# File 'lib/gitlab/git/repository.rb', line 588

def submodule_url_for(ref, path)
  wrapped_gitaly_errors do
    gitaly_submodule_url_for(ref, path)
  end
end

#submodule_urls_for(ref) ⇒ Object

Returns path to url mappings for submodules

Ex.

@repository.submodule_urls_for('master')
# => { 'rack' => 'git@localhost:rack.git' }


600
601
602
603
604
# File 'lib/gitlab/git/repository.rb', line 600

def submodule_urls_for(ref)
  wrapped_gitaly_errors do
    gitaly_submodule_urls_for(ref)
  end
end

#tag_countObject

Returns the number of valid tags



204
205
206
# File 'lib/gitlab/git/repository.rb', line 204

def tag_count
  tag_names.count
end

#tag_exists?(name) ⇒ Boolean

Returns true if the given tag exists

name - The name of the tag as a String.

Returns:

  • (Boolean)


235
236
237
238
239
# File 'lib/gitlab/git/repository.rb', line 235

def tag_exists?(name)
  wrapped_gitaly_errors do
    gitaly_ref_exists?("refs/tags/#{name}")
  end
end

#tag_namesObject

Returns an Array of tag names



209
210
211
212
213
# File 'lib/gitlab/git/repository.rb', line 209

def tag_names
  refs = list_refs([Gitlab::Git::TAG_REF_PREFIX])

  refs.map { |ref| Gitlab::Git.tag_name(ref.name) }
end

#tag_names_contains_sha(sha, limit: 0) ⇒ Object



1114
1115
1116
# File 'lib/gitlab/git/repository.rb', line 1114

def tag_names_contains_sha(sha, limit: 0)
  gitaly_ref_client.tag_names_contains_sha(sha, limit: limit)
end

#tags(sort_by: nil, pagination_params: nil) ⇒ Object

Returns an Array of Tags



217
218
219
220
221
# File 'lib/gitlab/git/repository.rb', line 217

def tags(sort_by: nil, pagination_params: nil)
  wrapped_gitaly_errors do
    gitaly_ref_client.tags(sort_by: sort_by, pagination_params: pagination_params)
  end
end

#to_sObject



69
70
71
# File 'lib/gitlab/git/repository.rb', line 69

def to_s
  "<#{self.class.name}: #{self.gl_project_path}>"
end

#update_branch(branch_name, user:, newrev:, oldrev:) ⇒ Object



656
657
658
659
660
# File 'lib/gitlab/git/repository.rb', line 656

def update_branch(branch_name, user:, newrev:, oldrev:)
  wrapped_gitaly_errors do
    gitaly_operation_client.user_update_branch(branch_name, user, newrev, oldrev)
  end
end

#update_refs(ref_list) ⇒ Object

Update a list of references from X -> Y

Ref list is expected to be an array of hashes in the form: old_sha: new_sha reference:

When new_sha is Gitlab::Git::BLANK_SHA, then this will be deleted



774
775
776
777
778
# File 'lib/gitlab/git/repository.rb', line 774

def update_refs(ref_list)
  wrapped_gitaly_errors do
    gitaly_ref_client.update_refs(ref_list: ref_list) if ref_list.any?
  end
end

#update_submodule(user:, submodule:, commit_sha:, message:, branch:) ⇒ Object



732
733
734
735
736
737
738
739
740
741
742
743
744
# File 'lib/gitlab/git/repository.rb', line 732

def update_submodule(user:, submodule:, commit_sha:, message:, branch:)
  args = {
    user: user,
    submodule: submodule,
    commit_sha: commit_sha,
    branch: branch,
    message: message
  }

  wrapped_gitaly_errors do
    gitaly_operation_client.user_update_submodule(**args)
  end
end

#write_ref(ref_path, ref, old_ref: nil) ⇒ Object



889
890
891
892
893
894
895
# File 'lib/gitlab/git/repository.rb', line 889

def write_ref(ref_path, ref, old_ref: nil)
  ref_path = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref_path}" unless ref_path.start_with?("refs/") || ref_path == "HEAD"

  wrapped_gitaly_errors do
    gitaly_repository_client.write_ref(ref_path, ref, old_ref)
  end
end