class Gollum::Git::Git
Public Class Methods
new(repo)
click to toggle source
Rugged does not have a Git
class, but the Repository class should allows us to do what’s necessary.
# File lib/rugged_adapter/git_layer_rugged.rb, line 194 def initialize(repo) @repo = repo end
Public Instance Methods
cat_file(options, sha)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 224 def cat_file(options, sha) @repo.lookup(sha).read_raw end
checkout(path, ref = 'HEAD', options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 259 def checkout(path, ref = 'HEAD', options = {}) path = path.nil? ? path : [path] options = options.merge({:paths => path, :strategy => :force}) if ref == 'HEAD' @repo.checkout_head(**options) else ref = "refs/heads/#{ref}" unless ref =~ /^refs\/heads\// @repo.checkout_tree(sha_from_ref(ref), **options) end end
commit_from_ref(ref)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 335 def commit_from_ref(ref) sha_or_commit_from_ref(ref, :commit) end
exist?()
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 198 def exist? ::File.exist?(@repo.path) end
grep(search_terms, options={}) { |path, data| ... }
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 202 def grep(search_terms, options={}, &block) ref = options[:ref] ? options[:ref] : "HEAD" tree = @repo.lookup(sha_from_ref(ref)).tree tree = @repo.lookup(tree.path(options[:path])[:oid]) if options[:path] enc = options.fetch(:encoding, 'utf-8') results = [] tree.walk_blobs(:postorder) do |root, entry| blob = @repo.lookup(entry[:oid]) path = options[:path] ? ::File.join(options[:path], root, entry[:name]) : "#{root}#{entry[:name]}" data = blob.binary? ? nil : blob.content.force_encoding(enc) results << yield(path, data) end results.compact end
log(ref = Gollum::Git.default_ref_for_repo(@repo), path = nil, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 270 def log(ref = Gollum::Git.default_ref_for_repo(@repo), path = nil, options = {}) default_options = { :limit => options[:max_count] ? options[:max_count] : 10, :offset => options[:skip] ? options[:skip] : 0, :path => path, :follow => false, :skip_merges => false } options = default_options.merge(options) options[:limit] ||= 0 options[:offset] ||= 0 sha = sha_from_ref(ref) return [] if sha.nil? begin build_log(sha, options) rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError # Return an empty array if the ref wasn't found [] end end
lookup(id)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 308 def lookup(id) @repo.lookup(id) end
ls_files(query, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 295 def ls_files(query, options = {}) ref = options[:ref] || Gollum::Git.default_ref_for_repo(@repo) tree = @repo.lookup(sha_from_ref(ref)).tree tree = @repo.lookup(tree[options[:path]][:oid]) if options[:path] results = [] tree.walk_blobs do |root, blob| next unless blob[:name] =~ /#{query}/ path = options[:path] ? ::File.join(options[:path], root, blob[:name]) : "#{root}#{blob[:name]}" results << path end results end
pull(remote, branches = nil, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 344 def pull(remote, branches = nil, options = {}) branches = [branches].flatten.map {|branch| "refs/heads/#{branch}" unless branch =~ /^refs\/heads\//} r = @repo.remotes[remote] r.fetch(branches, **options) branches.each do |branch| branch_name = branch.match(/^refs\/heads\/(.*)/)[1] remote_name = remote.match(/^(refs\/heads\/)?(.*)/)[2] remote_ref = @repo.branches["#{remote_name}/#{branch_name}"].target local_ref = @repo.branches[branch].target index = @repo.merge_commits(local_ref, remote_ref) options = { author: Actor.default_actor.to_h, committer: Actor.default_actor.to_h, message: "Merged branch #{branch} of #{remote}.", parents: [local_ref, remote_ref], tree: index.write_tree(@repo), update_ref: branch } Rugged::Commit.create @repo, options @repo.checkout(@repo.head.name, :strategy => :force) if !@repo.bare? && branch == @repo.head.name end end
push(remote, branches = nil, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 339 def push(remote, branches = nil, options = {}) branches = [branches].flatten.map {|branch| "refs/heads/#{branch}" unless branch =~ /^refs\/heads\//} @repo.push(remote, branches, **options) end
ref_to_sha(query)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 312 def ref_to_sha(query) return query if sha?(query) query = "refs/heads/#{query}" if !query.nil? && !(query =~ /^refs\/heads\//) && !(query == "HEAD") begin return @repo.rev_parse_oid(query) rescue Rugged::ReferenceError, Rugged::InvalidError return nil end end
revert_commit(sha1, sha2)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 242 def revert_commit(sha1, sha2) diff = @repo.diff(sha2, sha1) index = @repo.revert_commit(sha2, sha1) return false unless index paths = [] diff.each_delta do |delta| paths << delta.new_file[:path] paths << delta.old_file[:path] end paths.uniq! begin return index.write_tree(@repo), paths rescue Rugged::IndexError return false end end
revert_path(path, sha1, sha2)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 228 def revert_path(path, sha1, sha2) diff = @repo.diff(sha2, sha1, {:paths => [path]}).first.diff begin result = @repo.apply(diff, {:location => :index, :path => path}) rescue RuntimeError, Rugged::PathError return false end begin return @repo.index.write_tree rescue Rugged::IndexError return false end end
rm(path, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 217 def rm(path, options = {}) index = @repo.index index.write to_delete = ::File.join(@repo.workdir, path) ::File.unlink to_delete if ::File.exist?(to_delete) end
sha_or_commit_from_ref(ref, request_kind = nil)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 322 def sha_or_commit_from_ref(ref, request_kind = nil) sha = ref_to_sha(ref) return nil if sha.nil? object = @repo.lookup(sha) if object.kind_of?(Rugged::Commit) then return Gollum::Git::Commit.new(object) if request_kind == :commit sha elsif object.respond_to?(:target) sha_or_commit_from_ref(object.target.oid, request_kind) end end
Also aliased as: sha_from_ref
versions_for_path(path = nil, ref = nil, options = {})
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 291 def versions_for_path(path = nil, ref = nil, options = {}) log(ref, path, options) end
Private Instance Methods
build_log(sha, options)
click to toggle source
Return an array of log commits, given a SHA hash and a hash of options. From Gitlab::Git
# File lib/rugged_adapter/git_layer_rugged.rb, line 374 def build_log(sha, options) # Instantiate a Walker and add the SHA hash walker = Rugged::Walker.new(@repo) walker.push(sha) commits = [] skipped = 0 current_path = options[:path].dup if options[:path] current_path = nil if current_path == '' renamed_path = current_path.nil? ? nil : current_path.dup track_pathnames = true if current_path && options[:follow] limit = options[:limit].to_i offset = options[:offset].to_i skip_merges = options[:skip_merges] walker.sorting(Rugged::SORT_DATE) walker.each do |c| break if limit > 0 && commits.length >= limit if skip_merges # Skip merge commits next if c.parents.length > 1 end if !current_path || commit_touches_path?(c, current_path, options[:follow], walker) # This is a commit we care about, unless we haven't skipped enough # yet skipped += 1 commits.push(Gollum::Git::Commit.new(c, track_pathnames ? renamed_path : nil)) if skipped > offset renamed_path = current_path.nil? ? nil : current_path.dup end end walker.reset commits end
commit_touches_path?(commit, path, follow, walker)
click to toggle source
Returns true if commit
introduced changes to path
, using commit trees to make that determination. Uses the history simplification rules that ‘git log` uses by default, where a commit is omitted if it is TREESAME to any parent.
If the follow
option is true and the file specified by path
was renamed, then the path value is set to the old path.
# File lib/rugged_adapter/git_layer_rugged.rb, line 415 def commit_touches_path?(commit, path, follow, walker) entry = tree_entry(commit, path) if commit.parents.empty? # This is the root commit, return true if it has +path+ in its tree return entry != nil end num_treesame = 0 commit.parents.each do |parent| parent_entry = tree_entry(parent, path) # Only follow the first TREESAME parent for merge commits if num_treesame > 0 walker.hide(parent.oid) next end if entry.nil? && parent_entry.nil? num_treesame += 1 elsif entry && parent_entry && entry[:oid] == parent_entry[:oid] num_treesame += 1 end end case num_treesame when 0 detect_rename(commit, commit.parents.first, path) if follow true else false end end
detect_rename(commit, parent, path)
click to toggle source
Compare commit
and parent
for path
. If path
is a file and was renamed in commit
, then set path
to the old filename.
# File lib/rugged_adapter/git_layer_rugged.rb, line 462 def detect_rename(commit, parent, path) diff = parent.diff(commit, paths: [path], disable_pathspec_match: true) # If +path+ is a filename, not a directory, then we should only have # one delta. We don't need to follow renames for directories. return nil if diff.each_delta.count > 1 delta = diff.each_delta.first if delta.added? full_diff = parent.diff(commit) full_diff.find_similar! full_diff.each_delta do |full_delta| if full_delta.renamed? && path == full_delta.new_file[:path] # Look for the old path in ancestors path.replace(full_delta.old_file[:path]) end end end end
sha?(str)
click to toggle source
# File lib/rugged_adapter/git_layer_rugged.rb, line 368 def sha?(str) !!(str =~ /^[0-9a-f]{40}$/) end
tree_entry(commit, path)
click to toggle source
Find the entry for path
in the tree for commit
# File lib/rugged_adapter/git_layer_rugged.rb, line 449 def tree_entry(commit, path) pathname = Pathname.new(path) tmp_entry = nil pathname.each_filename do |dir| tmp_entry = tmp_entry ? @repo.lookup(tmp_entry[:oid])[dir] : commit.tree[dir] return nil unless tmp_entry end tmp_entry end