Last active
June 5, 2026 16:59
-
-
Save felipec/10551806 to your computer and use it in GitHub Desktop.
Tool to check and fix git-remote-hg marks
This file contains hidden or 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
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree fetch origin
fatal: mark :26940 not declared
fast-import: dumping crash report to .git/fast_import_crash_15105
fatal: Error while running fast-import
Traceback (most recent call last):
File "/usr/local/bin/git-remote-hg", line 1311, in
sys.exit(main(sys.argv))
File "/usr/local/bin/git-remote-hg", line 1295, in main
do_import(parser)
File "/usr/local/bin/git-remote-hg", line 721, in do_import
export_branch(repo, branch)
File "/usr/local/bin/git-remote-hg", line 613, in export_branch
export_ref(repo, branch, 'branches', head)
File "/usr/local/bin/git-remote-hg", line 547, in export_ref
modified_final = export_files(c.filectx(f) for f in modified)
File "/usr/local/bin/git-remote-hg", line 288, in export_files
print d
IOError: [Errno 32] Broken pipe
Completed with errors, see above