diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -13,6 +13,7 @@ import hg, scmutil, util, revlog, extens import patch, help, url, encoding, templatekw, discovery import archival, changegroup, cmdutil, hbisect import sshserver, hgweb, hgweb.server, commandserver +import match as matchmod import merge as mergemod import minirst, revset, fileset import dagparser, context, simplemerge @@ -2432,23 +2433,45 @@ def forget(ui, repo, *pats, **opts): if not pats: raise util.Abort(_('no files specified')) - m = scmutil.match(repo[None], pats, opts) + wctx = repo[None] + m = scmutil.match(wctx, pats, opts) s = repo.status(match=m, clean=True) forget = sorted(s[0] + s[1] + s[3] + s[6]) + subforget = {} errs = 0 + for subpath in wctx.substate: + sub = wctx.sub(subpath) + try: + submatch = matchmod.narrowmatcher(subpath, m) + for fsub in sub.walk(submatch): + if submatch.exact(fsub): + subforget[os.path.join(subpath, fsub)] = (fsub, sub) + except error.LookupError: + ui.status(_("skipping missing subrepository: %s\n") % subpath) + for f in m.files(): if f not in repo.dirstate and not os.path.isdir(m.rel(f)): - if os.path.exists(m.rel(f)): - ui.warn(_('not removing %s: file is already untracked\n') - % m.rel(f)) - errs = 1 + if f not in subforget: + if os.path.exists(m.rel(f)): + ui.warn(_('not removing %s: file is already untracked\n') + % m.rel(f)) + errs = 1 for f in forget: if ui.verbose or not m.exact(f): ui.status(_('removing %s\n') % m.rel(f)) - repo[None].forget(forget) + if ui.verbose: + for f in sorted(subforget.keys()): + ui.status(_('removing %s\n') % m.rel(f)) + + wctx.forget(forget) + + for f in sorted(subforget.keys()): + fsub, sub = subforget[f] + sub.forget([fsub]) + return errs @command( diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt --- a/mercurial/help/subrepos.txt +++ b/mercurial/help/subrepos.txt @@ -95,6 +95,9 @@ Interaction with Mercurial Commands elements. Git and Subversion subrepositories are currently silently ignored. +:forget: forget currently only handles exact file matches in subrepos. + Git and Subversion subrepositories are currently silently ignored. + :incoming: incoming does not recurse in subrepos unless -S/--subrepos is specified. Git and Subversion subrepositories are currently silently ignored. diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -360,6 +360,9 @@ class abstractsubrepo(object): ''' pass + def forget(self, files): + pass + class hgsubrepo(abstractsubrepo): def __init__(self, ctx, path, state): self._path = path @@ -553,6 +556,10 @@ class hgsubrepo(abstractsubrepo): ctx = self._repo[None] return ctx.walk(match) + def forget(self, files): + ctx = self._repo[None] + ctx.forget(files) + 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 @@ -1006,12 +1006,12 @@ Adding with a pattern with -S also adds committing subrepository s Test behavior of forget for explicit path in subrepo: -Forgetting an explicit path in a subrepo currently gives a file untracked warn +Forgetting an explicit path in a subrepo untracks the file $ echo c19 > s/f19 $ hg add s/f19 $ hg st -S A s/f19 $ hg forget s/f19 - not removing s/f19: file is already untracked - [1] + $ hg st -S + ? s/f19 $ rm s/f19