# HG changeset patch # User Pierre-Yves David # Date 1495144502 -7200 # Node ID 37deace44b36fb7b27b6f545ad362802b9eda1e7 # Parent fd24f1c7accd6b910d1a616637cbba6855330dbd# Parent 979a8ea17e1e45bf67d9a60a77bf1e14fdc1a47d merge with future 6.2.0 No extra change were needed compared to 3.9. diff -r 979a8ea17e1e -r 37deace44b36 .hgtags --- a/.hgtags Wed May 03 13:52:19 2017 +0200 +++ b/.hgtags Thu May 18 23:55:02 2017 +0200 @@ -48,3 +48,4 @@ 70694b2621ba9d919bc38303f8901e84caf5da0f 5.6.1 165ad227993de4e7d819cc6c820d5b9f7b38b80d 6.0.0 5ef112a6eb875633a7925cde61b7d2d9e65b3a56 6.0.1 +8510d3fd7c3b312dc731f4c29badc415d504558a 6.1.0 diff -r 979a8ea17e1e -r 37deace44b36 README --- a/README Wed May 03 13:52:19 2017 +0200 +++ b/README Thu May 18 23:55:02 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, diff -r 979a8ea17e1e -r 37deace44b36 debian/changelog --- a/debian/changelog Wed May 03 13:52:19 2017 +0200 +++ b/debian/changelog Thu May 18 23:55:02 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 Thu, 18 May 2017 22:24:10 +0200 + +mercurial-evolve (6.1.0-1) unstable; urgency=medium + + * New upstream release + + -- Pierre-Yves David Wed, 03 May 2017 13:57:15 +0200 + +mercurial-evolve (6.0.1-1) unstable; urgency=medium * New upstream version - -- Pierre-Yves David Thu, 20 Apr 2017 12:58:35 +0200 + -- Pierre-Yves David Thu, 20 Apr 2017 12:58:35 +0200 mercurial-evolve (6.0.0-1) unstable; urgency=medium * New Upstream Release - -- Pierre-Yves David Thu, 20 Apr 2017 12:58:03 +0200 + -- Pierre-Yves David Thu, 20 Apr 2017 12:58:03 +0200 mercurial-evolve (5.5.0-1) unstable; urgency=medium diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/__init__.py Thu May 18 23:55:02 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) diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/metadata.py Thu May 18 23:55:02 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/' diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/obscache.py --- a/hgext3rd/evolve/obscache.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/obscache.py Thu May 18 23:55:02 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) diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/obsdiscovery.py --- a/hgext3rd/evolve/obsdiscovery.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/obsdiscovery.py Thu May 18 23:55:02 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) diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/obshistory.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/obshistory.py Thu May 18 23:55:02 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 +# +# 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") diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/serveronly.py Thu May 18 23:55:02 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 diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/evolve/stablerange.py --- a/hgext3rd/evolve/stablerange.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/evolve/stablerange.py Thu May 18 23:55:02 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 diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/topic/__init__.py Thu May 18 23:55:02 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): diff -r 979a8ea17e1e -r 37deace44b36 hgext3rd/topic/stack.py --- a/hgext3rd/topic/stack.py Wed May 03 13:52:19 2017 +0200 +++ b/hgext3rd/topic/stack.py Thu May 18 23:55:02 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 diff -r 979a8ea17e1e -r 37deace44b36 tests/test-check-commit.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-check-commit.t Thu May 18 23:55:02 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 diff -r 979a8ea17e1e -r 37deace44b36 tests/test-check-setup-manifest.t --- a/tests/test-check-setup-manifest.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -#require test-repo - - $ checkcm() { - > if ! (which check-manifest > /dev/null); then - > echo skipped: missing tool: check-manifest; - > exit 80; - > fi; - > }; - $ checkcm - $ cat << EOF >> $HGRCPATH - > [experimental] - > evolution=all - > EOF - -Run check manifest: - - $ cd $TESTDIR/.. - $ check-manifest - lists of files in version control and sdist match diff -r 979a8ea17e1e -r 37deace44b36 tests/test-discovery-obshashrange.t --- a/tests/test-discovery-obshashrange.t Wed May 03 13:52:19 2017 +0200 +++ b/tests/test-discovery-obshashrange.t Thu May 18 23:55:02 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,39 @@ 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 (*)> 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 (*)> 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 (*)> 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 (*)> 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 (*)> 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 (*)> 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 +149,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 +187,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: 532 + 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 httpheader=1024 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 +284,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 +299,46 @@ 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 (*)> 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 (*)> 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 (*)> 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 (*)> 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 +377,24 @@ 3 new obsolescence markers (run 'hg heads' to see heads, 'hg merge' to merge) + $ hg -R ../server blackbox + * @0000000000000000000000000000000000000000 (*)> debugobsolete --rev ::tip (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 (*)> 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 (*)> 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 +404,24 @@ 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 (*)> 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 +432,336 @@ 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 (*)> 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 + diff -r 979a8ea17e1e -r 37deace44b36 tests/test-evolve-obshistory.t --- a/tests/test-evolve-obshistory.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,514 +0,0 @@ -This test file test the various messages when accessing obsolete -revisions. - -Global setup -============ - - $ . $TESTDIR/testlib/common.sh - $ cat >> $HGRCPATH < [ui] - > interactive = true - > [phases] - > publish=False - > [extensions] - > evolve = - > EOF - -Test output on amended commit -============================= - -Test setup ----------- - - $ hg init $TESTTMP/local-amend - $ cd $TESTTMP/local-amend - $ mkcommit ROOT - $ mkcommit A0 - $ echo 42 >> A0 - $ hg amend -m "A1" - $ hg log --hidden -G - @ changeset: 3:a468dc9b3633 - | tag: tip - | parent: 0:ea207398892e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A1 - | - | x changeset: 2:f137d23bb3e1 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: temporary amend commit for 471f378eab4c - | | - | 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 update 471f378eab4c - abort: hidden revision '471f378eab4c'! - (use --hidden to access hidden revisions) - [255] - $ 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) - -Test output with pruned commit -============================== - -Test setup ----------- - - $ hg init $TESTTMP/local-prune - $ cd $TESTTMP/local-prune - $ mkcommit ROOT - $ mkcommit A0 # 0 - $ mkcommit B0 # 1 - $ hg log --hidden -G - @ changeset: 2:0dec01379d3b - | tag: tip - | 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 prune -r 'desc(B0)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - working directory now at 471f378eab4c - 1 changesets pruned - -Actual test ------------ - - $ hg up 1 - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg up 0dec01379d3b - abort: hidden revision '0dec01379d3b'! - (use --hidden to access hidden revisions) - [255] - $ hg up --hidden -r 'desc(B0)' - 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 parent successor) - -Test output with splitted commit -================================ - -Test setup ----------- - - $ hg init $TESTTMP/local-split - $ cd $TESTTMP/local-split - $ mkcommit ROOT - $ echo 42 >> a - $ echo 43 >> b - $ hg commit -A -m "A0" - adding a - adding b - $ hg log --hidden -G - @ changeset: 1:471597cad322 - | 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 split -r 'desc(A0)' -d "0 0" << EOF - > y - > y - > n - > n - > y - > y - > EOF - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - adding a - adding b - diff --git a/a b/a - new file mode 100644 - examine changes to 'a'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +42 - record change 1/2 to 'a'? [Ynesfdaq?] y - - diff --git a/b b/b - new file mode 100644 - examine changes to 'b'? [Ynesfdaq?] n - - created new head - Done splitting? [yN] n - diff --git a/b b/b - new file mode 100644 - examine changes to 'b'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +43 - record this change to 'b'? [Ynesfdaq?] y - - no more change to split - - $ hg log --hidden -G - @ changeset: 3:f257fde29c7a - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - o changeset: 2:337fec4d2edc - | parent: 0:ea207398892e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - | x changeset: 1:471597cad322 - |/ 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 update 471597cad322 - abort: hidden revision '471597cad322'! - (use --hidden to access hidden revisions) - [255] - $ hg update --hidden 'min(desc(A0))' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory parent is obsolete! (471597cad322) - (use 'hg evolve' to update to its tipmost successor: 337fec4d2edc, f257fde29c7a) - -Test output with lots of splitted commit -======================================== - -Test setup ----------- - - $ hg init $TESTTMP/local-lots-split - $ cd $TESTTMP/local-lots-split - $ mkcommit ROOT - $ echo 42 >> a - $ echo 43 >> b - $ echo 44 >> c - $ echo 45 >> d - $ hg commit -A -m "A0" - adding a - adding b - adding c - adding d - $ hg log --hidden -G - @ changeset: 1:de7290d8b885 - | 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 split -r 'desc(A0)' -d "0 0" << EOF - > y - > y - > n - > n - > n - > n - > y - > y - > n - > n - > n - > y - > y - > n - > n - > y - > y - > EOF - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - adding a - adding b - adding c - adding d - diff --git a/a b/a - new file mode 100644 - examine changes to 'a'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +42 - record change 1/4 to 'a'? [Ynesfdaq?] y - - diff --git a/b b/b - new file mode 100644 - examine changes to 'b'? [Ynesfdaq?] n - - diff --git a/c b/c - new file mode 100644 - examine changes to 'c'? [Ynesfdaq?] n - - diff --git a/d b/d - new file mode 100644 - examine changes to 'd'? [Ynesfdaq?] n - - created new head - Done splitting? [yN] n - diff --git a/b b/b - new file mode 100644 - examine changes to 'b'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +43 - record change 1/3 to 'b'? [Ynesfdaq?] y - - diff --git a/c b/c - new file mode 100644 - examine changes to 'c'? [Ynesfdaq?] n - - diff --git a/d b/d - new file mode 100644 - examine changes to 'd'? [Ynesfdaq?] n - - Done splitting? [yN] n - diff --git a/c b/c - new file mode 100644 - examine changes to 'c'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +44 - record change 1/2 to 'c'? [Ynesfdaq?] y - - diff --git a/d b/d - new file mode 100644 - examine changes to 'd'? [Ynesfdaq?] n - - Done splitting? [yN] n - diff --git a/d b/d - new file mode 100644 - examine changes to 'd'? [Ynesfdaq?] y - - @@ -0,0 +1,1 @@ - +45 - record this change to 'd'? [Ynesfdaq?] y - - no more change to split - - $ hg log --hidden -G - @ changeset: 5:c7f044602e9b - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - o changeset: 4:1ae8bc733a14 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - o changeset: 3:f257fde29c7a - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - o changeset: 2:337fec4d2edc - | parent: 0:ea207398892e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A0 - | - | x changeset: 1:de7290d8b885 - |/ 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 update de7290d8b885 - abort: hidden revision 'de7290d8b885'! - (use --hidden to access hidden revisions) - [255] - $ hg update --hidden 'min(desc(A0))' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory parent is obsolete! (de7290d8b885) - (use 'hg evolve' to update to its tipmost successor: 337fec4d2edc, f257fde29c7a and 2 more) - -Test output with folded commit -============================== - -Test setup ----------- - - $ hg init $TESTTMP/local-fold - $ cd $TESTTMP/local-fold - $ mkcommit ROOT - $ mkcommit A0 - $ mkcommit B0 - $ hg log --hidden -G - @ changeset: 2:0dec01379d3b - | tag: tip - | 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(B0)' --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: 3:eb5a0daa2192 - | tag: tip - | parent: 0:ea207398892e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: C0 - | - | 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 - ----------- - - $ 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 0dec01379d3b - working directory parent is obsolete! (471f378eab4c) - (use 'hg evolve' to update to its successor: eb5a0daa2192) - abort: hidden revision '0dec01379d3b'! - (use --hidden to access hidden revisions) - [255] - $ hg update --hidden 'desc(B0)' - 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) - -Test output with divergence -=========================== - -Test setup ----------- - - $ hg init $TESTTMP/local-divergence - $ cd $TESTTMP/local-divergence - $ mkcommit ROOT - $ mkcommit A0 - $ hg amend -m "A1" - $ hg log --hidden -G - @ changeset: 2:fdf9bde5129a - | tag: tip - | 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 - - $ hg update --hidden 'desc(A0)' - 0 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: fdf9bde5129a) - $ hg amend -m "A2" - 2 new divergent changesets - $ hg log --hidden -G - @ changeset: 3:65b757b745b9 - | tag: tip - | parent: 0:ea207398892e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: A2 - | - | o 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 update 471f378eab4c - abort: hidden revision '471f378eab4c'! - (use --hidden to access hidden revisions) - [255] - $ hg update --hidden 'desc(A0)' - 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) diff -r 979a8ea17e1e -r 37deace44b36 tests/test-evolve-serveronly-bundle2.t diff -r 979a8ea17e1e -r 37deace44b36 tests/test-evolve-topic.t --- a/tests/test-evolve-topic.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ - -Check we can find the topic extensions - - $ cat >> $HGRCPATH < [defaults] - > amend=-d "0 0" - > fold=-d "0 0" - > [phases] - > publish = False - > [ui] - > logtemplate = {rev} - \{{get(namespaces, "topics")}} {node|short} {desc} ({phase})\n - > [diff] - > git = 1 - > unified = 0 - > [extensions] - > rebase = - > EOF - $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH - $ echo "topic=$(echo $(dirname $TESTDIR))/hgext3rd/topic/" >> $HGRCPATH - - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - -Create a simple setup - - $ hg init repoa - $ cd repoa - $ mkcommit aaa - $ mkcommit bbb - $ hg topic foo - $ mkcommit ccc - $ mkcommit ddd - $ mkcommit eee - $ mkcommit fff - $ hg topic bar - $ mkcommit ggg - $ mkcommit hhh - $ mkcommit iii - $ mkcommit jjj - - $ hg log -G - @ 9 - {bar} 1d964213b023 add jjj (draft) - | - o 8 - {bar} fcab990f3261 add iii (draft) - | - o 7 - {bar} b0c2554835ac add hhh (draft) - | - o 6 - {bar} c748293f1c1a add ggg (draft) - | - o 5 - {foo} 6a6b7365c751 add fff (draft) - | - o 4 - {foo} 3969ab847d9c add eee (draft) - | - o 3 - {foo} 4e3a154f38c7 add ddd (draft) - | - o 2 - {foo} cced9bac76e3 add ccc (draft) - | - o 1 - {} a4dbed0837ea add bbb (draft) - | - o 0 - {} 199cc73e9a0b add aaa (draft) - - -Test that evolve --all evolve the current topic ------------------------------------------------ - -make a mess - - $ hg up foo - switching to topic foo - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - $ hg topic -l - ### topic: foo (?) - ### branch: default (?) - t4@ add fff (current) - t3: add eee - t2: add ddd - t1: add ccc - ^ add bbb - $ hg up 'desc(ddd)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo ddd >> ddd - $ hg amend - 6 new unstable changesets - $ hg up 'desc(fff)' - 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo fff >> fff - $ hg amend - - $ hg log -G - @ 13 - {foo} e104f49bab28 add fff (draft) - | - | o 11 - {foo} d9cacd156ffc add ddd (draft) - | | - | | o 9 - {bar} 1d964213b023 add jjj (draft) - | | | - | | o 8 - {bar} fcab990f3261 add iii (draft) - | | | - | | o 7 - {bar} b0c2554835ac add hhh (draft) - | | | - | | o 6 - {bar} c748293f1c1a add ggg (draft) - | | | - +---x 5 - {foo} 6a6b7365c751 add fff (draft) - | | - o | 4 - {foo} 3969ab847d9c add eee (draft) - | | - x | 3 - {foo} 4e3a154f38c7 add ddd (draft) - |/ - o 2 - {foo} cced9bac76e3 add ccc (draft) - | - o 1 - {} a4dbed0837ea add bbb (draft) - | - o 0 - {} 199cc73e9a0b add aaa (draft) - - -Run evolve --all - - $ hg evolve --all - move:[4] add eee - atop:[11] add ddd - move:[13] add fff - atop:[14] add eee - working directory is now at 070c5573d8f9 - $ hg log -G - @ 15 - {foo} 070c5573d8f9 add fff (draft) - | - o 14 - {foo} 42b49017ff90 add eee (draft) - | - o 11 - {foo} d9cacd156ffc add ddd (draft) - | - | o 9 - {bar} 1d964213b023 add jjj (draft) - | | - | o 8 - {bar} fcab990f3261 add iii (draft) - | | - | o 7 - {bar} b0c2554835ac add hhh (draft) - | | - | o 6 - {bar} c748293f1c1a add ggg (draft) - | | - | x 5 - {foo} 6a6b7365c751 add fff (draft) - | | - | x 4 - {foo} 3969ab847d9c add eee (draft) - | | - | x 3 - {foo} 4e3a154f38c7 add ddd (draft) - |/ - o 2 - {foo} cced9bac76e3 add ccc (draft) - | - o 1 - {} a4dbed0837ea add bbb (draft) - | - o 0 - {} 199cc73e9a0b add aaa (draft) - - -Test that evolve does not loose topic information -------------------------------------------------- - - $ hg evolve --rev 'topic(bar)' - move:[6] add ggg - atop:[15] add fff - move:[7] add hhh - atop:[16] add ggg - move:[8] add iii - atop:[17] add hhh - move:[9] add jjj - atop:[18] add iii - working directory is now at 9bf430c106b7 - $ hg log -G - @ 19 - {bar} 9bf430c106b7 add jjj (draft) - | - o 18 - {bar} d2dc89c57700 add iii (draft) - | - o 17 - {bar} 20bc4d02aa62 add hhh (draft) - | - o 16 - {bar} 16d6f664b17c add ggg (draft) - | - o 15 - {foo} 070c5573d8f9 add fff (draft) - | - o 14 - {foo} 42b49017ff90 add eee (draft) - | - o 11 - {foo} d9cacd156ffc add ddd (draft) - | - o 2 - {foo} cced9bac76e3 add ccc (draft) - | - o 1 - {} a4dbed0837ea add bbb (draft) - | - o 0 - {} 199cc73e9a0b add aaa (draft) - - -Tests next and prev behavior -============================ - -Basic move are restricted to the current topic - - $ hg up foo - switching to topic foo - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - $ hg prev - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - [14] add eee - $ hg next - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - [15] add fff - $ hg next - no children on topic "foo" - do you want --no-topic - [1] - $ hg next --no-topic - switching to topic bar - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - [16] add ggg - $ hg prev - no parent in topic "bar" - (do you want --no-topic) - $ hg prev --no-topic - switching to topic foo - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - [15] add fff diff -r 979a8ea17e1e -r 37deace44b36 tests/test-evolve.t --- a/tests/test-evolve.t Wed May 03 13:52:19 2017 +0200 +++ b/tests/test-evolve.t Thu May 18 23:55:02 2017 +0200 @@ -767,12 +767,6 @@ $ hg debugrebuildstate $ hg st -Test olog - - $ hg olog - 4 : add 4 - test - 11 : add 3 - test - Test obsstore stat $ hg debugobsstorestat diff -r 979a8ea17e1e -r 37deace44b36 tests/test-exchange-obsmarkers-case-A3.t diff -r 979a8ea17e1e -r 37deace44b36 tests/test-obsolete.t --- a/tests/test-obsolete.t Wed May 03 13:52:19 2017 +0200 +++ b/tests/test-obsolete.t Thu May 18 23:55:02 2017 +0200 @@ -1,3 +1,5 @@ + + $ . $TESTDIR/testlib/common.sh $ cat >> $HGRCPATH < [web] > push_ssl = false @@ -8,6 +10,7 @@ > debugobsolete=debugobsolete -d '0 0' > [extensions] > hgext.rebase= + > color = > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH $ mkcommit() { @@ -15,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 @@ -689,12 +688,6 @@ [4] add obsol_c' [10] add obsol_c [2] - $ hg olog - changeset: 2:4538525df7e2 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: add c - Check import reports new unstable changeset: diff -r 979a8ea17e1e -r 37deace44b36 tests/test-prev-next.t --- a/tests/test-prev-next.t Wed May 03 13:52:19 2017 +0200 +++ b/tests/test-prev-next.t Thu May 18 23:55:02 2017 +0200 @@ -1,6 +1,7 @@ $ cat >> $HGRCPATH < [extensions] > hgext.graphlog= + > color = > EOF $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH @@ -47,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 @@ -147,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 diff -r 979a8ea17e1e -r 37deace44b36 tests/test-sharing.t diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic-dest.t --- a/tests/test-topic-dest.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,492 +0,0 @@ - $ . "$TESTDIR/testlib/topic_setup.sh" - - $ hg init jungle - $ cd jungle - $ cat <> .hg/hgrc - > [extensions] - > rebase= - > histedit= - > [phases] - > publish=false - > EOF - $ cat <> $HGRCPATH - > [ui] - > logtemplate = '{rev} ({topics}) {desc}\n' - > EOF - - $ for x in alpha beta gamma delta ; do - > echo file $x >> $x - > hg add $x - > hg ci -m "c_$x" - > done - -Test NGTip feature -================== - -Simple linear case - - $ echo babar >> jungle - $ hg add jungle - $ hg ci -t elephant -m babar - - $ hg log -G - @ 4 (elephant) babar - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - $ hg log -r 'ngtip(.)' - 3 () c_delta - $ hg log -r 'default' - 3 () c_delta - - -multiple heads with topic - - $ hg up "desc('c_beta')" - 0 files updated, 0 files merged, 3 files removed, 0 files unresolved - $ echo zephir >> jungle - $ hg add jungle - $ hg ci -t monkey -m zephir - $ hg log -G - @ 5 (monkey) zephir - | - | o 4 (elephant) babar - | | - | o 3 () c_delta - | | - | o 2 () c_gamma - |/ - o 1 () c_beta - | - o 0 () c_alpha - - $ hg log -r 'ngtip(.)' - 3 () c_delta - $ hg log -r 'default' - 3 () c_delta - -one of the head is a valid tip - - $ hg up "desc('c_delta')" - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo epsilon >> epsilon - $ hg add epsilon - $ hg ci -m "c_epsilon" - $ hg log -G - @ 6 () c_epsilon - | - | o 5 (monkey) zephir - | | - +---o 4 (elephant) babar - | | - o | 3 () c_delta - | | - o | 2 () c_gamma - |/ - o 1 () c_beta - | - o 0 () c_alpha - - $ hg log -r 'ngtip(.)' - 6 () c_epsilon - $ hg log -r 'default' - 6 () c_epsilon - -rebase destination -================== - -rebase on branch ngtip - - $ hg up elephant - switching to topic elephant - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg rebase - rebasing 4:cb7ae72f4a80 "babar" - $ hg log -G - @ 7 (elephant) babar - | - o 6 () c_epsilon - | - | o 5 (monkey) zephir - | | - o | 3 () c_delta - | | - o | 2 () c_gamma - |/ - o 1 () c_beta - | - o 0 () c_alpha - - $ hg up monkey - switching to topic monkey - 1 files updated, 0 files merged, 3 files removed, 0 files unresolved - $ hg rebase - rebasing 5:d832ddc604ec "zephir" - $ hg log -G - @ 8 (monkey) zephir - | - | o 7 (elephant) babar - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -Rebase on other topic heads if any - - $ hg up 'desc(c_delta)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo "General Huc" >> monkeyville - $ hg add monkeyville - $ hg ci -t monkey -m Huc - $ hg log -G - @ 9 (monkey) Huc - | - | o 8 (monkey) zephir - | | - | | o 7 (elephant) babar - | |/ - | o 6 () c_epsilon - |/ - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - $ hg rebase - rebasing 9:d79a104e2902 "Huc" (tip) - $ hg log -G - @ 10 (monkey) Huc - | - o 8 (monkey) zephir - | - | o 7 (elephant) babar - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -merge destination -================= - - $ hg up 'ngtip(default)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg up default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo zeta >> zeta - $ hg add zeta - $ hg ci -m "c_zeta" - $ hg log -G - @ 11 () c_zeta - | - | o 10 (monkey) Huc - | | - | o 8 (monkey) zephir - |/ - | o 7 (elephant) babar - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - $ hg up elephant - switching to topic elephant - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg rebase -d 'desc(c_zeta)' # make sure tip is elsewhere - rebasing 7:8d0b77140b05 "babar" - $ hg up monkey - switching to topic monkey - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg merge - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - (branch merge, don't forget to commit) - $ hg topic - elephant - * monkey - $ hg ci -m 'merge with default' - $ hg topic - elephant - * monkey - $ hg log -G - @ 13 (monkey) merge with default - |\ - | | o 12 (elephant) babar - | |/ - | o 11 () c_zeta - | | - o | 10 (monkey) Huc - | | - o | 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - - -Check pull --rebase -------------------- - -(we broke it a some point) - - $ cd .. - $ hg clone jungle other --rev '2' - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files - updating to branch default - 3 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd other - $ echo other > other - $ hg add other - $ hg ci -m 'c_other' - $ hg pull -r default --rebase - pulling from $TESTTMP/jungle (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - rebasing 3:dbc48dd9e743 "c_other" - $ hg log -G - @ 7 () c_other - | - o 6 () c_zeta - | - o 5 () c_epsilon - | - o 4 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - $ cd ../jungle - - -Default destination for update -=============================== - -initial setup - - $ hg up elephant - switching to topic elephant - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo arthur >> jungle - $ hg ci -m arthur - $ echo pompadour >> jungle - $ hg ci -m pompadour - $ hg up 'roots(all())' - 0 files updated, 0 files merged, 6 files removed, 0 files unresolved - $ hg log -G - o 15 (elephant) pompadour - | - o 14 (elephant) arthur - | - | o 13 (monkey) merge with default - | |\ - o---+ 12 (elephant) babar - / / - | o 11 () c_zeta - | | - o | 10 (monkey) Huc - | | - o | 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - @ 0 () c_alpha - - -testing default destination on a branch - - $ hg up - 5 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg log -G - o 15 (elephant) pompadour - | - o 14 (elephant) arthur - | - | o 13 (monkey) merge with default - | |\ - o---+ 12 (elephant) babar - / / - | @ 11 () c_zeta - | | - o | 10 (monkey) Huc - | | - o | 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -extra setup for topic -(making sure tip is not the topic) - - $ hg up 'desc(c_zeta)' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo 'eta' >> 'eta' - $ hg add 'eta' - $ hg commit -m 'c_eta' - $ hg log -G - @ 16 () c_eta - | - | o 15 (elephant) pompadour - | | - | o 14 (elephant) arthur - | | - +---o 13 (monkey) merge with default - | | | - | o | 12 (elephant) babar - |/ / - o | 11 () c_zeta - | | - | o 10 (monkey) Huc - | | - | o 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -Testing default destination for topic - - $ hg up 'roots(topic(elephant))' - switching to topic elephant - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg up - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg log -G - o 16 () c_eta - | - | @ 15 (elephant) pompadour - | | - | o 14 (elephant) arthur - | | - +---o 13 (monkey) merge with default - | | | - | o | 12 (elephant) babar - |/ / - o | 11 () c_zeta - | | - | o 10 (monkey) Huc - | | - | o 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -Testing default destination for topic - - $ hg up 'p1(roots(topic(elephant)))' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic elephant - $ hg up - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg log -G - o 16 () c_eta - | - | @ 15 (elephant) pompadour - | | - | o 14 (elephant) arthur - | | - +---o 13 (monkey) merge with default - | | | - | o | 12 (elephant) babar - |/ / - o | 11 () c_zeta - | | - | o 10 (monkey) Huc - | | - | o 8 (monkey) zephir - |/ - o 6 () c_epsilon - | - o 3 () c_delta - | - o 2 () c_gamma - | - o 1 () c_beta - | - o 0 () c_alpha - - -Default destination for histedit -================================ - -By default histedit should edit with the current topic only -(even when based on other draft - - $ hg phase 'desc(c_zeta)' - 11: draft - $ HGEDITOR=cat hg histedit | grep pick - pick e44744d9ad73 12 babar - pick 38eea8439aee 14 arthur - pick 411315c48bdc 15 pompadour - # p, pick = use commit diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic-push.t --- a/tests/test-topic-push.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ - $ . "$TESTDIR/testlib/topic_setup.sh" - - $ cat << EOF >> $HGRCPATH - > [ui] - > logtemplate = {rev} {branch} {get(namespaces, "topics")} {phase} {desc|firstline}\n - > [ui] - > ssh =python "$RUNTESTDIR/dummyssh" - > EOF - - $ hg init main - $ hg init draft - $ cat << EOF >> draft/.hg/hgrc - > [phases] - > publish=False - > EOF - $ hg clone main client - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat << EOF >> client/.hg/hgrc - > [paths] - > draft=../draft - > EOF - - -Testing core behavior to make sure we did not break anything -============================================================ - -Pushing a first changeset - - $ cd client - $ echo aaa > aaa - $ hg add aaa - $ hg commit -m 'CA' - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 0 default draft CA - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - -Pushing two heads - - $ echo aaa > bbb - $ hg add bbb - $ hg commit -m 'CB' - $ echo aaa > ccc - $ hg up 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg add ccc - $ hg commit -m 'CC' - created new head - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 2 default draft CC - - o 1 default draft CB - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote head 9fe81b7f425d! - (merge or see "hg help push" for details about pushing new heads) - [255] - $ hg outgoing -r 'desc(CB)' -G - comparing with $TESTTMP/main (glob) - searching for changes - o 1 default draft CB - - $ hg push -r 'desc(CB)' - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files - -Pushing a new branch - - $ hg branch mountain - marked working directory as branch mountain - (branches are permanent and global, did you want a bookmark?) - $ hg commit --amend - $ hg outgoing -G - comparing with $TESTTMP/main (glob) - searching for changes - @ 4 mountain draft CC - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote branches: mountain! - (use 'hg push --new-branch' to create new remote branches) - [255] - $ hg push --new-branch - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - 2 new obsolescence markers - -Including on non-publishing - - $ hg push --new-branch draft - pushing to $TESTTMP/draft (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - 2 new obsolescence markers - -Testing topic behavior -====================== - -Local peer tests ----------------- - - $ hg up -r 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic babar - $ echo aaa > ddd - $ hg add ddd - $ hg commit -m 'CD' - $ hg log -G # keep track of phase because I saw some strange bug during developement - @ 5 default babar draft CD - | - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server should not be seen as a new head - - $ hg push draft - pushing to $TESTTMP/draft (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - $ hg log -G - @ 5 default babar draft CD - | - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a publishing server should be seen as a new head - - $ hg push - pushing to $TESTTMP/main (glob) - searching for changes - abort: push creates new remote head 67f579af159d! - (merge or see "hg help push" for details about pushing new heads) - [255] - $ hg log -G - @ 5 default babar draft CD - | - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -wireprotocol tests ------------------- - - $ hg up -r 'desc(CA)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic celeste - $ echo aaa > eee - $ hg add eee - $ hg commit -m 'CE' - $ hg log -G # keep track of phase because I saw some strange bug during developement - @ 6 default celeste draft CE - | - | o 5 default babar draft CD - |/ - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server without topic -> new head - - $ cat << EOF >> ../draft/.hg/hgrc - > [extensions] - > topic=! - > EOF - $ hg push ssh://user@dummy/draft - pushing to ssh://user@dummy/draft - searching for changes - abort: push creates new remote head 84eaf32db6c3! - (merge or see "hg help push" for details about pushing new heads) - [255] - $ hg log -G - @ 6 default celeste draft CE - | - | o 5 default babar draft CD - |/ - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a non publishing server should not be seen as a new head - - $ printf "topic=" >> ../draft/.hg/hgrc - $ hg config extensions.topic >> ../draft/.hg/hgrc - $ hg push ssh://user@dummy/draft - pushing to ssh://user@dummy/draft - searching for changes - remote: adding changesets - remote: adding manifests - remote: adding file changes - remote: added 1 changesets with 1 changes to 1 files (+1 heads) - $ hg log -G - @ 6 default celeste draft CE - | - | o 5 default babar draft CD - |/ - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Pushing a new topic to a publishing server should be seen as a new head - - $ hg push ssh://user@dummy/main - pushing to ssh://user@dummy/main - searching for changes - abort: push creates new remote head 67f579af159d! - (merge or see "hg help push" for details about pushing new heads) - [255] - $ hg log -G - @ 6 default celeste draft CE - | - | o 5 default babar draft CD - |/ - | o 4 mountain public CC - |/ - | o 1 default public CB - |/ - o 0 default public CA - - -Check that we reject multiple head on the same topic ----------------------------------------------------- - - $ hg up 'desc(CB)' - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic babar - $ echo aaa > fff - $ hg add fff - $ hg commit -m 'CF' - $ hg log -G - @ 7 default babar draft CF - | - | o 6 default celeste draft CE - | | - | | o 5 default babar draft CD - | |/ - | | o 4 mountain public CC - | |/ - o | 1 default public CB - |/ - o 0 default public CA - - - $ hg push draft - pushing to $TESTTMP/draft (glob) - searching for changes - abort: push creates new remote head f0bc62a661be on branch 'default:babar'! - (merge or see "hg help push" for details about pushing new heads) - [255] - -Multiple head on a branch merged in a topic changesets ------------------------------------------------------------------------- - - - $ hg up 'desc(CA)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo aaa > ggg - $ hg add ggg - $ hg commit -m 'CG' - created new head - $ hg up 'desc(CF)' - switching to topic babar - 2 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg merge 'desc(CG)' - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - (branch merge, don't forget to commit) - $ hg commit -m 'CM' - $ hg log -G - @ 9 default babar draft CM - |\ - | o 8 default draft CG - | | - o | 7 default babar draft CF - | | - | | o 6 default celeste draft CE - | |/ - | | o 5 default babar draft CD - | |/ - | | o 4 mountain public CC - | |/ - o | 1 default public CB - |/ - o 0 default public CA - - -Reject when pushing to draft - - $ hg push draft -r . - pushing to $TESTTMP/draft (glob) - searching for changes - abort: push creates new remote head 4937c4cad39e! - (merge or see "hg help push" for details about pushing new heads) - [255] - - -Reject when pushing to publishing - - $ hg push -r . - pushing to $TESTTMP/main (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 2 changes to 2 files - - $ cd .. - -Test phase move -================================== - -setup, two repo knowns about two small topic branch - - $ hg init repoA - $ hg clone repoA repoB - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat << EOF >> repoA/.hg/hgrc - > [phases] - > publish=False - > EOF - $ cat << EOF >> repoB/.hg/hgrc - > [phases] - > publish=False - > EOF - $ cd repoA - $ echo aaa > base - $ hg add base - $ hg commit -m 'CBASE' - $ echo aaa > aaa - $ hg add aaa - $ hg topic topicA - $ hg commit -m 'CA' - $ hg up 'desc(CBASE)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo aaa > bbb - $ hg add bbb - $ hg topic topicB - $ hg commit -m 'CB' - $ cd .. - $ hg push -R repoA repoB - pushing to repoB - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 3 files (+1 heads) - $ hg log -G -R repoA - @ 2 default topicB draft CB - | - | o 1 default topicA draft CA - |/ - o 0 default draft CBASE - - -We turn different topic to public on each side, - - $ hg -R repoA phase --public topicA - $ hg -R repoB phase --public topicB - -Pushing should complain because it create to heads on default - - $ hg push -R repoA repoB - pushing to repoB - searching for changes - no changes found - abort: push create a new head on branch "default" - [255] diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic-stack-data.t --- a/tests/test-topic-stack-data.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -Setup -===== - - $ . "$TESTDIR/testlib/topic_setup.sh" - - $ hg init test-list - $ cd test-list - $ cat <> .hg/hgrc - > [phases] - > publish=false - > EOF - $ cat <> $HGRCPATH - > [experimental] - > # disable the new graph style until we drop 3.7 support - > graphstyle.missing = | - > # turn evolution on - > evolution=all - > EOF - - - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - -Build some basic graph ----------------------- - - $ for x in base_a base_b base_c base_d base_e ; do - > mkcommit $x - > done - -Add another branch with two heads - - $ hg up 'desc(base_a)' - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - $ hg branch lake - marked working directory as branch lake - (branches are permanent and global, did you want a bookmark?) - $ mkcommit lake_a - $ mkcommit lake_b - $ hg up 'desc(lake_a)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit lake_c - created new head - - -Add some topics ---------------- - -A simple topic that need rebasing - - $ hg up 'desc(base_c)' - 2 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg topic baz - $ mkcommit baz_a - $ mkcommit baz_b - -A simple topic with unstability - - $ hg up 'desc(base_d)' - 1 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg topic fuz - $ mkcommit fuz_a - $ mkcommit fuz_b - $ mkcommit fuz_c - $ hg up 'desc(fuz_a)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg commit --amend --message 'fuz1_a' - -A topic with multiple heads - - $ hg up 'desc(base_e)' - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg topic bar - $ mkcommit bar_a - $ mkcommit bar_b - $ mkcommit bar_c - $ hg up 'desc(bar_b)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit bar_d - $ mkcommit bar_e - $ hg up 'desc(bar_d)' - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ hg commit --amend --message 'bar1_d' - -topic 'foo' on the multi headed branch - - $ hg up 'desc(lake_a)' - 1 files updated, 0 files merged, 7 files removed, 0 files unresolved - $ hg topic foo - $ mkcommit foo_a - $ mkcommit foo_b - -Summary -------- - - $ hg summary - parent: 21:3e54b49a3113 tip - add foo_b - branch: lake - commit: (clean) - update: 2 new changesets (update) - phases: 22 draft - unstable: 3 changesets - topic: foo - $ hg log --graph -T '{desc} ({branch}) [{topic}]' - @ add foo_b (lake) [] - | - o add foo_a (lake) [] - | - | o bar1_d (default) [] - | | - | | o add bar_e (default) [] - | | | - | | x add bar_d (default) [] - | |/ - | | o add bar_c (default) [] - | |/ - | o add bar_b (default) [] - | | - | o add bar_a (default) [] - | | - | | o fuz1_a (default) [] - | | | - | | | o add fuz_c (default) [] - | | | | - | | | o add fuz_b (default) [] - | | | | - | | | x add fuz_a (default) [] - | | |/ - | | | o add baz_b (default) [] - | | | | - | | | o add baz_a (default) [] - | | | | - +-------o add lake_c (lake) [] - | | | | - +-------o add lake_b (lake) [] - | | | | - o | | | add lake_a (lake) [] - | | | | - | o | | add base_e (default) [] - | |/ / - | o / add base_d (default) [] - | |/ - | o add base_c (default) [] - | | - | o add base_b (default) [] - |/ - o add base_a (default) [] - - -Actual Testing -============== - -basic output - - $ hg topic - bar - baz - * foo - fuz - -quiet version - - $ hg topic --quiet - bar - baz - foo - fuz - -verbose - - $ hg topic --verbose - bar (on branch: default, 5 changesets, 1 troubled, 2 heads) - baz (on branch: default, 2 changesets, 2 behind) - * foo (on branch: lake, 2 changesets, ambiguous destination) - fuz (on branch: default, 3 changesets, 2 troubled, 1 behind) - -json - - $ hg topic -T json - [ - { - "active": false, - "topic": "bar" - }, - { - "active": false, - "topic": "baz" - }, - { - "active": true, - "topic": "foo" - }, - { - "active": false, - "topic": "fuz" - } - ] - -json --verbose - - $ hg topic -T json --verbose - [ - { - "active": false, - "branches+": "default", - "changesetcount": 5, - "headcount": 2, - "topic": "bar", - "troubledcount": 1 - }, - { - "active": false, - "behindcount": 2, - "branches+": "default", - "changesetcount": 2, - "topic": "baz" - }, - { - "active": true, - "behinderror": "ambiguous destination", - "branches+": "lake", - "changesetcount": 2, - "topic": "foo" - }, - { - "active": false, - "behindcount": 1, - "branches+": "default", - "changesetcount": 3, - "topic": "fuz", - "troubledcount": 2 - } - ] - -Also test this situation with 'hg stack' -======================================= - - $ hg stack bar - ### topic: bar (2 heads) - ### branch: default - t5: add bar_c - t2^ add bar_b (base) - t4$ add bar_e (unstable) - t3: bar1_d - t2: add bar_b - t1: add bar_a - ^ add base_e - $ hg stack baz - ### topic: baz - ### branch: default, 2 behind - t2: add baz_b - t1: add baz_a - ^ add base_c - $ hg stack foo - ### topic: foo - ### branch: lake, ambigious rebase destination - t2@ add foo_b (current) - t1: add foo_a - ^ add lake_a - $ hg stack fuz - ### topic: fuz - ### branch: default, 1 behind - t3$ add fuz_c (unstable) - t2$ add fuz_b (unstable) - t1: fuz1_a - ^ add base_d diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic-stack.t --- a/tests/test-topic-stack.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,254 +0,0 @@ - $ . "$TESTDIR/testlib/topic_setup.sh" - -Initial setup - - - $ cat << EOF >> $HGRCPATH - > [ui] - > logtemplate = {rev} {branch} \{{get(namespaces, "topics")}} {phase} {desc|firstline}\n - > [experimental] - > evolution=createmarkers,exchange,allowunstable - > EOF - - $ hg init main - $ cd main - $ hg topic other - $ echo aaa > aaa - $ hg add aaa - $ hg commit -m c_a - $ echo aaa > bbb - $ hg add bbb - $ hg commit -m c_b - $ hg topic foo - $ echo aaa > ccc - $ hg add ccc - $ hg commit -m c_c - $ echo aaa > ddd - $ hg add ddd - $ hg commit -m c_d - $ echo aaa > eee - $ hg add eee - $ hg commit -m c_e - $ echo aaa > fff - $ hg add fff - $ hg commit -m c_f - $ hg log -G - @ 5 default {foo} draft c_f - | - o 4 default {foo} draft c_e - | - o 3 default {foo} draft c_d - | - o 2 default {foo} draft c_c - | - o 1 default {other} draft c_b - | - o 0 default {other} draft c_a - - -Check that topic without any parent does not crash --list ---------------------------------------------------------- - - $ hg up other - switching to topic other - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - $ hg topic --list - ### topic: other - ### branch: default - t2@ c_b (current) - t1: c_a - $ hg phase --public 'topic("other")' - $ hg up foo - switching to topic foo - 4 files updated, 0 files merged, 0 files removed, 0 files unresolved - -Simple test ------------ - -'hg stack' list all changeset in the topic - - $ hg topic - * foo - $ hg stack - ### topic: foo - ### branch: default - t4@ c_f (current) - t3: c_e - t2: c_d - t1: c_c - ^ c_b - -error case, nothing to list - - $ hg topic --clear - $ hg stack - abort: no active topic to list - [255] - -Test "t#" reference -------------------- - - - $ hg up t2 - abort: cannot resolve "t2": no active topic - [255] - $ hg topic foo - $ hg up t42 - abort: cannot resolve "t42": topic "foo" has only 4 changesets - [255] - $ hg up t2 - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg summary - parent: 3:e629654d7050 - c_d - branch: default - commit: (clean) - update: (current) - phases: 4 draft - topic: foo - -Case with some of the topic unstable ------------------------------------- - - $ echo bbb > ddd - $ hg commit --amend - $ hg log -G - @ 7 default {foo} draft c_d - | - | o 5 default {foo} draft c_f - | | - | o 4 default {foo} draft c_e - | | - | x 3 default {foo} draft c_d - |/ - o 2 default {foo} draft c_c - | - o 1 default {} public c_b - | - o 0 default {} public c_a - - $ hg topic --list - ### topic: foo - ### branch: default - t4$ c_f (unstable) - t3$ c_e (unstable) - t2@ c_d (current) - t1: c_c - ^ c_b - -Also test the revset: - - $ hg log -r 'stack()' - 2 default {foo} draft c_c - 7 default {foo} draft c_d - 4 default {foo} draft c_e - 5 default {foo} draft c_f - -Case with multiple heads on the topic -------------------------------------- - -Make things linear again - - $ hg rebase -s 'desc(c_e)' -d 'desc(c_d) - obsolete()' - rebasing 4:0f9ac936c87d "c_e" - rebasing 5:6559e6d93aea "c_f" - $ hg log -G - o 9 default {foo} draft c_f - | - o 8 default {foo} draft c_e - | - @ 7 default {foo} draft c_d - | - o 2 default {foo} draft c_c - | - o 1 default {} public c_b - | - o 0 default {} public c_a - - - -Create the second branch - - $ hg up 'desc(c_d)' - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo aaa > ggg - $ hg add ggg - $ hg commit -m c_g - $ echo aaa > hhh - $ hg add hhh - $ hg commit -m c_h - $ hg log -G - @ 11 default {foo} draft c_h - | - o 10 default {foo} draft c_g - | - | o 9 default {foo} draft c_f - | | - | o 8 default {foo} draft c_e - |/ - o 7 default {foo} draft c_d - | - o 2 default {foo} draft c_c - | - o 1 default {} public c_b - | - o 0 default {} public c_a - - -Test output - - $ hg top -l - ### topic: foo (2 heads) - ### branch: default - t6: c_f - t5: c_e - t2^ c_d (base) - t4@ c_h (current) - t3: c_g - t2: c_d - t1: c_c - ^ c_b - -Case with multiple heads on the topic with unstability involved ---------------------------------------------------------------- - -We amend the message to make sure the display base pick the right changeset - - $ hg up 'desc(c_d)' - 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ echo ccc > ddd - $ hg commit --amend -m 'c_D' - $ hg rebase -d . -s 'desc(c_g)' - rebasing 10:81264ae8a36a "c_g" - rebasing 11:fde5f5941642 "c_h" - $ hg log -G - o 15 default {foo} draft c_h - | - o 14 default {foo} draft c_g - | - @ 13 default {foo} draft c_D - | - | o 9 default {foo} draft c_f - | | - | o 8 default {foo} draft c_e - | | - | x 7 default {foo} draft c_d - |/ - o 2 default {foo} draft c_c - | - o 1 default {} public c_b - | - o 0 default {} public c_a - - - $ hg topic --list - ### topic: foo (2 heads) - ### branch: default - t6$ c_f (unstable) - t5$ c_e (unstable) - t2^ c_D (base) - t4: c_h - t3: c_g - t2@ c_D (current) - t1: c_c - ^ c_b diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic-tutorial.t --- a/tests/test-topic-tutorial.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,468 +0,0 @@ -============== -Topic Tutorial -============== - -.. This test file is also supposed to be able to compile as a rest file. - - -.. Some Setup:: - - $ . "$TESTDIR/testlib/topic_setup.sh" - $ hg init server - $ cd server - $ cat >> .hg/hgrc << EOF - > [ui] - > user= Shopping Master - > EOF - $ cat >> shopping << EOF - > Spam - > Whizzo butter - > Albatross - > Rat (rather a lot) - > Jugged fish - > Blancmange - > Salmon mousse - > EOF - $ hg commit -A -m "Shopping list" - adding shopping - $ cd .. - $ hg clone server client - updating to branch default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cd client - $ cat >> .hg/hgrc << EOF - > [ui] - > user= Tutorial User - > EOF - -Topic branches are lightweight branches which disappear when changes are -finalized (move to the public phase). They can help users to organise and share -their unfinished work. - -Topic Basics -============ - -Let's says we use Mercurial to manage our shopping list:: - - $ hg log --graph - @ changeset: 0:38da43f0a2ea - tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - -We are about to do some edition to this list and would like to do them within -a topic. Creating a new topic is done using the ``topic`` command:: - - $ hg topic food - -As for named branch, our topic is active but it does not contains any changesets yet:: - - $ hg topic - * food - $ hg summary - parent: 0:38da43f0a2ea tip - Shopping list - branch: default - commit: (clean) - update: (current) - topic: food - $ hg log --graph - @ changeset: 0:38da43f0a2ea - tag: tip - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - -Our next commit will be part of the active topic:: - - $ cat >> shopping << EOF - > Egg - > Suggar - > Vinegar - > Oil - > EOF - $ hg commit -m "adding condiments" - $ hg log --graph --rev 'topic("food")' - @ changeset: 1:13900241408b - | tag: tip - ~ topic: food - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: adding condiments - - -And future commit will be part of that topic too:: - - $ cat >> shopping << EOF - > Bananas - > Pear - > Apple - > EOF - $ hg commit -m "adding fruits" - $ hg log --graph --rev 'topic("food")' - @ changeset: 2:287de11b401f - | tag: tip - | topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding fruits - | - o changeset: 1:13900241408b - | topic: food - ~ user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: adding condiments - - -We can get a compact view of the content of our topic using the ``stack`` command:: - - $ hg stack - ### topic: food - ### branch: default - t2@ adding fruits (current) - t1: adding condiments - ^ Shopping list - -The topic desactivate when we update away from it:: - - $ hg up default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic - food - -Note that ``default`` (name of the branch) now refers to the tipmost changeset of default without a topic:: - - $ hg log --graph - o changeset: 2:287de11b401f - | tag: tip - | topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding fruits - | - o changeset: 1:13900241408b - | topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding condiments - | - @ changeset: 0:38da43f0a2ea - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - -And updating back to the topic reactivate it:: - - $ hg up food - switching to topic food - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic - * food - -The name used for updating does not affect the activation of the topic, updating to a revision part of a topic will activate it in all cases:: - - $ hg up default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg up --rev 'desc("condiments")' - switching to topic food - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic - * food - -.. server side activity:: - - $ cd ../server/ - $ cat > shopping << EOF - > T-Shirt - > Trousers - > Spam - > Whizzo butter - > Albatross - > Rat (rather a lot) - > Jugged fish - > Blancmange - > Salmon mousse - > EOF - $ hg commit -A -m "Adding clothes" - $ cd ../client - -Topic will also affect rebase and merge destination. Let's pull the latest update from the main server:: - - $ hg pull - pulling from $TESTTMP/server (glob) - searching for changes - 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 log -G - o changeset: 3:6104862e8b84 - | tag: tip - | parent: 0:38da43f0a2ea - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Adding clothes - | - | o changeset: 2:287de11b401f - | | topic: food - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: adding fruits - | | - | @ changeset: 1:13900241408b - |/ topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding condiments - | - o changeset: 0:38da43f0a2ea - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - -The topic head will not be considered when merge from the new head of the branch:: - - $ hg up default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg merge - abort: branch 'default' has one head - please merge with an explicit rev - (run 'hg heads' to see all heads) - [255] - -But the topic will see that branch head as a valid destination:: - - $ hg up food - switching to topic food - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg rebase - rebasing 1:13900241408b "adding condiments" - merging shopping - rebasing 2:287de11b401f "adding fruits" - merging shopping - $ hg log --graph - @ changeset: 5:2d50db8b5b4c - | tag: tip - | topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding fruits - | - o changeset: 4:4011b46eeb33 - | topic: food - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding condiments - | - o changeset: 3:6104862e8b84 - | parent: 0:38da43f0a2ea - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Adding clothes - | - o changeset: 0:38da43f0a2ea - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - -The topic information will fade out when we publish the changesets:: - - $ hg topic - food - $ hg push - pushing to $TESTTMP/server (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 1 files - 2 new obsolescence markers - $ hg topic - $ hg log --graph - @ changeset: 5:2d50db8b5b4c - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding fruits - | - o changeset: 4:4011b46eeb33 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: adding condiments - | - o changeset: 3:6104862e8b84 - | parent: 0:38da43f0a2ea - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Adding clothes - | - o changeset: 0:38da43f0a2ea - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Shopping list - - $ hg up default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - -Working with Multiple Topics -============================ - -In the above example, topic are not bring much benefit since you only have one -line of developement. Topic start to be more useful when you have to work on -multiple features are the same time. - -We might go shopping in a hardware store in the same go, so let's add some -tools to the shopping list withing a new topic:: - - $ hg topic tools - $ echo hammer >> shopping - $ hg ci -m 'Adding hammer' - $ echo saw >> shopping - $ hg ci -m 'Adding saw' - $ echo drill >> shopping - $ hg ci -m 'Adding drill' - -But are not sure to actually go in the hardward store, so in the meantime, we -want to extend the list with drinks. We go back to the official default branch -and start a new topic:: - - $ hg up default - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic drinks - $ echo 'apple juice' >> shopping - $ hg ci -m 'Adding apple juice' - $ echo 'orange juice' >> shopping - $ hg ci -m 'Adding orange juice' - -We now have two topics:: - - $ hg topic - * drinks - tools - -The information ``hg stack`` command adapt to the active topic:: - - $ hg stack - ### topic: drinks - ### branch: default - t2@ Adding orange juice (current) - t1: Adding apple juice - ^ adding fruits - $ hg up tools - switching to topic tools - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg stack - ### topic: tools - ### branch: default - t3@ Adding drill (current) - t2: Adding saw - t1: Adding hammer - ^ adding fruits - -They are seen as independant branch by Mercurial. No rebase or merge betwen them will be attempted by default:: - - $ hg rebase - nothing to rebase - [1] - -.. server activity:: - - $ cd ../server - $ hg up - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ mv shopping foo - $ echo 'Coat' > shopping - $ cat foo >> shopping - $ hg ci -m 'add a coat' - $ echo 'Coat' > shopping - $ echo 'Shoes' >> shopping - $ cat foo >> shopping - $ hg rm foo - not removing foo: file is untracked - [1] - $ hg ci -m 'add a pair of shoes' - $ cd ../client - -Lets see what other people did in the mean time:: - - $ hg pull - pulling from $TESTTMP/server (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 1 files (+1 heads) - (run 'hg heads' to see heads) - -There is new changes! We can simply use ``hg rebase`` to update our changeset on top of the latest:: - - $ hg rebase - rebasing 6:183984ef46d1 "Adding hammer" - merging shopping - rebasing 7:cffff85af537 "Adding saw" - merging shopping - rebasing 8:34255b455dac "Adding drill" - merging shopping - -But what about the other topic? You can use 'hg topic --verbose' to see information about them:: - - $ hg topic --verbose - drinks (on branch: default, 2 changesets, 2 behind) - tools (on branch: default, 3 changesets) - -The "2 behind" is telling you that there is 2 new changesets on the named branch of the topic. You need to merge or rebase to incorporate them. - -Pushing that topic would create a new heads will be prevented:: - - $ hg push --rev drinks - pushing to $TESTTMP/server (glob) - searching for changes - abort: push creates new remote head 70dfa201ed73! - (merge or see "hg help push" for details about pushing new heads) - [255] - - -Even after a rebase Pushing all active topics at the same time will complains about the multiple heads it would create on that branch:: - - $ hg rebase -b drinks - rebasing 9:8dfa45bd5e0c "Adding apple juice" - merging shopping - rebasing 10:70dfa201ed73 "Adding orange juice" - merging shopping - switching to topic tools - $ hg push - pushing to $TESTTMP/server (glob) - searching for changes - abort: push creates new remote head 4cd7c1591a67! - (merge or see "hg help push" for details about pushing new heads) - [255] - -Publishing only one of them is allowed (as long as it does not create a new branch head has we just saw in the previous case):: - - $ hg push -r drinks - pushing to $TESTTMP/server (glob) - searching for changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 1 files - 2 new obsolescence markers - -The publishing topic has now vanished, and the one still draft is now marked as "behind":: - - $ hg topic --verbose - * tools (on branch: default, 3 changesets, 2 behind) - $ hg stack - ### topic: tools - ### branch: default, 2 behind - t3@ Adding drill (current) - t2: Adding saw - t1: Adding hammer - ^ add a pair of shoes - diff -r 979a8ea17e1e -r 37deace44b36 tests/test-topic.t --- a/tests/test-topic.t Wed May 03 13:52:19 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,654 +0,0 @@ - $ . "$TESTDIR/testlib/topic_setup.sh" - - $ hg init pinky - $ cd pinky - $ cat <> .hg/hgrc - > [phases] - > publish=false - > EOF - $ cat <> $HGRCPATH - > [experimental] - > # disable the new graph style until we drop 3.7 support - > graphstyle.missing = | - > EOF - - $ hg help topics - hg topics [TOPIC] - - View current topic, set current topic, or see all topics. - - The --verbose version of this command display various information on the - state of each topic. - - options: - - --clear clear active topic if any - --change VALUE revset of existing revisions to change topic - -l --list show the stack of changeset in the topic - - (some details hidden, use --verbose to show complete help) - $ hg topics - -Test topics interaction with evolution: - - $ hg topics --config experimental.evolution= - $ hg topics --config experimental.evolution= --change . bob - abort: must have obsolete enabled to use --change - [255] - -Create some changes: - - $ for x in alpha beta gamma delta ; do - > echo file $x >> $x - > hg addremove - > hg ci -m "Add file $x" - > done - adding alpha - adding beta - adding gamma - adding delta - -Still no topics - $ hg topics - -Test commit flag and help text - - $ echo stuff >> alpha - $ HGEDITOR=cat hg ci -t topicflag - - - HG: Enter commit message. Lines beginning with 'HG:' are removed. - HG: Leave message empty to abort commit. - HG: -- - HG: user: test - HG: topic 'topicflag' - HG: branch 'default' - HG: changed alpha - abort: empty commit message - [255] - $ hg revert alpha - $ hg topic - * topicflag - -Make a topic - $ hg topic narf - $ hg topics - * narf - $ echo topic work >> alpha - $ hg ci -m 'start on narf' - $ hg co .^ - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic fran - $ hg topics - * fran - narf - $ echo >> fran work >> beta - $ hg ci -m 'start on fran' - $ hg co narf - switching to topic narf - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg topic - fran - * narf - $ hg log -r . -T '{topics}\n' - narf - $ echo 'narf!!!' >> alpha - $ hg ci -m 'narf!' - $ hg log -G - @ changeset: 6:7c34953036d6 - | tag: tip - | topic: narf - | parent: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: narf! - | - | o changeset: 5:0469d521db49 - | | topic: fran - | | parent: 3:a53952faf762 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: start on fran - | | - o | changeset: 4:fb147b0b417c - |/ topic: narf - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - o changeset: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file delta - | - o changeset: 2:15d1eb11d2fa - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file gamma - | - o changeset: 1:c692ea2c9224 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file beta - | - o changeset: 0:c2b7d2f7d14b - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Add file alpha - - -Exchanging of topics: - $ cd .. - $ hg init brain - $ hg -R pinky push -r 4 brain - pushing to brain - searching for changes - adding changesets - adding manifests - adding file changes - added 5 changesets with 5 changes to 4 files - -Export - - $ hg -R pinky export - # HG changeset patch - # User test - # Date 0 0 - # Thu Jan 01 00:00:00 1970 +0000 - # Node ID 7c34953036d6a36eae468c550d0592b89ee8bffc - # Parent fb147b0b417c25ca15547cd945acf51cf8dcaf02 - # EXP-Topic narf - narf! - - diff -r fb147b0b417c -r 7c34953036d6 alpha - --- a/alpha Thu Jan 01 00:00:00 1970 +0000 - +++ b/alpha Thu Jan 01 00:00:00 1970 +0000 - @@ -1,2 +1,3 @@ - file alpha - topic work - +narf!!! - -Import - - $ hg -R pinky export > narf.diff - $ hg -R pinky --config extensions.strip= strip . - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - saved backup bundle to $TESTTMP/pinky/.hg/strip-backup/7c34953036d6-1ff3bae2-backup.hg (glob) - $ hg -R pinky import narf.diff - applying narf.diff - $ hg -R pinky log -r . - changeset: 6:7c34953036d6 - tag: tip - topic: narf - parent: 4:fb147b0b417c - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: narf! - -Now that we've pushed to brain, the work done on narf is no longer a -draft, so we won't see that topic name anymore: - - $ hg log -R pinky -G - @ changeset: 6:7c34953036d6 - | tag: tip - | topic: narf - | parent: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: narf! - | - | o changeset: 5:0469d521db49 - | | topic: fran - | | parent: 3:a53952faf762 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: start on fran - | | - o | changeset: 4:fb147b0b417c - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - o changeset: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file delta - | - o changeset: 2:15d1eb11d2fa - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file gamma - | - o changeset: 1:c692ea2c9224 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file beta - | - o changeset: 0:c2b7d2f7d14b - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Add file alpha - - $ cd brain - $ hg co tip - 4 files updated, 0 files merged, 0 files removed, 0 files unresolved - -Because the change is public, we won't inherit the topic from narf. - - $ hg topic - $ echo what >> alpha - $ hg topic query - $ hg ci -m 'what is narf, pinky?' - $ hg log -Gl2 - @ changeset: 5:c01515cfc331 - | tag: tip - | topic: query - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: what is narf, pinky? - | - o changeset: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - $ hg push -f ../pinky -r query - pushing to ../pinky - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - $ hg -R ../pinky log -Gl 4 - o changeset: 7:c01515cfc331 - | tag: tip - | topic: query - | parent: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: what is narf, pinky? - | - | @ changeset: 6:7c34953036d6 - |/ topic: narf - | parent: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: narf! - | - | o changeset: 5:0469d521db49 - | | topic: fran - | | parent: 3:a53952faf762 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: start on fran - | | - o | changeset: 4:fb147b0b417c - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - $ hg topics - * query - $ cd ../pinky - $ hg co query - switching to topic query - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo answer >> alpha - $ hg ci -m 'Narf is like `zort` or `poit`!' - $ hg merge narf - merging alpha - warning: conflicts while merging alpha! (edit, then use 'hg resolve --mark') - 0 files updated, 0 files merged, 0 files removed, 1 files unresolved - use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon - [1] - $ hg revert -r narf alpha - $ hg resolve -m alpha - (no more unresolved files) - $ hg topic narf - $ hg ci -m 'Finish narf' - $ hg topics - fran - * narf - query - $ hg debugnamecomplete # branch:topic here is a buggy side effect - default - default:fran - default:narf - default:query - fran - narf - query - tip - $ hg phase --public narf - -POSSIBLE BUG: narf topic stays alive even though we just made all -narf commits public: - - $ hg topics - fran - * narf - $ hg log -Gl 6 - @ changeset: 9:ae074045b7a7 - |\ tag: tip - | | parent: 8:54c943c1c167 - | | parent: 6:7c34953036d6 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: Finish narf - | | - | o changeset: 8:54c943c1c167 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: Narf is like `zort` or `poit`! - | | - | o changeset: 7:c01515cfc331 - | | parent: 4:fb147b0b417c - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: what is narf, pinky? - | | - o | changeset: 6:7c34953036d6 - |/ parent: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: narf! - | - | o changeset: 5:0469d521db49 - | | topic: fran - | | parent: 3:a53952faf762 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: start on fran - | | - o | changeset: 4:fb147b0b417c - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - $ cd ../brain - $ hg topics - * query - $ hg pull ../pinky -r narf - pulling from ../pinky - abort: unknown revision 'narf'! - [255] - $ hg pull ../pinky -r default - pulling from ../pinky - searching for changes - adding changesets - adding manifests - adding file changes - added 3 changesets with 3 changes to 1 files - (run 'hg update' to get a working copy) - $ hg topics - * query - -We can pull in the draft-phase change and we get the new topic - - $ hg pull ../pinky - pulling from ../pinky - searching for changes - 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 topics - fran - * query - $ hg log -Gr 'draft()' - o changeset: 9:0469d521db49 - | tag: tip - | topic: fran - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - -query is not an open topic, so when we clear the current topic it'll -disappear: - - $ hg topics --clear - $ hg topics - fran - ---clear when we don't have an active topic isn't an error: - - $ hg topics --clear - -Topic revset - $ hg log -r 'topic()' -G - o changeset: 9:0469d521db49 - | tag: tip - | topic: fran - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - $ hg log -r 'not topic()' -G - o changeset: 8:ae074045b7a7 - |\ parent: 7:54c943c1c167 - | | parent: 6:7c34953036d6 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: Finish narf - | | - | o changeset: 7:54c943c1c167 - | | parent: 5:c01515cfc331 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: Narf is like `zort` or `poit`! - | | - o | changeset: 6:7c34953036d6 - | | parent: 4:fb147b0b417c - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: narf! - | | - | @ changeset: 5:c01515cfc331 - |/ user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: what is narf, pinky? - | - o changeset: 4:fb147b0b417c - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on narf - | - o changeset: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file delta - | - o changeset: 2:15d1eb11d2fa - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file gamma - | - o changeset: 1:c692ea2c9224 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: Add file beta - | - o changeset: 0:c2b7d2f7d14b - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: Add file alpha - -No matches because narf is already closed: - $ hg log -r 'topic(narf)' -G -This regexp should match the topic `fran`: - $ hg log -r 'topic("re:.ra.")' -G - o changeset: 9:0469d521db49 - | tag: tip - | topic: fran - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | -Exact match on fran: - $ hg log -r 'topic(fran)' -G - o changeset: 9:0469d521db49 - | tag: tip - | topic: fran - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - -Match current topic: - $ hg topic - fran - $ hg log -r 'topic(.)' -(no output is expected) - $ hg co fran - switching to topic fran - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg log -r 'topic(.)' - changeset: 9:0469d521db49 - tag: tip - topic: fran - parent: 3:a53952faf762 - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: start on fran - - -Deactivate the topic. - $ hg topics - * fran - $ hg topics --clear - $ echo fran? >> beta - $ hg ci -m 'fran?' - created new head - $ hg log -Gr 'draft()' - @ changeset: 10:4073470c35e1 - | tag: tip - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: fran? - | - o changeset: 9:0469d521db49 - | topic: fran - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - $ hg topics - fran -Changing topic fails if we don't give a topic - $ hg topic --change 9 - abort: changing topic requires a topic name or --clear - [255] - -Can't change topic of a public change - $ hg topic --change 1:: --clear - abort: can't change topic of a public change - [255] - -Can clear topics - $ hg topic --change 9 --clear - changed topic on 1 changes - please run hg evolve --rev "not topic()" now - $ hg log -Gr 'draft() and not obsolete()' - o changeset: 11:783930e1d79e - | tag: tip - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - | @ changeset: 10:4073470c35e1 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: fran? - | | - -Normally you'd do this with evolve, but we'll use rebase to avoid -bonus deps in the testsuite. - - $ hg rebase -d tip -s . - rebasing 10:4073470c35e1 "fran?" - -Can add a topic to an existing change - $ hg topic --change 11 wat - changed topic on 1 changes - please run hg evolve --rev "topic(wat)" now - $ hg log -Gr 'draft() and not obsolete()' - o changeset: 13:d91cd8fd490e - | tag: tip - | topic: wat - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - | @ changeset: 12:d9e32f4c4806 - | | user: test - | | date: Thu Jan 01 00:00:00 1970 +0000 - | | summary: fran? - | | - -Normally you'd do this with evolve, but we'll use rebase to avoid -bonus deps in the testsuite. - - $ hg rebase -d tip -s . - rebasing 12:d9e32f4c4806 "fran?" - - $ hg log -Gr 'draft()' - @ changeset: 14:cf24ad8bbef5 - | tag: tip - | topic: wat - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: fran? - | - o changeset: 13:d91cd8fd490e - | topic: wat - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - -Amend a topic - - $ hg topic watwat - $ hg ci --amend - $ hg log -Gr 'draft()' - @ changeset: 16:893ffcf66c1f - | tag: tip - | topic: watwat - | parent: 13:d91cd8fd490e - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: fran? - | - o changeset: 13:d91cd8fd490e - | topic: wat - | parent: 3:a53952faf762 - | user: test - | date: Thu Jan 01 00:00:00 1970 +0000 - | summary: start on fran - | - -Clear and amend: - - $ hg topic --clear - $ hg ci --amend - $ hg log -r . - changeset: 18:a13639e22b65 - tag: tip - parent: 13:d91cd8fd490e - user: test - date: Thu Jan 01 00:00:00 1970 +0000 - summary: fran? - -Readding the same topic with topic --change should work: - $ hg topic --change . watwat - changed topic on 1 changes diff -r 979a8ea17e1e -r 37deace44b36 tests/test-wireproto-bundle1.t diff -r 979a8ea17e1e -r 37deace44b36 tests/test-wireproto.t