Is there a 'git cherry' in libgit2

时间:2018-03-25 20:13:08

标签: ruby git rugged

I'm working on a project and one of the requirements is the need to call git cherry command to get some differences between on branch and the other - (note this is not git cherry-pick).

I was planning to use ruby rugged gem for this project but I cannot find anything in the documentation whether it supports the git cherry API or not.

Rugged is a ruby wrapper around libgit2 but I could not find anything in its documentation either.

1 个答案:

答案 0 :(得分:1)

libgit2(并且通过扩展,构建在它之上的东西,如Rugged)是相当低级别的。可能不会像内置git cherry一样的功能,但你通常可以自己写一个。

不幸的是,目前,libgit2并没有提供补丁ID实现,这是Git用来确定相同补丁的技术。如果确实如此,或者您想编写自己的版本,则可以使用Rugged::Walker在两个范围内自行执行修订版步骤,比较第二个范围中的哪些修补程序ID也存在于第一个范围内。这基本上就是Git在幕后所做的事情。

以下是您可能会执行的操作示例,将patch_id函数替换为真实函数:

require 'rugged'
require 'digest'

def patch_id(patch)
  # This is not a real implementation; replace it with a real one.
  Digest::SHA1.hexdigest(patch.each_line.reject { |l| l =~ /^(diff|index|---|\+\+\+|@@)/ }.join)
end

def walk_revisions(repo, from, to)
  revisions = {}
  walker = Rugged::Walker.new(repo)
  walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE)
  walker.push(to)
  walker.hide(from)
  walker.each do |c|
    diff = c.parents[0].diff(c)
    revisions[patch_id(diff.patch)] = c.oid
  end
  revisions
end

repo = Rugged::Repository.new(ARGV[0])
a, b, c = ARGV[1..3].map { |r| repo.rev_parse(r) }
first = walk_revisions(repo, b, a)
second = walk_revisions(repo, c, b)
second.each do |id, rev|
  char = first.include?(id) ? '-' : '+'
  puts "#{char} #{rev}"
end