mirror of
https://github.com/frej/fast-export.git
synced 2025-10-29 23:55:47 +01:00
157 lines
5.0 KiB
Python
Executable File
157 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2007, 2008 Rocco Rutte <pdmef@gmx.net> and others.
|
|
# License: GPLv2
|
|
|
|
from mercurial import node
|
|
from hg2git import setup_repo,load_cache,get_changeset,get_git_sha1
|
|
from optparse import OptionParser
|
|
import sys
|
|
from binascii import hexlify
|
|
|
|
def heads(ui,repo,start=None,stop=None,max=None):
|
|
# this is copied from mercurial/revlog.py and differs only in
|
|
# accepting a max argument for xrange(startrev+1,...) defaulting
|
|
# to the original repo.changelog.count()
|
|
if start is None:
|
|
start = node.nullid
|
|
if stop is None:
|
|
stop = []
|
|
if max is None:
|
|
max = repo.changelog.count()
|
|
stoprevs = dict.fromkeys([repo.changelog.rev(n) for n in stop])
|
|
startrev = repo.changelog.rev(start)
|
|
reachable = {startrev: 1}
|
|
heads = {startrev: 1}
|
|
|
|
parentrevs = repo.changelog.parentrevs
|
|
for r in range(startrev + 1, max):
|
|
for p in parentrevs(r):
|
|
if p in reachable:
|
|
if r not in stoprevs:
|
|
reachable[r] = 1
|
|
heads[r] = 1
|
|
if p in heads and p not in stoprevs:
|
|
del heads[p]
|
|
|
|
return [(repo.changelog.node(r), b"%d" % r) for r in heads]
|
|
|
|
def get_branches(ui,repo,heads_cache,marks_cache,mapping_cache,max):
|
|
h=heads(ui,repo,max=max)
|
|
stale=dict.fromkeys(heads_cache)
|
|
changed=[]
|
|
unchanged=[]
|
|
for node,rev in h:
|
|
_,_,user,(_,_),_,desc,branch,_=get_changeset(ui,repo,rev)
|
|
del stale[branch]
|
|
git_sha1=get_git_sha1(branch)
|
|
cache_sha1=marks_cache.get(b"%d" % (int(rev)+1))
|
|
if git_sha1!=None and git_sha1==cache_sha1:
|
|
unchanged.append([branch,cache_sha1,rev,desc.split(b'\n')[0],user])
|
|
else:
|
|
changed.append([branch,cache_sha1,rev,desc.split(b'\n')[0],user])
|
|
changed.sort()
|
|
unchanged.sort()
|
|
return stale,changed,unchanged
|
|
|
|
def get_tags(ui,repo,marks_cache,mapping_cache,max):
|
|
l=repo.tagslist()
|
|
good,bad=[],[]
|
|
for tag,node in l:
|
|
if tag==b'tip': continue
|
|
rev=int(mapping_cache[hexlify(node)])
|
|
cache_sha1=marks_cache.get(b"%d" % (int(rev)+1))
|
|
_,_,user,(_,_),_,desc,branch,_=get_changeset(ui,repo,rev)
|
|
if int(rev)>int(max):
|
|
bad.append([tag,branch,cache_sha1,rev,desc.split(b'\n')[0],user])
|
|
else:
|
|
good.append([tag,branch,cache_sha1,rev,desc.split(b'\n')[0],user])
|
|
good.sort()
|
|
bad.sort()
|
|
return good,bad
|
|
|
|
def mangle_mark(mark):
|
|
return b"%d" % (int(mark)-1)
|
|
|
|
if __name__=='__main__':
|
|
def bail(parser,opt):
|
|
sys.stderr.write('Error: No option %s given\n' % opt)
|
|
parser.print_help()
|
|
sys.exit(2)
|
|
|
|
parser=OptionParser()
|
|
|
|
parser.add_option("--marks",dest="marksfile",
|
|
help="File to read git-fast-import's marks from")
|
|
parser.add_option("--mapping",dest="mappingfile",
|
|
help="File to read last run's hg-to-git SHA1 mapping")
|
|
parser.add_option("--heads",dest="headsfile",
|
|
help="File to read last run's git heads from")
|
|
parser.add_option("--status",dest="statusfile",
|
|
help="File to read status from")
|
|
parser.add_option("-r","--repo",dest="repourl",
|
|
help="URL of repo to import")
|
|
parser.add_option("-R","--revision",type=int,dest="revision",
|
|
help="Revision to reset to")
|
|
|
|
(options,args)=parser.parse_args()
|
|
|
|
if options.marksfile==None: bail(parser,'--marks option')
|
|
if options.mappingfile==None: bail(parser,'--mapping option')
|
|
if options.headsfile==None: bail(parser,'--heads option')
|
|
if options.statusfile==None: bail(parser,'--status option')
|
|
if options.repourl==None: bail(parser,'--repo option')
|
|
if options.revision==None: bail(parser,'-R/--revision')
|
|
|
|
heads_cache=load_cache(options.headsfile)
|
|
marks_cache=load_cache(options.marksfile,mangle_mark)
|
|
state_cache=load_cache(options.statusfile)
|
|
mapping_cache = load_cache(options.mappingfile)
|
|
|
|
l=int(state_cache.get(b'tip',options.revision))
|
|
if options.revision+1>l:
|
|
sys.stderr.write('Revision is beyond last revision imported: %d>%d\n' % (options.revision,l))
|
|
sys.exit(1)
|
|
|
|
ui,repo=setup_repo(options.repourl)
|
|
|
|
stale,changed,unchanged=get_branches(ui,repo,heads_cache,marks_cache,mapping_cache,options.revision+1)
|
|
good,bad=get_tags(ui,repo,marks_cache,mapping_cache,options.revision+1)
|
|
|
|
print("Possibly stale branches:")
|
|
for b in stale:
|
|
sys.stdout.write('\t%s\n' % b.decode('utf8'))
|
|
|
|
print("Possibly stale tags:")
|
|
for b in bad:
|
|
sys.stdout.write(
|
|
'\t%s on %s (r%s)\n'
|
|
% (b[0].decode('utf8'), b[1].decode('utf8'), b[3].decode('utf8'))
|
|
)
|
|
|
|
print("Unchanged branches:")
|
|
for b in unchanged:
|
|
sys.stdout.write('\t%s (r%s)\n' % (b[0].decode('utf8'),b[2].decode('utf8')))
|
|
|
|
print("Unchanged tags:")
|
|
for b in good:
|
|
sys.stdout.write(
|
|
'\t%s on %s (r%s)\n'
|
|
% (b[0].decode('utf8'), b[1].decode('utf8'), b[3].decode('utf8'))
|
|
)
|
|
|
|
print("Reset branches in '%s' to:" % options.headsfile)
|
|
for b in changed:
|
|
sys.stdout.write(
|
|
'\t:%s %s\n\t\t(r%s: %s: %s)\n'
|
|
% (
|
|
b[0].decode('utf8'),
|
|
b[1].decode('utf8'),
|
|
b[2].decode('utf8'),
|
|
b[4].decode('utf8'),
|
|
b[3].decode('utf8'),
|
|
)
|
|
)
|
|
|
|
print("Reset ':tip' in '%s' to '%d'" % (options.statusfile,options.revision))
|