Last active
September 8, 2016 02:32
-
-
Save felipec/10551806 to your computer and use it in GitHub Desktop.
Tool to check and fix git-remote-hg marks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'json' | |
$fix = false | |
$verbose = false | |
$git_marks = {} | |
$r_marks = {} | |
$note_marks = {} | |
$mode = 'hg' | |
# Parse arguments | |
ARGV.delete_if do |cur| | |
next false if cur[0] != '-' | |
case cur | |
when /^-f$/, /^--fix$/ | |
$fix = true | |
true | |
when /^-v$/, /^--verbose$/ | |
$verbose = true | |
true | |
when /^-m(.+)$/, /^--mode=(.+)$/ | |
$mode = $1 | |
true | |
end | |
end | |
$remote = ARGV[0] || 'origin' | |
$dir = File.join('.git', $mode, $remote) | |
$git_file = File.join($dir, 'marks-git') | |
$r_file = File.join($dir, 'marks-' + $mode) | |
# TODO | |
$r_file = File.join($dir, 'marks-int') if $mode == 'bzr' | |
# Get git marks | |
File.open($git_file).each do |l| | |
if l =~ /:(\d+) (\h+)$/ | |
$git_marks[$1.to_i] = $2 | |
end | |
end | |
# Remove non commit objects | |
File.popen(%w[git cat-file --batch-check], 'r+') do |p| | |
$git_marks.each do |mark,id| | |
p.write(id + "\n") | |
if p.readline =~ /(\h+) (\w+)(?: (\d+))?/ | |
type = $2 | |
$git_marks.delete(mark) unless type == 'commit' | |
end | |
end | |
end | |
# Remove notes | |
File.popen(%W[git rev-list refs/notes/#{$mode}], 'r', :err => File::NULL) do |p| | |
p.each do |l| | |
mark, id = $git_marks.find { |_,x| x == l.chomp } | |
if mark | |
$git_marks.delete(mark) | |
$note_marks[mark] = id | |
end | |
end | |
end | |
# Get remote marks | |
r_data = JSON.parse(File.read($r_file)) | |
$r_marks = r_data['marks'].invert | |
r_missing = $git_marks.reject { |mark,id| $r_marks[mark] } | |
git_missing = $r_marks.reject { |mark,id| $git_marks[mark] } | |
if $verbose | |
r_missing.each do |mark,id| | |
puts "Missing %s (%d) from #{$mode}" % [id, mark] | |
end | |
git_missing.each do |mark,id| | |
puts "Missing %s (%d) from git" % [id, mark] | |
end | |
end | |
if $fix | |
# Fix remote marks | |
r_data['marks'].delete_if { |mark,id| git_missing.has_key?(id) } | |
File.write($r_file, r_data.to_json) | |
# Fix git marks | |
File.open($git_file, 'w') do |f| | |
$git_marks.each do |mark,id| | |
next if r_missing.has_key?(mark) | |
f.puts ':%d %s' % [mark, id] | |
end | |
$note_marks.each do |mark,id| | |
f.puts ':%d %s' % [mark, id] | |
end | |
end | |
end | |
if r_missing.empty? and git_missing.empty? | |
puts 'Everything OK' | |
else | |
puts 'Issues detected' | |
exit 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is awesome! Thanks