Mercurial > public > mercurial-scm > hg
diff hgext/mq.py @ 19826:4b1cbcfdabf7
mq: extract strip function as its standalone extension (issue3824)
Strip now lives in its own extension
reminder: The extension is surprisingly called `strip`. The `mq` extension
force the use of the strip extension when its enabled. This is both necessary
for backward compatibility (people expect `mq` to comes with strip) and become
some utility function used by `mq` are now in the strip extension.
author | Pierre-Yves David <pierre-yves.david@ens-lyon.org> |
---|---|
date | Thu, 26 Sep 2013 23:57:21 +0200 |
parents | 4b4997068143 |
children | 28b1b7b9b4a9 |
line wrap: on
line diff
--- a/hgext/mq.py Thu Sep 26 23:43:00 2013 +0200 +++ b/hgext/mq.py Thu Sep 26 23:57:21 2013 +0200 @@ -57,13 +57,16 @@ make them behave as if --keep-changes were passed, and non-conflicting local changes will be tolerated and preserved. If incompatible options such as -f/--force or --exact are passed, this setting is ignored. + +This extension used to provide a strip command. This command now lives +in the strip extension. ''' from mercurial.i18n import _ from mercurial.node import bin, hex, short, nullid, nullrev from mercurial.lock import release from mercurial import commands, cmdutil, hg, scmutil, util, revset -from mercurial import extensions, error, phases, bookmarks +from mercurial import extensions, error, phases from mercurial import patch as patchmod from mercurial import localrepo from mercurial import subrepo @@ -2912,160 +2915,6 @@ q.savedirty() return 0 -@command("strip", - [ - ('r', 'rev', [], _('strip specified revision (optional, ' - 'can specify revisions without this ' - 'option)'), _('REV')), - ('f', 'force', None, _('force removal of changesets, discard ' - 'uncommitted changes (no backup)')), - ('b', 'backup', None, _('bundle only changesets with local revision' - ' number greater than REV which are not' - ' descendants of REV (DEPRECATED)')), - ('', 'no-backup', None, _('no backups')), - ('', 'nobackup', None, _('no backups (DEPRECATED)')), - ('n', '', None, _('ignored (DEPRECATED)')), - ('k', 'keep', None, _("do not modify working copy during strip")), - ('B', 'bookmark', '', _("remove revs only reachable from given" - " bookmark"))], - _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...')) -def stripcmd(ui, repo, *revs, **opts): - """strip changesets and all their descendants from the repository - - The strip command removes the specified changesets and all their - descendants. If the working directory has uncommitted changes, the - operation is aborted unless the --force flag is supplied, in which - case changes will be discarded. - - If a parent of the working directory is stripped, then the working - directory will automatically be updated to the most recent - available ancestor of the stripped parent after the operation - completes. - - Any stripped changesets are stored in ``.hg/strip-backup`` as a - bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can - be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`, - where BUNDLE is the bundle file created by the strip. Note that - the local revision numbers will in general be different after the - restore. - - Use the --no-backup option to discard the backup bundle once the - operation completes. - - Strip is not a history-rewriting operation and can be used on - changesets in the public phase. But if the stripped changesets have - been pushed to a remote repository you will likely pull them again. - - Return 0 on success. - """ - backup = 'all' - if opts.get('backup'): - backup = 'strip' - elif opts.get('no_backup') or opts.get('nobackup'): - backup = 'none' - - cl = repo.changelog - revs = list(revs) + opts.get('rev') - revs = set(scmutil.revrange(repo, revs)) - - if opts.get('bookmark'): - mark = opts.get('bookmark') - marks = repo._bookmarks - if mark not in marks: - raise util.Abort(_("bookmark '%s' not found") % mark) - - # If the requested bookmark is not the only one pointing to a - # a revision we have to only delete the bookmark and not strip - # anything. revsets cannot detect that case. - uniquebm = True - for m, n in marks.iteritems(): - if m != mark and n == repo[mark].node(): - uniquebm = False - break - if uniquebm: - rsrevs = repo.revs("ancestors(bookmark(%s)) - " - "ancestors(head() and not bookmark(%s)) - " - "ancestors(bookmark() and not bookmark(%s))", - mark, mark, mark) - revs.update(set(rsrevs)) - if not revs: - del marks[mark] - marks.write() - ui.write(_("bookmark '%s' deleted\n") % mark) - - if not revs: - raise util.Abort(_('empty revision set')) - - descendants = set(cl.descendants(revs)) - strippedrevs = revs.union(descendants) - roots = revs.difference(descendants) - - update = False - # if one of the wdir parent is stripped we'll need - # to update away to an earlier revision - for p in repo.dirstate.parents(): - if p != nullid and cl.rev(p) in strippedrevs: - update = True - break - - rootnodes = set(cl.node(r) for r in roots) - - q = getattr(repo, 'mq', None) - if q is not None and q.applied: - # refresh queue state if we're about to strip - # applied patches - if cl.rev(repo.lookup('qtip')) in strippedrevs: - q.applieddirty = True - start = 0 - end = len(q.applied) - for i, statusentry in enumerate(q.applied): - if statusentry.node in rootnodes: - # if one of the stripped roots is an applied - # patch, only part of the queue is stripped - start = i - break - del q.applied[start:end] - q.savedirty() - - revs = sorted(rootnodes) - if update and opts.get('keep'): - wlock = repo.wlock() - try: - urev, p2 = repo.changelog.parents(revs[0]) - if (util.safehasattr(repo, 'mq') and p2 != nullid - and p2 in [x.node for x in repo.mq.applied]): - urev = p2 - uctx = repo[urev] - - # only reset the dirstate for files that would actually change - # between the working context and uctx - descendantrevs = repo.revs("%s::." % uctx.rev()) - changedfiles = [] - for rev in descendantrevs: - # blindly reset the files, regardless of what actually changed - changedfiles.extend(repo[rev].files()) - - # reset files that only changed in the dirstate too - dirstate = repo.dirstate - dirchanges = [f for f in dirstate if dirstate[f] != 'n'] - changedfiles.extend(dirchanges) - - repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles) - repo.dirstate.write() - update = False - finally: - wlock.release() - - if opts.get('bookmark'): - if mark == repo._bookmarkcurrent: - bookmarks.setcurrent(repo, None) - del marks[mark] - marks.write() - ui.write(_("bookmark '%s' deleted\n") % mark) - - strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force')) - - return 0 @command("qselect", [('n', 'none', None, _('disable all guards')),