libgit2 (and by extension, the things built on top of it, like Rugged) is pretty low level. There probably won't ever be a git cherry
-like functionality built in, but you could normally write one yourself.
Unfortunately, at the moment, libgit2 doesn't provide a patch ID implementation, which is the technique that Git uses to determine identical patches. If it did, or if you wanted to write your own, you could perform the revision walk yourself over the two ranges using Rugged::Walker
, comparing which patch IDs from the second range were also present in the first range. That's essentially what Git does under the hood.
The following is an example of what you might do, replacing the patch_id function with a real one:
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