##// END OF EJS Templates
namespaces: let namespaces override singlenode() definition...
namespaces: let namespaces override singlenode() definition Some namespaces have multiple nodes per name (meaning that their namemap() returns multiple nodes). One such namespace is the "topics" namespace (from the evolve repo). We also have our own internal namespace at Google (for review units) that has multiple nodes per name. These namespaces may not want to use the default "pick highest revnum" resolution that we currently use when resolving a name to a single node. As an example, they may decide that `hg co <name>` should check out a commit that's last in some sense even if an earlier commit had just been amended and thus had a higher revnum [1]. This patch gives the namespace the option to continue to return multiple nodes and to override how the best node is picked. Allowing namespaces to override that may also be useful as an optimization (it may be cheaper for the namespace to find just that node). I have been arguing (in D3715) for using all the nodes returned from namemap() when resolving the symbol to a revset, so e.g. `hg log -r stable` would resolve to *all* nodes on stable, not just the one with the highest revnum (except that I don't actually think we should change it for the branch namespace because of BC). Most people seem opposed to that. If we decide not to do it, I think we can deprecate the namemap() function in favor of the new singlenode() (I find it weird to have namespaces, like the branch namespace, where namemap() isn't nodemap()'s inverse). I therefore think this patch makes sense regardless of what we decide on that issue. [1] Actually, even the branch namespace would have wanted to override singlenode() if it had supported multiple nodes. That's because closes branch heads are mostly ignored, so "hg co default" will not check out the highest-revnum node if that's a closed head. Differential Revision: https://phab.mercurial-scm.org/D3852

File last commit:

