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.
--- a/mercurial/cmdutil.py Wed Mar 28 11:42:17 2012 +0200
+++ b/mercurial/cmdutil.py Wed Mar 28 11:42:17 2012 +0200
@@ -1369,11 +1369,8 @@
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)
--- a/mercurial/subrepo.py Wed Mar 28 11:42:17 2012 +0200
+++ b/mercurial/subrepo.py Wed Mar 28 11:42:17 2012 +0200
@@ -577,13 +577,37 @@
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
--- a/tests/test-subrepo.t Wed Mar 28 11:42:17 2012 +0200
+++ b/tests/test-subrepo.t Wed Mar 28 11:42:17 2012 +0200
@@ -38,20 +38,20 @@
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