Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Add Felipe's git-marks-check to the repository, for convenience
Browse files Browse the repository at this point in the history
This doesn't solve the actual issues, but helps mitigate them in many
cases.

I am not completely sure what the "actual" issues are, but one seems to
be that it is apparently relatively easy to end up with a corrupt marks
file (and indeed, the code loading / saving marks does not attempt to be
particular robust).

The other problem hinted at in issue #4 seems to  be when tips in the
remote hg repository change, then this seems to also cause troubles.

See also:
  felipec#4
  felipec#10
  • Loading branch information
fingolfin committed Jan 13, 2015
1 parent 01d04d8 commit 13b20f8
Showing 1 changed file with 96 additions and 0 deletions.
96 changes: 96 additions & 0 deletions git-marks-check
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env ruby

require 'json'

$fix = false
$verbose = false
$git_marks = {}
$r_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]

$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|
$git_marks.delete_if { |mark,id| id == l.chomp }
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
end
end

if r_missing.empty? and git_missing.empty?
puts 'Everything OK'
else
puts 'Issues detected'
exit 1
end

0 comments on commit 13b20f8

Please sign in to comment.