r38413:f0b0c853 default
r38505:4c068365 @58 default
Show More
repair.py
435 lines | 14.9 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
Gregory Szorc
repair: use absolute_import
r25970 from __future__ import absolute_import
Alain Leufroy
repair: fix missing import...
r16440 import errno
Augie Fackler
cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1...
r29341 import hashlib
Matt Mackall
strip: move strip code to a new repair module
r4702
Gregory Szorc
repair: use absolute_import
r25970 from .i18n import _
Augie Fackler
repair: reliably obtain bytestr of node ids
r34219 from .node import (
hex,
short,
)
Gregory Szorc
repair: use absolute_import
r25970 from . import (
bundle2,
changegroup,
strip: use the 'writenewbundle' function to get bundle on disk...
r32468 discovery,
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 error,
Gregory Szorc
repair: use absolute_import
r25970 exchange,
Kostia Balytskyi
obsstore: move delete function from obsstore class to repair module...
r28868 obsolete,
obsutil: move 'exclusivemarkers' to the new modules...
r33144 obsutil,
Gregory Szorc
repair: use absolute_import
r25970 util,
)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
stringutil,
)
Gregory Szorc
repair: use absolute_import
r25970
Gregory Szorc
repair: rename _backup to backupbundle...
r37034 def backupbundle(repo, bases, heads, node, suffix, compress=True,
obsolescence=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
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
Yuya Nishihara
repair: use _hexlist() to build revset expression from binary nodes...
r25340 allcommits = repo.set('%ln::%ln', bases, heads)
Durham Goode
bundles: do not overwrite existing backup bundles (BC)...
r23835 allhashes = sorted(c.hex() for c in allcommits)
Augie Fackler
repair: reliably obtain bytestr of node ids
r34219 totalhash = hashlib.sha1(''.join(allhashes)).digest()
name = "%s/%s-%s-%s.hg" % (backupdir, short(node),
hex(totalhash[:4]), suffix)
Durham Goode
bundles: do not overwrite existing backup bundles (BC)...
r23835
Martin von Zweigbergk
repair: preserve phase also when not using generaldelta (issue5678)...
r34179 cgversion = changegroup.localversion(repo)
Pierre-Yves David
strip: compress bundle2 backup using BZ...
r26425 comp = None
Pierre-Yves David
strip: use bundle2 + cg2 by default when repository use general delta...
r26423 if cgversion != '01':
Pierre-Yves David
bundle2: rename format, parts and config to final names...
r24686 bundletype = "HG20"
Pierre-Yves David
strip: compress bundle2 backup using BZ...
r26425 if compress:
comp = 'BZ'
Eric Sumner
repair: add experimental option to write bundle2 files...
r23898 elif compress:
Nicolas Dumazet
repair: do not compress partial bundle if we do not keep it on disk...
r11791 bundletype = "HG10BZ"
else:
bundletype = "HG10UN"
strip: use the 'writenewbundle' function to get bundle on disk...
r32468
outgoing = discovery.outgoing(repo, missingroots=bases, missingheads=heads)
Martin von Zweigbergk
strip: include phases in bundle (BC)...
r33032 contentopts = {
'cg.version': cgversion,
'obsolescence': obsolescence,
'phases': True,
}
strip: use the 'writenewbundle' function to get bundle on disk...
r32468 return bundle2.writenewbundle(repo.ui, repo, 'strip', name, bundletype,
outgoing, contentopts, vfs, compression=comp)
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
Durham Goode
repair: refactor broken linkrev collection...
r33690 def _collectrevlog(revlog, striprev):
_, brokenset = revlog.getstrippoint(striprev)
return [revlog.linkrev(r) for r in brokenset]
def _collectmanifest(repo, striprev):
return _collectrevlog(repo.manifestlog._revlog, striprev)
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()
Alexis S. L. Carvalho
strip: calculate list of extra nodes to save and pass it to changegroupsubset...
r5909
Durham Goode
repair: refactor broken linkrev collection...
r33690 s.update(_collectmanifest(repo, striprev))
Matt Mackall
strip: simplify collectone
r13705 for fname in files:
Durham Goode
repair: refactor broken linkrev collection...
r33690 s.update(_collectrevlog(repo.file(fname), striprev))
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'):
Martin von Zweigbergk
repair: clarify in comment that caller must take lock, but not transaction...
r32922 # This function requires the caller to lock the repo, but it operates
# within a transaction of its own, and thus requires there to be no current
# transaction when it is called.
Martin von Zweigbergk
repair: move check for existing transaction earlier...
r32924 if repo.currenttransaction() is not None:
raise error.ProgrammingError('cannot strip from inside a transaction')
Jordi Gutiérrez Hermoso
strip: remove -b/--backup codepaths...
r22057 # 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
Martin von Zweigbergk
repair: combine two loops over changelog revisions...
r30707 files = _collectfiles(repo, striprev)
saverevs = _collectbrokencsets(repo, files, striprev)
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)
Martin von Zweigbergk
repair: combine two loops over changelog revisions...
r30707 saveheads = set(saverevs)
Martin von Zweigbergk
repair: speed up stripping of many roots...
r30706 for r in cl.revs(start=striprev + 1):
if any(p in tostrip for p in cl.parentrevs(r)):
tostrip.add(r)
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
strip: strip obsmarkers exclusive to the stripped changeset...
r32629 stripobsidx = obsmarkers = ()
config: register the 'devel.strip-obsmarkers' config...
r33167 if repo.ui.configbool('devel', 'strip-obsmarkers'):
obsutil: move 'exclusivemarkers' to the new modules...
r33144 obsmarkers = obsutil.exclusivemarkers(repo, stripbases)
strip: strip obsmarkers exclusive to the stripped changeset...
r32629 if obsmarkers:
stripobsidx = [i for i, m in enumerate(repo.obsstore)
if m in obsmarkers]
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
Mike Edgar
repair: define explicit local variable, don't reuse a comprehension variable...
r24252 node = nodelist[-1]
Jordi Gutiérrez Hermoso
strip: remove -b/--backup codepaths...
r22057 if backup:
Gregory Szorc
repair: rename _backup to backupbundle...
r37034 backupfile = backupbundle(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))
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 tmpbundlefile = None
Martin von Zweigbergk
strip: simplify some repeated conditions...
r29951 if saveheads:
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 # do not compress temporary bundle if we remove it from disk later
strip: do not include obsolescence markers for the temporary bundle...
r32628 #
# We do not include obsolescence, it might re-introduce prune markers
# we are trying to strip. This is harmless since the stripped markers
# are already backed up and we did not touched the markers for the
# saved changesets.
Gregory Szorc
repair: rename _backup to backupbundle...
r37034 tmpbundlefile = backupbundle(repo, savebases, saveheads, node, 'temp',
compress=False, obsolescence=False)
Matt Mackall
strip: move strip code to a new repair module
r4702
Bryan O'Sullivan
with: use context manager for transaction in strip
r27873 try:
with repo.transaction("strip") as tr:
offset = len(tr.entries)
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073
Bryan O'Sullivan
with: use context manager for transaction in strip
r27873 tr.startgroup()
cl.strip(striprev, tr)
Durham Goode
repair: move manifest strip to a separate function...
r33691 stripmanifest(repo, striprev, tr, files)
Durham Goode
strip: move tree strip logic to it's own function...
r32196
Bryan O'Sullivan
with: use context manager for transaction in strip
r27873 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 for i in xrange(offset, len(tr.entries)):
file, troffset, ignore = tr.entries[i]
FUJIWARA Katsunori
repair: open a file with checkambig=True to avoid file stat ambiguity...
r30001 with repo.svfs(file, 'a', checkambig=True) as fp:
fp.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
strip: strip obsmarkers exclusive to the stripped changeset...
r32629 deleteobsmarkers(repo.obsstore, stripobsidx)
del repo.obsstore
Martin von Zweigbergk
repair: invalidate volatile sets after stripping...
r35796 repo.invalidatevolatilesets()
Martin von Zweigbergk
repair: filter out unknown revisions from phasecache within transaction...
r35725 repo._phasecache.filterunknown(repo)
strip: strip obsmarkers exclusive to the stripped changeset...
r32629
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 if tmpbundlefile:
Matt Mackall
strip: hide unbundle messages by default...
r11202 ui.note(_("adding branch\n"))
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 f = vfs.open(tmpbundlefile, "rb")
gen = exchange.readbundle(ui, f, tmpbundlefile, vfs)
Matt Mackall
strip: hide unbundle messages by default...
r11202 if not repo.ui.verbose:
# silence internal shuffling chatter
repo.ui.pushbuffer()
Martin von Zweigbergk
repair: create transaction for bundle1 unbundling earlier...
r32929 tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile)
Martin von Zweigbergk
bundle: transpose transaction scope with bundle type switch...
r33042 txnname = 'strip'
if not isinstance(gen, bundle2.unbundle20):
txnname = "strip\n%s" % util.hidepassword(tmpbundleurl)
with repo.transaction(txnname) as tr:
Martin von Zweigbergk
bundle: make applybundle() delegate v1 bundles to applybundle1()
r33043 bundle2.applybundle(repo, gen, tr, source='strip',
Martin von Zweigbergk
strip: don't allow empty changegroup in bundle1...
r33307 url=tmpbundleurl)
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 Harbison
repair: use context manager for lock management...
r31626
Martin von Zweigbergk
repair: remove unnecessary locking for bookmarks...
r32925 with repo.transaction('repair') as tr:
Boris Feld
bookmark: use 'applychanges' in 'repair.strip'
r33490 bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm]
bm.applychanges(repo, tr, bmchanges)
Laurent Charignon
repair: use bookmarks.recordchange instead of bookmarks.write...
r27157
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)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as e:
Idan Kamara
repair: remove undo files after strip
r16237 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') %
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 (undovfs.join(undofile),
stringutil.forcebytestr(e)))
Idan Kamara
repair: remove undo files after strip
r16237
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 von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 ui.warn(_("strip failed, backup bundle stored in '%s'\n")
FUJIWARA Katsunori
repair: make "strip()" treat bundle files via vfs...
r20979 % vfs.join(backupfile))
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 if tmpbundlefile:
Martin von Zweigbergk
strip: clarify that user action is required to recover temp bundle...
r29953 ui.warn(_("strip failed, unrecovered changes stored in '%s'\n")
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 % vfs.join(tmpbundlefile))
Martin von Zweigbergk
strip: clarify that user action is required to recover temp bundle...
r29953 ui.warn(_("(fix the problem, then recover the changesets with "
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 "\"hg unbundle '%s'\")\n") % vfs.join(tmpbundlefile))
Henrik Stuart
strip: make repair.strip transactional to avoid repository corruption...
r8073 raise
Jordi Gutiérrez Hermoso
strip: remove -b/--backup codepaths...
r22057 else:
Martin von Zweigbergk
strip: don't use "full" and "partial" to describe bundles...
r29954 if tmpbundlefile:
# Remove temporary bundle only if there were no exceptions
vfs.unlink(tmpbundlefile)
Matt Mackall
strip: move strip code to a new repair module
r4702
Pierre-Yves David
destroyed: drop complex branchcache rebuilt logic...
r18395 repo.destroyed()
Martin von Zweigbergk
repair: make strip() return backup file path...
r30274 # return the backup file path (or None if 'backup' was False) so
# extensions can use it
return backupfile
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652
Jun Wu
strip: add a delayedstrip method that works in a transaction...
r33087 def safestriproots(ui, repo, nodes):
"""return list of roots of nodes where descendants are covered by nodes"""
torev = repo.unfiltered().changelog.rev
revs = set(torev(n) for n in nodes)
# tostrip = wanted - unsafe = wanted - ancestors(orphaned)
# orphaned = affected - wanted
# affected = descendants(roots(wanted))
# wanted = revs
tostrip = set(repo.revs('%ld-(::((roots(%ld)::)-%ld))', revs, revs, revs))
notstrip = revs - tostrip
if notstrip:
nodestr = ', '.join(sorted(short(repo[n].node()) for n in notstrip))
ui.warn(_('warning: orphaned descendants detected, '
'not stripping %s\n') % nodestr)
return [c.node() for c in repo.set('roots(%ld)', tostrip)]
class stripcallback(object):
"""used as a transaction postclose callback"""
def __init__(self, ui, repo, backup, topic):
self.ui = ui
self.repo = repo
self.backup = backup
self.topic = topic or 'backup'
self.nodelist = []
def addnodes(self, nodes):
self.nodelist.extend(nodes)
def __call__(self, tr):
roots = safestriproots(self.ui, self.repo, self.nodelist)
if roots:
Jun Wu
strip: respect the backup option in stripcallback...
r33108 strip(self.ui, self.repo, roots, self.backup, self.topic)
Jun Wu
strip: add a delayedstrip method that works in a transaction...
r33087
def delayedstrip(ui, repo, nodelist, topic=None):
"""like strip, but works inside transaction and won't strip irreverent revs
nodelist must explicitly contain all descendants. Otherwise a warning will
be printed that some nodes are not stripped.
Always do a backup. The last non-None "topic" will be used as the backup
topic name. The default backup topic name is "backup".
"""
tr = repo.currenttransaction()
if not tr:
nodes = safestriproots(ui, repo, nodelist)
return strip(ui, repo, nodes, True, topic)
# transaction postclose callbacks are called in alphabet order.
# use '\xff' as prefix so we are likely to be called last.
callback = tr.getpostclose('\xffstrip')
if callback is None:
callback = stripcallback(ui, repo, True, topic)
tr.addpostclose('\xffstrip', callback)
if topic:
callback.topic = topic
callback.addnodes(nodelist)
Durham Goode
repair: move manifest strip to a separate function...
r33691 def stripmanifest(repo, striprev, tr, files):
revlog = repo.manifestlog._revlog
revlog.strip(striprev, tr)
striptrees(repo, tr, striprev, files)
Durham Goode
strip: move tree strip logic to it's own function...
r32196 def striptrees(repo, tr, striprev, files):
if 'treemanifest' in repo.requirements: # safe but unnecessary
# otherwise
Durham Goode
hg: backout optimizing for treemanifests...
r32296 for unencoded, encoded, size in repo.store.datafiles():
if (unencoded.startswith('meta/') and
unencoded.endswith('00manifest.i')):
dir = unencoded[5:-12]
repo.manifestlog._revlog.dirlog(dir).strip(striprev, tr)
Durham Goode
strip: move tree strip logic to it's own function...
r32196
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 def rebuildfncache(ui, repo):
"""Rebuilds the fncache file from repo history.
Missing entries will be added. Extra entries will be removed.
"""
repo = repo.unfiltered()
if 'fncache' not in repo.requirements:
ui.warn(_('(not rebuilding fncache because repository does not '
Wagner Bruna
repair: fix typo in warning message
r25874 'support fncache)\n'))
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 return
Bryan O'Sullivan
with: use context manager in rebuildfncache again
r27860 with repo.lock():
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 fnc = repo.store.fncache
# Trigger load of fncache.
if 'irrelevant' in fnc:
pass
oldentries = set(fnc.entries)
newentries = set()
seenfiles = set()
Martin von Zweigbergk
repair: use progress helper...
r38413 progress = ui.makeprogress(_('rebuilding'), unit=_('changesets'),
total=len(repo))
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 for rev in repo:
Martin von Zweigbergk
repair: use progress helper...
r38413 progress.update(rev)
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652
ctx = repo[rev]
for f in ctx.files():
# This is to minimize I/O.
if f in seenfiles:
continue
seenfiles.add(f)
i = 'data/%s.i' % f
d = 'data/%s.d' % f
if repo.store._exists(i):
newentries.add(i)
if repo.store._exists(d):
newentries.add(d)
Martin von Zweigbergk
repair: use progress helper...
r38413 progress.complete()
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652
Martin von Zweigbergk
treemanifest: fix debugrebuildfncache...
r28031 if 'treemanifest' in repo.requirements: # safe but unnecessary otherwise
Martin von Zweigbergk
treemanifests: fix streaming clone...
r28007 for dir in util.dirs(seenfiles):
i = 'meta/%s/00manifest.i' % dir
d = 'meta/%s/00manifest.d' % dir
if repo.store._exists(i):
newentries.add(i)
if repo.store._exists(d):
newentries.add(d)
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 addcount = len(newentries - oldentries)
removecount = len(oldentries - newentries)
for p in sorted(oldentries - newentries):
ui.write(_('removing %s\n') % p)
for p in sorted(newentries - oldentries):
ui.write(_('adding %s\n') % p)
if addcount or removecount:
ui.write(_('%d items added, %d removed from fncache\n') %
(addcount, removecount))
fnc.entries = newentries
fnc._dirty = True
Bryan O'Sullivan
with: use context manager in rebuildfncache
r27871 with repo.transaction('fncache') as tr:
Gregory Szorc
repair: add functionality to rebuild fncache...
r25652 fnc.write(tr)
else:
ui.write(_('fncache already up to date\n'))
Kostia Balytskyi
obsstore: move delete function from obsstore class to repair module...
r28868 def deleteobsmarkers(obsstore, indices):
"""Delete some obsmarkers from obsstore and return how many were deleted
'indices' is a list of ints which are the indices
of the markers to be deleted.
Every invocation of this function completely rewrites the obsstore file,
skipping the markers we want to be removed. The new temporary file is
created, remaining markers are written there and on .close() this file
gets atomically renamed to obsstore, thus guaranteeing consistency."""
if not indices:
# we don't want to rewrite the obsstore with the same content
return
left = []
current = obsstore._all
n = 0
for i, m in enumerate(current):
if i in indices:
n += 1
continue
left.append(m)
newobsstorefile = obsstore.svfs('obsstore', 'w', atomictemp=True)
for bytes in obsolete.encodemarkers(left, True, obsstore._version):
newobsstorefile.write(bytes)
newobsstorefile.close()
return n