##// END OF EJS Templates
convert: document splicemap, allow setting of multiple parents
convert: document splicemap, allow setting of multiple parents

File last commit:

r5910:b9a830fa default
r6143:5b159ebb default
Show More
repair.py
151 lines | 4.6 KiB | text/x-python | PythonLexer
Matt Mackall
strip: move strip code to a new repair module
r4702 # repair.py - functions for repository repair for mercurial
#
# Copyright 2005, 2006 Chris Mason <mason@suse.com>
# Copyright 2007 Matt Mackall
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
Alexis S. L. Carvalho
repair.py: use node.* directly
r5899 import changegroup, os
from node import *
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 def _limitheads(cl, stoprev):
"""return the list of all revs >= stoprev that have no children"""
seen = {}
heads = []
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 for r in xrange(cl.count() - 1, stoprev - 1, -1):
if r not in seen:
heads.append(r)
for p in cl.parentrevs(r):
seen[p] = 1
return heads
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 def _bundle(repo, bases, heads, node, suffix, extranodes=None):
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 """create a bundle with the specified revisions as a backup"""
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 cg = repo.changegroupsubset(bases, heads, 'strip', extranodes)
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 backupdir = repo.join("strip-backup")
if not os.path.isdir(backupdir):
os.mkdir(backupdir)
name = os.path.join(backupdir, "%s-%s" % (short(node), suffix))
repo.ui.warn("saving bundle to %s\n" % name)
return changegroup.writebundle(cg, name, "HG10BZ")
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 def _collectfiles(repo, striprev):
"""find out the filelogs affected by the strip"""
files = {}
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 for x in xrange(striprev, repo.changelog.count()):
for name in repo.changectx(x).files():
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 if name in files:
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 continue
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 files[name] = 1
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 files = files.keys()
files.sort()
return files
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 def _collectextranodes(repo, files, link):
"""return the nodes that have to be saved before the strip"""
def collectone(revlog):
extra = []
startrev = count = revlog.count()
# find the truncation point of the revlog
for i in xrange(0, count):
node = revlog.node(i)
lrev = revlog.linkrev(node)
if lrev >= link:
startrev = i + 1
break
# see if any revision after that point has a linkrev less than link
# (we have to manually save these guys)
for i in xrange(startrev, count):
node = revlog.node(i)
lrev = revlog.linkrev(node)
if lrev < link:
extra.append((node, cl.node(lrev)))
return extra
extranodes = {}
cl = repo.changelog
extra = collectone(repo.manifest)
if extra:
extranodes[1] = extra
for fname in files:
f = repo.file(fname)
extra = collectone(f)
if extra:
extranodes[fname] = extra
return extranodes
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 def strip(ui, repo, node, backup="all"):
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 cl = repo.changelog
Matt Mackall
strip: move strip code to a new repair module
r4702 # TODO delete the undo files, and handle undo of merge sets
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 pp = cl.parents(node)
striprev = cl.rev(node)
Matt Mackall
strip: move strip code to a new repair module
r4702
# save is a list of all the branches we are truncating away
# that we actually want to keep. changegroup will be used
# to preserve them and add them back after the truncate
saveheads = []
savebases = {}
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 heads = [cl.node(r) for r in _limitheads(cl, striprev)]
Matt Mackall
strip: move strip code to a new repair module
r4702 seen = {}
# search through all the heads, finding those where the revision
# we want to strip away is an ancestor. Also look for merges
# that might be turned into new heads by the strip.
while heads:
h = heads.pop()
n = h
while True:
seen[n] = 1
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 pp = cl.parents(n)
Alexis S. L. Carvalho
repair.py: use node.* directly
r5899 if pp[1] != nullid:
Matt Mackall
strip: move strip code to a new repair module
r4702 for p in pp:
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 if cl.rev(p) > striprev and p not in seen:
Matt Mackall
strip: move strip code to a new repair module
r4702 heads.append(p)
Alexis S. L. Carvalho
repair.py: use node.* directly
r5899 if pp[0] == nullid:
Matt Mackall
strip: move strip code to a new repair module
r4702 break
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 if cl.rev(pp[0]) < striprev:
Matt Mackall
strip: move strip code to a new repair module
r4702 break
n = pp[0]
Alexis S. L. Carvalho
repair.py: nodes are nodes, revs are revs...
r5900 if n == node:
Matt Mackall
strip: move strip code to a new repair module
r4702 break
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 r = cl.reachable(h, node)
Alexis S. L. Carvalho
repair.py: nodes are nodes, revs are revs...
r5900 if node not in r:
Matt Mackall
strip: move strip code to a new repair module
r4702 saveheads.append(h)
for x in r:
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 if cl.rev(x) > striprev:
Matt Mackall
strip: move strip code to a new repair module
r4702 savebases[x] = 1
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 files = _collectfiles(repo, striprev)
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 extranodes = _collectextranodes(repo, files, striprev)
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Matt Mackall
strip: move strip code to a new repair module
r4702 # create a changegroup for all the branches we need to keep
if backup == "all":
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 _bundle(repo, [node], cl.heads(), node, 'backup')
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 if saveheads or extranodes:
chgrpfile = _bundle(repo, savebases.keys(), saveheads, node, 'temp',
extranodes)
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
simplify revlog.strip interface and callers; add docstring...
r5910 cl.strip(striprev)
repo.manifest.strip(striprev)
for name in files:
f = repo.file(name)
f.strip(striprev)
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 if saveheads or extranodes:
Matt Mackall
strip: move strip code to a new repair module
r4702 ui.status("adding branch\n")
Alexis S. L. Carvalho
repair.py: don't import commands.py
r5898 f = open(chgrpfile, "rb")
gen = changegroup.readbundle(f, chgrpfile)
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909 repo.addchangegroup(gen, 'strip', 'bundle:' + chgrpfile, True)
Alexis S. L. Carvalho
repair.py: don't import commands.py
r5898 f.close()
Matt Mackall
strip: move strip code to a new repair module
r4702 if backup != "strip":
os.unlink(chgrpfile)