# HG changeset patch # User Pierre-Yves David # Date 1509576715 -3600 # Node ID f42a87cc864de3eeafaf17e942ccc223433bfe79 # Parent c3953ae44b879687e1af24cc7aff3d8b80e3dc84# Parent 90515d0bfb08eef1db5d7c10749b92e1c8717c6a branching: merge with stable to prepare version 7.0.0 diff -r c3953ae44b87 -r f42a87cc864d CHANGELOG --- a/CHANGELOG Mon Oct 23 16:04:23 2017 +0200 +++ b/CHANGELOG Wed Nov 01 23:51:55 2017 +0100 @@ -1,6 +1,23 @@ Changelog ========= +7.0.0 - in progress +------------------- + + * drop compatibility with Mercurial 3.8, 3.9 and 4.0, + * drop support for old and deprecated method to exchange obsmarkers, + * forbid usage of the old pushbey based protocol to exchange obsmarkers, + * evolve: rename '--contentdivergent' flag to '--content-divergent' + * evolve: rename '--phasedivergent' flag to '--phase-divergent' + +topic + + * add an experimental flag to enforce one head per name policy, + (off by default, see 'hg help -e topic' for details) + * add an experimental flag to have changesets without topic published on push, + (off by default, see 'hg help -e topic' for details) + * add a '--publish' flag to `hg push` (4.4+ only), + 6.8.0 -- 2017-10-23 ------------------- diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/__init__.py --- a/hgext3rd/evolve/__init__.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/__init__.py Wed Nov 01 23:51:55 2017 +0100 @@ -32,7 +32,7 @@ backported to older version of Mercurial by this extension. Some older experimental protocol are also supported for a longer time in the extensions to help people transitioning. (The extensions is currently compatible down to -Mercurial version 3.8). +Mercurial version 4.1). New Config:: @@ -420,6 +420,8 @@ if not evolveopts: evolveopts = ['all'] ui.setconfig('experimental', 'evolution', evolveopts, 'evolve') + if obsolete.isenabled(repo, 'exchange'): + repo.ui.setconfig('server', 'bundle1', False) @eh.uisetup def _configurecmdoptions(ui): @@ -703,7 +705,7 @@ if reason == 'pruned': solvemsg = _("use 'hg evolve' to update to its parent successor") elif reason == 'diverged': - debugcommand = "hg evolve --list --contentdivergent" + debugcommand = "hg evolve --list --content-divergent" basemsg = _("%s has diverged, use '%s' to resolve the issue") solvemsg = basemsg % (shortnode, debugcommand) elif reason == 'superseed': @@ -1058,28 +1060,28 @@ } hintmap = { - 'phasedivergent': _("do you want to use --phasedivergent"), + 'phasedivergent': _("do you want to use --phase-divergent"), 'phasedivergent+contentdivergent': _("do you want to use " - "--phasedivergent or" - " --contentdivergent"), - 'phasedivergent+orphan': _("do you want to use --phasedivergent" + "--phase-divergent or" + " --content-divergent"), + 'phasedivergent+orphan': _("do you want to use --phase-divergent" " or --orphan"), - 'contentdivergent': _("do you want to use --contentdivergent"), - 'contentdivergent+orphan': _("do you want to use --contentdivergent" + 'contentdivergent': _("do you want to use --content-divergent"), + 'contentdivergent+orphan': _("do you want to use --content-divergent" " or --orphan"), 'orphan': _("do you want to use --orphan"), 'any+phasedivergent': _("do you want to use --any (or --rev) and" - " --phasedivergent"), + " --phase-divergent"), 'any+phasedivergent+contentdivergent': _("do you want to use --any" " (or --rev) and" - " --phasedivergent or" - " --contentdivergent"), + " --phase-divergent or" + " --content-divergent"), 'any+phasedivergent+orphan': _("do you want to use --any (or --rev)" - " and --phasedivergent or --orphan"), + " and --phase-divergent or --orphan"), 'any+contentdivergent': _("do you want to use --any (or --rev) and" - " --contentdivergent"), + " --content-divergent"), 'any+contentdivergent+orphan': _("do you want to use --any (or --rev)" - " and --contentdivergent or " + " and --content-divergent or " "--orphan"), 'any+orphan': _("do you want to use --any (or --rev)" "and --orphan"), @@ -1416,9 +1418,9 @@ 'directory')), ('r', 'rev', [], _('solves troubles of these revisions')), ('', 'bumped', False, _('solves only bumped changesets')), - ('', 'phasedivergent', False, _('solves only phase-divergent changesets')), + ('', 'phase-divergent', False, _('solves only phase-divergent changesets')), ('', 'divergent', False, _('solves only divergent changesets')), - ('', 'contentdivergent', False, _('solves only content-divergent changesets')), + ('', 'content-divergent', False, _('solves only content-divergent changesets')), ('', 'unstable', False, _('solves only unstable changesets')), ('', 'orphan', False, _('solves only orphan changesets (default)')), ('a', 'all', False, _('evolve all troubled changesets related to the ' @@ -1518,20 +1520,22 @@ if opts['divergent']: msg = ("'evolve --divergent' is deprecated, " - "use 'evolve --contentdivergent'") + "use 'evolve --content-divergent'") repo.ui.deprecwarn(msg, '4.4') - opts['contentdivergent'] = opts['divergent'] + opts['content_divergent'] = opts['divergent'] if opts['bumped']: msg = ("'evolve --bumped' is deprecated, " - "use 'evolve --phasedivergent'") + "use 'evolve --phase-divergent'") repo.ui.deprecwarn(msg, '4.4') - opts['phasedivergent'] = opts['bumped'] + opts['phase_divergent'] = opts['bumped'] - troublecategories = ['phasedivergent', 'contentdivergent', 'orphan'] - specifiedcategories = [t for t in troublecategories if opts[t]] + troublecategories = ['phase_divergent', 'content_divergent', 'orphan'] + specifiedcategories = [t.replace('_', '') + for t in troublecategories + if opts[t]] if listopt: compat.startpager(ui, 'evolve') listtroubles(ui, repo, specifiedcategories, **opts) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/hack/directaccess.py --- a/hgext3rd/evolve/hack/directaccess.py Mon Oct 23 16:04:23 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -""" This extension provides direct access -It is the ability to refer and access hidden sha in commands provided that you -know their value. -For example hg log -r xxx where xxx is a commit has should work whether xxx is -hidden or not as we assume that the user knows what he is doing when referring -to xxx. -""" -from mercurial import extensions -from mercurial import repoview -from mercurial import branchmap -from mercurial import registrar -from mercurial import revset -from mercurial import error -from mercurial import commands -from mercurial import hg -from mercurial import util -from mercurial.i18n import _ - -cmdtable = {} - -if util.safehasattr(registrar, 'command'): - command = registrar.command(cmdtable) -else: # compat with hg < 4.3 - from mercurial import cmdutil - command = cmdutil.command(cmdtable) - -if util.safehasattr(registrar, 'configitem'): - configtable = {} - configitem = registrar.configitem(configtable) - - configitem('directaccess', 'loadsafter', - default=[], - ) - -# By default, all the commands have directaccess with warnings -# List of commands that have no directaccess and directaccess with no warning -directaccesslevel = [ - # Format: - # ('nowarning', 'evolve', 'prune'), - # means: no directaccess warning, for the command in evolve named prune - # - # ('error', None, 'serve'), - # means: no directaccess for the command in core named serve - # - # The list is ordered alphabetically by command names, starting with all - # the commands in core then all the commands in the extensions - # - # The general guideline is: - # - remove directaccess warnings for read only commands - # - no direct access for commands with consequences outside of the repo - # - leave directaccess warnings for all the other commands - # - ('nowarning', None, 'annotate'), - ('nowarning', None, 'archive'), - ('nowarning', None, 'bisect'), - ('nowarning', None, 'bookmarks'), - ('nowarning', None, 'bundle'), - ('nowarning', None, 'cat'), - ('nowarning', None, 'diff'), - ('nowarning', None, 'export'), - ('nowarning', None, 'identify'), - ('nowarning', None, 'incoming'), - ('nowarning', None, 'log'), - ('nowarning', None, 'manifest'), - ('error', None, 'outgoing'), # confusing if push errors and not outgoing - ('error', None, 'push'), # destructive - ('nowarning', None, 'revert'), - ('error', None, 'serve'), - ('nowarning', None, 'tags'), - ('nowarning', None, 'unbundle'), - ('nowarning', None, 'update'), -] - -def reposetup(ui, repo): - repo._explicitaccess = set() - -def _computehidden(repo): - hidden = repoview.filterrevs(repo, 'visible') - cl = repo.changelog - dynamic = hidden & repo._explicitaccess - if dynamic: - blocked = cl.ancestors(dynamic, inclusive=True) - hidden = frozenset(r for r in hidden if r not in blocked) - return hidden - -def setupdirectaccess(): - """ Add two new filtername that behave like visible to provide direct access - and direct access with warning. Wraps the commands to setup direct access - """ - repoview.filtertable.update({'visible-directaccess-nowarn': _computehidden}) - repoview.filtertable.update({'visible-directaccess-warn': _computehidden}) - branchmap.subsettable['visible-directaccess-nowarn'] = 'visible' - branchmap.subsettable['visible-directaccess-warn'] = 'visible' - - for warn, ext, cmd in directaccesslevel: - try: - cmdtable = extensions.find(ext).cmdtable if ext else commands.table - wrapper = wrapwitherror if warn == 'error' else wrapwithoutwarning - extensions.wrapcommand(cmdtable, cmd, wrapper) - except (error.UnknownCommand, KeyError): - pass - -def wrapwitherror(orig, ui, repo, *args, **kwargs): - if repo and repo.filtername == 'visible-directaccess-warn': - repo = repo.filtered('visible') - return orig(ui, repo, *args, **kwargs) - -def wrapwithoutwarning(orig, ui, repo, *args, **kwargs): - if repo and repo.filtername == 'visible-directaccess-warn': - repo = repo.filtered("visible-directaccess-nowarn") - return orig(ui, repo, *args, **kwargs) - -def uisetup(ui): - """ Change ordering of extensions to ensure that directaccess extsetup comes - after the one of the extensions in the loadsafter list """ - loadsafter = ui.configlist('directaccess', 'loadsafter') - order = list(extensions._order) - directaccesidx = order.index('directaccess') - - # The min idx for directaccess to load after all the extensions in loadafter - minidxdirectaccess = directaccesidx - - for ext in loadsafter: - try: - minidxdirectaccess = max(minidxdirectaccess, order.index(ext)) - except ValueError: - pass # extension not loaded - - if minidxdirectaccess > directaccesidx: - order.insert(minidxdirectaccess + 1, 'directaccess') - order.remove('directaccess') - extensions._order = order - -def _repository(orig, *args, **kwargs): - """Make visible-directaccess-warn the default filter for new repos""" - repo = orig(*args, **kwargs) - return repo.filtered("visible-directaccess-warn") - -def extsetup(ui): - extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook) - extensions.wrapfunction(hg, 'repository', _repository) - setupdirectaccess() - -hashre = util.re.compile('[0-9a-fA-F]{1,40}') - -_listtuple = ('symbol', '_list') - -def _ishashsymbol(symbol, maxrev): - # Returns true if symbol looks like a hash - try: - n = int(symbol) - if n <= maxrev: - # It's a rev number - return False - except ValueError: - pass - return hashre.match(symbol) - -def gethashsymbols(tree, maxrev): - # Returns the list of symbols of the tree that look like hashes - # for example for the revset 3::abe3ff it will return ('abe3ff') - if not tree: - return [] - - results = [] - if len(tree) in (2, 3) and tree[0] == "symbol": - results.append(tree[1]) - elif tree[0] == "func" and tree[1] == _listtuple: - # the optimiser will group sequence of hash request - results += tree[2][1].split('\0') - elif len(tree) >= 2: - for subtree in tree[1:]: - results += gethashsymbols(subtree, maxrev) - # return directly, we don't need to filter symbols again - return results - return [s for s in results if _ishashsymbol(s, maxrev)] - -def _posttreebuilthook(orig, tree, repo): - # This is use to enabled direct hash access - # We extract the symbols that look like hashes and add them to the - # explicitaccess set - orig(tree, repo) - filternm = "" - if repo is not None: - filternm = repo.filtername - if filternm is not None and filternm.startswith('visible-directaccess'): - prelength = len(repo._explicitaccess) - accessbefore = set(repo._explicitaccess) - cl = repo.unfiltered().changelog - repo.symbols = gethashsymbols(tree, len(cl)) - for node in repo.symbols: - try: - node = cl._partialmatch(node) - except error.LookupError: - node = None - if node is not None: - rev = cl.rev(node) - if rev not in repo.changelog: - repo._explicitaccess.add(rev) - if prelength != len(repo._explicitaccess): - if repo.filtername != 'visible-directaccess-nowarn': - unhiddencommits = repo._explicitaccess - accessbefore - repo.ui.warn(_("Warning: accessing hidden changesets %s " - "for write operation\n") % - (",".join([str(repo.unfiltered()[l]) - for l in unhiddencommits]))) - repo.invalidatevolatilesets() diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/hack/inhibit.py --- a/hgext3rd/evolve/hack/inhibit.py Mon Oct 23 16:04:23 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,319 +0,0 @@ -"""reduce the changesets evolution feature scope for early and noob friendly ui - -the full scale changeset evolution have some massive bleeding edge and it is -very easy for people not very intimate with the concept to end up in intricate -situation. in order to get some of the benefit sooner, this extension is -disabling some of the less polished aspect of evolution. it should gradually -get thinner and thinner as changeset evolution will get more polished. this -extension is only recommended for large scale organisations. individual user -should probably stick on using evolution in its current state, understand its -concept and provide feedback - -This extension provides the ability to "inhibit" obsolescence markers. obsolete -revision can be cheaply brought back to life that way. -However as the inhibitor are not fitting in an append only model, this is -incompatible with sharing mutable history. -""" -from mercurial import bookmarks -from mercurial import commands -from mercurial import error -from mercurial import extensions -from mercurial import localrepo -from mercurial import lock as lockmod -from mercurial import obsolete -from mercurial import registrar -from mercurial import scmutil -from mercurial import util -from mercurial.i18n import _ - -cmdtable = {} - -if util.safehasattr(registrar, 'command'): - command = registrar.command(cmdtable) -else: # compat with hg < 4.3 - from mercurial import cmdutil - command = cmdutil.command(cmdtable) - -def _inhibitenabled(repo): - return util.safehasattr(repo, '_obsinhibit') - -def reposetup(ui, repo): - - class obsinhibitedrepo(repo.__class__): - - @localrepo.storecache('obsinhibit') - def _obsinhibit(self): - # XXX we should make sure it is invalidated by transaction failure - obsinhibit = set() - raw = self.svfs.tryread('obsinhibit') - for i in xrange(0, len(raw), 20): - obsinhibit.add(raw[i:i + 20]) - return obsinhibit - - def commit(self, *args, **kwargs): - newnode = super(obsinhibitedrepo, self).commit(*args, **kwargs) - if newnode is not None: - _inhibitmarkers(repo, [newnode]) - return newnode - - repo.__class__ = obsinhibitedrepo - -def _update(orig, ui, repo, *args, **kwargs): - """ - When moving to a commit we want to inhibit any obsolete commit affecting - the changeset we are updating to. In other words we don't want any visible - commit to be obsolete. - """ - wlock = None - try: - # Evolve is running a hook on lock release to display a warning message - # if the workind dir's parent is obsolete. - # We take the lock here to make sure that we inhibit the parent before - # that hook get a chance to run. - wlock = repo.wlock() - res = orig(ui, repo, *args, **kwargs) - newhead = repo['.'].node() - _inhibitmarkers(repo, [newhead]) - return res - finally: - lockmod.release(wlock) - -def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs): - """ Add inhibition markers to every obsolete bookmarks """ - repo = bkmstoreinst._repo - bkmstorenodes = [repo[v].node() for v in bkmstoreinst.values()] - _inhibitmarkers(repo, bkmstorenodes) - return orig(bkmstoreinst, *args, **kwargs) - -def _bookmark(orig, ui, repo, *bookmarks, **opts): - """ Add a -D option to the bookmark command, map it to prune -B """ - haspruneopt = opts.get('prune', False) - if not haspruneopt: - return orig(ui, repo, *bookmarks, **opts) - elif opts.get('rename'): - raise error.Abort('Cannot use both -m and -D') - elif len(bookmarks) == 0: - hint = _('make sure to put a space between -D and your bookmark name') - raise error.Abort(_('Error, please check your command'), hint=hint) - - # Call prune -B - evolve = extensions.find('evolve') - optsdict = { - 'new': [], - 'succ': [], - 'rev': [], - 'bookmark': bookmarks, - 'keep': None, - 'biject': False, - } - evolve.cmdrewrite.cmdprune(ui, repo, **optsdict) - -# obsolescence inhibitor -######################## - -def _schedulewrite(tr, obsinhibit): - """Make sure on disk content will be updated on transaction commit""" - def writer(fp): - """Serialize the inhibited list to disk. - """ - raw = ''.join(obsinhibit) - fp.write(raw) - tr.addfilegenerator('obsinhibit', ('obsinhibit',), writer) - tr.hookargs['obs_inbihited'] = '1' - -def _filterpublic(repo, nodes): - """filter out inhibitor on public changeset - - Public changesets are already immune to obsolescence""" - getrev = repo.changelog.nodemap.get - getphase = repo._phasecache.phase - return (n for n in nodes - if getrev(n) is not None and getphase(repo, getrev(n))) - -def _inhibitmarkers(repo, nodes): - """add marker inhibitor for all obsolete revision under - - Content of and all mutable ancestors are considered. Marker for - obsolete revision only are created. - """ - if not _inhibitenabled(repo): - return - - # we add (non public()) as a lower boundary to - # - use the C code in 3.6 (no ancestors in C as this is written) - # - restrict the search space. Otherwise, the ancestors can spend a lot of - # time iterating if you have a check very low in the repo. We do not need - # to iterate over tens of thousand of public revisions with higher - # revision number - # - # In addition, the revset logic could be made significantly smarter here. - newinhibit = repo.revs('(not public())::%ln and obsolete()', nodes) - if newinhibit: - node = repo.changelog.node - lock = tr = None - try: - lock = repo.lock() - tr = repo.transaction('obsinhibit') - repo._obsinhibit.update(node(r) for r in newinhibit) - _schedulewrite(tr, _filterpublic(repo, repo._obsinhibit)) - repo.invalidatevolatilesets() - tr.close() - finally: - lockmod.release(tr, lock) - -def _deinhibitmarkers(repo, nodes): - """lift obsolescence inhibition on a set of nodes - - This will be triggered when inhibited nodes received new obsolescence - markers. Otherwise the new obsolescence markers would also be inhibited. - """ - if not _inhibitenabled(repo): - return - - deinhibited = repo._obsinhibit & set(nodes) - if deinhibited: - tr = repo.transaction('obsinhibit') - try: - repo._obsinhibit -= deinhibited - _schedulewrite(tr, _filterpublic(repo, repo._obsinhibit)) - repo.invalidatevolatilesets() - tr.close() - finally: - tr.release() - -def _createmarkers(orig, repo, relations, *args, **kwargs): - """wrap markers create to make sure we de-inhibit target nodes""" - # wrapping transactio to unify the one in each function - lock = tr = None - try: - lock = repo.lock() - tr = repo.transaction('add-obsolescence-marker') - orig(repo, relations, *args, **kwargs) - precs = (r[0].node() for r in relations) - _deinhibitmarkers(repo, precs) - tr.close() - finally: - lockmod.release(tr, lock) - -def _filterobsoleterevswrap(orig, repo, rebasesetrevs, *args, **kwargs): - repo._notinhibited = rebasesetrevs - try: - repo.invalidatevolatilesets() - r = orig(repo, rebasesetrevs, *args, **kwargs) - finally: - del repo._notinhibited - repo.invalidatevolatilesets() - return r - -def transactioncallback(orig, repo, desc, *args, **kwargs): - """ Wrap localrepo.transaction to inhibit new obsolete changes """ - def inhibitposttransaction(transaction): - # At the end of the transaction we catch all the new visible and - # obsolete commit to inhibit them - visibleobsolete = repo.revs('obsolete() - hidden()') - ignoreset = set(getattr(repo, '_rebaseset', [])) - ignoreset |= set(getattr(repo, '_obsoletenotrebased', [])) - visibleobsolete = list(r for r in visibleobsolete if r not in ignoreset) - if visibleobsolete: - _inhibitmarkers(repo, [repo[r].node() for r in visibleobsolete]) - transaction = orig(repo, desc, *args, **kwargs) - if desc != 'strip' and _inhibitenabled(repo): - transaction.addpostclose('inhibitposttransaction', - inhibitposttransaction) - return transaction - - -# We wrap these two functions to address the following scenario: -# - Assuming that we have markers between commits in the rebase set and -# destination and that these markers are inhibited -# - At the end of the rebase the nodes are still visible because rebase operate -# without inhibition and skip these nodes -# We keep track in repo._obsoletenotrebased of the obsolete commits skipped by -# the rebase and lift the inhibition in the end of the rebase. - -def _computeobsoletenotrebased(orig, repo, *args, **kwargs): - r = orig(repo, *args, **kwargs) - repo._obsoletenotrebased = r.keys() - return r - -def _clearrebased(orig, ui, repo, dest, state, skipped, collapsedas=None, - keepf=False, **kwargs): - r = orig(ui, repo, dest, state, skipped, collapsedas, keepf, **kwargs) - if keepf: - return r - tonode = repo.changelog.node - if util.safehasattr(repo, '_obsoletenotrebased'): - _deinhibitmarkers(repo, [tonode(k) for k in repo._obsoletenotrebased]) - return r - - -def extsetup(ui): - # lets wrap the computation of the obsolete set - # We apply inhibition there - obsfunc = obsolete.cachefuncs['obsolete'] - - def _computeobsoleteset(repo): - """remove any inhibited nodes from the obsolete set - - This will trickle down to other part of mercurial (hidden, log, etc)""" - obs = obsfunc(repo) - if _inhibitenabled(repo): - getrev = repo.changelog.nodemap.get - blacklist = getattr(repo, '_notinhibited', set()) - for n in repo._obsinhibit: - if getrev(n) not in blacklist: - obs.discard(getrev(n)) - return obs - try: - extensions.find('directaccess') - except KeyError: - errormsg = _('cannot use inhibit without the direct access extension\n') - hint = _("(please enable it or inhibit won\'t work)\n") - ui.warn(errormsg) - ui.warn(hint) - return - - # Wrapping this to inhibit obsolete revs resulting from a transaction - extensions.wrapfunction(localrepo.localrepository, - 'transaction', transactioncallback) - - obsolete.cachefuncs['obsolete'] = _computeobsoleteset - # wrap create marker to make it able to lift the inhibition - extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers) - # drop divergence computation since it is incompatible with "light revive" - obsolete.cachefuncs['divergent'] = lambda repo: set() - # drop bumped computation since it is incompatible with "light revive" - obsolete.cachefuncs['bumped'] = lambda repo: set() - # wrap update to make sure that no obsolete commit is visible after an - # update - extensions.wrapcommand(commands.table, 'update', _update) - try: - rebase = extensions.find('rebase') - if rebase: - if util.safehasattr(rebase, '_filterobsoleterevs'): - extensions.wrapfunction(rebase, - '_filterobsoleterevs', - _filterobsoleterevswrap) - extensions.wrapfunction(rebase, 'clearrebased', _clearrebased) - if util.safehasattr(rebase, '_computeobsoletenotrebased'): - extensions.wrapfunction(rebase, - '_computeobsoletenotrebased', - _computeobsoletenotrebased) - - except KeyError: - pass - # There are two ways to save bookmark changes during a transation, we - # wrap both to add inhibition markers. - extensions.wrapfunction(bookmarks.bmstore, 'recordchange', _bookmarkchanged) - if getattr(bookmarks.bmstore, 'write', None) is not None:# mercurial < 3.9 - extensions.wrapfunction(bookmarks.bmstore, 'write', _bookmarkchanged) - # Add bookmark -D option - entry = extensions.wrapcommand(commands.table, 'bookmark', _bookmark) - entry[1].append(('D', 'prune', None, - _('delete the bookmark and prune the commits underneath'))) - -@command('debugobsinhibit', [], '') -def cmddebugobsinhibit(ui, repo, *revs): - """inhibit obsolescence markers effect on a set of revs""" - nodes = (repo[r].node() for r in scmutil.revrange(repo, revs)) - _inhibitmarkers(repo, nodes) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/metadata.py --- a/hgext3rd/evolve/metadata.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/metadata.py Wed Nov 01 23:51:55 2017 +0100 @@ -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.8.1.dev' -testedwith = '3.8.4 3.9.2 4.0.2 4.1.3 4.2.3 4.3.2 4.4' -minimumhgversion = '3.8' +__version__ = '7.0.0.dev' +testedwith = '4.1.3 4.2.3 4.3.2 4.4' +minimumhgversion = '4.1' buglink = 'https://bz.mercurial-scm.org/' diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/obscache.py --- a/hgext3rd/evolve/obscache.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/obscache.py Wed Nov 01 23:51:55 2017 +0100 @@ -49,15 +49,7 @@ except ImportError: from mercurial import scmutil as vfsmod -try: - obsstorefilecache = localrepo.localrepository.obsstore -except AttributeError: - # XXX hg-3.8 compat - # - # mercurial 3.8 has issue with accessing file cache property from their - # cache. This is fix by 36fbd72c2f39fef8ad52d7c559906c2bc388760c in core - # and shipped in 3.9 - obsstorefilecache = localrepo.localrepository.__dict__['obsstore'] +obsstorefilecache = localrepo.localrepository.obsstore # obsstore is a filecache so we have do to some spacial dancing @eh.wrapfunction(obsstorefilecache, 'func') diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/obsdiscovery.py --- a/hgext3rd/evolve/obsdiscovery.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/obsdiscovery.py Wed Nov 01 23:51:55 2017 +0100 @@ -557,15 +557,7 @@ obsstore.rangeobshashcache.clear() return orig(obsstore, *args, **kwargs) -try: - obsstorefilecache = localrepo.localrepository.obsstore -except AttributeError: - # XXX hg-3.8 compat - # - # mercurial 3.8 has issue with accessing file cache property from their - # cache. This is fix by 36fbd72c2f39fef8ad52d7c559906c2bc388760c in core - # and shipped in 3.9 - obsstorefilecache = localrepo.localrepository.__dict__['obsstore'] +obsstorefilecache = localrepo.localrepository.obsstore # obsstore is a filecache so we have do to some spacial dancing diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/obsexchange.py --- a/hgext3rd/evolve/obsexchange.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/obsexchange.py Wed Nov 01 23:51:55 2017 +0100 @@ -14,24 +14,18 @@ import io StringIO = io.StringIO -import errno -import socket - from mercurial import ( bundle2, error, exchange, extensions, - httppeer, - localrepo, lock as lockmod, node, obsolete, + pushkey, util, wireproto, ) -from mercurial.hgweb import hgweb_mod -from mercurial.i18n import _ from . import ( exthelper, @@ -182,17 +176,6 @@ obsdata.seek(0) return obsdata -# The wireproto.streamres API changed, handling chunking and compression -# directly. Handle either case. -if util.safehasattr(wireproto.abstractserverproto, 'groupchunks'): - # We need to handle chunking and compression directly - def streamres(d, proto): - return wireproto.streamres(proto.groupchunks(d)) -else: - # Leave chunking and compression to streamres - def streamres(d, proto): - return wireproto.streamres(reader=d, v1compressible=True) - def srv_pullobsmarkers(repo, proto, others): """serves a binary stream of markers. @@ -209,245 +192,15 @@ finaldata.write('%20i' % len(obsdata)) finaldata.write(obsdata) finaldata.seek(0) - return streamres(finaldata, proto) - -############################################### -### Support for old legacy exchange methods ### -############################################### - -class pushobsmarkerStringIO(StringIO): - """hacky string io for progress""" - - @util.propertycache - def length(self): - return len(self.getvalue()) - - def read(self, size=None): - obsexcprg(self.ui, self.tell(), unit=_("bytes"), total=self.length) - return StringIO.read(self, size) - - def __iter__(self): - d = self.read(4096) - while d: - yield d - d = self.read(4096) - -# compat-code: _pushobsolete -# -# the _pushobsolete function is a core function used to exchange -# obsmarker with repository that does not support bundle2 + return wireproto.streamres(reader=finaldata, v1compressible=True) -@eh.wrapfunction(exchange, '_pushobsolete') -def _pushobsolete(orig, pushop): - """utility function to push obsolete markers to a remote""" - if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt): - return - if 'obsmarkers' in pushop.stepsdone: - return - pushop.stepsdone.add('obsmarkers') - if pushop.cgresult == 0: - return - pushop.ui.debug('try to push obsolete markers to remote\n') - repo = pushop.repo - remote = pushop.remote - if (repo.obsstore and 'obsolete' in remote.listkeys('namespaces')): - markers = pushop.outobsmarkers - if not markers: - obsexcmsg(repo.ui, "no marker to push\n") - elif remote.capable('_evoext_pushobsmarkers_0'): - msg = ('the remote repository use years old versions of Mercurial' - ' and evolve\npushing obsmarker using legacy method\n') - repo.ui.warn(msg) - repo.ui.warn('(please upgrade your server)\n') - obsdata = pushobsmarkerStringIO() - for chunk in obsolete.encodemarkers(markers, True): - obsdata.write(chunk) - obsdata.seek(0) - obsdata.ui = repo.ui - obsexcmsg(repo.ui, "pushing %i obsolescence markers (%i bytes)\n" - % (len(markers), len(obsdata.getvalue())), - True) - remote.evoext_pushobsmarkers_0(obsdata) - obsexcprg(repo.ui, None) - - else: - # XXX core could be able do the same things but without the debug - # and progress output. - msg = ('the remote repository usea years old version of Mercurial' - ' and not evolve extension\n') - repo.ui.warn(msg) - msg = 'pushing obsmarker using and extremely slow legacy method\n' - repo.ui.warn(msg) - repo.ui.warn('(please upgrade your server and enable evolve.serveronly on it)\n') - rslts = [] - remotedata = obsolete._pushkeyescape(markers).items() - totalbytes = sum(len(d) for k, d in remotedata) - sentbytes = 0 - obsexcmsg(repo.ui, "pushing %i obsolescence markers in %i " - "pushkey payload (%i bytes)\n" - % (len(markers), len(remotedata), totalbytes), - True) - for key, data in remotedata: - obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"), - total=totalbytes) - rslts.append(remote.pushkey('obsolete', key, '', data)) - sentbytes += len(data) - obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"), - total=totalbytes) - obsexcprg(repo.ui, None) - if [r for r in rslts if not r]: - msg = _('failed to push some obsolete markers!\n') - repo.ui.warn(msg) - obsexcmsg(repo.ui, "DONE\n") - -# Supporting legacy way to push obsmarker so that old client can still push -# them somewhat efficiently - -@eh.addattr(wireproto.wirepeer, 'evoext_pushobsmarkers_0') -def client_pushobsmarkers(self, obsfile): - """wireprotocol peer method""" - self.requirecap('_evoext_pushobsmarkers_0', - _('push obsolete markers faster')) - ret, output = self._callpush('evoext_pushobsmarkers_0', obsfile) - for l in output.splitlines(True): - self.ui.status(_('remote: '), l) - return ret - -@eh.addattr(httppeer.httppeer, 'evoext_pushobsmarkers_0') -def httpclient_pushobsmarkers(self, obsfile): - """httpprotocol peer method - (Cannot simply use _callpush as http is doing some special handling)""" - self.requirecap('_evoext_pushobsmarkers_0', - _('push obsolete markers faster')) - try: - r = self._call('evoext_pushobsmarkers_0', data=obsfile) - vals = r.split('\n', 1) - if len(vals) < 2: - raise error.ResponseError(_("unexpected response:"), r) +abortmsg = "won't exchange obsmarkers through pushkey" +hint = "upgrade your client or server to use the bundle2 protocol" - for l in vals[1].splitlines(True): - if l.strip(): - self.ui.status(_('remote: '), l) - return vals[0] - except socket.error as err: - if err.args[0] in (errno.ECONNRESET, errno.EPIPE): - raise error.Abort(_('push failed: %s') % err.args[1]) - raise error.Abort(err.args[1]) - -@eh.wrapfunction(localrepo.localrepository, '_restrictcapabilities') -def local_pushobsmarker_capabilities(orig, repo, caps): - caps = orig(repo, caps) - caps.add('_evoext_pushobsmarkers_0') - return caps - -@eh.addattr(localrepo.localpeer, 'evoext_pushobsmarkers_0') -def local_pushobsmarkers(peer, obsfile): - data = obsfile.read() - _pushobsmarkers(peer._repo, data) - -# compat-code: _pullobsolete -# -# the _pullobsolete function is a core function used to exchange -# obsmarker with repository that does not support bundle2 - -@eh.wrapfunction(exchange, '_pullobsolete') -def _pullobsolete(orig, pullop): - if not obsolete.isenabled(pullop.repo, obsolete.exchangeopt): - return None - if 'obsmarkers' in pullop.stepsdone: - return None - wirepull = pullop.remote.capable('_evoext_pullobsmarkers_0') - if 'obsolete' not in pullop.remote.listkeys('namespaces'): - return None # remote opted out of obsolescence marker exchange - if not wirepull: - return orig(pullop) - tr = None - ui = pullop.repo.ui - boundaries = obsdiscovery.buildpullobsmarkersboundaries(pullop, bundle2=False) - if 'missing' in boundaries and not boundaries['missing']: - obsexcmsg(ui, "nothing to pull\n") - return None - elif not set(boundaries['heads']) - set(boundaries['common']): - obsexcmsg(ui, "nothing to pull\n") - return None - - obsexcmsg(ui, "pull obsolescence markers\n", True) - new = 0 - - msg = ('the remote repository use years old versions of Mercurial and evolve\n' - 'pulling obsmarker using legacy method\n') - ui.warn(msg) - ui.warn('(please upgrade your server)\n') +def forbidpushkey(repo=None, key=None, old=None, new=None): + """prevent exchange through pushkey""" + raise error.Abort(abortmsg, hint=hint) - obsdata = pullop.remote.evoext_pullobsmarkers_0(**boundaries) - obsdata = obsdata.read() - if len(obsdata) > 5: - msg = "merging obsolescence markers (%i bytes)\n" % len(obsdata) - obsexcmsg(ui, msg) - tr = pullop.gettransaction() - old = len(pullop.repo.obsstore._all) - pullop.repo.obsstore.mergemarkers(tr, obsdata) - new = len(pullop.repo.obsstore._all) - old - obsexcmsg(ui, "%i obsolescence markers added\n" % new, True) - else: - obsexcmsg(ui, "no unknown remote markers\n") - obsexcmsg(ui, "DONE\n") - if new: - pullop.repo.invalidatevolatilesets() - return tr - -@eh.addattr(wireproto.wirepeer, 'evoext_pullobsmarkers_0') -def client_pullobsmarkers(self, heads=None, common=None): - self.requirecap('_evoext_pullobsmarkers_0', _('look up remote obsmarkers')) - opts = {} - if heads is not None: - opts['heads'] = wireproto.encodelist(heads) - if common is not None: - opts['common'] = wireproto.encodelist(common) - f = self._callcompressable("evoext_pullobsmarkers_0", **opts) - length = int(f.read(20)) - chunk = 4096 - current = 0 - data = StringIO() - ui = self.ui - obsexcprg(ui, current, unit=_("bytes"), total=length) - while current < length: - readsize = min(length - current, chunk) - data.write(f.read(readsize)) - current += readsize - obsexcprg(ui, current, unit=_("bytes"), total=length) - obsexcprg(ui, None) - data.seek(0) - return data - -@eh.addattr(localrepo.localpeer, 'evoext_pullobsmarkers_0') -def local_pullobsmarkers(self, heads=None, common=None): - return _getobsmarkersstream(self._repo, heads=heads, - common=common) - -def _legacypush_capabilities(orig, repo, proto): - """wrapper to advertise new capability""" - caps = orig(repo, proto) - if obsolete.isenabled(repo, obsolete.exchangeopt): - caps = caps.split() - caps.append('_evoext_pushobsmarkers_0') - caps.append('_evoext_pullobsmarkers_0') - caps.sort() - caps = ' '.join(caps) - return caps - -@eh.extsetup -def extsetup(ui): - # legacy standalone method - hgweb_mod.perms['evoext_pushobsmarkers_0'] = 'push' - hgweb_mod.perms['evoext_pullobsmarkers_0'] = 'pull' - wireproto.commands['evoext_pushobsmarkers_0'] = (srv_pushobsmarkers, '') - wireproto.commands['evoext_pullobsmarkers_0'] = (srv_pullobsmarkers, '*') - - extensions.wrapfunction(wireproto, 'capabilities', _legacypush_capabilities) - # wrap command content - oldcap, args = wireproto.commands['capabilities'] - - def newcap(repo, proto): - return _legacypush_capabilities(oldcap, repo, proto) - wireproto.commands['capabilities'] = (newcap, args) +@eh.uisetup +def setuppushkeyforbidding(ui): + pushkey._namespaces['obsolete'] = (forbidpushkey, forbidpushkey) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/rewriteutil.py --- a/hgext3rd/evolve/rewriteutil.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/rewriteutil.py Wed Nov 01 23:51:55 2017 +0100 @@ -24,7 +24,6 @@ phases, repair, revset, - util, ) from mercurial.i18n import _ @@ -47,10 +46,7 @@ shorts = [node.short(tonode(r)) for r in revs] summary = ', '.join(shorts) else: - if util.safehasattr(revs, 'first'): - first = revs.first() - else: - first = revs[0] + first = revs.first() summary = _('%s and %d others') summary %= (node.short(tonode(first)), numrevs - 1) return summary diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/serveronly.py --- a/hgext3rd/evolve/serveronly.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/serveronly.py Wed Nov 01 23:51:55 2017 +0100 @@ -13,6 +13,8 @@ import sys import os +from mercurial import obsolete + try: from . import ( compat, @@ -55,3 +57,5 @@ if not evolveopts: evolveopts = 'all' ui.setconfig('experimental', 'evolution', evolveopts) + if obsolete.isenabled(repo, 'exchange'): + repo.ui.setconfig('server', 'bundle1', False) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/evolve/stablerange.py --- a/hgext3rd/evolve/stablerange.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/evolve/stablerange.py Wed Nov 01 23:51:55 2017 +0100 @@ -395,13 +395,7 @@ # data about the merge. But I'm not sure this function will be even # call for the general case. - # Lrudict.get in hg-3.9 returns the lrunode instead of the - # value, use __getitem__ instead and catch the exception directly - try: - allrevs = self._stablesortcache[headrev] - except KeyError: - allrevs = None - + allrevs = self._stablesortcache.get(headrev) if allrevs is None: allrevs = self._getrevsfrommerge(repo, headrev) if allrevs is None: @@ -450,11 +444,8 @@ self._stablesortprepared[merge] = (sortedrevs, len(sortedrevs)) def _getrevsfrommerge(self, repo, merge): - # Lrudict.get in hg-3.9 returns the lrunode instead of the - # value, use __getitem__ instead and catch the exception directly - try: - prepared = self._stablesortprepared[merge] - except KeyError: + prepared = self._stablesortprepared.get(merge) + if prepared is None: return None mergedepth = self.depthrev(repo, merge) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/topic/__init__.py Wed Nov 01 23:51:55 2017 +0100 @@ -63,6 +63,40 @@ topic-mode = enforce-all # abort the commit (even for merge) topic-mode = random # use a randomized generated topic (except for merge) topic-mode = random-all # use a randomized generated topic (even for merge) + +Single head enforcing +===================== + +The extensions come with an option to enforce that there is only one heads for +each name in the repository at any time. + + [experimental] + enforce-single-head = yes + +Publishing behavior +=================== + +Topic vanish when changeset move to the public phases. Moving to the public +phase usually happens on push, but it is possible ot update that behavior. The +server needs to have specific config for this. + + # everything pushed become public (the default) + [phase] + publish = yes + + # nothing push turned public + [phase] + publish = no + + # topic branches are not published, changeset without topic are + [phase] + publish = no + [experimental] + topic.publish-bare-branch = yes + +In addition, the topic extension adds a ``--publish`` flag on :hg:`push`. When +used, the pushed revisions are published if the push succeeds. It also applies +to common revisions selected by the push. """ from __future__ import absolute_import @@ -99,6 +133,7 @@ from . import ( compat, constants, + flow, revset as topicrevset, destination, stack, @@ -139,10 +174,10 @@ 'topic.active': 'green', } -__version__ = '0.4.1.dev' +__version__ = '0.5.0.dev' -testedwith = '4.0.2 4.1.3 4.2.3 4.3.3 4.4' -minimumhgversion = '4.0' +testedwith = '4.1.3 4.2.3 4.3.3 4.4' +minimumhgversion = '4.1' buglink = 'https://bz.mercurial-scm.org/' if util.safehasattr(registrar, 'configitem'): @@ -152,9 +187,15 @@ configitem('experimental', 'enforce-topic', default=False, ) + configitem('experimental', 'enforce-single-head', + default=False, + ) configitem('experimental', 'topic-mode', default=None, ) + configitem('experimental', 'topic.publish-bare-branch', + default=False, + ) configitem('_internal', 'keep-topic', default=False, ) @@ -245,6 +286,8 @@ extensions.afterloaded('rebase', _fixrebase) + flow.installpushflag(ui) + entry = extensions.wrapcommand(commands.table, 'commit', commitwrap) entry[1].append(('t', 'topic', '', _("use specified topic"), _('TOPIC'))) @@ -368,6 +411,30 @@ if desc in ('strip', 'repair') or ctr is not None: return tr + reporef = weakref.ref(self) + if repo.ui.configbool('experimental', 'enforce-single-head'): + origvalidator = tr.validator + + def validator(tr2): + repo = reporef() + flow.enforcesinglehead(repo, tr2) + origvalidator(tr2) + tr.validator = validator + + if (repo.ui.configbool('experimental', 'topic.publish-bare-branch') + and (desc.startswith('push') + or desc.startswith('serve')) + ): + origclose = tr.close + trref = weakref.ref(tr) + + def close(): + repo = reporef() + tr2 = trref() + flow.publishbarebranch(repo, tr2) + origclose() + tr.close = close + # real transaction start ct = self.currenttopic if not ct: @@ -769,11 +836,8 @@ # phase handling commitphase = c.phase() - if util.safehasattr(repo.ui, 'configoverride'): - overrides = {('phases', 'new-commit'): commitphase} - with repo.ui.configoverride(overrides, 'changetopic'): - newnode = repo.commitctx(mc) - else: # do not attempt to preserver phase (hg <= 4.0) + overrides = {('phases', 'new-commit'): commitphase} + with repo.ui.configoverride(overrides, 'changetopic'): newnode = repo.commitctx(mc) successors[c.node()] = (newnode,) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/topic/destination.py --- a/hgext3rd/topic/destination.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/topic/destination.py Wed Nov 01 23:51:55 2017 +0100 @@ -6,7 +6,6 @@ destutil, error, extensions, - util, ) from . import topicmap from .evolvebits import builddependencies @@ -54,12 +53,7 @@ msg = _("topic '%s' has %d heads " "- please merge with an explicit rev") % (top, len(heads)) raise error.ManyMergeDestAbort(msg) - if len(getattr(orig, 'func_defaults', ())) == 3: # version hg-3.7 - return orig(repo, action, sourceset, onheadcheck) - if 3 < len(getattr(orig, 'func_defaults', ())): # version hg-3.8 and above - return orig(repo, action, sourceset, onheadcheck, destspace=destspace) - else: - return orig(repo) + return orig(repo, action, sourceset, onheadcheck, destspace=destspace) def _destupdatetopic(repo, clean, check=None): """decide on an update destination from current topic""" @@ -100,24 +94,8 @@ def modsetup(ui): """run a uisetup time to install all destinations wrapping""" - if util.safehasattr(destutil, '_destmergebranch'): - extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch) - try: - rebase = extensions.find('rebase') - except KeyError: - rebase = None - - # Mercurial 4.4 rename _definesets into _definedestmap - rebasebefore38 = not util.safehasattr(rebase, '_definesets') - rebasebefore44 = not util.safehasattr(rebase, '_definedestmap') - - if (util.safehasattr(rebase, '_destrebase') - # logic not shared with merge yet < hg-3.8 - and rebasebefore38 and rebasebefore44): - extensions.wrapfunction(rebase, '_destrebase', _destmergebranch) - if util.safehasattr(destutil, 'destupdatesteps'): - bridx = destutil.destupdatesteps.index('branch') - destutil.destupdatesteps.insert(bridx, 'topic') - destutil.destupdatestepmap['topic'] = _destupdatetopic - if util.safehasattr(destutil, 'desthistedit'): - extensions.wrapfunction(destutil, 'desthistedit', desthistedit) + extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch) + bridx = destutil.destupdatesteps.index('branch') + destutil.destupdatesteps.insert(bridx, 'topic') + destutil.destupdatestepmap['topic'] = _destupdatetopic + extensions.wrapfunction(destutil, 'desthistedit', desthistedit) diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/topic/flow.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/topic/flow.py Wed Nov 01 23:51:55 2017 +0100 @@ -0,0 +1,69 @@ +from __future__ import absolute_import + +from mercurial import ( + commands, + error, + exchange, + extensions, + node, + phases, + util, +) + +from mercurial.i18n import _ + +def enforcesinglehead(repo, tr): + for name, heads in repo.filtered('visible').branchmap().iteritems(): + if len(heads) > 1: + hexs = [node.short(n) for n in heads] + raise error.Abort(_('%d heads on "%s"') % (len(heads), name), + hint=(', '.join(hexs))) + +def publishbarebranch(repo, tr): + """Publish changeset without topic""" + if 'node' not in tr.hookargs: # no new node + return + startnode = node.bin(tr.hookargs['node']) + topublish = repo.revs('not public() and (%n:) - hidden() - topic()', startnode) + if topublish: + cl = repo.changelog + nodes = [cl.node(r) for r in topublish] + repo._phasecache.advanceboundary(repo, tr, phases.public, nodes) + +def wrappush(orig, repo, remote, *args, **kwargs): + """interpret the --publish flag and pass it to the push operation""" + newargs = kwargs.copy() + if kwargs.pop('publish', False): + opargs = kwargs.get('opargs') + if opargs is None: + opargs = {} + newargs['opargs'] = opargs.copy() + newargs['opargs']['publish'] = True + return orig(repo, remote, *args, **newargs) + +def extendpushoperation(orig, *args, **kwargs): + publish = kwargs.pop('publish', False) + op = orig(*args, **kwargs) + op.publish = publish + return op + +def wrapphasediscovery(orig, pushop): + orig(pushop) + if pushop.publish: + if not util.safehasattr(pushop, 'remotephases'): + msg = _('--publish flag only supported from Mercurial 4.4 and higher') + raise error.Abort(msg) + if not pushop.remotephases.publishing: + unfi = pushop.repo.unfiltered() + droots = pushop.remotephases.draftroots + revset = '%ln and (not public() or %ln::)' + future = list(unfi.set(revset, pushop.futureheads, droots)) + pushop.outdatedphases = future + +def installpushflag(ui): + entry = extensions.wrapcommand(commands.table, 'push', wrappush) + entry[1].append(('', 'publish', False, + _('push the changeset as public'))) + extensions.wrapfunction(exchange, 'pushoperation', extendpushoperation) + extensions.wrapfunction(exchange, '_pushdiscoveryphase', wrapphasediscovery) + exchange.pushdiscoverymapping['phase'] = exchange._pushdiscoveryphase diff -r c3953ae44b87 -r f42a87cc864d hgext3rd/topic/revset.py --- a/hgext3rd/topic/revset.py Mon Oct 23 16:04:23 2017 +0200 +++ b/hgext3rd/topic/revset.py Wed Nov 01 23:51:55 2017 +0100 @@ -72,11 +72,10 @@ run).""" err = 'stack() takes no argument, it works on current topic' revset.getargs(x, 0, 0, err) - topic = repo.currenttopic topic = None branch = None - if not topic and repo.currenttopic: + if repo.currenttopic: topic = repo.currenttopic - if not topic: + else: branch = repo[None].branch() return revset.baseset(stack.stack(repo, branch=branch, topic=topic)[1:]) & subset diff -r c3953ae44b87 -r f42a87cc864d tests/test-discovery-obshashrange.t --- a/tests/test-discovery-obshashrange.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-discovery-obshashrange.t Wed Nov 01 23:51:55 2017 +0100 @@ -183,8 +183,8 @@ running python "*/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) sending hello command sending between command - remote: 533 - 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%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + remote: 483 + remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 batch * (glob) remote: 1 preparing listkeys for "phases" sending listkeys command diff -r c3953ae44b87 -r f42a87cc864d tests/test-divergent.t --- a/tests/test-divergent.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-divergent.t Wed Nov 01 23:51:55 2017 +0100 @@ -53,7 +53,7 @@ |/ o 0:135f39f4bd78@default(draft) add _a [] - $ hg evolve --all --any --contentdivergent + $ hg evolve --all --any --content-divergent merge:[2] add bdivergent1 with: [3] add bdivergent2 base: [1] add _b @@ -98,7 +98,7 @@ |/ o 0:135f39f4bd78@default(draft) add _a [] - $ hg evolve --all --any --contentdivergent + $ hg evolve --all --any --content-divergent merge:[6] add cdivergent1 with: [7] cdivergent2 base: [5] add _c @@ -146,9 +146,9 @@ > EOF $ hg evolve --all nothing to evolve on current working copy parent - (do you want to use --contentdivergent) + (do you want to use --content-divergent) [2] - $ hg evolve --contentdivergent + $ hg evolve --content-divergent merge:[3] add bdivergent2 with: [2] add bdivergent1 base: [1] add _b diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-bumped.t --- a/tests/test-evolve-bumped.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-evolve-bumped.t Wed Nov 01 23:51:55 2017 +0100 @@ -70,7 +70,7 @@ no changes found 1 new phase-divergent changesets - $ hg evolve -a -A --phasedivergent + $ hg evolve -a -A --phase-divergent recreate:[2] tweak a atop:[1] modify a computing new diff @@ -122,5 +122,5 @@ | o 0:d3873e73d99e@default(public) init - $ hg evolve --all --phasedivergent + $ hg evolve --all --phase-divergent skipping b28e84916d8c : we do not handle merge yet diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-obshistory.t --- a/tests/test-evolve-obshistory.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-evolve-obshistory.t Wed Nov 01 23:51:55 2017 +0100 @@ -1287,7 +1287,7 @@ $ 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 --contentdivergent' to resolve the issue) + (471f378eab4c has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) Test output with amended + folded commit ======================================== diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-serveronly-bundle2.t --- a/tests/test-evolve-serveronly-bundle2.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-evolve-serveronly-bundle2.t Wed Nov 01 23:51:55 2017 +0100 @@ -86,9 +86,9 @@ =================== $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort bookmarks @@ -151,9 +151,9 @@ obsolete phases $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) $ echo '[experimental]' >> server/.hg/hgrc $ echo 'evolution=!' >> server/.hg/hgrc @@ -178,9 +178,9 @@ phases $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) + capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob) $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) + _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob) Test obshashrange discover =========================================== diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-serveronly-legacy.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-serveronly-legacy.t Wed Nov 01 23:51:55 2017 +0100 @@ -0,0 +1,63 @@ + + $ . ${TESTDIR}/testlib/pythonpath.sh + + $ cat >> $HGRCPATH < [defaults] + > amend=-d "0 0" + > [web] + > push_ssl = false + > allow_push = * + > [phases] + > publish = False + > [experimental] + > bundle2-exp=False # < Mercurial-4.0 + > [devel] + > legacy.exchange=bundle1 + > [extensions] + > EOF + + $ mkcommit() { + > echo "$1" > "$1" + > hg add "$1" + > hg ci -m "add $1" + > } + + + $ hg init server + +Try the multiple ways to setup the extension + + $ hg -R server log --config 'extensions.evolve.serveronly=' + $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" + $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" + +setup repo + + $ echo "[extensions]" >> ./server/.hg/hgrc + $ echo "evolve.serveronly=" >> ./server/.hg/hgrc + $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback + $ cat hg.pid >> $DAEMON_PIDS + + $ hg clone http://localhost:$HGPORT/ client + no changes found + updating to branch default + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cat ./errors.log + $ echo "[extensions]" >> ./client/.hg/hgrc + $ echo "evolve=" >> ./client/.hg/hgrc + $ cp -r client other + +Smoke testing +=============== + + $ cd client + $ mkcommit 0 + $ mkcommit a + $ hg push + pushing to http://localhost:$HGPORT/ + searching for changes + abort: remote error: + incompatible Mercurial client; bundle2 required + (see https://www.mercurial-scm.org/wiki/IncompatibleClient) + [255] + $ cat ../errors.log diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-serveronly.t --- a/tests/test-evolve-serveronly.t Mon Oct 23 16:04:23 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,198 +0,0 @@ - - $ . ${TESTDIR}/testlib/pythonpath.sh - - $ cat >> $HGRCPATH < [defaults] - > amend=-d "0 0" - > [web] - > push_ssl = false - > allow_push = * - > [phases] - > publish = False - > [experimental] - > bundle2-exp=False # < Mercurial-4.0 - > [devel] - > legacy.exchange=bundle1 - > [extensions] - > EOF - - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - - - $ hg init server - -Try the multiple ways to setup the extension - - $ hg -R server log --config 'extensions.evolve.serveronly=' - $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" - $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py" - -setup repo - - $ echo "[extensions]" >> ./server/.hg/hgrc - $ echo "evolve.serveronly=" >> ./server/.hg/hgrc - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback - $ cat hg.pid >> $DAEMON_PIDS - - $ hg clone http://localhost:$HGPORT/ client - no changes found - updating to branch default - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ cat ./errors.log - $ echo "[extensions]" >> ./client/.hg/hgrc - $ echo "evolve=" >> ./client/.hg/hgrc - $ cp -r client other - -Smoke testing -=============== - - $ cd client - $ mkcommit 0 - $ mkcommit a - $ hg push - pushing to http://localhost:$HGPORT/ - searching for changes - remote: adding changesets - remote: adding manifests - remote: adding file changes - remote: added 2 changesets with 2 changes to 2 files - $ hg pull - pulling from http://localhost:$HGPORT/ - searching for changes - no changes found - $ cat ../errors.log - $ hg pull -R ../other - pulling from http://localhost:$HGPORT/ - requesting all changes - adding changesets - adding manifests - adding file changes - added 2 changesets with 2 changes to 2 files - pull obsolescence markers - the remote repository use years old versions of Mercurial and evolve - pulling obsmarker using legacy method - (please upgrade your server) - new changesets 8685c6d34325:4957bfdac07e - (run 'hg update' to get a working copy) - $ cat ../errors.log - $ hg push -R ../other - pushing to http://localhost:$HGPORT/ - searching for changes - no changes found - [1] - $ cat ../errors.log - -Capacity testing -=================== - - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - -Push -============= - - $ echo 'A' > a - $ hg amend - $ hg push - pushing to http://localhost:$HGPORT/ - 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) - the remote repository use years old versions of Mercurial and evolve - pushing obsmarker using legacy method - (please upgrade your server) - pushing 1 obsolescence markers (* bytes) (glob) - remote: 1 obsolescence markers added - remote: obsoleted 1 changesets - $ cat ../errors.log - $ hg push - pushing to http://localhost:$HGPORT/ - searching for changes - no changes found - [1] - $ cat ../errors.log - -Pull -============= - - $ hg -R ../other pull - pulling from http://localhost:$HGPORT/ - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re) - pull obsolescence markers - the remote repository use years old versions of Mercurial and evolve - pulling obsmarker using legacy method - (please upgrade your server) - 1 obsolescence markers added - obsoleted 1 changesets - new changesets 9d1c114e7797 - (run 'hg heads' to see heads) - $ cat ../errors.log - $ hg -R ../other pull - pulling from http://localhost:$HGPORT/ - searching for changes - no changes found - $ cat ../errors.log - - $ cd .. - -Test disabling obsolete advertisement -=========================================== -(used by bitbucket to select which repo use evolve) - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) - - $ echo '[experimental]' >> server/.hg/hgrc - $ echo 'evolution=!' >> server/.hg/hgrc - $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log - $ cat hg.pid >> $DAEMON_PIDS - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello | grep _evoext_pushobsmarkers_0 - [1] - $ curl -s http://localhost:$HGPORT/?cmd=capabilities | grep _evoext_pushobsmarkers_0 - [1] - - $ echo 'evolution=' >> server/.hg/hgrc - $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS - $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log - $ cat hg.pid >> $DAEMON_PIDS - - $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort - bookmarks - namespaces - obsolete - phases - $ curl -s http://localhost:$HGPORT/?cmd=hello - capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob) - $ curl -s http://localhost:$HGPORT/?cmd=capabilities - _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob) diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve-templates.t --- a/tests/test-evolve-templates.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-evolve-templates.t Wed Nov 01 23:51:55 2017 +0100 @@ -659,7 +659,7 @@ $ hg up 'desc(A0)' --hidden 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 --contentdivergent' to resolve the issue) + (471f378eab4c has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) Precursors template should show current revision as it is the working copy $ hg tlog diff -r c3953ae44b87 -r f42a87cc864d tests/test-evolve.t --- a/tests/test-evolve.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-evolve.t Wed Nov 01 23:51:55 2017 +0100 @@ -406,7 +406,7 @@ | o 0:e55e0562ee93@default(public) base - $ hg evolve --any --traceback --phasedivergent + $ hg evolve --any --traceback --phase-divergent recreate:[6] another feature that rox atop:[5] another feature (child of ba0ec09b1bab) computing new diff @@ -1058,7 +1058,7 @@ |/ o 0 : a0 - test - $ hg evolve -r "desc('add new file bumped')" --phasedivergent + $ hg evolve -r "desc('add new file bumped')" --phase-divergent recreate:[11] add new file bumped atop:[10] a2 computing new diff @@ -1131,7 +1131,7 @@ set of specified revisions is empty [1] - $ hg evolve --rev "cce26b684bfe::" --phasedivergent + $ hg evolve --rev "cce26b684bfe::" --phase-divergent no phasedivergent changesets in specified revisions (do you want to use --orphan) [2] diff -r c3953ae44b87 -r f42a87cc864d tests/test-inhibit.t --- a/tests/test-inhibit.t Mon Oct 23 16:04:23 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,955 +0,0 @@ - $ cat >> $HGRCPATH < [ui] - > logtemplate = {rev}:{node|short} {desc}\n - > [experimental] - > prunestrip=True - > evolution=createmarkers - > [extensions] - > rebase= - > strip= - > EOF - $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH - $ echo "directaccess=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/directaccess.py" >> $HGRCPATH - $ echo "inhibit=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/inhibit.py" >> $HGRCPATH - $ mkcommit() { - > echo "$1" > "$1" - > hg add "$1" - > hg ci -m "add $1" - > } - - $ hg init inhibit - $ cd inhibit - $ mkcommit cA - $ mkcommit cB - $ mkcommit cC - $ mkcommit cD - $ hg up 'desc(cA)' - 0 files updated, 0 files merged, 3 files removed, 0 files unresolved - $ mkcommit cE - created new head - $ mkcommit cG - $ mkcommit cH - $ mkcommit cJ - $ hg log -G - @ 7:18214586bf78 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | o 3:2db36d8066ff add cD - | | - | o 2:7df62a38b9bf add cC - | | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - -plain prune - - $ hg strip 1:: - 3 changesets pruned - $ hg log -G - @ 7:18214586bf78 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg debugobsinhibit --hidden 1:: - $ hg log -G - @ 7:18214586bf78 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | o 3:2db36d8066ff add cD - | | - | o 2:7df62a38b9bf add cC - | | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - $ hg strip --hidden 1:: - 3 changesets pruned - $ hg log -G - @ 7:18214586bf78 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - -after amend - - $ echo babar > cJ - $ hg commit --amend - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg debugobsinhibit --hidden 18214586bf78 - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - -and no divergence - - $ hg summary - parent: 8:55c73a90e4b4 tip - add cJ - branch: default - commit: (clean) - update: 1 new changesets, 2 branch heads (merge) - phases: 6 draft - -check public revision got cleared -(when adding the second inhibitor, the first one is removed because it is public) - - $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//' - 20 .hg/store/obsinhibit - $ hg strip 7 - 1 changesets pruned - $ hg debugobsinhibit --hidden 18214586bf78 - $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//' - 20 .hg/store/obsinhibit - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg phase --public 7 - 1 new phase-divergent changesets - $ hg strip 8 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - working directory now at cf5c4f4554ce - 1 changesets pruned - $ hg log -G - o 7:18214586bf78 add cJ - | - @ 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg debugobsinhibit --hidden 55c73a90e4b4 - $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//' - 20 .hg/store/obsinhibit - $ hg log -G - o 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - @ 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - -Update should inhibit all related unstable commits - - $ hg update 2 --hidden - 2 files updated, 0 files merged, 3 files removed, 0 files unresolved - $ hg log -G - o 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | @ 2:7df62a38b9bf add cC - | | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - - $ hg update 8 - 4 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | o 2:7df62a38b9bf add cC - | | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - $ hg strip --hidden 1:: - 3 changesets pruned - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - -Bookmark should inhibit all related unstable commits - $ hg bookmark -r 2 book1 --hidden - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | o 2:7df62a38b9bf add cC - | | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - -Removing a bookmark with bookmark -D should prune the changes underneath -that are not reachable from another bookmark or head - - $ hg bookmark -r 1 book2 - $ hg bookmark -D book1 --config experimental.evolution=createmarkers #--config to make sure prune is not registered as a command. - bookmark 'book1' deleted - 1 changesets pruned - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - | o 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - $ hg bookmark -D book2 - bookmark 'book2' deleted - 1 changesets pruned - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - -Test edge cases of bookmark -D - $ hg book -D book2 -m hello - abort: Cannot use both -m and -D - [255] - - $ hg book -Draster-fix - abort: Error, please check your command - (make sure to put a space between -D and your bookmark name) - [255] - -Test that direct access make changesets visible - - $ hg export 2db36d8066ff 02bcbc3f6e56 - # HG changeset patch - # User test - # Date 0 0 - # Thu Jan 01 00:00:00 1970 +0000 - # Node ID 2db36d8066ff50e8be3d3e6c2da1ebc0a8381d82 - # Parent 7df62a38b9bf9daf968de235043ba88a8ef43393 - add cD - - diff -r 7df62a38b9bf -r 2db36d8066ff cD - --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - +++ b/cD Thu Jan 01 00:00:00 1970 +0000 - @@ -0,0 +1,1 @@ - +cD - # HG changeset patch - # User test - # Date 0 0 - # Thu Jan 01 00:00:00 1970 +0000 - # Node ID 02bcbc3f6e56fb2928efec2c6e24472720bf5511 - # Parent 54ccbc537fc2d6845a5d61337c1cfb80d1d2815e - add cB - - diff -r 54ccbc537fc2 -r 02bcbc3f6e56 cB - --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - +++ b/cB Thu Jan 01 00:00:00 1970 +0000 - @@ -0,0 +1,1 @@ - +cB - -But only with hash - - $ hg export 2db36d8066ff:: - # HG changeset patch - # User test - # Date 0 0 - # Thu Jan 01 00:00:00 1970 +0000 - # Node ID 2db36d8066ff50e8be3d3e6c2da1ebc0a8381d82 - # Parent 7df62a38b9bf9daf968de235043ba88a8ef43393 - add cD - - diff -r 7df62a38b9bf -r 2db36d8066ff cD - --- /dev/null Thu Jan 01 00:00:00 1970 +0000 - +++ b/cD Thu Jan 01 00:00:00 1970 +0000 - @@ -0,0 +1,1 @@ - +cD - - $ hg export 1 3 - abort: hidden revision '1'! - (use --hidden to access hidden revisions; pruned) - [255] - - -Test directaccess in a larger revset - - $ hg log -r '. + .^ + 2db36d8066ff' -T '{node|short}\n' - 55c73a90e4b4 - cf5c4f4554ce - 2db36d8066ff - -Test directaccess only takes hashes - - $ HOOKPATH=$TESTTMP/printexplicitaccess.py - $ cat >> $HOOKPATH < def hook(ui, repo, **kwds): - > for i in sorted(repo._explicitaccess): - > ui.write('directaccess: %s\n' % i) - > EOF - - $ hg log -r 1 -r 2 -r 2db36d8066f -T '{rev}\n' --config hooks.post-log=python:$HOOKPATH:hook - 1 - 2 - 3 - directaccess: 3 - -With severals hidden sha, rebase of one hidden stack onto another one: - $ hg update -C 0 - 0 files updated, 0 files merged, 4 files removed, 0 files unresolved - $ mkcommit cK - created new head - $ mkcommit cL - $ hg update -C 8 - 4 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg log -G - o 10:53a94305e133 add cL - | - o 9:ad78ff7d621f add cK - | - | @ 8:55c73a90e4b4 add cJ - | | - | | o 7:18214586bf78 add cJ - | |/ - | o 6:cf5c4f4554ce add cH - | | - | o 5:5419eb264a33 add cG - | | - | o 4:98065434e5c6 add cE - |/ - o 0:54ccbc537fc2 add cA - - $ hg strip --hidden 9: - 2 changesets pruned - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg rebase -s 9 -d 3 - abort: hidden revision '9'! - (use --hidden to access hidden revisions; pruned) - [255] - $ hg rebase -r ad78ff7d621f -r 53a94305e133 -d 2db36d8066ff --config experimental.rebaseskipobsolete=0 - Warning: accessing hidden changesets ad78ff7d621f,53a94305e133 for write operation - Warning: accessing hidden changesets 2db36d8066ff for write operation - rebasing 9:ad78ff7d621f "add cK" - rebasing 10:53a94305e133 "add cL" (tip) - $ hg log -G - o 12:2f7b7704d714 add cL - | - o 11:fe1634cbe235 add cK - | - | @ 8:55c73a90e4b4 add cJ - | | - | | o 7:18214586bf78 add cJ - | |/ - | o 6:cf5c4f4554ce add cH - | | - | o 5:5419eb264a33 add cG - | | - | o 4:98065434e5c6 add cE - | | - o | 3:2db36d8066ff add cD - | | - o | 2:7df62a38b9bf add cC - | | - o | 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - -Check that amending in the middle of a stack does not show obsolete revs -Since we are doing operation in the middle of the stack we cannot just -have createmarkers as we are creating instability - - $ cat >> $HGRCPATH < [experimental] - > evolution=all - > EOF - - $ hg strip --hidden 1:: - 5 changesets pruned - $ hg log -G - @ 8:55c73a90e4b4 add cJ - | - | o 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg up 7 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ mkcommit cL - $ mkcommit cM - $ mkcommit cN - $ hg log -G - @ 15:a438c045eb37 add cN - | - o 14:2d66e189f5b5 add cM - | - o 13:d66ccb8c5871 add cL - | - | o 8:55c73a90e4b4 add cJ - | | - o | 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg up 14 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ echo "mmm" >> cM - $ hg amend - $ hg log -G - @ 16:210589181b14 add cM - | - | o 15:a438c045eb37 add cN - | | - | o 14:2d66e189f5b5 add cM - |/ - o 13:d66ccb8c5871 add cL - | - | o 8:55c73a90e4b4 add cJ - | | - o | 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - -Check that rebasing a commit twice makes the commit visible again - - $ hg rebase -d 16 -r 15 --keep - rebasing 15:a438c045eb37 "add cN" - $ hg log -r 13:: -G - o 17:104eed5354c7 add cN - | - @ 16:210589181b14 add cM - | - | o 15:a438c045eb37 add cN - | | - | o 14:2d66e189f5b5 add cM - |/ - o 13:d66ccb8c5871 add cL - | - ~ - $ hg strip -r 210589181b14 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - working directory now at d66ccb8c5871 - 2 changesets pruned - -Using a hash prefix solely made of digits should work - $ hg update 210589181 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg rebase -d 16 -r 15 --keep - rebasing 15:a438c045eb37 "add cN" - $ hg log -r 13:: -G - o 17:104eed5354c7 add cN - | - @ 16:210589181b14 add cM - | - | o 15:a438c045eb37 add cN - | | - | o 14:2d66e189f5b5 add cM - |/ - o 13:d66ccb8c5871 add cL - | - ~ - -Test prunestrip - - $ hg book foo -r 104eed5354c7 - $ hg strip -r 210589181b14 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - working directory now at d66ccb8c5871 - 2 changesets pruned - $ hg log -r 13:: -G -T '{rev}:{node|short} {desc|firstline} {bookmarks}\n' - o 15:a438c045eb37 add cN - | - o 14:2d66e189f5b5 add cM - | - @ 13:d66ccb8c5871 add cL foo - | - ~ - -Check that --hidden used with inhibit does not hide every obsolete commit -We show the log before and after a log -G --hidden, they should be the same - $ hg log -G - o 15:a438c045eb37 add cN - | - o 14:2d66e189f5b5 add cM - | - @ 13:d66ccb8c5871 add cL - | - | o 8:55c73a90e4b4 add cJ - | | - o | 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg log -G --hidden - x 17:104eed5354c7 add cN - | - x 16:210589181b14 add cM - | - | o 15:a438c045eb37 add cN - | | - | o 14:2d66e189f5b5 add cM - |/ - @ 13:d66ccb8c5871 add cL - | - | x 12:2f7b7704d714 add cL - | | - | x 11:fe1634cbe235 add cK - | | - | | x 10:53a94305e133 add cL - | | | - | | x 9:ad78ff7d621f add cK - | | | - | | | o 8:55c73a90e4b4 add cJ - | | | | - o-----+ 7:18214586bf78 add cJ - / / / - | | o 6:cf5c4f4554ce add cH - | | | - | | o 5:5419eb264a33 add cG - | | | - | | o 4:98065434e5c6 add cE - | |/ - x | 3:2db36d8066ff add cD - | | - x | 2:7df62a38b9bf add cC - | | - x | 1:02bcbc3f6e56 add cB - |/ - o 0:54ccbc537fc2 add cA - - - $ hg log -G - o 15:a438c045eb37 add cN - | - o 14:2d66e189f5b5 add cM - | - @ 13:d66ccb8c5871 add cL - | - | o 8:55c73a90e4b4 add cJ - | | - o | 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - -check that pruning and inhibited node does not confuse anything - - $ hg up --hidden 210589181b14 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg strip --bundle 210589181b14 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - saved backup bundle to $TESTTMP/inhibit/.hg/strip-backup/210589181b14-e09c7b88-backup.hg (glob) - $ hg unbundle .hg/strip-backup/210589181b14-e09c7b88-backup.hg # restore state - adding changesets - adding manifests - adding file changes - added 2 changesets with 1 changes to 2 files (+1 heads) - 3 new obsolescence markers - obsoleted 1 changesets - new changesets 210589181b14 - (run 'hg heads .' to see heads, 'hg merge' to merge) - - Only allow direct access and check that evolve works like before -(also disable evolve commands to avoid hint about using evolve) - $ cat >> $HGRCPATH < [extensions] - > inhibit=! - > [experimental] - > evolution=createmarkers - > EOF - - $ hg up 14 - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory parent is obsolete! (2d66e189f5b5) - $ cat >> $HGRCPATH < [experimental] - > evolution=all - > EOF - $ echo "CM" > cM - $ hg amend - $ hg log -G - @ 18:721c3c279519 add cM - | - | o 15:a438c045eb37 add cN - | | - | x 14:2d66e189f5b5 add cM - |/ - o 13:d66ccb8c5871 add cL - | - o 7:18214586bf78 add cJ - | - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ cat >> $HGRCPATH < [extensions] - > EOF - $ echo "inhibit=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/inhibit.py" >> $HGRCPATH - -Empty commit - $ hg amend - nothing changed - [1] - -Check that the behavior of rebase with obsolescence markers is maintained -despite inhibit - - $ hg up a438c045eb37 - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ hg rebase -r 14:: -d 18 --config experimental.rebaseskipobsolete=True - note: not rebasing 14:2d66e189f5b5 "add cM", already in destination as 18:721c3c279519 "add cM" (tip) - rebasing 15:a438c045eb37 "add cN" - $ hg up -q 2d66e189f5b5 # To inhibit it as the rest of test depends on it - $ hg up -q 18 - -Directaccess should load after some extensions precised in the conf -With no extension specified: - - $ cat >$TESTTMP/test_extension.py << EOF - > from mercurial import extensions - > def uisetup(ui): - > print extensions._order - > EOF - $ cat >> $HGRCPATH << EOF - > [extensions] - > testextension=$TESTTMP/test_extension.py - > EOF - $ hg id - ['rebase', 'strip', 'evolve', 'directaccess', 'inhibit', 'testextension'] - 721c3c279519 - -With test_extension specified: - $ cat >> $HGRCPATH << EOF - > [directaccess] - > loadsafter=testextension - > EOF - $ hg id - ['rebase', 'strip', 'evolve', 'inhibit', 'testextension', 'directaccess'] - 721c3c279519 - -Inhibit should not work without directaccess - $ cat >> $HGRCPATH < [extensions] - > directaccess=! - > testextension=! - > EOF - $ hg up . - cannot use inhibit without the direct access extension - (please enable it or inhibit won't work) - 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - $ echo "directaccess=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/directaccess.py" >> $HGRCPATH - $ cd .. - -hg push should not allow directaccess unless forced with --hidden -We copy the inhibhit repo to inhibit2 and make some changes to push to inhibit - - $ cp -r inhibit inhibit2 - $ pwd=$(pwd) - $ cd inhibit - $ mkcommit pk - created new head - $ hg id - 003a4735afde tip - $ echo "OO" > pk - $ hg amend - $ hg id - 71eb4f100663 tip - -Hidden commits cannot be pushed without --hidden - $ hg push -r 003a4735afde $pwd/inhibit2 - pushing to $TESTTMP/inhibit2 - abort: hidden revision '003a4735afde'! - (use --hidden to access hidden revisions; successor: 71eb4f100663) - [255] - -Visible commits can still be pushed - $ hg push -fr 71eb4f100663 $pwd/inhibit2 - pushing to $TESTTMP/inhibit2 - searching for changes - adding changesets - adding manifests - adding file changes - added 1 changesets with 1 changes to 1 files (+1 heads) - 1 new obsolescence markers - -Create a stack (obsolete with successor in dest) -> (not obsolete) and rebase -it. We expect to not see the stack at the end of the rebase. - $ hg log -G -r "003a4735afde::" - x 20:003a4735afde add pk - | - ~ - $ hg log -G - @ 21:71eb4f100663 add pk - | - | o 19:46cb6daad392 add cN - |/ - o 18:721c3c279519 add cM - | - | o 16:210589181b14 add cM - |/ - | o 14:2d66e189f5b5 add cM - |/ - o 13:d66ccb8c5871 add cL - | - | o 8:55c73a90e4b4 add cJ - | | - o | 7:18214586bf78 add cJ - |/ - o 6:cf5c4f4554ce add cH - | - o 5:5419eb264a33 add cG - | - o 4:98065434e5c6 add cE - | - o 0:54ccbc537fc2 add cA - - $ hg up -C 46cb6daad392 - 1 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit Dk - $ hg prune 46cb6daad392 -s 71eb4f100663 - 1 changesets pruned - $ hg rebase -s 46cb6daad392 -d 71eb4f100663 --config experimental.rebaseskipobsolete=True - note: not rebasing 19:46cb6daad392 "add cN", already in destination as 21:71eb4f100663 "add pk" - rebasing 22:7ad60e760c7b "add Dk" (tip) - $ hg log -G -r "71eb4f100663::" - @ 23:1192fa9fbc68 add Dk - | - o 21:71eb4f100663 add pk - | - ~ - -Create a stack (obsolete with succ in dest) -> (not obsolete) -> (not obsolete). -Rebase the first two revs of the stack onto dest, we expect to see one new -revision on the destination and everything visible. - $ hg up 71eb4f100663 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - $ mkcommit Dl - created new head - $ mkcommit Dp - $ mkcommit Do - $ hg log -G -r "71eb4f100663::" - @ 26:b517facce1ef add Do - | - o 25:c5a47ab27c2e add Dp - | - o 24:8c1c2edbaf1b add Dl - | - | o 23:1192fa9fbc68 add Dk - |/ - o 21:71eb4f100663 add pk - | - ~ - $ hg prune 8c1c2edbaf1b -s 1192fa9fbc68 - 1 changesets pruned - $ hg up 71eb4f100663 - 0 files updated, 0 files merged, 3 files removed, 0 files unresolved - $ hg rebase -r "8c1c2edbaf1b + c5a47ab27c2e" --keep -d 1192fa9fbc68 --config experimental.rebaseskipobsolete=True - note: not rebasing 24:8c1c2edbaf1b "add Dl", already in destination as 23:1192fa9fbc68 "add Dk" - rebasing 25:c5a47ab27c2e "add Dp" - $ hg log -G -r "71eb4f100663::" - o 27:7d8affb1f604 add Dp - | - | o 26:b517facce1ef add Do - | | - | o 25:c5a47ab27c2e add Dp - | | - | o 24:8c1c2edbaf1b add Dl - | | - o | 23:1192fa9fbc68 add Dk - |/ - @ 21:71eb4f100663 add pk - | - ~ - -Rebase the same stack in full on the destination, we expect it to disappear -and only see the top revision added to destination. We don\'t expect 29 to be -skipped as we used --keep before. - $ hg rebase -s 8c1c2edbaf1b -d 1192fa9fbc68 --config experimental.rebaseskipobsolete=True - note: not rebasing 24:8c1c2edbaf1b "add Dl", already in destination as 23:1192fa9fbc68 "add Dk" - rebasing 25:c5a47ab27c2e "add Dp" - rebasing 26:b517facce1ef "add Do" - $ hg log -G -r "71eb4f100663::" - o 28:1d43fff9e26f add Do - | - o 27:7d8affb1f604 add Dp - | - o 23:1192fa9fbc68 add Dk - | - @ 21:71eb4f100663 add pk - | - ~ - -Pulling from a inhibit repo to a non-inhibit repo should work - - $ cd .. - $ hg clone -q inhibit not-inhibit - $ cat >> not-inhibit/.hg/hgrc < [extensions] - > inhibit=! - > directaccess=! - > evolve=! - > EOF - $ cd not-inhibit - $ hg book -d foo - $ hg pull - pulling from $TESTTMP/inhibit (glob) - searching for changes - no changes found - adding remote bookmark foo - -Test that bookmark -D can take multiple branch names - $ cd ../inhibit - $ hg bookmark book2 book1 book3 - $ touch foo && hg add foo && hg ci -m "add foo" - created new head - $ hg up book1 - 0 files updated, 0 files merged, 1 files removed, 0 files unresolved - (activating bookmark book1) - $ hg bookmark -D book2 book3 - bookmark 'book2' deleted - bookmark 'book3' deleted - 1 changesets pruned diff -r c3953ae44b87 -r f42a87cc864d tests/test-obsolete.t --- a/tests/test-obsolete.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-obsolete.t Wed Nov 01 23:51:55 2017 +0100 @@ -721,7 +721,7 @@ $ hg up --hidden 2 1 files updated, 0 files merged, 1 files removed, 0 files unresolved working directory parent is obsolete! (4538525df7e2) - (4538525df7e2 has diverged, use 'hg evolve --list --contentdivergent' to resolve the issue) + (4538525df7e2 has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) $ hg export 9468a5f5d8b2 | hg import - applying patch from stdin 1 new orphan changesets diff -r c3953ae44b87 -r f42a87cc864d tests/test-sharing.t --- a/tests/test-sharing.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-sharing.t Wed Nov 01 23:51:55 2017 +0100 @@ -505,7 +505,7 @@ 6:e3f99ce9d9cd draft fix bug 24 (v2 by alice) Use evolve to fix the divergence. - $ HGMERGE=internal:other hg evolve --contentdivergent + $ HGMERGE=internal:other hg evolve --content-divergent merge:[5] fix bug 24 (v2 by bob) with: [6] fix bug 24 (v2 by alice) base: [4] fix bug 24 (v1) diff -r c3953ae44b87 -r f42a87cc864d tests/test-stabilize-result.t --- a/tests/test-stabilize-result.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-stabilize-result.t Wed Nov 01 23:51:55 2017 +0100 @@ -153,20 +153,20 @@ Stabilize! - $ hg evolve --any --dry-run --phasedivergent + $ hg evolve --any --dry-run --phase-divergent recreate:[9] newer a atop:[6] newer a hg rebase --rev d5c7ef82d003 --dest 66719795a494; hg update 1cf0aacfd363; hg revert --all --rev d5c7ef82d003; hg commit --msg "bumped update to %s" (no-eol) - $ hg evolve --any --confirm --phasedivergent + $ hg evolve --any --confirm --phase-divergent recreate:[9] newer a atop:[6] newer a perform evolve? [Ny] n abort: evolve aborted by user [255] - $ echo y | hg evolve --any --confirm --config ui.interactive=True --phasedivergent + $ echo y | hg evolve --any --confirm --config ui.interactive=True --phase-divergent recreate:[9] newer a atop:[6] newer a perform evolve? [Ny] y @@ -244,14 +244,14 @@ Stabilize it - $ hg evolve -qn --confirm --contentdivergent + $ hg evolve -qn --confirm --content-divergent merge:[14] More addition with: [13] More addition base: [12] More addition perform evolve? [Ny] n abort: evolve aborted by user [255] - $ echo y | hg evolve -qn --confirm --config ui.interactive=True --contentdivergent + $ echo y | hg evolve -qn --confirm --config ui.interactive=True --content-divergent merge:[14] More addition with: [13] More addition base: [12] More addition @@ -262,7 +262,7 @@ hg up -C 3932c176bbaa && hg revert --all --rev tip && hg commit -m "`hg log -r eacc9c8240fe --template={desc}`"; - $ hg evolve -v --contentdivergent + $ hg evolve -v --content-divergent merge:[14] More addition with: [13] More addition base: [12] More addition @@ -336,14 +336,14 @@ $ hg phase 'contentdivergent()' 15: draft 17: draft - $ hg evolve -qn --contentdivergent + $ hg evolve -qn --content-divergent hg update -c 0b336205a5d0 && hg merge f344982e63c4 && hg commit -m "auto merge resolving conflict between 0b336205a5d0 and f344982e63c4"&& hg up -C 3932c176bbaa && hg revert --all --rev tip && hg commit -m "`hg log -r 0b336205a5d0 --template={desc}`"; - $ hg evolve --contentdivergent + $ hg evolve --content-divergent merge:[17] More addition (2) with: [15] More addition base: [12] More addition diff -r c3953ae44b87 -r f42a87cc864d tests/test-topic-flow-publish-bare.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-topic-flow-publish-bare.t Wed Nov 01 23:51:55 2017 +0100 @@ -0,0 +1,292 @@ +===================== +Test workflow options +===================== + + $ . "$TESTDIR/testlib/topic_setup.sh" + $ . "$TESTDIR/testlib/common.sh" + +Publishing of bare branch +========================= + + $ hg init bare-branch-server + $ cd bare-branch-server + $ cat <> .hg/hgrc + > [phases] + > publish = no + > [experimental] + > topic.publish-bare-branch = yes + > EOF + $ mkcommit ROOT + $ mkcommit c_dA0 + $ hg phase --public -r 'all()' + $ cd .. + + $ hg clone bare-branch-server bare-client + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + +pushing a simple branch publish it +---------------------------------- + + $ cd bare-client + $ mkcommit c_dB0 + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +pushing two heads at the same time +---------------------------------- + + $ hg update 'desc("c_dA0")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkcommit c_dC0 + created new head + $ hg update 'desc("c_dA0")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkcommit c_dD0 + created new head + $ hg push -f + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files (+2 heads) + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 4:9bf953aa81f6 c_dD0 public default + | + | o 3:9d5b8e1f08a4 c_dC0 public default + |/ + | o 2:286d02a6e2a2 c_dB0 public default + |/ + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +pushing something not on default +-------------------------------- + + $ hg update 'desc("ROOT")' + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg branch branchA + marked working directory as branch branchA + (branches are permanent and global, did you want a bookmark?) + $ mkcommit c_aE0 + $ hg push --new-branch + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 5:0db08e758601 c_aE0 public branchA + | + | o 4:9bf953aa81f6 c_dD0 public default + | | + | | o 3:9d5b8e1f08a4 c_dC0 public default + | |/ + | | o 2:286d02a6e2a2 c_dB0 public default + | |/ + | o 1:134bc3852ad2 c_dA0 public default + |/ + o 0:ea207398892e ROOT public default + + +pushing topic +------------- + + $ hg update 'desc("c_dD0")' + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg topic foo + marked working directory as topic: foo + $ mkcommit c_dF0 + active topic 'foo' grew its first changeset + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 6:0867c4471796 c_dF0 draft default foo + | + o 4:9bf953aa81f6 c_dD0 public default + | + | o 3:9d5b8e1f08a4 c_dC0 public default + |/ + | o 2:286d02a6e2a2 c_dB0 public default + |/ + o 1:134bc3852ad2 c_dA0 public default + | + | o 5:0db08e758601 c_aE0 public branchA + |/ + o 0:ea207398892e ROOT public default + + +pushing topic over a bare branch +-------------------------------- + + $ hg update 'desc("c_dC0")' + 1 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ mkcommit c_dG0 + $ hg topic bar + marked working directory as topic: bar + $ mkcommit c_dH0 + active topic 'bar' grew its first changeset + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 8:858be9a8daaf c_dH0 draft default bar + | + o 7:0e4041d324d0 c_dG0 public default + | + o 3:9d5b8e1f08a4 c_dC0 public default + | + | o 2:286d02a6e2a2 c_dB0 public default + |/ + | o 6:0867c4471796 c_dF0 draft default foo + | | + | o 4:9bf953aa81f6 c_dD0 public default + |/ + o 1:134bc3852ad2 c_dA0 public default + | + | o 5:0db08e758601 c_aE0 public branchA + |/ + o 0:ea207398892e ROOT public default + + +Pushing topic in between bare branch +------------------------------------ + + $ hg update 'desc("c_dB0")' + 1 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ mkcommit c_dI0 + $ hg update 'desc("c_dH0")' + switching to topic bar + 3 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ mkcommit c_dJ0 + $ hg update 'desc("c_aE0")' + 1 files updated, 0 files merged, 5 files removed, 0 files unresolved + $ mkcommit c_aK0 + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 3 changesets with 3 changes to 3 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 11:b0a00ebdfd24 c_aK0 public branchA + | + o 5:0db08e758601 c_aE0 public branchA + | + | o 10:abb5c84eb9e9 c_dJ0 draft default bar + | | + | o 8:858be9a8daaf c_dH0 draft default bar + | | + | o 7:0e4041d324d0 c_dG0 public default + | | + | o 3:9d5b8e1f08a4 c_dC0 public default + | | + | | o 9:4b5570d89f0f c_dI0 public default + | | | + | | o 2:286d02a6e2a2 c_dB0 public default + | |/ + | | o 6:0867c4471796 c_dF0 draft default foo + | | | + | | o 4:9bf953aa81f6 c_dD0 public default + | |/ + | o 1:134bc3852ad2 c_dA0 public default + |/ + o 0:ea207398892e ROOT public default + + +merging a topic in branch +------------------------- + + $ hg update default + 3 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg merge foo + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg ci -m 'c_dL0' + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 0 files (-1 heads) + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 12:a6f9f8c6c6cc c_dL0 public default + |\ + | o 9:4b5570d89f0f c_dI0 public default + | | + o | 6:0867c4471796 c_dF0 public default + | | + o | 4:9bf953aa81f6 c_dD0 public default + | | + | | o 10:abb5c84eb9e9 c_dJ0 draft default bar + | | | + | | o 8:858be9a8daaf c_dH0 draft default bar + | | | + | | o 7:0e4041d324d0 c_dG0 public default + | | | + +---o 3:9d5b8e1f08a4 c_dC0 public default + | | + | o 2:286d02a6e2a2 c_dB0 public default + |/ + o 1:134bc3852ad2 c_dA0 public default + | + | o 11:b0a00ebdfd24 c_aK0 public branchA + | | + | o 5:0db08e758601 c_aE0 public branchA + |/ + o 0:ea207398892e ROOT public default + + $ hg log -R ../bare-branch-server --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + o 12:a6f9f8c6c6cc c_dL0 public default + |\ + | o 9:4b5570d89f0f c_dI0 public default + | | + o | 6:0867c4471796 c_dF0 public default + | | + o | 4:9bf953aa81f6 c_dD0 public default + | | + | | o 10:abb5c84eb9e9 c_dJ0 draft default bar + | | | + | | o 8:858be9a8daaf c_dH0 draft default bar + | | | + | | o 7:0e4041d324d0 c_dG0 public default + | | | + +---o 3:9d5b8e1f08a4 c_dC0 public default + | | + | o 2:286d02a6e2a2 c_dB0 public default + |/ + @ 1:134bc3852ad2 c_dA0 public default + | + | o 11:b0a00ebdfd24 c_aK0 public branchA + | | + | o 5:0db08e758601 c_aE0 public branchA + |/ + o 0:ea207398892e ROOT public default + diff -r c3953ae44b87 -r f42a87cc864d tests/test-topic-flow-publish-flag.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-topic-flow-publish-flag.t Wed Nov 01 23:51:55 2017 +0100 @@ -0,0 +1,282 @@ +===================== +Test workflow options +===================== + + $ . "$TESTDIR/testlib/topic_setup.sh" + $ . "$TESTDIR/testlib/common.sh" + +testing hg push --publish flag +============================== + + $ hg init bare-branch-server + $ cd bare-branch-server + $ cat <> .hg/hgrc + > [phases] + > publish = no + > EOF + $ mkcommit ROOT + $ mkcommit c_dA0 + $ hg phase --public -r 'all()' + $ cd .. + + $ hg clone bare-branch-server bare-client + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd bare-client + +Pushing a 1 new changeset +------------------------- + + $ mkcommit c_dB0 + $ hg push --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Pushing a 2 new changeset (same branch) +--------------------------------------- + + $ mkcommit c_dC0 + $ mkcommit c_dD0 + $ hg push --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Pushing a 2 new changeset two head +---------------------------------- + + $ mkcommit c_dE0 + $ hg update 'desc("c_dD0")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg branch other + marked working directory as branch other + (branches are permanent and global, did you want a bookmark?) + $ mkcommit c_oF0 + $ hg push -f --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files (+1 heads) + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 6:45b23c834b6a c_oF0 public other + | + | o 5:5576ae39eaee c_dE0 public default + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Publishing 1 common changeset +----------------------------- + $ mkcommit c_oG0 + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 7:d293f74a1233 c_oG0 draft other + | + o 6:45b23c834b6a c_oF0 public other + | + | o 5:5576ae39eaee c_dE0 public default + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + $ hg push --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + no changes found + [1] + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 7:d293f74a1233 c_oG0 public other + | + o 6:45b23c834b6a c_oF0 public other + | + | o 5:5576ae39eaee c_dE0 public default + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Selectively publishing 1 changeset +---------------------------------- + + $ mkcommit c_oH0 + $ hg update default + 1 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ mkcommit c_dI0 + $ hg push -r default --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 9:fbf2be276221 c_dI0 public default + | + o 5:5576ae39eaee c_dE0 public default + | + | o 8:8e85646c135f c_oH0 draft other + | | + | o 7:d293f74a1233 c_oG0 public other + | | + | o 6:45b23c834b6a c_oF0 public other + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Selectively publishing 1 common changeset +----------------------------------------- + + $ mkcommit c_dJ0 + $ hg push + pushing to $TESTTMP/bare-branch-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 10:ac4cf59f2aac c_dJ0 draft default + | + o 9:fbf2be276221 c_dI0 public default + | + o 5:5576ae39eaee c_dE0 public default + | + | o 8:8e85646c135f c_oH0 draft other + | | + | o 7:d293f74a1233 c_oG0 public other + | | + | o 6:45b23c834b6a c_oF0 public other + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + $ hg push --rev default --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + no changes found + [1] + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 10:ac4cf59f2aac c_dJ0 public default + | + o 9:fbf2be276221 c_dI0 public default + | + o 5:5576ae39eaee c_dE0 public default + | + | o 8:8e85646c135f c_oH0 draft other + | | + | o 7:d293f74a1233 c_oG0 public other + | | + | o 6:45b23c834b6a c_oF0 public other + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + + +Selectively publishing no changeset +----------------------------------- + + $ hg push --rev default --publish + pushing to $TESTTMP/bare-branch-server + searching for changes + no changes found + [1] + $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}' + @ 10:ac4cf59f2aac c_dJ0 public default + | + o 9:fbf2be276221 c_dI0 public default + | + o 5:5576ae39eaee c_dE0 public default + | + | o 8:8e85646c135f c_oH0 draft other + | | + | o 7:d293f74a1233 c_oG0 public other + | | + | o 6:45b23c834b6a c_oF0 public other + |/ + o 4:c63e7dd93a91 c_dD0 public default + | + o 3:7d56a56d2547 c_dC0 public default + | + o 2:286d02a6e2a2 c_dB0 public default + | + o 1:134bc3852ad2 c_dA0 public default + | + o 0:ea207398892e ROOT public default + diff -r c3953ae44b87 -r f42a87cc864d tests/test-topic-flow-single-head.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-topic-flow-single-head.t Wed Nov 01 23:51:55 2017 +0100 @@ -0,0 +1,189 @@ +===================== +Test workflow options +===================== + + $ . "$TESTDIR/testlib/topic_setup.sh" + $ . "$TESTDIR/testlib/common.sh" + +Test single head enforcing - Setup +============================================= + + $ hg init single-head-server + $ cd single-head-server + $ cat <> .hg/hgrc + > [phases] + > publish = no + > [experimental] + > enforce-single-head = yes + > evolution = all + > EOF + $ mkcommit ROOT + $ mkcommit c_dA0 + $ cd .. + + $ hg clone single-head-server client + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Test single head enforcing - with branch only +--------------------------------------------- + + $ cd client + +continuing the current defaultbranch + + $ mkcommit c_dB0 + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +creating a new branch + + $ hg up 'desc("ROOT")' + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg branch branch_A + marked working directory as branch branch_A + (branches are permanent and global, did you want a bookmark?) + $ mkcommit c_aC0 + $ hg push --new-branch + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + +Create a new head on the default branch + + $ hg up 'desc("c_dA0")' + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkcommit c_dD0 + created new head + $ hg push -f + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + transaction abort! + rollback completed + abort: 2 heads on "default" + (286d02a6e2a2, 9bf953aa81f6) + [255] + +remerge them + + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ mkcommit c_dE0 + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + +Test single head enforcing - with topic +--------------------------------------- + +pushing a new topic + + $ hg topic foo + marked working directory as topic: foo + $ mkcommit c_dF0 + active topic 'foo' grew its first changeset + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + +pushing a new topo branch (with a topic) + + $ hg up 'desc("c_dD0")' + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ hg topic bar + marked working directory as topic: bar + $ mkcommit c_dG0 + active topic 'bar' grew its first changeset + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + +detect multiple heads on the topic + + $ mkcommit c_dH0 + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + $ hg up 'desc("c_dG0")' + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ mkcommit c_dI0 + $ hg push -f + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + transaction abort! + rollback completed + abort: 2 heads on "default:bar" + (5194f5dcd542, 48a01453c1c5) + [255] + +merge works fine + + $ hg merge + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ mkcommit c_dJ0 + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 2 changesets with 2 changes to 2 files + +Test single head enforcing - by phase move +------------------------------------------ + + $ hg -R ../single-head-server phase --public 'desc("c_dJ0")' + abort: 2 heads on "default" + (6ed1df20edb1, 678bca4de98c) + [255] + +Test single head enforcing - after rewrite +------------------------------------------ + + $ hg up foo + switching to topic foo + 3 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ hg commit --amend -m c_dF1 + $ hg push + pushing to $TESTTMP/single-head-server + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 0 changes to 1 files (+1 heads) + 1 new obsolescence markers + obsoleted 1 changesets diff -r c3953ae44b87 -r f42a87cc864d tests/test-uncommit.t --- a/tests/test-uncommit.t Mon Oct 23 16:04:23 2017 +0200 +++ b/tests/test-uncommit.t Wed Nov 01 23:51:55 2017 +0100 @@ -287,7 +287,7 @@ $ hg up -C 3 --hidden 1 files updated, 0 files merged, 0 files removed, 0 files unresolved working directory parent is obsolete! (5eb72dbe0cb4) - (5eb72dbe0cb4 has diverged, use 'hg evolve --list --contentdivergent' to resolve the issue) + (5eb72dbe0cb4 has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) $ hg --config extensions.purge= purge $ hg uncommit --all -X e 1 new content-divergent changesets