Mercurial > evolve
changeset 2431:0405bbda7402 mercurial-4.1
merge with future 6.2.0
There are been (multiple) minor output changes.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 18 May 2017 23:12:52 +0200 |
parents | d4ee0274a8ef (diff) 677dfbb8bdbf (current diff) |
children | 765b2561fa90 e5e502407ab0 |
files | tests/test-discovery-obshashrange.t tests/test-evolve-obshistory.t tests/test-evolve-serveronly-bundle2.t tests/test-evolve.t tests/test-obsolete.t tests/test-prev-next.t tests/test-topic-stack.t tests/test-wireproto-bundle1.t tests/test-wireproto.t |
diffstat | 19 files changed, 2680 insertions(+), 250 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu May 18 22:53:01 2017 +0200 +++ b/.hgtags Thu May 18 23:12:52 2017 +0200 @@ -48,3 +48,4 @@ 70694b2621ba9d919bc38303f8901e84caf5da0f 5.6.1 165ad227993de4e7d819cc6c820d5b9f7b38b80d 6.0.0 5ef112a6eb875633a7925cde61b7d2d9e65b3a56 6.0.1 +8510d3fd7c3b312dc731f4c29badc415d504558a 6.1.0
--- a/README Thu May 18 22:53:01 2017 +0200 +++ b/README Thu May 18 23:12:52 2017 +0200 @@ -112,7 +112,24 @@ Changelog ========= -6.1.0 - in progress +6.2.0 -- 2017-05-18 +------------------- + + - olog: a new command to inspect the obs-history of a changeset (hg-4.0 + only), + - topic: have thg display topic name if possible, + - blackbox: log more information about discovery and cache computation, + - obscache: more efficient update in the (rare) case of a transaction adding + markers without changesets, + - obscache: fix more cache invalidation propagation, + - obscache: also enable the new cache (from 6.1.0) for 'evolve.server-only', + - obshashrange-cache: update incrementally in the (common) case of a + transaction not affecting existing range, + - obshashrange-cache: keep the cache warm after each transaction, + - topic: now requires Mercurial 4.0 or above, + - stack: now display if current revision is in bad state (issue5533), + - stack: fix json output to be valid json. + +6.1.0 -- 2017-05-03 ------------------- - improve message about obsolete working copy parent,
--- a/debian/changelog Thu May 18 22:53:01 2017 +0200 +++ b/debian/changelog Thu May 18 23:12:52 2017 +0200 @@ -1,14 +1,26 @@ -mercurial-evolve (6.0.1-1) UNRELEASED; urgency=medium +mercurial-evolve (6.2.0-1) unstable; urgency=medium + + * new upstream release + + -- Pierre-Yves David <pierre-yves.david@ens-lyon.org> Thu, 18 May 2017 22:24:10 +0200 + +mercurial-evolve (6.1.0-1) unstable; urgency=medium + + * New upstream release + + -- Pierre-Yves David <pierre-yves.david@ens-lyon.org> Wed, 03 May 2017 13:57:15 +0200 + +mercurial-evolve (6.0.1-1) unstable; urgency=medium * New upstream version - -- Pierre-Yves David <marmoute@nodosa.octopoid.net> Thu, 20 Apr 2017 12:58:35 +0200 + -- Pierre-Yves David <pierre-yves.david@ens-lyon.org> Thu, 20 Apr 2017 12:58:35 +0200 mercurial-evolve (6.0.0-1) unstable; urgency=medium * New Upstream Release - -- Pierre-Yves David <marmoute@nodosa.octopoid.net> Thu, 20 Apr 2017 12:58:03 +0200 + -- Pierre-Yves David <pierre-yves.david@ens-lyon.org> Thu, 20 Apr 2017 12:58:03 +0200 mercurial-evolve (5.5.0-1) unstable; urgency=medium
--- a/hgext3rd/evolve/__init__.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/__init__.py Thu May 18 23:12:52 2017 +0200 @@ -148,6 +148,7 @@ obsexchange, safeguard, utility, + obshistory ) __version__ = metadata.__version__ @@ -162,6 +163,15 @@ obsexcmsg = utility.obsexcmsg +colortable = {'evolve.node': 'yellow', + 'evolve.user': 'green', + 'evolve.rev': 'blue', + 'evolve.short_description': '', + 'evolve.date': 'cyan', + 'evolve.current_rev': 'bold', + 'evolve.verb': '', + } + _pack = struct.pack _unpack = struct.unpack @@ -180,6 +190,7 @@ eh.merge(checkheads.eh) eh.merge(safeguard.eh) eh.merge(obscache.eh) +eh.merge(obshistory.eh) uisetup = eh.final_uisetup extsetup = eh.final_extsetup reposetup = eh.final_reposetup @@ -269,9 +280,6 @@ ui.setconfig('alias', 'pstatus', 'status --rev .^', 'evolve') if ui.config('alias', 'pdiff', None) is None: ui.setconfig('alias', 'pdiff', 'diff --rev .^', 'evolve') - if ui.config('alias', 'olog', None) is None: - ui.setconfig('alias', 'olog', "log -r 'precursors(.)' --hidden", - 'evolve') if ui.config('alias', 'odiff', None) is None: ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .", @@ -1881,7 +1889,7 @@ raise error.Abort("base of divergent changeset %s not found" % ctx, hint='this case is not yet handled') -shorttemplate = '[{rev}] {desc|firstline}\n' +shorttemplate = "[{label('evolve.rev', rev)}] {desc|firstline}\n" @eh.command( '^previous', @@ -2055,7 +2063,8 @@ result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt, False, lambda: None, category='unstable') if not result: - ui.status(_('working directory now at %s\n') % repo['.']) + ui.status(_('working directory now at %s\n') + % ui.label(repo['.'], 'evolve.node')) return result return 1 return result @@ -2261,7 +2270,8 @@ repo._bookmarks[bookactive] = newnode.node() repo._bookmarks.recordchange(tr) commands.update(ui, repo, newnode.rev()) - ui.status(_('working directory now at %s\n') % newnode) + ui.status(_('working directory now at %s\n') + % ui.label(newnode, 'evolve.node')) if movebookmark: bookmarksmod.activate(repo, bookactive)
--- a/hgext3rd/evolve/metadata.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/metadata.py Thu May 18 23:12:52 2017 +0200 @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -__version__ = '6.1.0.dev' -testedwith = '3.8.4 3.9.2 4.0.2 4.1.1 4.2' +__version__ = '6.2.0' +testedwith = '3.8.4 3.9.2 4.0.2 4.1.2 4.2' minimumhgversion = '3.8' buglink = 'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/obscache.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/obscache.py Thu May 18 23:12:52 2017 +0200 @@ -7,25 +7,42 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +import errno import hashlib +import os import struct +import time import weakref -import errno from mercurial import ( + error, localrepo, obsolete, phases, + pycompat, node, util, ) +from mercurial.i18n import _ + from . import ( exthelper, ) eh = exthelper.exthelper() +# prior to hg-4.2 there are not util.timer +if util.safehasattr(util, 'timer'): + timer = util.timer +elif util.safehasattr(time, "perf_counter"): + timer = time.perf_counter +elif getattr(pycompat, 'osname', os.name) == 'nt': + timer = time.clock +else: + timer = time.time + + try: obsstorefilecache = localrepo.localrepository.obsstore except AttributeError: @@ -76,91 +93,235 @@ except (OSError, IOError) as e: if e.errno != errno.ENOENT: raise - key = hashlib.sha1(keydata).digest() + if keydata: + key = hashlib.sha1(keydata).digest() + else: + # reusing an existing "empty" value make it easier to define a + # default cachekey for 'no data'. + key = node.nullid return obsstoresize, key obsstore.__class__ = cachekeyobsstore return obsstore -emptykey = (node.nullrev, node.nullid, 0, 0, node.nullid) - -def getcachekey(repo): - """get a cache key covering the changesets and obsmarkers content - - IT contains the following data. Combined with 'upgradeneeded' it allows to - do iterative upgrade for cache depending of theses two data. +# XXX copied as is from Mercurial 4.2 and added the "offset" parameters +@util.nogc +def _readmarkers(data, offset=None): + """Read and enumerate markers from raw data""" + off = 0 + diskversion = struct.unpack('>B', data[off:off + 1])[0] + if offset is None: + off += 1 + else: + assert 1 <= offset + off = offset + if diskversion not in obsolete.formats: + raise error.Abort(_('parsing obsolete marker: unknown version %r') + % diskversion) + return diskversion, obsolete.formats[diskversion][0](data, off) - The cache key parts are" - - tip-rev, - - tip-node, - - obsstore-length (nb markers), - - obsstore-file-size (in bytes), - - obsstore "cache key" - """ - assert repo.filtername is None - cl = repo.changelog - index, key = repo.obsstore.cachekey() - tiprev = len(cl) - 1 - return (tiprev, - cl.node(tiprev), - len(repo.obsstore), - index, - key) +def markersfrom(obsstore, byteoffset, firstmarker): + if not firstmarker: + return list(obsstore) + elif '_all' in vars(obsstore): + # if the data are in memory, just use that + return obsstore._all[firstmarker:] + else: + obsdata = obsstore.svfs.tryread('obsstore') + return _readmarkers(obsdata, byteoffset)[1] -def upgradeneeded(repo, key): - """return (valid, start-rev, start-obs-idx) - 'valid': is "False" if older cache value needs invalidation, +class dualsourcecache(object): + """An abstract class for cache that needs both changelog and obsstore - 'start-rev': first revision not in the cache. None if cache is up to date, - - 'start-obs-idx': index of the first obs-markers not in the cache. None is - up to date. + This class handle the tracking of changelog and obsstore update. It provide + data to performs incremental update (see the 'updatefrom' function for + details). This class can also detect stripping of the changelog or the + obsstore and can reset the cache in this cache (see the 'clear' function + for details). """ - # XXX ideally, this function would return a bounded amount of changeset and - # obsmarkers and the associated new cache key. Otherwise we are exposed to - # a race condition between the time the cache is updated and the new cache - # key is computed. (however, we do not want to compute the full new cache - # key in all case because we want to skip reading the obsstore content. We - # could have a smarter implementation here. + # default key used for an empty cache + # + # The cache key covering the changesets and obsmarkers content # - # In pratice the cache is only updated after each transaction within a - # lock. So we should be fine. We could enforce this with a new repository - # requirement (or fix the race, that is not too hard). - invalid = (False, 0, 0) - if key is None: - return invalid + # The cache key parts are: + # - tip-rev, + # - tip-node, + # - obsstore-length (nb markers), + # - obsstore-file-size (in bytes), + # - obsstore "cache key" + emptykey = (node.nullrev, node.nullid, 0, 0, node.nullid) + _cachename = None # used for error message + + def __init__(self): + super(dualsourcecache, self).__init__() + self._cachekey = None + + def _updatefrom(self, repo, revs, obsmarkers): + """override this method to update your cache data incrementally + + revs: list of new revision in the changelog + obsmarker: list of new obsmarkers in the obsstore + """ + raise NotImplementedError + + def clear(self, reset=False): + """invalidate the cache content + + if 'reset' is passed, we detected a strip and the cache will have to be + recomputed. + """ + # /!\ IMPORTANT /!\ + # You must overide this method to actually + if reset: + self._cachekey = self.emptykey if reset else None + else: + self._cachekey = None + + def load(self, repo): + """Load data from disk + + Do not forget to restore the "cachekey" attribute while doing so. + """ + raise NotImplementedError + + # Useful public function (no need to override them) + + def uptodate(self, repo): + """return True if the cache content is up to date False otherwise + + This method can be used to detect of the cache is lagging behind new + data in either changelog or obsstore. + """ + if self._cachekey is None: + self.load(repo) + status = self._checkkey(repo.changelog, repo.obsstore) + return (status is not None + and status[0] == self._cachekey[0] # tiprev + and status[1] == self._cachekey[3]) # obssize + + def update(self, repo): + """update the cache with new repository data + + The update will be incremental when possible""" + repo = repo.unfiltered() + # If we do not have any data, try loading from disk + if self._cachekey is None: + self.load(repo) + + assert repo.filtername is None + cl = repo.changelog + + upgrade = self._upgradeneeded(repo) + if upgrade is None: + return + + reset, revs, obsmarkers, obskeypair = upgrade + if reset or self._cachekey is None: + repo.ui.log('evoext-cache', 'strip detected, %s cache reset\n' % self._cachename) + self.clear(reset=True) + + starttime = timer() + self._updatefrom(repo, revs, obsmarkers) + duration = timer() - starttime + repo.ui.log('evoext-cache', 'updated %s in %.4f seconds (%sr, %so)\n', + self._cachename, duration, len(revs), len(obsmarkers)) - ### Is the cache valid ? - keytiprev, keytipnode, keyobslength, keyobssize, keyobskey = key - # check for changelog strip - cl = repo.changelog - tiprev = len(cl) - 1 - if (tiprev < keytiprev - or cl.node(keytiprev) != keytipnode): - return invalid - # check for obsstore strip - obssize, obskey = repo.obsstore.cachekey(index=keyobssize) - if obskey != keyobskey: - return invalid + # update the key from the new data + key = list(self._cachekey) + if revs: + key[0] = len(cl) - 1 + key[1] = cl.node(key[0]) + if obsmarkers: + key[2] += len(obsmarkers) + key[3], key[4] = obskeypair + self._cachekey = tuple(key) + + # from here, there are internal function only + + def _checkkey(self, changelog, obsstore): + """internal function""" + key = self._cachekey + if key is None: + return None + + ### Is the cache valid ? + keytiprev, keytipnode, keyobslength, keyobssize, keyobskey = key + # check for changelog strip + tiprev = len(changelog) - 1 + if (tiprev < keytiprev + or changelog.node(keytiprev) != keytipnode): + return None + # check for obsstore strip + obssize, obskey = obsstore.cachekey(index=keyobssize) + if obskey != keyobskey: + return None + if obssize != keyobssize: + # we want to return the obskey for the new size + __, obskey = obsstore.cachekey(index=obssize) + return tiprev, obssize, obskey + + def _upgradeneeded(self, repo): + """return (valid, start-rev, start-obs-idx) + + 'valid': is "False" if older cache value needs invalidation, + + 'start-rev': first revision not in the cache. None if cache is up to date, + + 'start-obs-idx': index of the first obs-markers not in the cache. None is + up to date. + """ - ### cache is valid, is there anything to update + # We need to ensure we use the same changelog and obsstore through the + # processing. Otherwise some invalidation could update the object and their + # content after we computed the cache key. + cl = repo.changelog + obsstore = repo.obsstore + key = self._cachekey + + reset = False - # any new changesets ? - startrev = None - if keytiprev < tiprev: - startrev = keytiprev + 1 + status = self._checkkey(cl, obsstore) + if status is None: + reset = True + key = self.emptykey + obssize, obskey = obsstore.cachekey() + tiprev = len(cl) - 1 + else: + tiprev, obssize, obskey = status + + keytiprev, keytipnode, keyobslength, keyobssize, keyobskey = key + + if not reset and keytiprev == tiprev and keyobssize == obssize: + return None # nothing to upgrade - # any new markers - startidx = None - if keyobssize < obssize: - startidx = keyobslength + ### cache is valid, is there anything to update + + # any new changesets ? + revs = () + if keytiprev < tiprev: + revs = list(cl.revs(start=keytiprev + 1, stop=tiprev)) - return True, startrev, startidx + # any new markers + markers = () + if keyobssize < obssize: + # XXX Three are a small race change here. Since the obsstore might have + # move forward between the time we computed the cache key and we access + # the data. To fix this we need so "up to" argument when fetching the + # markers here. Otherwise we might return more markers than covered by + # the cache key. + # + # In pratice the cache is only updated after each transaction within a + # lock. So we should be fine. We could enforce this with a new repository + # requirement (or fix the race, that is not too hard). + markers = markersfrom(obsstore, keyobssize, keyobslength) -class obscache(object): + return reset, revs, markers, (obssize, obskey) + + +class obscache(dualsourcecache): """cache the "does a rev" is the precursors of some obsmarkers data This is not directly holding the "is this revision obsolete" information, @@ -197,16 +358,12 @@ _filepath = 'cache/evoext-obscache-00' _headerformat = '>q20sQQ20s' + _cachename = 'evo-ext-obscache' # used for error message + def __init__(self, repo): + super(obscache, self).__init__() + self._ondiskkey = None self._vfs = repo.vfs - # The cache key parts are" - # - tip-rev, - # - tip-node, - # - obsstore-length (nb markers), - # - obsstore-file-size (in bytes), - # - obsstore "cache key" - self._cachekey = None - self._ondiskkey = None self._data = bytearray() def get(self, rev): @@ -215,90 +372,56 @@ Make sure the cache has been updated to match the repository content before using it""" return self._data[rev] - def clear(self): + def clear(self, reset=False): """invalidate the cache content""" - self._cachekey = None + super(obscache, self).clear(reset=reset) self._data = bytearray() - def uptodate(self, repo): - if self._cachekey is None: - self.load(repo) - valid, startrev, startidx = upgradeneeded(repo, self._cachekey) - return (valid and startrev is None and startidx is None) + def _updatefrom(self, repo, revs, obsmarkers): + if revs: + self._updaterevs(repo, revs) + if obsmarkers: + self._updatemarkers(repo, obsmarkers) + + def _updaterevs(self, repo, revs): + """update the cache with new revisions + + Newly added changeset might be affected by obsolescence markers + we already have locally. So we needs to have some global + knowledge about the markers to handle that question. + + Right now this requires parsing all markers in the obsstore. We could + imagine using various optimisation (eg: another cache, network + exchange, etc). - def update(self, repo): - """Iteratively update the cache with new repository data""" - # If we do not have any data, try loading from disk - if self._cachekey is None: - self.load(repo) + A possible approach to this is to build a set of all node used as + precursors in `obsstore._obscandidate`. If markers are not loaded yet, + we could initialize it by doing a quick scan through the obsstore data + and filling a (pre-sized) set. Doing so would be much faster than + parsing all the obsmarkers since we would access less data, not create + any object beside the nodes and not have to decode any complex data. - valid, startrev, startidx = upgradeneeded(repo, self._cachekey) - if not valid: - self.clear() - - if startrev is None and startidx is None: - return - - # process the new changesets + For now we stick to the simpler approach of paying the + performance cost on new changesets. + """ + node = repo.changelog.node + succs = repo.obsstore.successors + for r in revs: + if node(r) in succs: + val = 1 + else: + val = 0 + self._data.append(val) cl = repo.changelog - if startrev is not None: - node = cl.node - # Note: - # - # Newly added changeset might be affected by obsolescence markers - # we already have locally. So we needs to have soem global - # knowledge about the markers to handle that question. Right this - # requires parsing all markers in the obsstore. However, we could - # imagine using various optimisation (eg: bloom filter, other on - # disk cache) to remove this full parsing. - # - # For now we stick to the simpler approach or paying the - # performance cost on new changesets. - succs = repo.obsstore.successors - for r in cl.revs(startrev): - if node(r) in succs: - val = 1 - else: - val = 0 - self._data.append(val) assert len(self._data) == len(cl), (len(self._data), len(cl)) - # process the new obsmarkers - if startidx is not None: - rev = cl.nodemap.get - markers = repo.obsstore._all - # Note: - # - # There are no actually needs to load the full obsstore here, - # since we only read the latest ones. We do it for simplicity in - # the first implementation. Loading the full obsstore has a - # performance cost and should go away in this case too. We have - # two simples options for that: - # - # 1) provide and API to start reading markers from a byte offset - # (we have that data in the cache key) - # - # 2) directly update the cache at a lower level, in the code - # responsible for adding a markers. - # - # Option 2 is probably a bit more invasive, but more solid on the long run - - for i in xrange(startidx, len(repo.obsstore)): - r = rev(markers[i][0]) - # If markers affect a newly added nodes, it would have been - # caught in the previous loop, (so we skip < startrev) - if r is not None and (startrev is None or r < startrev): - self._data[r] = 1 - - assert repo._currentlock(repo._lockref) is not None - # XXX note that there are a potential race condition here, since the - # repo "might" have changed side the cache update above. However, this - # code will only be running in a lock so we ignore the issue for now. - # - # To work around this, 'upgradeneeded' should return a bounded amount - # of changeset and markers to read with their associated cachekey. see - # 'upgradeneeded' for detail. - self._cachekey = getcachekey(repo) + def _updatemarkers(self, repo, obsmarkers): + """update the cache with new markers""" + rev = repo.changelog.nodemap.get + for m in obsmarkers: + r = rev(m[0]) + if r is not None: + self._data[r] = 1 def save(self, repo): """save the data to disk""" @@ -319,7 +442,7 @@ data = repo.vfs.tryread(self._filepath) if not data: - self._cachekey = emptykey + self._cachekey = self.emptykey self._data = bytearray() else: headersize = struct.calcsize(self._headerformat) @@ -339,7 +462,7 @@ if notpublic: obscache = repo.obsstore.obscache # Since we warm the cache at the end of every transaction, the cache - # should be up to date. However a non-enabled client might have touced + # should be up to date. However a non-enabled client might have touched # the repository. # # Updating the cache without a lock is sloppy, so we fallback to the @@ -348,17 +471,18 @@ # # With the current implementation updating the cache will requires to # load the obsstore anyway. Once loaded, hitting the obsstore directly - # will be about as fast.. + # will be about as fast... if not obscache.uptodate(repo): if repo.currenttransaction() is None: - repo.ui.log('evoext-obscache', + repo.ui.log('evoext-cache', 'obscache is out of date, ' 'falling back to slower obsstore version\n') repo.ui.debug('obscache is out of date') return orig(repo) else: - # If a transaction is open, it is worthwhile to update and use the - # cache as it will be written on disk when the transaction close. + # If a transaction is open, it is worthwhile to update and use + # the cache, the lock prevent race and it will be written on + # disk when the transaction close. obscache.update(repo) isobs = obscache.get for r in notpublic: @@ -381,6 +505,7 @@ def destroyed(self): if 'obsstore' in vars(self): self.obsstore.obscache.clear() + super(obscacherepo, self).destroyed() def transaction(self, *args, **kwargs): tr = super(obscacherepo, self).transaction(*args, **kwargs) @@ -391,11 +516,10 @@ if repo is None: return repo = repo.unfiltered() - # As pointed in 'obscache.update', we could have the - # changelog and the obsstore in charge of updating the - # cache when new items goes it. The tranaction logic would - # then only be involved for the 'pending' and final saving - # logic. + # As pointed in 'obscache.update', we could have the changelog + # and the obsstore in charge of updating the cache when new + # items goes it. The tranaction logic would then only be + # involved for the 'pending' and final writing on disk. self.obsstore.obscache.update(repo) self.obsstore.obscache.save(repo)
--- a/hgext3rd/evolve/obsdiscovery.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/obsdiscovery.py Thu May 18 23:12:52 2017 +0200 @@ -24,8 +24,10 @@ import hashlib import heapq +import os import sqlite3 import struct +import time import weakref from mercurial import ( @@ -36,6 +38,7 @@ localrepo, node, obsolete, + pycompat, scmutil, setdiscovery, util, @@ -46,10 +49,21 @@ from . import ( exthelper, + obscache, utility, stablerange, ) +# prior to hg-4.2 there are not util.timer +if util.safehasattr(util, 'timer'): + timer = util.timer +elif util.safehasattr(time, "perf_counter"): + timer = time.perf_counter +elif getattr(pycompat, 'osname', os.name) == 'nt': + timer = time.clock +else: + timer = time.time + _pack = struct.pack _unpack = struct.unpack _calcsize = struct.calcsize @@ -214,6 +228,7 @@ initialsamplesize=100, fullsamplesize=200): missing = set() + starttime = timer() heads = local.revs('heads(%ld)', probeset) local.stablerange.warmup(local) @@ -241,6 +256,7 @@ entry = (h, 0) addentry(entry) + local.obsstore.rangeobshashcache.update(local) querycount = 0 ui.progress(_("comparing obsmarker with other"), querycount) overflow = [] @@ -300,6 +316,12 @@ ui.progress(_("comparing obsmarker with other"), querycount) ui.progress(_("comparing obsmarker with other"), None) local.obsstore.rangeobshashcache.save(local) + duration = timer() - starttime + logmsg = ('obsdiscovery, %d/%d mismatch' + ' - %d obshashrange queries in %.4f seconds\n') + logmsg %= (len(missing), len(probeset), querycount, duration) + ui.log('evoext-obsdiscovery', logmsg) + ui.debug(logmsg) return sorted(missing) def _queryrange(ui, repo, remote, allentries): @@ -342,6 +364,7 @@ linetemplate = '%12d %12s %12d %12d %12d %12s\n' headertemplate = linetemplate.replace('d', 's') ui.status(headertemplate % headers) + repo.obsstore.rangeobshashcache.update(repo) for r in ranges: d = (r[0], s(cl.node(r[0])), @@ -392,10 +415,11 @@ _sqliteschema = [ """CREATE TABLE meta(schemaversion INTEGER NOT NULL, + tiprev INTEGER NOT NULL, + tipnode BLOB NOT NULL, nbobsmarker INTEGER NOT NULL, - obstipdata BLOB NOT NULL, - tiprev INTEGER NOT NULL, - tipnode BLOB NOT NULL + obssize BLOB NOT NULL, + obskey BLOB NOT NULL );""", """CREATE TABLE obshashrange(rev INTEGER NOT NULL, idx INTEGER NOT NULL, @@ -404,53 +428,132 @@ "CREATE INDEX range_index ON obshashrange(rev, idx);", ] _queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND name='meta';" -_newmeta = """INSERT INTO meta (schemaversion, nbobsmarker, obstipdata, tiprev, tipnode) - VALUES (?,?,?,?,?);""" +_clearmeta = """DELETE FROM meta;""" +_newmeta = """INSERT INTO meta (schemaversion, tiprev, tipnode, nbobsmarker, obssize, obskey) + VALUES (?,?,?,?,?,?);""" _updateobshash = "INSERT INTO obshashrange(rev, idx, obshash) VALUES (?,?,?);" -_querymeta = "SELECT schemaversion, nbobsmarker, obstipdata, tiprev, tipnode FROM meta;" +_querymeta = "SELECT schemaversion, tiprev, tipnode, nbobsmarker, obssize, obskey FROM meta;" _queryobshash = "SELECT obshash FROM obshashrange WHERE (rev = ? AND idx = ?);" -class _obshashcache(dict): +_reset = "DELETE FROM obshashrange;" + +class _obshashcache(obscache.dualsourcecache): - _schemaversion = 0 + _schemaversion = 1 + + _cachename = 'evo-ext-obshashrange' # used for error message def __init__(self, repo): super(_obshashcache, self).__init__() - self._path = repo.vfs.join('cache/evoext_obshashrange_v0.sqlite') + self._vfs = repo.vfs + self._path = repo.vfs.join('cache/evoext_obshashrange_v1.sqlite') self._new = set() self._valid = True self._repo = weakref.ref(repo.unfiltered()) # cache status self._ondiskcachekey = None + self._data = {} - def clear(self): - self._valid = False - super(_obshashcache, self).clear() + def clear(self, reset=False): + super(_obshashcache, self).clear(reset=reset) + self._data.clear() self._new.clear() + if reset: + self._valid = False + if '_con' in vars(self): + del self._con def get(self, rangeid): - value = super(_obshashcache, self).get(rangeid) + # revision should be covered by the tiprev + # + # XXX there are issue with cache warming, we hack around it for now + if not getattr(self, '_updating', False): + if self._cachekey[0] < rangeid[0]: + msg = ('using unwarmed obshashrangecache (%s %s)' + % (rangeid[0], self._cachekey[0])) + raise error.ProgrammingError(msg) + + value = self._data.get(rangeid) if value is None and self._con is not None: nrange = (rangeid[0], rangeid[1]) obshash = self._con.execute(_queryobshash, nrange).fetchone() if obshash is not None: value = obshash[0] + self._data[rangeid] = value return value def __setitem__(self, rangeid, obshash): self._new.add(rangeid) - super(_obshashcache, self).__setitem__(rangeid, obshash) + self._data[rangeid] = obshash + + def _updatefrom(self, repo, revs, obsmarkers): + """override this method to update your cache data incrementally + + revs: list of new revision in the changelog + obsmarker: list of new obsmarkers in the obsstore + """ + # XXX for now, we'll not actually update the cache, but we'll be + # smarter at invalidating it. + # + # 1) new revisions does not get their entry updated (not update) + # 2) if we detect markers affecting non-new revision we reset the cache + + self._updating = True + + setrevs = set(revs) + rev = repo.changelog.nodemap.get + # if we have a new markers affecting a node already covered by the + # cache, we must abort. + affected = set() + for m in obsmarkers: + # check successors and parent + for l in (m[1], m[5]): + if l is None: + continue + for p in l: + r = rev(p) + if r is not None and r not in setrevs: + # XXX should check < min(setrevs) or tiprevs + affected.add(r) - def _cachekey(self, repo): - # XXX for now the cache is very volatile, but this is still a win - nbobsmarker = len(repo.obsstore._all) - if nbobsmarker: - tipdata = obsolete._fm1encodeonemarker(repo.obsstore._all[-1]) - else: - tipdata = node.nullid - tiprev = len(repo.changelog) - 1 - tipnode = repo.changelog.node(tiprev) - return (self._schemaversion, nbobsmarker, tipdata, tiprev, tipnode) + if affected: + repo.ui.log('evoext-cache', 'obshashcache reset - ' + 'new markers affect cached ranges\n') + # XXX the current reset is too strong we could just drop the affected range + con = self._con + if con is not None: + con.execute(_reset) + # rewarm the whole cache + stop = self._cachekey[0] # tiprev + if revs: + stop = max(revs) + if 0 <= stop: + revs = repo.changelog.revs(stop=stop) + + # warm the cache for the new revs + for r in revs: + _obshashrange(repo, (r, 0)) + + del self._updating + + @property + def _fullcachekey(self): + return (self._schemaversion, ) + self._cachekey + + def load(self, repo): + if self._con is None: + self._cachekey = self.emptykey + self._ondiskcachekey = self.emptykey + assert self._cachekey is not None + + def _db(self): + try: + util.makedirs(self._vfs.dirname(self._path)) + except OSError: + return None + con = sqlite3.connect(self._path) + con.text_factory = str + return con @util.propertycache def _con(self): @@ -459,25 +562,27 @@ repo = self._repo() if repo is None: return None - cachekey = self._cachekey(repo) - con = sqlite3.connect(self._path) - con.text_factory = str + con = self._db() + if con is None: + return None cur = con.execute(_queryexist) if cur.fetchone() is None: self._valid = False return None meta = con.execute(_querymeta).fetchone() - if meta != cachekey: + if meta is None or meta[0] != self._schemaversion: self._valid = False return None - self._ondiskcachekey = meta + self._cachekey = self._ondiskcachekey = meta[1:] return con def save(self, repo): + if self._cachekey is None: + return + if self._cachekey == self._ondiskcachekey and not self._new: + return repo = repo.unfiltered() try: - if not self._new: - return with repo.lock(): self._save(repo) except error.LockError: @@ -493,32 +598,38 @@ if '_con' in vars(self): del self._con - con = sqlite3.connect(self._path) - con.text_factory = str + con = self._db() + if con is None: + repo.ui.log('evoext-cache', 'unable to write obshashrange cache' + ' - cannot create database') + return with con: for req in _sqliteschema: con.execute(req) - con.execute(_newmeta, self._cachekey(repo)) + con.execute(_newmeta, self._fullcachekey) else: con = self._con if self._ondiskcachekey is not None: meta = con.execute(_querymeta).fetchone() - if meta != self._ondiskcachekey: + if meta[1:] != self._ondiskcachekey: # drifting is currently an issue because this means another # process might have already added the cache line we are about # to add. This will confuse sqlite msg = _('obshashrange cache: skipping write, ' 'database drifted under my feet\n') - data = (meta[2], meta[1], self._ondisktiprev, self._ondisktipnode) + data = (meta[2], meta[1], self._ondiskcachekey[0], self._ondiskcachekey[1]) repo.ui.warn(msg) - data = ((rangeid[0], rangeid[1], self[rangeid]) for rangeid in self._new) + return + data = ((rangeid[0], rangeid[1], self.get(rangeid)) for rangeid in self._new) con.executemany(_updateobshash, data) - cachekey = self._cachekey(repo) + cachekey = self._fullcachekey + con.execute(_clearmeta) # remove the older entry con.execute(_newmeta, cachekey) con.commit() self._new.clear() - self._ondiskcachekey = cachekey + self._ondiskcachekey = self._cachekey + self._valid = True @eh.wrapfunction(obsolete.obsstore, '_addmarkers') def _addmarkers(orig, obsstore, *args, **kwargs): @@ -549,10 +660,31 @@ class obshashrepo(repo.__class__): @localrepo.unfilteredmethod def destroyed(self): - if 'stablerange' in vars(self): - del self.stablerange + if 'obsstore' in vars(self): + self.obsstore.rangeobshashcache.clear() super(obshashrepo, self).destroyed() + def transaction(self, *args, **kwargs): + tr = super(obshashrepo, self).transaction(*args, **kwargs) + reporef = weakref.ref(self) + + def _warmcache(tr): + repo = reporef() + if repo is None: + return + if not repo.ui.configbool('experimental', 'obshashrange', False): + return + repo = repo.unfiltered() + # As pointed in 'obscache.update', we could have the changelog + # and the obsstore in charge of updating the cache when new + # items goes it. The tranaction logic would then only be + # involved for the 'pending' and final writing on disk. + self.obsstore.rangeobshashcache.update(repo) + self.obsstore.rangeobshashcache.save(repo) + + tr.addpostclose('warmcache-20-obscacherange', _warmcache) + return tr + repo.__class__ = obshashrepo ### wire protocol commands @@ -570,6 +702,7 @@ if maxrev is not None: repo.stablerange.warmup(repo, upto=maxrev) result = [] + repo.obsstore.rangeobshashcache.update(repo) for r in ranges: if r[0] is None: result.append(node.wdirid)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/obshistory.py Thu May 18 23:12:52 2017 +0200 @@ -0,0 +1,357 @@ +# Code dedicated to display and exploration of the obsolescence history +# +# This module content aims at being upstreamed enventually. +# +# Copyright 2017 Octobus SAS <contact@octobus.net> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from mercurial import ( + cmdutil, + commands, + error, + graphmod, + node as nodemod, + scmutil, +) + +from mercurial.i18n import _ + +from . import ( + exthelper, +) + +eh = exthelper.exthelper() + +@eh.command( + 'olog', + [('G', 'graph', True, _("show the revision DAG")), + ('r', 'rev', [], _('show the specified revision or revset'), _('REV')) + ] + commands.formatteropts, + _('hg olog [OPTION]... [REV]')) +def cmdobshistory(ui, repo, *revs, **opts): + """show the obsolescence history of the specified revisions. + + If no revision range is specified, we display the log for the current + working copy parent. + + By default this command prints the selected revisions and all its + precursors. For precursors pointing on existing revisions in the repository, + it will display revisions node id, revision number and the first line of the + description. For precursors pointing on non existing revisions in the + repository (that can happen when exchanging obsolescence-markers), display + only the node id. + + In both case, for each node, its obsolescence marker will be displayed with + the obsolescence operation (rewritten or pruned) in addition of the user and + date of the operation. + + The output is a graph by default but can deactivated with the option '--no- + graph'. + + 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete, + and '+' represents a fork where the changeset from the lines below is a + parent of the 'o' merge on the same line. + + Paths in the DAG are represented with '|', '/' and so forth. + + Returns 0 on success. + """ + revs = list(revs) + opts['rev'] + if not revs: + revs = ['.'] + revs = scmutil.revrange(repo, revs) + + if opts['graph']: + return _debugobshistorygraph(ui, repo, revs, opts) + + fm = ui.formatter('debugobshistory', opts) + revs.reverse() + _debugobshistorysingle(fm, repo, revs) + + fm.end() + +class obsmarker_printer(cmdutil.changeset_printer): + """show (available) information about a node + + We display the node, description (if available) and various information + about obsolescence markers affecting it""" + + def show(self, ctx, copies=None, matchfn=None, **props): + if self.buffered: + self.ui.pushbuffer(labeled=True) + + changenode = ctx.node() + + fm = self.ui.formatter('debugobshistory', props) + _debugobshistorydisplaynode(fm, self.repo, changenode) + + succs = self.repo.obsstore.successors.get(changenode, ()) + + markerfm = fm.nested("debugobshistory.markers") + for successor in sorted(succs): + _debugobshistorydisplaymarker(markerfm, self.repo, successor) + markerfm.end() + + markerfm.plain('\n') + + self.hunk[ctx.node()] = self.ui.popbuffer() + else: + ### graph output is buffered only + msg = 'cannot be used outside of the graphlog (yet)' + raise error.ProgrammingError(msg) + + def flush(self, ctx): + ''' changeset_printer has some logic around buffering data + in self.headers that we don't use + ''' + pass + +class missingchangectx(object): + ''' a minimal object mimicking changectx for change contexts + references by obs markers but not available locally ''' + + def __init__(self, repo, nodeid): + self._repo = repo + self._node = nodeid + + def node(self): + return self._node + + def obsolete(self): + # If we don't have it locally, it's obsolete + return True + +def cyclic(graph): + """Return True if the directed graph has a cycle. + The graph must be represented as a dictionary mapping vertices to + iterables of neighbouring vertices. For example: + + >>> cyclic({1: (2,), 2: (3,), 3: (1,)}) + True + >>> cyclic({1: (2,), 2: (3,), 3: (4,)}) + False + + Taken from: https://codereview.stackexchange.com/a/86067 + + """ + visited = set() + o = object() + path = [o] + path_set = set(path) + stack = [iter(graph)] + while stack: + for v in sorted(stack[-1]): + if v in path_set: + path_set.remove(o) + return path_set + elif v not in visited: + visited.add(v) + path.append(v) + path_set.add(v) + stack.append(iter(graph.get(v, ()))) + break + else: + path_set.remove(path.pop()) + stack.pop() + return False + +def _obshistorywalker(repo, revs): + """ Directly inspired by graphmod.dagwalker, + walk the obs marker tree and yield + (id, CHANGESET, ctx, [parentinfo]) tuples + """ + + # Get the list of nodes and links between them + candidates, nodesucc, nodeprec = _obshistorywalker_links(repo, revs) + + # Shown, set of nodes presents in items + shown = set() + + def isvalidcandidate(candidate): + """ Function to filter candidates, check the candidate succ are + in shown set + """ + return nodesucc.get(candidate, set()).issubset(shown) + + # While we have some nodes to show + while candidates: + + # Filter out candidates, returns only nodes with all their successors + # already shown + validcandidates = filter(isvalidcandidate, candidates) + + # If we likely have a cycle + if not validcandidates: + cycle = cyclic(nodesucc) + assert cycle + + # Then choose a random node from the cycle + breaknode = sorted(cycle)[0] + # And display it by force + repo.ui.debug('obs-cycle detected, forcing display of %s\n' + % nodemod.short(breaknode)) + validcandidates = [breaknode] + + # Display all valid candidates + for cand in sorted(validcandidates): + # Remove candidate from candidates set + candidates.remove(cand) + # And remove it from nodesucc in case of future cycle detected + try: + del nodesucc[cand] + except KeyError: + pass + + shown.add(cand) + + # Add the right changectx class + if cand in repo: + changectx = repo[cand] + else: + changectx = missingchangectx(repo, cand) + + childrens = [(graphmod.PARENT, x) for x in nodeprec.get(cand, ())] + yield (cand, 'M', changectx, childrens) + +def _obshistorywalker_links(repo, revs): + """ Iterate the obs history tree starting from revs, traversing + each revision precursors recursively. + Return a tuple of: + - The list of node crossed + - The dictionnary of each node successors, values are a set + - The dictionnary of each node precursors, values are a list + """ + precursors = repo.obsstore.precursors + nodec = repo.changelog.node + + # Parents, set of parents nodes seen during walking the graph for node + nodesucc = dict() + # Childrens + nodeprec = dict() + + nodes = [nodec(r) for r in revs] + seen = set(nodes) + + # Iterate on each node + while nodes: + node = nodes.pop() + + precs = precursors.get(node, ()) + + nodeprec[node] = [] + + for prec in sorted(precs): + precnode = prec[0] + + # Mark node as prec successor + nodesucc.setdefault(precnode, set()).add(node) + + # Mark precnode as node precursor + nodeprec[node].append(precnode) + + # Add prec for future processing if not node already processed + if precnode not in seen: + seen.add(precnode) + nodes.append(precnode) + + return sorted(seen), nodesucc, nodeprec + +def _debugobshistorygraph(ui, repo, revs, opts): + displayer = obsmarker_printer(ui, repo.unfiltered(), None, opts, buffered=True) + edges = graphmod.asciiedges + cmdutil.displaygraph(ui, repo, _obshistorywalker(repo.unfiltered(), revs), displayer, edges) + +def _debugobshistorysingle(fm, repo, revs): + """ Display the obsolescence history for a single revision + """ + precursors = repo.obsstore.precursors + successors = repo.obsstore.successors + nodec = repo.changelog.node + nodes = [nodec(r) for r in revs] + + seen = set(nodes) + + while nodes: + ctxnode = nodes.pop() + + _debugobshistorydisplaynode(fm, repo, ctxnode) + + succs = successors.get(ctxnode, ()) + + markerfm = fm.nested("debugobshistory.markers") + for successor in sorted(succs): + _debugobshistorydisplaymarker(markerfm, repo, successor) + markerfm.end() + + precs = precursors.get(ctxnode, ()) + for p in sorted(precs): + # Only show nodes once + if p[0] not in seen: + seen.add(p[0]) + nodes.append(p[0]) + +def _debugobshistorydisplaynode(fm, repo, node): + if node in repo.unfiltered(): + _debugobshistorydisplayctx(fm, repo.unfiltered()[node]) + else: + _debugobshistorydisplaymissingctx(fm, node) + +def _debugobshistorydisplayctx(fm, ctx): + shortdescription = ctx.description().splitlines()[0] + + fm.startitem() + fm.write('debugobshistory.node', '%s', str(ctx), + label="evolve.node") + fm.plain(' ') + + fm.write('debugobshistory.rev', '(%d)', int(ctx), + label="evolve.rev") + fm.plain(' ') + + fm.write('debugobshistory.shortdescription', '%s', shortdescription, + label="evolve.short_description") + fm.plain('\n') + +def _debugobshistorydisplaymissingctx(fm, nodewithoutctx): + hexnode = nodemod.short(nodewithoutctx) + fm.startitem() + fm.write('debugobshistory.node', '%s', hexnode, + label="evolve.node evolve.missing_change_ctx") + fm.plain('\n') + +def _debugobshistorydisplaymarker(fm, repo, marker): + succnodes = marker[1] + date = marker[4] + metadata = dict(marker[3]) + + fm.startitem() + fm.plain(' ') + + # Detect pruned revisions + if len(succnodes) == 0: + verb = 'pruned' + else: + verb = 'rewritten' + + fm.write('debugobshistory.verb', '%s', verb, + label="evolve.verb") + fm.plain(' by ') + + fm.write('debugobshistory.marker_user', '%s', metadata['user'], + label="evolve.user") + fm.plain(' ') + + fm.write('debugobshistory.marker_date', '(%s)', fm.formatdate(date), + label="evolve.date") + + if len(succnodes) > 0: + fm.plain(' as ') + + shortsnodes = (nodemod.short(succnode) for succnode in sorted(succnodes)) + nodes = fm.formatlist(shortsnodes, 'debugobshistory.succnodes', sep=', ') + fm.write('debugobshistory.succnodes', '%s', nodes, + label="evolve.node") + + fm.plain("\n")
--- a/hgext3rd/evolve/serveronly.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/serveronly.py Thu May 18 23:12:52 2017 +0200 @@ -17,6 +17,7 @@ from . import ( exthelper, metadata, + obscache, obsexchange, ) except ValueError as exc: @@ -27,6 +28,7 @@ from evolve import ( exthelper, metadata, + obscache, obsexchange, ) @@ -36,6 +38,7 @@ buglink = metadata.buglink eh = exthelper.exthelper() +eh.merge(obscache.eh) eh.merge(obsexchange.eh) uisetup = eh.final_uisetup extsetup = eh.final_extsetup
--- a/hgext3rd/evolve/stablerange.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/evolve/stablerange.py Thu May 18 23:12:52 2017 +0200 @@ -10,7 +10,9 @@ import collections import heapq import math +import os import sqlite3 +import time import weakref from mercurial import ( @@ -19,6 +21,7 @@ error, localrepo, node as nodemod, + pycompat, scmutil, util, ) @@ -31,6 +34,16 @@ eh = exthelper.exthelper() +# prior to hg-4.2 there are not util.timer +if util.safehasattr(util, 'timer'): + timer = util.timer +elif util.safehasattr(time, "perf_counter"): + timer = time.perf_counter +elif getattr(pycompat, 'osname', os.name) == 'nt': + timer = time.clock +else: + timer = time.time + ################################## ### Stable topological sorting ### ################################## @@ -263,6 +276,7 @@ # # we use the revnumber as an approximation for depth ui = repo.ui + starttime = timer() if upto is None: upto = len(cl) - 1 @@ -308,6 +322,10 @@ self._tiprev = upto self._tipnode = cl.node(upto) + duration = timer() - starttime + repo.ui.log('evoext-cache', 'updated stablerange cache in %.4f seconds\n', + duration) + def depthrev(self, repo, rev): repo = repo.unfiltered() cl = repo.changelog @@ -714,6 +732,7 @@ def __init__(self, repo): super(sqlstablerange, self).__init__() + self._vfs = repo.vfs self._path = repo.vfs.join('cache/evoext_stablerange_v0.sqlite') self._cl = repo.unfiltered().changelog # (okay to keep an old one) self._ondisktiprev = None @@ -777,10 +796,20 @@ self._loaddepth() return super(sqlstablerange, self)._inheritancepoint(*args, **kwargs) + def _db(self): + try: + util.makedirs(self._vfs.dirname(self._path)) + except OSError: + return None + con = sqlite3.connect(self._path) + con.text_factory = str + return con + @util.propertycache def _con(self): - con = sqlite3.connect(self._path) - con.text_factory = str + con = self._db() + if con is None: + return None cur = con.execute(_queryexist) if cur.fetchone() is None: return None @@ -810,8 +839,9 @@ if '_con' in vars(self): del self._con - con = sqlite3.connect(self._path) - con.text_factory = str + con = self._db() + if con is None: + return with con: for req in _sqliteschema: con.execute(req) @@ -902,7 +932,7 @@ # new nodes ! repo.stablerange.warmup(repo) - tr.addpostclose('warmcache-stablerange', _warmcache) + tr.addpostclose('warmcache-10-stablerange', _warmcache) return tr repo.__class__ = stablerangerepo
--- a/hgext3rd/topic/__init__.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/topic/__init__.py Thu May 18 23:12:52 2017 +0200 @@ -100,9 +100,13 @@ 'topic.stack.summary.behindcount': 'cyan', 'topic.stack.summary.behinderror': 'red', 'topic.stack.summary.headcount.multiple': 'yellow', + # default color to help log output and thg + # (first pick I could think off, update as needed + 'log.topic': 'green_background', + 'topic.active': 'green', } -testedwith = '3.9' +testedwith = '4.0.2 4.1.3 4.2' def _contexttopic(self): return self.extra().get(constants.extrakey, '') @@ -157,6 +161,10 @@ if not isinstance(repo, localrepo.localrepository): return # this can be a peer in the ssh case (puzzling) + if repo.ui.config('experimental', 'thg.displaynames', None) is None: + repo.ui.setconfig('experimental', 'thg.displaynames', 'topics', + source='topic-extension') + class topicrepo(repo.__class__): def _restrictcapabilities(self, caps):
--- a/hgext3rd/topic/stack.py Thu May 18 22:53:01 2017 +0200 +++ b/hgext3rd/topic/stack.py Thu May 18 23:12:52 2017 +0200 @@ -15,6 +15,12 @@ trevs = repo.revs("topic(%s) - obsolete()", topic) return _orderrevs(repo, trevs) +def labelsgen(prefix, labelssuffix): + """ Takes a label prefix and a list of suffixes. Returns a string of the prefix + formatted with each suffix separated with a space. + """ + return ' '.join(prefix % suffix for suffix in labelssuffix) + def showstack(ui, repo, topic, opts): fm = ui.formatter('topicstack', opts) prev = None @@ -59,35 +65,44 @@ # super crude initial version for idx, isentry, ctx in entries[::-1]: + + states = [] + iscurrentrevision = repo.revs('%d and parents()', ctx.rev()) + + if iscurrentrevision: + states.append('current') + if not isentry: symbol = '^' - state = 'base' - elif repo.revs('%d and parents()', ctx.rev()): + # "base" is kind of a "ghost" entry + # skip other label for them (no current, no unstable) + states = ['base'] + elif iscurrentrevision: symbol = '@' - state = 'current' elif repo.revs('%d and unstable()', ctx.rev()): symbol = '$' - state = 'unstable' + states.append('unstable') else: symbol = ':' - state = 'clean' + states.append('clean') fm.startitem() fm.data(isentry=isentry) + if idx is None: fm.plain(' ') else: fm.write('topic.stack.index', 't%d', idx, - label='topic.stack.index topic.stack.index.%s' % state) + label='topic.stack.index ' + labelsgen('topic.stack.index.%s', states)) fm.write('topic.stack.state.symbol', '%s', symbol, - label='topic.stack.state topic.stack.state.%s' % state) + label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states)) fm.plain(' ') fm.write('topic.stack.desc', '%s', ctx.description().splitlines()[0], - label='topic.stack.desc topic.stack.desc.%s' % state) - fm.condwrite(state != 'clean' and idx is not None, 'topic.stack.state', - ' (%s)', state, - label='topic.stack.state topic.stack.state.%s' % state) + label='topic.stack.desc ' + labelsgen('topic.stack.desc.%s', states)) + fm.condwrite(states != ['clean'] and idx is not None, 'topic.stack.state', + ' (%s)', fm.formatlist(states, 'topic.stack.state'), + label='topic.stack.state ' + labelsgen('topic.stack.state.%s', states)) fm.plain('\n') - fm.end() + fm.end() def stackdata(repo, topic): """get various data about a stack
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-check-commit.t Thu May 18 23:12:52 2017 +0200 @@ -0,0 +1,22 @@ +#require test-repo + +Enable obsolescence to avoid the warning issue when obsmarker are found + + $ cat << EOF >> $HGRCPATH + > [experimental] + > evolution=all + > EOF + +Go back in the hg repo + + $ cd $TESTDIR/.. + + $ for node in `hg log --rev 'not public() and ::. and not desc("# no-check-commit")' --template '{node|short}\n'`; do + > hg export $node | ${RUNTESTDIR}/../contrib/check-commit > ${TESTTMP}/check-commit.out + > if [ $? -ne 0 ]; then + > echo "Revision $node does not comply with rules" + > echo '------------------------------------------------------' + > cat ${TESTTMP}/check-commit.out + > echo + > fi + > done
--- a/tests/test-discovery-obshashrange.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-discovery-obshashrange.t Thu May 18 23:12:52 2017 +0200 @@ -6,6 +6,9 @@ $ cat << EOF >> $HGRCPATH > [extensions] > hgext3rd.evolve = + > blackbox = + > [defaults] + > blackbox = -l 100 > [experimental] > obshashrange=1 > verbose-obsolescence-exchange=1 @@ -17,7 +20,7 @@ > EOF $ getid() { - > hg log --hidden --template '{node}\n' --rev "$1" + > hg log --hidden --template '{node}\n' --rev "$1" --config 'extensions.blackbox=!' > } $ hg init server @@ -27,6 +30,31 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd server $ hg debugbuilddag '.+7' + $ hg blackbox + * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 0o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (8r, 0o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm .hg/blackbox.log $ hg log -G o 7 4de32a90b66c r7 tip | @@ -57,6 +85,45 @@ dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + $ hg blackbox + * @0000000000000000000000000000000000000000 (*)> log -G (glob) + * @0000000000000000000000000000000000000000 (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @0000000000000000000000000000000000000000 (*)> log -G exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm .hg/blackbox.log $ hg debugobshashrange --subranges --rev tip rev node index size depth obshash 7 4de32a90b66c 0 8 8 38d1e7ad86ea @@ -88,10 +155,30 @@ added 5 changesets with 0 changes to 0 files 3 new obsolescence markers (run 'hg update' to get a working copy) + $ hg -R ../server blackbox + * @0000000000000000000000000000000000000000 (*)> debugobshashrange --subranges --rev tip (glob) + * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobshashrange --subranges --rev tip exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm ../server/.hg/blackbox.log $ hg -R ../server/ debugobsolete --rev ::4 | sort aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + $ rm ../server/.hg/blackbox.log + $ hg blackbox + * @0000000000000000000000000000000000000000 (*)> pull --rev 4 (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 3o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (5r, 3o) (glob) + * @0000000000000000000000000000000000000000 (*)> 5 incoming changes - new heads: bebd167eb94d (glob) + * @0000000000000000000000000000000000000000 (*)> pull --rev 4 exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm .hg/blackbox.log $ hg debugobsolete | sort aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -106,17 +193,75 @@ $ hg add foo $ hg commit -m foo $ hg debugobsolete ffffffffffffffffffffffffffffffffffffffff `getid '.'` - $ hg push -f + $ hg push -f --debug pushing to ssh://user@dummy/server + running python "*/dummyssh" user@dummy 'hg -R server serve --stdio' (glob) + sending hello command + sending between command + remote: 516 + remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + remote: 1 + preparing listkeys for "phases" + sending listkeys command + received listkey for "phases": 58 bytes + query 1; heads + sending batch command searching for changes + taking quick initial sample + query 2; still undecided: 5, sample size is: 5 + sending known command + 2 total queries + preparing listkeys for "phases" + sending listkeys command + received listkey for "phases": 58 bytes + preparing listkeys for "namespaces" + sending listkeys command + received listkey for "namespaces": 40 bytes OBSEXC: computing relevant nodes OBSEXC: looking for common markers in 6 nodes + query 0; add more sample (target 100, current 1) + query 0; sample size is 9, largest range 5 + sending evoext_obshashrange_v0 command + obsdiscovery, 0/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) OBSEXC: computing markers relevant to 1 nodes + checking for updated bookmarks + preparing listkeys for "bookmarks" + sending listkeys command + received listkey for "bookmarks": 0 bytes + 1 changesets found + list of changesets: + 45f8b879de922f6a6e620ba04205730335b6fc7e + sending unbundle command + bundle2-output-bundle: "HG20", 4 parts total + bundle2-output-part: "replycaps" 172 bytes payload + bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload + bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload + bundle2-output-part: "obsmarkers" streamed payload remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files (+1 heads) remote: 1 new obsolescence markers + bundle2-input-bundle: with-transaction + bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported + bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported + bundle2-input-part: "reply:obsmarkers" (params: 0 advisory) supported + bundle2-input-bundle: 2 parts total + preparing listkeys for "phases" + sending listkeys command + received listkey for "phases": 58 bytes + $ hg -R ../server blackbox + * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (1r, 0o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 2 nodes (glob) + * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> 1 incoming changes - new heads: 45f8b879de92 (glob) + * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm ../server/.hg/blackbox.log testing push with extra local markers ===================================== @@ -145,6 +290,14 @@ no changes found remote: 2 new obsolescence markers [1] + $ hg -R ../server blackbox + * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 2o) (glob) + * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm ../server/.hg/blackbox.log $ hg -R ../server/ debugobsolete --rev ::tip | sort 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -152,6 +305,50 @@ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} ffffffffffffffffffffffffffffffffffffffff 45f8b879de922f6a6e620ba04205730335b6fc7e 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + $ hg blackbox + * @0000000000000000000000000000000000000000 (*)> debugobsolete (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> up (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> up exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> add foo (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> add foo exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> commit -m foo (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (1r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated served branch cache in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote served branch cache with 1 labels and 1 nodes (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 0o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> commit -m foo exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete ffffffffffffffffffffffffffffffffffffffff 45f8b879de922f6a6e620ba04205730335b6fc7e (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete ffffffffffffffffffffffffffffffffffffffff 45f8b879de922f6a6e620ba04205730335b6fc7e exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push -f --debug (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push -f --debug exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/6 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push exited True after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log $ hg debugobsolete | sort 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -190,6 +387,27 @@ 3 new obsolescence markers (run 'hg heads' to see heads, 'hg merge' to merge) + $ hg -R ../server blackbox + * @0000000000000000000000000000000000000000 (*)> debugobsolete --rev ::tip (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev ::tip exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaa11111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> -R ../server debugobsolete aaaaaaa11111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbb2222222222bbbbbbbbbbbbb2222222222 bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) + * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> -R ../server debugobsolete bbbbbbb2222222222bbbbbbbbbbbbb2222222222 bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> blackbox (glob) + $ rm ../server/.hg/blackbox.log $ hg -R ../server/ debugobsolete --rev '::6' | sort 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -199,6 +417,25 @@ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r 6 (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/6 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (2r, 0o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (2r, 3o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 3o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 2 incoming changes - new heads: f69452c5b1af (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r 6 exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log $ hg debugobsolete --rev '::6' | sort 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} @@ -209,3 +446,337 @@ cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'} +Test cache behavior +=================== + +Adding markers affecting already used range: +-------------------------------------------- + + $ hg debugobshashrange --subranges --rev 'heads(all())' + rev node index size depth obshash + 7 f69452c5b1af 0 7 7 000000000000 + 5 45f8b879de92 0 6 6 1643971dbe2d + 3 2dc09a01254d 0 4 4 6be48f31976a + 7 f69452c5b1af 4 3 7 000000000000 + 3 2dc09a01254d 2 2 4 9522069ae085 + 5 45f8b879de92 4 2 6 9c26c72819c0 + 1 66f7d451a68b 0 2 2 853c77a32154 + 6 c8d03c1b5e94 4 2 6 ec8a3e92c525 + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 8a2acf8e1cde + 5 45f8b879de92 5 1 6 1a0c08180b65 + 1 66f7d451a68b 1 1 2 853c77a32154 + 4 bebd167eb94d 4 1 5 20a2cc572e4b + 6 c8d03c1b5e94 5 1 6 446c2dc3bce5 + 7 f69452c5b1af 6 1 7 000000000000 + $ hg -R ../server debugobsolete aaaa333333333aaaaa333a3a3a3a3a3a3a3a3a3a `getid 'desc(r1)'` + $ hg -R ../server debugobsolete bb4b4b4b4b4b4b4b44b4b4b4b4b4b4b4b4b4b4b4 `getid 'desc(r3)'` + $ hg pull -r `getid 'desc(r6)'` + pulling from ssh://user@dummy/server + no changes found + OBSEXC: looking for common markers in 7 nodes + OBSEXC: request obsmarkers for 2 common nodes + 2 new obsolescence markers + $ hg debugobshashrange --subranges --rev 'desc("r3")' -R ../server + rev node index size depth obshash + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 1 66f7d451a68b 1 1 2 327c7dd73d29 + $ hg debugobshashrange --subranges --rev 'desc("r3")' + rev node index size depth obshash + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 1 66f7d451a68b 1 1 2 327c7dd73d29 + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev ::6 (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev ::6 exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/7 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 2o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev desc("r3") (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev desc("r3") exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log + +Adding prune markers on existing changeset +------------------------------------------ + + $ hg -R ../server debugobsolete --record-parents `getid 'desc(foo)'` + $ hg pull -r `getid 'desc(r4)'` + pulling from ssh://user@dummy/server + no changes found + OBSEXC: looking for common markers in 5 nodes + OBSEXC: request obsmarkers for 1 common nodes + 1 new obsolescence markers + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 1/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log + $ hg debugobshashrange --subranges --rev 'heads(all())' + rev node index size depth obshash + 7 f69452c5b1af 0 7 7 000000000000 + 5 45f8b879de92 0 6 6 b8a4206b0fc6 + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 7 f69452c5b1af 4 3 7 000000000000 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 5 45f8b879de92 4 2 6 31fc49d36a59 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 6 c8d03c1b5e94 4 2 6 89755fd39e6d + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 5 45f8b879de92 5 1 6 1a0c08180b65 + 1 66f7d451a68b 1 1 2 327c7dd73d29 + 4 bebd167eb94d 4 1 5 b21465ecb790 + 6 c8d03c1b5e94 5 1 6 446c2dc3bce5 + 7 f69452c5b1af 6 1 7 000000000000 + +Recover after rollback + + $ hg pull + pulling from ssh://user@dummy/server + searching for changes + OBSEXC: looking for common markers in 8 nodes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 0 files + 1 new obsolescence markers + (run 'hg update' to get a working copy) + $ hg rollback + repository tip rolled back to revision 7 (undo pull) + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 0o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> rollback (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated base branch cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote base branch cache with 1 labels and 2 nodes (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> rollback exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log + $ hg debugobshashrange --subranges --rev 'heads(all())' + rev node index size depth obshash + 7 f69452c5b1af 0 7 7 000000000000 + 5 45f8b879de92 0 6 6 b8a4206b0fc6 + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 7 f69452c5b1af 4 3 7 000000000000 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 5 45f8b879de92 4 2 6 31fc49d36a59 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 6 c8d03c1b5e94 4 2 6 89755fd39e6d + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 5 45f8b879de92 5 1 6 1a0c08180b65 + 1 66f7d451a68b 1 1 2 327c7dd73d29 + 4 bebd167eb94d 4 1 5 b21465ecb790 + 6 c8d03c1b5e94 5 1 6 446c2dc3bce5 + 7 f69452c5b1af 6 1 7 000000000000 + $ hg pull + pulling from ssh://user@dummy/server + searching for changes + OBSEXC: looking for common markers in 8 nodes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 0 files + 1 new obsolescence markers + (run 'hg update' to get a working copy) + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-obshashrange cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 12o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-obscache cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (9r, 12o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) + $ rm .hg/blackbox.log + $ hg debugobshashrange --subranges --rev 'heads(all())' + rev node index size depth obshash + 8 4de32a90b66c 0 8 8 c7f1f7e9925b + 5 45f8b879de92 0 6 6 b8a4206b0fc6 + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 8 4de32a90b66c 4 4 8 c681c3e58c27 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 5 45f8b879de92 4 2 6 31fc49d36a59 + 8 4de32a90b66c 6 2 8 033544c939f0 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 6 c8d03c1b5e94 4 2 6 89755fd39e6d + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 5 45f8b879de92 5 1 6 1a0c08180b65 + 8 4de32a90b66c 7 1 8 033544c939f0 + 1 66f7d451a68b 1 1 2 327c7dd73d29 + 4 bebd167eb94d 4 1 5 b21465ecb790 + 6 c8d03c1b5e94 5 1 6 446c2dc3bce5 + 7 f69452c5b1af 6 1 7 000000000000 + +Recover after stripping (in the middle of the repo) + +We strip a branch that is not the tip of the reporiosy so part of the affected +revision are reapplied after the target is stripped. + + $ hg log -G + o 8 4de32a90b66c r7 tip + | + o 7 f69452c5b1af r6 + | + o 6 c8d03c1b5e94 r5 + | + | @ 5 45f8b879de92 foo + |/ + o 4 bebd167eb94d r4 + | + o 3 2dc09a01254d r3 + | + o 2 01241442b3c2 r2 + | + o 1 66f7d451a68b r1 + | + o 0 1ea73414a91b r0 + + $ hg --config extensions.strip= strip -r 'desc("foo")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + saved backup bundle to $TESTTMP/client/.hg/strip-backup/45f8b879de92-94c82517-backup.hg (glob) + $ hg log -G + o 7 4de32a90b66c r7 tip + | + o 6 f69452c5b1af r6 + | + o 5 c8d03c1b5e94 r5 + | + @ 4 bebd167eb94d r4 + | + o 3 2dc09a01254d r3 + | + o 2 01241442b3c2 r2 + | + o 1 66f7d451a68b r1 + | + o 0 1ea73414a91b r0 + + $ hg pull + pulling from ssh://user@dummy/server + searching for changes + OBSEXC: looking for common markers in 8 nodes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + (run 'hg heads' to see heads, 'hg merge' to merge) + $ hg log -G + o 8 45f8b879de92 foo tip + | + | o 7 4de32a90b66c r7 + | | + | o 6 f69452c5b1af r6 + | | + | o 5 c8d03c1b5e94 r5 + |/ + @ 4 bebd167eb94d r4 + | + o 3 2dc09a01254d r3 + | + o 2 01241442b3c2 r2 + | + o 1 66f7d451a68b r1 + | + o 0 1ea73414a91b r0 + + $ hg blackbox + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev heads(all()) exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip -r desc("foo") (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> saved backup bundle to $TESTTMP/client/.hg/strip-backup/45f8b879de92-94c82517-backup.hg (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obshashrange cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 13o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obscache cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (5r, 13o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (3r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (3r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 1 nodes (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> 3 incoming changes - new heads: 4de32a90b66c (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> --config extensions.strip= strip -r desc("foo") exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> pull (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (1r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated served branch cache in *.???? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote served branch cache with 1 labels and 2 nodes (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> 1 incoming changes - new heads: 45f8b879de92 (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> pull exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G exited 0 after *.?? seconds (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> blackbox (glob) + $ rm .hg/blackbox.log + $ hg debugobshashrange --subranges --rev 'heads(all())' + rev node index size depth obshash + 7 4de32a90b66c 0 8 8 c7f1f7e9925b + 8 45f8b879de92 0 6 6 b8a4206b0fc6 + 3 2dc09a01254d 0 4 4 8932bf980bb4 + 7 4de32a90b66c 4 4 8 c681c3e58c27 + 3 2dc09a01254d 2 2 4 ce1937ca1278 + 8 45f8b879de92 4 2 6 31fc49d36a59 + 7 4de32a90b66c 6 2 8 033544c939f0 + 1 66f7d451a68b 0 2 2 327c7dd73d29 + 5 c8d03c1b5e94 4 2 6 89755fd39e6d + 2 01241442b3c2 2 1 3 1ed3c61fb39a + 0 1ea73414a91b 0 1 1 000000000000 + 3 2dc09a01254d 3 1 4 26f996446ecb + 8 45f8b879de92 5 1 6 1a0c08180b65 + 7 4de32a90b66c 7 1 8 033544c939f0 + 1 66f7d451a68b 1 1 2 327c7dd73d29 + 4 bebd167eb94d 4 1 5 b21465ecb790 + 5 c8d03c1b5e94 5 1 6 446c2dc3bce5 + 6 f69452c5b1af 6 1 7 000000000000 +
--- a/tests/test-evolve-obshistory.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-evolve-obshistory.t Thu May 18 23:12:52 2017 +0200 @@ -26,9 +26,11 @@ $ mkcommit ROOT $ mkcommit A0 $ echo 42 >> A0 - $ hg amend -m "A1" + $ hg amend -m "A1 + > + > Better commit message" $ hg log --hidden -G - @ changeset: 3:a468dc9b3633 + @ changeset: 3:4ae3a4151de9 | tag: tip | parent: 0:ea207398892e | user: test @@ -52,7 +54,64 @@ Actual test ----------- - + $ hg olog 4ae3a4151de9 + @ 4ae3a4151de9 (3) A1 + | + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 4ae3a4151de9 (glob) + + $ hg olog 4ae3a4151de9 --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "4ae3a4151de9", + "debugobshistory.rev": 3, + "debugobshistory.shortdescription": "A1" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "4ae3a4151de9" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] + $ hg olog --hidden 471f378eab4c + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 4ae3a4151de9 (glob) + + $ hg olog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "4ae3a4151de9" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] $ hg update 471f378eab4c abort: hidden revision '471f378eab4c'! (use --hidden to access hidden revisions) @@ -60,7 +119,7 @@ $ hg update --hidden "desc(A0)" 1 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory parent is obsolete! (471f378eab4c) - (use 'hg evolve' to update to its successor: a468dc9b3633) + (use 'hg evolve' to update to its successor: 4ae3a4151de9) Test output with pruned commit ============================== @@ -94,10 +153,61 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory now at 471f378eab4c 1 changesets pruned + $ hg log --hidden -G + x changeset: 2:0dec01379d3b + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B0 + | + @ changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + Actual test ----------- + $ hg olog 'desc(B0)' --hidden + x 0dec01379d3b (2) B0 + pruned by test (*20*) (glob) + + $ hg olog 'desc(B0)' --hidden --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.verb": "pruned" + } + ], + "debugobshistory.node": "0dec01379d3b", + "debugobshistory.rev": 2, + "debugobshistory.shortdescription": "B0" + } + ] + $ hg olog 'desc(A0)' + @ 471f378eab4c (1) A0 + + $ hg olog 'desc(A0)' --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] $ hg up 1 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg up 0dec01379d3b @@ -196,6 +306,59 @@ Actual test ----------- +Check that debugobshistory on splitted commit show both targets + $ hg olog 471597cad322 --hidden + x 471597cad322 (1) A0 + rewritten by test (*20*) as 337fec4d2edc, f257fde29c7a (glob) + + $ hg olog 471597cad322 --hidden --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "337fec4d2edc", + "f257fde29c7a" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471597cad322", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] +Check that debugobshistory on the first successor after split show +the revision plus the splitted one + $ hg olog 337fec4d2edc + o 337fec4d2edc (2) A0 + | + x 471597cad322 (1) A0 + rewritten by test (*20*) as 337fec4d2edc, f257fde29c7a (glob) + +Check that debugobshistory on the second successor after split show +the revision plus the splitted one + $ hg olog f257fde29c7a + @ f257fde29c7a (3) A0 + | + x 471597cad322 (1) A0 + rewritten by test (*20*) as 337fec4d2edc, f257fde29c7a (glob) + +Check that debugobshistory on both successors after split show +a coherent graph + $ hg olog 'f257fde29c7a+337fec4d2edc' + o 337fec4d2edc (2) A0 + | + | @ f257fde29c7a (3) A0 + |/ + x 471597cad322 (1) A0 + rewritten by test (*20*) as 337fec4d2edc, f257fde29c7a (glob) + $ hg update 471597cad322 abort: hidden revision '471597cad322'! (use --hidden to access hidden revisions) @@ -358,6 +521,83 @@ Actual test ----------- + $ hg olog de7290d8b885 --hidden + x de7290d8b885 (1) A0 + rewritten by test (*20*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + + $ hg olog de7290d8b885 --hidden --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "1ae8bc733a14", + "337fec4d2edc", + "c7f044602e9b", + "f257fde29c7a" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "de7290d8b885", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] + $ hg olog c7f044602e9b + @ c7f044602e9b (5) A0 + | + x de7290d8b885 (1) A0 + rewritten by test (*20*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + + $ hg olog c7f044602e9b --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "c7f044602e9b", + "debugobshistory.rev": 5, + "debugobshistory.shortdescription": "A0" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "1ae8bc733a14", + "337fec4d2edc", + "c7f044602e9b", + "f257fde29c7a" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "de7290d8b885", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] +Check that debugobshistory on all heads show a coherent graph + $ hg olog 2::5 + o 1ae8bc733a14 (4) A0 + | + | o 337fec4d2edc (2) A0 + |/ + | @ c7f044602e9b (5) A0 + |/ + | o f257fde29c7a (3) A0 + |/ + x de7290d8b885 (1) A0 + rewritten by test (*20*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob) + $ hg update de7290d8b885 abort: hidden revision 'de7290d8b885'! (use --hidden to access hidden revisions) @@ -424,6 +664,74 @@ Actual test ----------- +Check that debugobshistory on the first folded revision show only +the revision with the target + $ hg olog --hidden 471f378eab4c + x 471f378eab4c (1) A0 + rewritten by test (*20*) as eb5a0daa2192 (glob) + +Check that debugobshistory on the second folded revision show only +the revision with the target + $ hg olog --hidden 0dec01379d3b + x 0dec01379d3b (2) B0 + rewritten by test (*20*) as eb5a0daa2192 (glob) + +Check that debugobshistory on the successor revision show a coherent +graph + $ hg olog eb5a0daa2192 + @ eb5a0daa2192 (3) C0 + |\ + x | 0dec01379d3b (2) B0 + / rewritten by test (*20*) as eb5a0daa2192 (glob) + | + x 471f378eab4c (1) A0 + rewritten by test (*20*) as eb5a0daa2192 (glob) + + $ hg olog eb5a0daa2192 --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "eb5a0daa2192", + "debugobshistory.rev": 3, + "debugobshistory.shortdescription": "C0" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "eb5a0daa2192" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "eb5a0daa2192" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "0dec01379d3b", + "debugobshistory.rev": 2, + "debugobshistory.shortdescription": "B0" + } + ] $ hg update 471f378eab4c abort: hidden revision '471f378eab4c'! (use --hidden to access hidden revisions) @@ -507,6 +815,117 @@ Actual test ----------- +Check that debugobshistory on the divergent revision show both destinations + $ hg olog --hidden 471f378eab4c + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 65b757b745b9 (glob) + rewritten by test (*20*) as fdf9bde5129a (glob) + + $ hg olog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "65b757b745b9" + ], + "debugobshistory.verb": "rewritten" + }, + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "fdf9bde5129a" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] +Check that debugobshistory on the first diverged revision show the revision +and the diverent one + $ hg olog fdf9bde5129a + o fdf9bde5129a (2) A1 + | + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 65b757b745b9 (glob) + rewritten by test (*20*) as fdf9bde5129a (glob) + +Check that debugobshistory on the second diverged revision show the revision +and the diverent one + $ hg olog 65b757b745b9 + @ 65b757b745b9 (3) A2 + | + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 65b757b745b9 (glob) + rewritten by test (*20*) as fdf9bde5129a (glob) + +Check that debugobshistory on the both diverged revision show a coherent +graph + $ hg olog '65b757b745b9+fdf9bde5129a' + @ 65b757b745b9 (3) A2 + | + | o fdf9bde5129a (2) A1 + |/ + x 471f378eab4c (1) A0 + rewritten by test (*20*) as 65b757b745b9 (glob) + rewritten by test (*20*) as fdf9bde5129a (glob) + + $ hg olog '65b757b745b9+fdf9bde5129a' --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "65b757b745b9", + "debugobshistory.rev": 3, + "debugobshistory.shortdescription": "A2" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "65b757b745b9" + ], + "debugobshistory.verb": "rewritten" + }, + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "fdf9bde5129a" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + }, + { + "debugobshistory.markers": [], + "debugobshistory.node": "fdf9bde5129a", + "debugobshistory.rev": 2, + "debugobshistory.shortdescription": "A1" + } + ] $ hg update 471f378eab4c abort: hidden revision '471f378eab4c'! (use --hidden to access hidden revisions) @@ -515,3 +934,630 @@ 0 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory parent is obsolete! (471f378eab4c) (471f378eab4c has diverged, use 'hg evolve -list --divergent' to resolve the issue) + +Test output with amended + folded commit +======================================== + +Test setup +---------- + + $ hg init $TESTTMP/local-amend-fold + $ cd $TESTTMP/local-amend-fold + $ mkcommit ROOT + $ mkcommit A0 + $ mkcommit B0 + $ hg amend -m "B1" + $ hg log --hidden -G + @ changeset: 3:b7ea6d14e664 + | tag: tip + | parent: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B1 + | + | x changeset: 2:0dec01379d3b + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B0 + | + o changeset: 1:471f378eab4c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg fold --exact -r 'desc(A0) + desc(B1)' --date "0 0" -m "C0" + 2 changesets folded + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg log --hidden -G + @ changeset: 4:eb5a0daa2192 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + | x changeset: 3:b7ea6d14e664 + | | parent: 1:471f378eab4c + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B1 + | | + | | x changeset: 2:0dec01379d3b + | |/ user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | summary: B0 + | | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + Actual test + ----------- + +Check that debugobshistory on head show a coherent graph + $ hg olog eb5a0daa2192 + @ eb5a0daa2192 (4) C0 + |\ + x | 471f378eab4c (1) A0 + / rewritten by test (*20*) as eb5a0daa2192 (glob) + | + x b7ea6d14e664 (3) B1 + | rewritten by test (*20*) as eb5a0daa2192 (glob) + | + x 0dec01379d3b (2) B0 + rewritten by test (*20*) as b7ea6d14e664 (glob) + + $ hg olog eb5a0daa2192 --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [], + "debugobshistory.node": "eb5a0daa2192", + "debugobshistory.rev": 4, + "debugobshistory.shortdescription": "C0" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "eb5a0daa2192" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "b7ea6d14e664", + "debugobshistory.rev": 3, + "debugobshistory.shortdescription": "B1" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "b7ea6d14e664" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "0dec01379d3b", + "debugobshistory.rev": 2, + "debugobshistory.shortdescription": "B0" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 (glob) + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "eb5a0daa2192" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "471f378eab4c", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A0" + } + ] + $ hg update 471f378eab4c + abort: hidden revision '471f378eab4c'! + (use --hidden to access hidden revisions) + [255] + $ hg update --hidden 'desc(A0)' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (471f378eab4c) + (use 'hg evolve' to update to its successor: eb5a0daa2192) + $ hg update --hidden 0dec01379d3b + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (0dec01379d3b) + (use 'hg evolve' to update to its successor: eb5a0daa2192) + $ hg update 0dec01379d3b + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (0dec01379d3b) + (use 'hg evolve' to update to its successor: eb5a0daa2192) + $ hg update --hidden 'desc(B0)' + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (0dec01379d3b) + (use 'hg evolve' to update to its successor: eb5a0daa2192) + +Test output with pushed and pulled obs markers +============================================== + +Test setup +---------- + + $ hg init $TESTTMP/local-remote-markers-1 + $ cd $TESTTMP/local-remote-markers-1 + $ mkcommit ROOT + $ mkcommit A0 + $ hg log --hidden -G + @ changeset: 1:471f378eab4c + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg clone $TESTTMP/local-remote-markers-1 $TESTTMP/local-remote-markers-2 + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd $TESTTMP/local-remote-markers-2 + $ hg log --hidden -G + @ changeset: 1:471f378eab4c + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ cd $TESTTMP/local-remote-markers-1 + $ hg amend -m "A1" + $ hg amend -m "A2" + $ hg log --hidden -G + @ changeset: 3:7a230b46bf61 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A2 + | + | x changeset: 2:fdf9bde5129a + |/ parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A1 + | + | x changeset: 1:471f378eab4c + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + Actual test + ----------- + + $ hg olog 7a230b46bf61 + @ 7a230b46bf61 (3) A2 + | + x fdf9bde5129a (2) A1 + | rewritten by test (*20*) as 7a230b46bf61 (glob) + | + x 471f378eab4c (1) A0 + rewritten by test (*20*) as fdf9bde5129a (glob) + + $ cd $TESTTMP/local-remote-markers-2 + $ hg pull + pulling from $TESTTMP/local-remote-markers-1 + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 1 files (+1 heads) + 2 new obsolescence markers + (run 'hg heads' to see heads, 'hg merge' to merge) + working directory parent is obsolete! (471f378eab4c) + (use 'hg evolve' to update to its successor: 7a230b46bf61) +Check that debugobshistory works with markers pointing to missing local +changectx + $ hg olog 7a230b46bf61 + o 7a230b46bf61 (2) A2 + | + x fdf9bde5129a + | rewritten by test (*20*) as 7a230b46bf61 (glob) + | + @ 471f378eab4c (1) A0 + rewritten by test (*20*) as fdf9bde5129a (glob) + + $ hg olog 7a230b46bf61 --color=debug + o [evolve.node|7a230b46bf61] [evolve.rev|(2)] [evolve.short_description|A2] + | + x [evolve.node evolve.missing_change_ctx|fdf9bde5129a] + | [evolve.verb|rewritten] by [evolve.user|test] [evolve.date|(*20*)] as [evolve.node|7a230b46bf61] (glob) + | + @ [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0] + [evolve.verb|rewritten] by [evolve.user|test] [evolve.date|(*20*)] as [evolve.node|fdf9bde5129a] (glob) + + +Test with cycle +=============== + +Test setup +---------- + + $ hg init $TESTTMP/cycle + $ cd $TESTTMP/cycle + $ mkcommit ROOT + $ mkcommit A + $ mkcommit B + $ mkcommit C + $ hg log -G + @ changeset: 3:a8df460dbbfe + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + o changeset: 2:c473644ee0e9 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 1:2a34000d3544 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Create a cycle + $ hg prune -s "desc(B)" "desc(A)" + 1 changesets pruned + 2 new unstable changesets + $ hg prune -s "desc(C)" "desc(B)" + 1 changesets pruned + $ hg prune -s "desc(A)" "desc(C)" + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + working directory now at 2a34000d3544 + 1 changesets pruned + $ hg log --hidden -G + x changeset: 3:a8df460dbbfe + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + x changeset: 2:c473644ee0e9 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + @ changeset: 1:2a34000d3544 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + +Check that debugobshistory never crash on a cycle + + $ hg olog "desc(A)" --hidden + @ 2a34000d3544 (1) A + | rewritten by test (*20*) as c473644ee0e9 (glob) + | + x a8df460dbbfe (3) C + | rewritten by test (*20*) as 2a34000d3544 (glob) + | + x c473644ee0e9 (2) B + | rewritten by test (*20*) as a8df460dbbfe (glob) + | + + $ hg olog "desc(B)" --hidden + @ 2a34000d3544 (1) A + | rewritten by test (*20*) as c473644ee0e9 (glob) + | + x a8df460dbbfe (3) C + | rewritten by test (*20*) as 2a34000d3544 (glob) + | + x c473644ee0e9 (2) B + | rewritten by test (*20*) as a8df460dbbfe (glob) + | + + $ hg olog "desc(C)" --hidden + @ 2a34000d3544 (1) A + | rewritten by test (*20*) as c473644ee0e9 (glob) + | + x a8df460dbbfe (3) C + | rewritten by test (*20*) as 2a34000d3544 (glob) + | + x c473644ee0e9 (2) B + | rewritten by test (*20*) as a8df460dbbfe (glob) + | + +Test with multiple cyles +======================== + +Test setup +---------- + + $ hg init $TESTTMP/multiple-cycle + $ cd $TESTTMP/multiple-cycle + $ mkcommit ROOT + $ mkcommit A + $ mkcommit B + $ mkcommit C + $ mkcommit D + $ mkcommit E + $ mkcommit F + $ hg log -G + @ changeset: 6:d9f908fde1a1 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: F + | + o changeset: 5:0da815c333f6 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: E + | + o changeset: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: D + | + o changeset: 3:a8df460dbbfe + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + o changeset: 2:c473644ee0e9 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + o changeset: 1:2a34000d3544 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Create a first cycle + $ hg prune -s "desc(B)" "desc(A)" + 1 changesets pruned + 5 new unstable changesets + $ hg prune -s "desc(C)" "desc(B)" + 1 changesets pruned + $ hg prune --split -s "desc(A)" -s "desc(D)" "desc(C)" + 1 changesets pruned +And create a second one + $ hg prune -s "desc(E)" "desc(D)" + 1 changesets pruned + $ hg prune -s "desc(F)" "desc(E)" + 1 changesets pruned + $ hg prune -s "desc(D)" "desc(F)" + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + working directory now at 868d2e0eb19c + 1 changesets pruned + $ hg log --hidden -G + x changeset: 6:d9f908fde1a1 + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: F + | + x changeset: 5:0da815c333f6 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: E + | + @ changeset: 4:868d2e0eb19c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: D + | + x changeset: 3:a8df460dbbfe + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C + | + x changeset: 2:c473644ee0e9 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: B + | + x changeset: 1:2a34000d3544 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: A + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Actual test +----------- + +Check that debugobshistory never crash on a cycle + + $ hg olog "desc(D)" --hidden + x 0da815c333f6 (5) E + | rewritten by test (*20*) as d9f908fde1a1 (glob) + | + @ 868d2e0eb19c (4) D + |\ rewritten by test (*20*) as 0da815c333f6 (glob) + | | + | x d9f908fde1a1 (6) F + | | rewritten by test (*20*) as 868d2e0eb19c (glob) + | | + +---x 2a34000d3544 (1) A + | | rewritten by test (*20*) as c473644ee0e9 (glob) + | | + x | a8df460dbbfe (3) C + | | rewritten by test (*20*) as 2a34000d3544, 868d2e0eb19c (glob) + | | + x | c473644ee0e9 (2) B + | | rewritten by test (*20*) as a8df460dbbfe (glob) + | | + +Check the json output is valid in this case + + $ hg olog "desc(D)" --hidden --no-graph -Tjson | python -m json.tool + [ + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "0da815c333f6" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "868d2e0eb19c", + "debugobshistory.rev": 4, + "debugobshistory.shortdescription": "D" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "868d2e0eb19c" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "d9f908fde1a1", + "debugobshistory.rev": 6, + "debugobshistory.shortdescription": "F" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "d9f908fde1a1" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "0da815c333f6", + "debugobshistory.rev": 5, + "debugobshistory.shortdescription": "E" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "2a34000d3544", + "868d2e0eb19c" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "a8df460dbbfe", + "debugobshistory.rev": 3, + "debugobshistory.shortdescription": "C" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "a8df460dbbfe" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "c473644ee0e9", + "debugobshistory.rev": 2, + "debugobshistory.shortdescription": "B" + }, + { + "debugobshistory.markers": [ + { + "debugobshistory.marker_date": [ + *, (glob) + 0 + ], + "debugobshistory.marker_user": "test", + "debugobshistory.succnodes": [ + "c473644ee0e9" + ], + "debugobshistory.verb": "rewritten" + } + ], + "debugobshistory.node": "2a34000d3544", + "debugobshistory.rev": 1, + "debugobshistory.shortdescription": "A" + } + ]
--- a/tests/test-evolve.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-evolve.t Thu May 18 23:12:52 2017 +0200 @@ -769,9 +769,17 @@ Test olog - $ hg olog - 4 : add 4 - test - 11 : add 3 - test + $ hg olog | head -n 10 # hg touch makes the output unstable (fix it with devel option for more stable touch) + @ d26d339c513f (12) add 4 + |\ + x | af636757ce3b (11) add 3 + |\ \ rewritten by test (*) as d26d339c513f (glob) + | | | + | \ \ + | |\ \ + | | | x ce341209337f (4) add 4 + | | | rewritten by test (*) as d26d339c513f (glob) + | | | Test obsstore stat
--- a/tests/test-obsolete.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-obsolete.t Thu May 18 23:12:52 2017 +0200 @@ -1,3 +1,5 @@ + + $ . $TESTDIR/testlib/common.sh $ cat >> $HGRCPATH <<EOF > [web] > push_ssl = false @@ -16,10 +18,6 @@ > hg add "$1" > hg ci -m "add $1" > } - $ getid() { - > hg id --hidden --debug -ir "$1" - > } - $ alias qlog="hg log --template='{rev}\n- {node|short}\n'" $ hg init local $ cd local @@ -695,10 +693,12 @@ [10] add obsol_c [2] $ hg olog - changeset: 2:4538525df7e2 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add c + @ 0d3f46688ccc (3) add obsol_c + | rewritten by test (*) as 2033b4e49474 (glob) + | rewritten by test (Thu Jan 01 00:00:00 1970 +0000) as 725c380fe99b + | + x 4538525df7e2 (2) add c + rewritten by test (Thu Jan 01 00:00:00 1970 +0000) as 0d3f46688ccc Check import reports new unstable changeset:
--- a/tests/test-prev-next.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-prev-next.t Thu May 18 23:12:52 2017 +0200 @@ -48,6 +48,9 @@ $ hg bookmarks mark 1:6e742c9127b3 * mark2 0:a154386e50d1 + $ hg next --dry-run --color=debug + hg update 1; + [[evolve.rev|1]] added b $ hg next 1 files updated, 0 files merged, 0 files removed, 0 files unresolved [1] added b @@ -148,6 +151,9 @@ $ hg next --evolve no children [1] + $ hg prev --dry-run --color=debug + hg update 1; + [[evolve.rev|1]] added b $ hg prev 0 files updated, 0 files merged, 1 files removed, 0 files unresolved [1] added b
--- a/tests/test-topic-stack.t Thu May 18 22:53:01 2017 +0200 +++ b/tests/test-topic-stack.t Thu May 18 23:12:52 2017 +0200 @@ -79,6 +79,53 @@ t2: c_d t1: c_c ^ c_b + $ hg stack -Tjson | python -m json.tool + [ + { + "isentry": true, + "topic.stack.desc": "c_f", + "topic.stack.index": 4, + "topic.stack.state": [ + "current" + ], + "topic.stack.state.symbol": "@" + }, + { + "isentry": true, + "topic.stack.desc": "c_e", + "topic.stack.index": 3, + "topic.stack.state": [ + "clean" + ], + "topic.stack.state.symbol": ":" + }, + { + "isentry": true, + "topic.stack.desc": "c_d", + "topic.stack.index": 2, + "topic.stack.state": [ + "clean" + ], + "topic.stack.state.symbol": ":" + }, + { + "isentry": true, + "topic.stack.desc": "c_c", + "topic.stack.index": 1, + "topic.stack.state": [ + "clean" + ], + "topic.stack.state.symbol": ":" + }, + { + "isentry": false, + "topic.stack.desc": "c_b", + "topic.stack.state": [ + "base" + ], + "topic.stack.state.symbol": "^" + } + ] error case, nothing to list @@ -137,6 +184,26 @@ t2@ c_d (current) t1: c_c ^ c_b + $ hg up t3 + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg topic --list + ### topic: foo + ### branch: default + t4$ c_f (unstable) + t3@ c_e (current) + t2: c_d + t1: c_c + ^ c_b + $ hg topic --list --color=debug + [topic.stack.summary.topic|### topic: [topic.active|foo]] + [topic.stack.summary.branches|### branch: default] + [topic.stack.index topic.stack.index.unstable|t4][topic.stack.state topic.stack.state.unstable|$] [topic.stack.desc topic.stack.desc.unstable|c_f][topic.stack.state topic.stack.state.unstable| (unstable)] + [topic.stack.index topic.stack.index.current|t3][topic.stack.state topic.stack.state.current|@] [topic.stack.desc topic.stack.desc.current|c_e][topic.stack.state topic.stack.state.current| (current)] + [topic.stack.index topic.stack.index.clean|t2][topic.stack.state topic.stack.state.clean|:] [topic.stack.desc topic.stack.desc.clean|c_d] + [topic.stack.index topic.stack.index.clean|t1][topic.stack.state topic.stack.state.clean|:] [topic.stack.desc topic.stack.desc.clean|c_c] + [topic.stack.state topic.stack.state.base|^] [topic.stack.desc topic.stack.desc.base|c_b] + $ hg up t2 + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved Also test the revset: