diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py --- a/hgext/narrow/narrowcommands.py +++ b/hgext/narrow/narrowcommands.py @@ -328,6 +328,8 @@ @command('tracked', [('', 'addinclude', [], _('new paths to include')), ('', 'removeinclude', [], _('old paths to no longer include')), + ('', 'auto-remove-includes', False, + _('automatically choose unused includes to remove')), ('', 'addexclude', [], _('new paths to exclude')), ('', 'import-rules', '', _('import narrowspecs from a file')), ('', 'removeexclude', [], _('old paths to no longer exclude')), @@ -363,6 +365,10 @@ If --clear is specified without any further options, the narrowspec will be empty and will not match any files. + If --auto-remove-includes is specified, then those includes that don't match + any files modified by currently visible commits will be added to the set of + explicitly specified includes to remove. + --import-rules accepts a path to a file containing rules, allowing you to add --addinclude, --addexclude rules in bulk. Like the other include and exclude switches, the changes are applied immediately. @@ -398,10 +404,12 @@ removedincludes = narrowspec.parsepatterns(opts['removeinclude']) addedexcludes = narrowspec.parsepatterns(opts['addexclude']) removedexcludes = narrowspec.parsepatterns(opts['removeexclude']) + autoremoveincludes = opts['auto_remove_includes'] update_working_copy = opts['update_working_copy'] only_show = not (addedincludes or removedincludes or addedexcludes or - removedexcludes or newrules or update_working_copy) + removedexcludes or newrules or autoremoveincludes or + update_working_copy) oldincludes, oldexcludes = repo.narrowpats @@ -436,7 +444,7 @@ narrowspec.copytoworkingcopy(repo) return 0 - if not widening and not narrowing: + if not (widening or narrowing or autoremoveincludes): ui.status(_("nothing to widen or narrow\n")) return 0 @@ -459,6 +467,28 @@ commoninc = discovery.findcommonincoming(repo, remote) + if autoremoveincludes: + outgoing = discovery.findcommonoutgoing(repo, remote, + commoninc=commoninc) + ui.status(_('looking for unused includes to remove\n')) + localfiles = set() + for n in itertools.chain(outgoing.missing, outgoing.excluded): + localfiles.update(repo[n].files()) + suggestedremovals = [] + for include in sorted(oldincludes): + match = narrowspec.match(repo.root, [include], oldexcludes) + if not any(match(f) for f in localfiles): + suggestedremovals.append(include) + if suggestedremovals: + for s in suggestedremovals: + ui.status('%s\n' % s) + if (ui.promptchoice(_('remove these unused includes (yn)?' + '$$ &Yes $$ &No')) == 0): + removedincludes.update(suggestedremovals) + narrowing = True + else: + ui.status(_('found no unused includes\n')) + if narrowing: newincludes = oldincludes - removedincludes newexcludes = oldexcludes | addedexcludes diff --git a/tests/test-narrow-trackedcmd.t b/tests/test-narrow-trackedcmd.t --- a/tests/test-narrow-trackedcmd.t +++ b/tests/test-narrow-trackedcmd.t @@ -101,6 +101,8 @@ --addinclude VALUE [+] new paths to include --removeinclude VALUE [+] old paths to no longer include + --auto-remove-includes automatically choose unused includes to + remove --addexclude VALUE [+] new paths to exclude --import-rules VALUE import narrowspecs from a file --removeexclude VALUE [+] old paths to no longer exclude diff --git a/tests/test-narrow.t b/tests/test-narrow.t --- a/tests/test-narrow.t +++ b/tests/test-narrow.t @@ -447,3 +447,48 @@ abort: local changes found (use --force-delete-local-changes to ignore) [255] + $ cd .. + +Test --auto-remove-includes + $ hg clone --narrow ssh://user@dummy/master narrow-auto-remove -q \ + > --include d0 --include d1 --include d2 + $ cd narrow-auto-remove + $ echo a >> d0/f + $ hg ci -m 'local change to d0' + $ hg co '.^' + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ echo a >> d1/f + $ hg ci -m 'local change to d1' + created new head + $ hg debugobsolete $(hg log -T '{node}' -r 'desc("local change to d0")') + 1 new obsolescence markers + obsoleted 1 changesets + $ echo n | hg tracked --auto-remove-includes --config ui.interactive=yes + comparing with ssh://user@dummy/master + searching for changes + looking for unused includes to remove + path:d0 + path:d2 + remove these unused includes (yn)? n + $ hg tracked --auto-remove-includes + comparing with ssh://user@dummy/master + searching for changes + looking for unused includes to remove + path:d0 + path:d2 + remove these unused includes (yn)? y + looking for local changes to affected paths + saved backup bundle to $TESTTMP/narrow-auto-remove/.hg/strip-backup/*-narrow.hg (glob) + deleting data/d0/f.i + deleting data/d2/f.i + deleting meta/d0/00manifest.i (tree !) + deleting meta/d2/00manifest.i (tree !) + $ hg tracked + I path:d1 + $ hg files + d1/f + $ hg tracked --auto-remove-includes + comparing with ssh://user@dummy/master + searching for changes + looking for unused includes to remove + found no unused includes