--- a/hgext/narrow/narrowcommands.py Thu Sep 12 21:22:59 2019 -0700
+++ b/hgext/narrow/narrowcommands.py Thu Sep 12 21:55:45 2019 -0700
@@ -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,11 @@
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 @@
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 @@
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 @@
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