# HG changeset patch # User Angel Ezquerra # Date 2012-03-28 09:42:17 # Node ID 6883c2363f44ea7b0dcb83f3c507c71b0f1b4a34 # Parent 71dcce391a44407e763dda39cca0a9eed5b2a282 revert: add support for reverting subrepos without --no-backup and/or --all When a subrepo is reverted but --no-backup is not set, call revert on the subrepo that is being reverted prior to updating it to the revision specified in the parent repo's .hgsubstate file. The --all flag is passed down to the subrepo when it is being reverted. If the --all flag is not set, all files that are modified on the subrepo will be reverted. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1369,11 +1369,8 @@ def revert(ui, repo, ctx, parents, *pats if abs not in names: names[abs] = m.rel(abs), m.exact(abs) + # get the list of subrepos that must be reverted targetsubs = [s for s in repo[node].substate if m(s)] - if targetsubs and not opts.get('no_backup'): - msg = _("cannot revert subrepos without --no-backup") - raise util.Abort(msg) - m = scmutil.matchfiles(repo, names) changes = repo.status(match=m)[:4] modified, added, removed, deleted = map(set, changes) diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -577,13 +577,37 @@ class hgsubrepo(abstractsubrepo): os.path.join(prefix, self._path), True) def revert(self, ui, substate, *pats, **opts): - # reverting a subrepo is done by updating it to the revision - # specified in the corresponding substate dictionary + # reverting a subrepo is a 2 step process: + # 1. if the no_backup is not set, revert all modified + # files inside the subrepo + # 2. update the subrepo to the revision specified in + # the corresponding substate dictionary ui.status(_('reverting subrepo %s\n') % substate[0]) + if not opts.get('no_backup'): + # Revert all files on the subrepo, creating backups + # Note that this will not recursively revert subrepos + # We could do it if there was a set:subrepos() predicate + opts = opts.copy() + opts['date'] = None + opts['rev'] = substate[1] + + pats = [] + if not opts['all']: + pats = ['set:modified()'] + self.filerevert(ui, *pats, **opts) # Update the repo to the revision specified in the given substate self.get(substate, overwrite=True) + def filerevert(self, ui, *pats, **opts): + ctx = self._repo[opts['rev']] + parents = self._repo.dirstate.parents() + if opts['all']: + pats = ['set:modified()'] + else: + pats = [] + cmdutil.revert(ui, self._repo, ctx, parents, *pats, **opts) + class svnsubrepo(abstractsubrepo): def __init__(self, ctx, path, state): self._path = path diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t --- a/tests/test-subrepo.t +++ b/tests/test-subrepo.t @@ -38,20 +38,20 @@ Issue2232: committing a subrepo without update: (current) $ hg ci -m1 -Revert can't (yet) revert subrepos: +Revert subrepo: $ echo b > s/a $ hg revert s - abort: cannot revert subrepos without --no-backup - [255] - -Revert currently ignores subrepos by default + reverting subrepo s + reverting s/a + $ rm s/a.orig - $ hg revert -a - abort: cannot revert subrepos without --no-backup - [255] - $ hg revert -R s -a -C - reverting s/a (glob) +Revert subrepo with no backup. The "reverting s/a" line is gone since +we're really running 'hg update' in the subrepo: + + $ echo b > s/a + $ hg revert --no-backup s + reverting subrepo s Issue2022: update -C