# HG changeset patch # User Martin von Zweigbergk # Date 2019-09-13 04:55:45 # Node ID 40f78072fda98793ef7c3bcee8c8f6dce9a7b9dc # Parent c2676b5a9f597155506cb750a3ba307db7316b32 narrow: add option for automatically removing unused includes It's been a somewhat common request among our users to have Mercurial automatically pick includes to remove. This patch adds an option for that: `hg tracked --auto-remove-includes`. I'm not sure if this is the right name and semantics for it. Perhaps the feature should also add excludes of large subdirectories even if other files in the include are needed? Narrow clones are experimental, so we can change the name and/or semantics later if necessary. Differential Revision: https://phab.mercurial-scm.org/D6848 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 @@ def _widen(ui, repo, remote, commoninc, @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,11 @@ def trackedcmd(ui, repo, remotepath=None 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 local commits (those not shared by + the remote) 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 +405,12 @@ def trackedcmd(ui, repo, remotepath=None 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 +445,7 @@ def trackedcmd(ui, repo, remotepath=None 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 +468,28 @@ def trackedcmd(ui, repo, remotepath=None 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 @@ Testing the --import-rules flag of `hg t --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 @@ Now test it *with* verbose. 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