##// END OF EJS Templates
repair: add experimental option to write bundle2 files...
repair: add experimental option to write bundle2 files This adds an experimental option 'strip-bundle2-version' which causes backup bundles to use bundle2 formatting. Especially for generaldelta repositories, this should provide significant performance gains for any operation that needs to write a backup.

File last commit:

r23898:b21c2e0e default
r23898:b21c2e0e default
Show More
repair.py
216 lines | 7.3 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
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
strip: move strip code to a new repair module
r4702
Eric Sumner
repair: add experimental option to write bundle2 files...
r23898 from mercurial import changegroup, exchange, util, bundle2
Durham Goode
bundles: do not overwrite existing backup bundles (BC)...
r23835 from mercurial.node import short, hex
Alexander Solovyov
remove unused imports and variables
r14064 from mercurial.i18n import _
Alain Leufroy
repair: fix missing import...
r16440 import errno
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 def _bundle(repo, bases, heads, node, suffix, compress=True):
Alexis S. L. Carvalho
repair.py: don't use nested functions.
r5905 """create a bundle with the specified revisions as a backup"""
Eric Sumner
repair: add experimental option to write bundle2 files...
r23898 usebundle2 = (repo.ui.config('experimental', 'bundle2-exp') and
repo.ui.config('experimental', 'strip-bundle2-version'))
if usebundle2:
cgversion = repo.ui.config('experimental', 'strip-bundle2-version')
else:
cgversion = '01'
cg = changegroup.changegroupsubset(repo, bases, heads, 'strip',
version=cgversion)
FUJIWARA Katsunori
repair: make paths in "_bundle()" relative to ".hg"...
r20977 backupdir = "strip-backup"
vfs = repo.vfs
if not vfs.isdir(backupdir):
vfs.mkdir(backupdir)
Durham Goode
bundles: do not overwrite existing backup bundles (BC)...
r23835
# Include a hash of all the nodes in the filename for uniqueness
hexbases = (hex(n) for n in bases)
hexheads = (hex(n) for n in heads)
allcommits = repo.set('%ls::%ls', hexbases, hexheads)
allhashes = sorted(c.hex() for c in allcommits)
totalhash = util.sha1(''.join(allhashes)).hexdigest()
name = "%s/%s-%s-%s.hg" % (backupdir, short(node), totalhash[:8], suffix)
Eric Sumner
repair: add experimental option to write bundle2 files...
r23898 if usebundle2:
bundletype = "HG2Y"
elif compress:
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 bundletype = "HG10BZ"
else:
bundletype = "HG10UN"
Eric Sumner
changegroup.writebundle: provide ui...
r23895 return changegroup.writebundle(repo.ui, cg, name, bundletype, vfs)
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"""
Benoit Boissinot
repair: use set instead of dict
r8462 files = set()
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for x in xrange(striprev, len(repo)):
Martin Geisler
repair: bulk update sets...
r8479 files.update(repo[x].files())
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Benoit Boissinot
repair: use set instead of dict
r8462 return sorted(files)
Alexis S. L. Carvalho
repair.py: split stripall into two functions; clean it up a bit
r5902
Benoit Boissinot
strip: remove usage of extranodes...
r13702 def _collectbrokencsets(repo, files, striprev):
"""return the changesets which will be broken by the truncation"""
Matt Mackall
strip: simplify collectone
r13705 s = set()
Benoit Boissinot
strip: remove usage of extranodes...
r13702 def collectone(revlog):
Durham Goode
strip: add faster revlog strip computation...
r20074 _, brokenset = revlog.getstrippoint(striprev)
s.update([revlog.linkrev(r) for r in brokenset])
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Matt Mackall
strip: simplify collectone
r13705 collectone(repo.manifest)
for fname in files:
collectone(repo.file(fname))
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Matt Mackall
strip: simplify collectone
r13705 return s
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Jordi GutiƩrrez Hermoso
strip: remove -b/--backup codepaths...
r22057 def strip(ui, repo, nodelist, backup=True, topic='backup'):
# Simple way to maintain backwards compatibility for this
# argument.
if backup in ['none', 'strip']:
backup = False
Pierre-Yves David
clfilter: strip logic should be unfiltered...
r18004 repo = repo.unfiltered()
Idan Kamara
localrepo: introduce destroying function
r18310 repo.destroying()
Joshua Redstone
strip: incrementally update the branchheads cache after a strip...
r17013
Alexis S. L. Carvalho
repair.py: rename chlog to cl
r5901 cl = repo.changelog
Idan Kamara
repair: remove undo files after strip
r16237 # TODO handle undo of merge sets
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 if isinstance(nodelist, str):
nodelist = [nodelist]
striplist = [cl.rev(node) for node in nodelist]
striprev = min(striplist)
Matt Mackall
strip: move strip code to a new repair module
r4702
Alexis S. L. Carvalho
repair.py: rewrite a loop, making it cleaner and faster
r6147 # Some revisions with rev > striprev may not be descendants of striprev.
# We have to find these revisions and put them in a bundle, so that
# we can restore them after the truncations.
# To create the bundle we use repo.changegroupsubset which requires
# the list of heads and bases of the set of interesting revisions.
# (head = revision in the set that has no descendant in the set;
# base = revision in the set that has no ancestor in the set)
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 tostrip = set(striplist)
for rev in striplist:
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 for desc in cl.descendants([rev]):
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 tostrip.add(desc)
Benoit Boissinot
strip: remove usage of extranodes...
r13702
files = _collectfiles(repo, striprev)
Matt Mackall
strip: simplify collectone
r13705 saverevs = _collectbrokencsets(repo, files, striprev)
Benoit Boissinot
strip: remove usage of extranodes...
r13702
# compute heads
saveheads = set(saverevs)
Matt Mackall
add __len__ and __iter__ methods to repo and revlog
r6750 for r in xrange(striprev + 1, len(cl)):
Benoit Boissinot
strip: remove usage of extranodes...
r13702 if r not in tostrip:
saverevs.add(r)
saveheads.difference_update(cl.parentrevs(r))
saveheads.add(r)
saveheads = [cl.node(r) for r in saveheads]
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 # compute base nodes
if saverevs:
Bryan O'Sullivan
revlog: descendants(*revs) becomes descendants(revs) (API)...
r16867 descendants = set(cl.descendants(saverevs))
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 saverevs.difference_update(descendants)
savebases = [cl.node(r) for r in saverevs]
Wagner Bruna
strip: enhance repair.strip to receive a list of nodes (issue3299)...
r16252 stripbases = [cl.node(r) for r in tostrip]
Siddharth Agarwal
strip: make query to get new bookmark target cheaper...
r18040
# For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), but
# is much faster
newbmtarget = repo.revs('max(parents(%ld) - (%ld))', tostrip, tostrip)
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 if newbmtarget:
Pierre-Yves David
repair: use `first` instead of direct indexing...
r22818 newbmtarget = repo[newbmtarget.first()].node()
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 else:
newbmtarget = '.'
Matt Mackall
strip: move strip code to a new repair module
r4702
Matt Mackall
bookmarks: move strip support to repair
r13362 bm = repo._bookmarks
updatebm = []
for m in bm:
rev = repo[bm[m]].rev()
if rev in tostrip:
updatebm.append(m)
Matt Mackall
strip: move strip code to a new repair module
r4702 # create a changegroup for all the branches we need to keep
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 backupfile = None
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 vfs = repo.vfs
Jordi GutiƩrrez Hermoso
strip: remove -b/--backup codepaths...
r22057 if backup:
Idan Kamara
repair: allow giving strip backup a different name...
r16388 backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 repo.ui.status(_("saved backup bundle to %s\n") %
vfs.join(backupfile))
repo.ui.log("backupbundle", "saved backup bundle to %s\n",
vfs.join(backupfile))
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 if saveheads or savebases:
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 # do not compress partial bundle if we remove it from disk later
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
Jordi GutiƩrrez Hermoso
strip: remove -b/--backup codepaths...
r22057 compress=False)
Matt Mackall
strip: move strip code to a new repair module
r4702
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 mfst = repo.manifest
Steve Borho
localrepo: add desc parameter to transaction...
r10881 tr = repo.transaction("strip")
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 offset = len(tr.entries)
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 try:
tr.startgroup()
cl.strip(striprev, tr)
mfst.strip(striprev, tr)
for fn in files:
repo.file(fn).strip(striprev, tr)
tr.endgroup()
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 try:
for i in xrange(offset, len(tr.entries)):
file, troffset, ignore = tr.entries[i]
Angel Ezquerra
localrepo: remove all external users of localrepo.sopener...
r23878 repo.svfs(file, 'a').truncate(troffset)
Durham Goode
fncache: clean up fncache during strips...
r20885 if troffset == 0:
repo.store.markremoved(file)
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 tr.close()
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 tr.abort()
raise
Matt Mackall
strip: backout 73307643a09f (issue3077)
r15386 if saveheads or savebases:
Matt Mackall
strip: hide unbundle messages by default...
r11202 ui.note(_("adding branch\n"))
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 f = vfs.open(chgrpfile, "rb")
Pierre-Yves David
bundle2: add a ui argument to readbundle...
r21064 gen = exchange.readbundle(ui, f, chgrpfile, vfs)
Matt Mackall
strip: hide unbundle messages by default...
r11202 if not repo.ui.verbose:
# silence internal shuffling chatter
repo.ui.pushbuffer()
Eric Sumner
repair: add experimental option to write bundle2 files...
r23898 if isinstance(gen, bundle2.unbundle20):
tr = repo.transaction('strip')
try:
bundle2.processbundle(repo, gen, lambda: tr)
tr.close()
finally:
tr.release()
else:
changegroup.addchangegroup(repo, gen, 'strip',
'bundle:' + vfs.join(chgrpfile),
True)
Matt Mackall
strip: hide unbundle messages by default...
r11202 if not repo.ui.verbose:
repo.ui.popbuffer()
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 f.close()
Matt Mackall
bookmarks: move strip support to repair
r13362
Idan Kamara
repair: remove undo files after strip
r16237 # remove undo files
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 for undovfs, undofile in repo.undofiles():
Idan Kamara
repair: remove undo files after strip
r16237 try:
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 undovfs.unlink(undofile)
Idan Kamara
repair: remove undo files after strip
r16237 except OSError, e:
if e.errno != errno.ENOENT:
FUJIWARA Katsunori
localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"...
r20975 ui.warn(_('error removing %s: %s\n') %
(undovfs.join(undofile), str(e)))
Idan Kamara
repair: remove undo files after strip
r16237
Matt Mackall
bookmarks: move strip support to repair
r13362 for m in updatebm:
Augie Fackler
strip: move bookmarks to nearest ancestor rather than '.'...
r17264 bm[m] = repo[newbmtarget].node()
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 bm.write()
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 if backupfile:
Martin Geisler
mark ui.warn strings for translation
r11600 ui.warn(_("strip failed, full bundle stored in '%s'\n")
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 % vfs.join(backupfile))
Matt Mackall
strip: be quiet about temporary internal bundle
r11197 elif saveheads:
Martin Geisler
mark ui.warn strings for translation
r11600 ui.warn(_("strip failed, partial bundle stored in '%s'\n")
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 % vfs.join(chgrpfile))
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 raise
Jordi GutiƩrrez Hermoso
strip: remove -b/--backup codepaths...
r22057 else:
if saveheads or savebases:
# Remove partial backup only if there were no exceptions
vfs.unlink(chgrpfile)
Matt Mackall
strip: move strip code to a new repair module
r4702
Pierre-Yves David
destroyed: drop complex branchcache rebuilt logic...
r18395 repo.destroyed()