##// END OF EJS Templates
narrow: add progress-reporting when looking for local changes in `hg tracked`...
Martin von Zweigbergk -
r47789:1e761c1c default draft
parent child Browse files
Show More
@@ -1,679 +1,686 b''
1 1 # narrowcommands.py - command modifications for narrowhg extension
2 2 #
3 3 # Copyright 2017 Google, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 from __future__ import absolute_import
8 8
9 9 import itertools
10 10 import os
11 11
12 12 from mercurial.i18n import _
13 13 from mercurial.node import (
14 14 hex,
15 15 short,
16 16 )
17 17 from mercurial import (
18 18 bundle2,
19 19 cmdutil,
20 20 commands,
21 21 discovery,
22 22 encoding,
23 23 error,
24 24 exchange,
25 25 extensions,
26 26 hg,
27 27 narrowspec,
28 28 pathutil,
29 29 pycompat,
30 30 registrar,
31 31 repair,
32 32 repoview,
33 33 requirements,
34 34 sparse,
35 35 util,
36 36 wireprototypes,
37 37 )
38 38 from mercurial.utils import (
39 39 urlutil,
40 40 )
41 41
42 42 table = {}
43 43 command = registrar.command(table)
44 44
45 45
46 46 def setup():
47 47 """Wraps user-facing mercurial commands with narrow-aware versions."""
48 48
49 49 entry = extensions.wrapcommand(commands.table, b'clone', clonenarrowcmd)
50 50 entry[1].append(
51 51 (b'', b'narrow', None, _(b"create a narrow clone of select files"))
52 52 )
53 53 entry[1].append(
54 54 (
55 55 b'',
56 56 b'depth',
57 57 b'',
58 58 _(b"limit the history fetched by distance from heads"),
59 59 )
60 60 )
61 61 entry[1].append((b'', b'narrowspec', b'', _(b"read narrowspecs from file")))
62 62 # TODO(durin42): unify sparse/narrow --include/--exclude logic a bit
63 63 if b'sparse' not in extensions.enabled():
64 64 entry[1].append(
65 65 (b'', b'include', [], _(b"specifically fetch this file/directory"))
66 66 )
67 67 entry[1].append(
68 68 (
69 69 b'',
70 70 b'exclude',
71 71 [],
72 72 _(b"do not fetch this file/directory, even if included"),
73 73 )
74 74 )
75 75
76 76 entry = extensions.wrapcommand(commands.table, b'pull', pullnarrowcmd)
77 77 entry[1].append(
78 78 (
79 79 b'',
80 80 b'depth',
81 81 b'',
82 82 _(b"limit the history fetched by distance from heads"),
83 83 )
84 84 )
85 85
86 86 extensions.wrapcommand(commands.table, b'archive', archivenarrowcmd)
87 87
88 88
89 89 def clonenarrowcmd(orig, ui, repo, *args, **opts):
90 90 """Wraps clone command, so 'hg clone' first wraps localrepo.clone()."""
91 91 opts = pycompat.byteskwargs(opts)
92 92 wrappedextraprepare = util.nullcontextmanager()
93 93 narrowspecfile = opts[b'narrowspec']
94 94
95 95 if narrowspecfile:
96 96 filepath = os.path.join(encoding.getcwd(), narrowspecfile)
97 97 ui.status(_(b"reading narrowspec from '%s'\n") % filepath)
98 98 try:
99 99 fdata = util.readfile(filepath)
100 100 except IOError as inst:
101 101 raise error.Abort(
102 102 _(b"cannot read narrowspecs from '%s': %s")
103 103 % (filepath, encoding.strtolocal(inst.strerror))
104 104 )
105 105
106 106 includes, excludes, profiles = sparse.parseconfig(ui, fdata, b'narrow')
107 107 if profiles:
108 108 raise error.ConfigError(
109 109 _(
110 110 b"cannot specify other files using '%include' in"
111 111 b" narrowspec"
112 112 )
113 113 )
114 114
115 115 narrowspec.validatepatterns(includes)
116 116 narrowspec.validatepatterns(excludes)
117 117
118 118 # narrowspec is passed so we should assume that user wants narrow clone
119 119 opts[b'narrow'] = True
120 120 opts[b'include'].extend(includes)
121 121 opts[b'exclude'].extend(excludes)
122 122
123 123 if opts[b'narrow']:
124 124
125 125 def pullbundle2extraprepare_widen(orig, pullop, kwargs):
126 126 orig(pullop, kwargs)
127 127
128 128 if opts.get(b'depth'):
129 129 kwargs[b'depth'] = opts[b'depth']
130 130
131 131 wrappedextraprepare = extensions.wrappedfunction(
132 132 exchange, b'_pullbundle2extraprepare', pullbundle2extraprepare_widen
133 133 )
134 134
135 135 with wrappedextraprepare:
136 136 return orig(ui, repo, *args, **pycompat.strkwargs(opts))
137 137
138 138
139 139 def pullnarrowcmd(orig, ui, repo, *args, **opts):
140 140 """Wraps pull command to allow modifying narrow spec."""
141 141 wrappedextraprepare = util.nullcontextmanager()
142 142 if requirements.NARROW_REQUIREMENT in repo.requirements:
143 143
144 144 def pullbundle2extraprepare_widen(orig, pullop, kwargs):
145 145 orig(pullop, kwargs)
146 146 if opts.get('depth'):
147 147 kwargs[b'depth'] = opts['depth']
148 148
149 149 wrappedextraprepare = extensions.wrappedfunction(
150 150 exchange, b'_pullbundle2extraprepare', pullbundle2extraprepare_widen
151 151 )
152 152
153 153 with wrappedextraprepare:
154 154 return orig(ui, repo, *args, **opts)
155 155
156 156
157 157 def archivenarrowcmd(orig, ui, repo, *args, **opts):
158 158 """Wraps archive command to narrow the default includes."""
159 159 if requirements.NARROW_REQUIREMENT in repo.requirements:
160 160 repo_includes, repo_excludes = repo.narrowpats
161 161 includes = set(opts.get('include', []))
162 162 excludes = set(opts.get('exclude', []))
163 163 includes, excludes, unused_invalid = narrowspec.restrictpatterns(
164 164 includes, excludes, repo_includes, repo_excludes
165 165 )
166 166 if includes:
167 167 opts['include'] = includes
168 168 if excludes:
169 169 opts['exclude'] = excludes
170 170 return orig(ui, repo, *args, **opts)
171 171
172 172
173 173 def pullbundle2extraprepare(orig, pullop, kwargs):
174 174 repo = pullop.repo
175 175 if requirements.NARROW_REQUIREMENT not in repo.requirements:
176 176 return orig(pullop, kwargs)
177 177
178 178 if wireprototypes.NARROWCAP not in pullop.remote.capabilities():
179 179 raise error.Abort(_(b"server does not support narrow clones"))
180 180 orig(pullop, kwargs)
181 181 kwargs[b'narrow'] = True
182 182 include, exclude = repo.narrowpats
183 183 kwargs[b'oldincludepats'] = include
184 184 kwargs[b'oldexcludepats'] = exclude
185 185 if include:
186 186 kwargs[b'includepats'] = include
187 187 if exclude:
188 188 kwargs[b'excludepats'] = exclude
189 189 # calculate known nodes only in ellipses cases because in non-ellipses cases
190 190 # we have all the nodes
191 191 if wireprototypes.ELLIPSESCAP1 in pullop.remote.capabilities():
192 192 kwargs[b'known'] = [
193 193 hex(ctx.node())
194 194 for ctx in repo.set(b'::%ln', pullop.common)
195 195 if ctx.node() != repo.nullid
196 196 ]
197 197 if not kwargs[b'known']:
198 198 # Mercurial serializes an empty list as '' and deserializes it as
199 199 # [''], so delete it instead to avoid handling the empty string on
200 200 # the server.
201 201 del kwargs[b'known']
202 202
203 203
204 204 extensions.wrapfunction(
205 205 exchange, b'_pullbundle2extraprepare', pullbundle2extraprepare
206 206 )
207 207
208 208
209 209 def _narrow(
210 210 ui,
211 211 repo,
212 212 remote,
213 213 commoninc,
214 214 oldincludes,
215 215 oldexcludes,
216 216 newincludes,
217 217 newexcludes,
218 218 force,
219 219 backup,
220 220 ):
221 221 oldmatch = narrowspec.match(repo.root, oldincludes, oldexcludes)
222 222 newmatch = narrowspec.match(repo.root, newincludes, newexcludes)
223 223
224 224 # This is essentially doing "hg outgoing" to find all local-only
225 225 # commits. We will then check that the local-only commits don't
226 226 # have any changes to files that will be untracked.
227 227 unfi = repo.unfiltered()
228 228 outgoing = discovery.findcommonoutgoing(unfi, remote, commoninc=commoninc)
229 229 ui.status(_(b'looking for local changes to affected paths\n'))
230 progress = ui.makeprogress(
231 topic=_(b'changesets'),
232 unit=_(b'changesets'),
233 total=len(outgoing.missing) + len(outgoing.excluded),
234 )
230 235 localnodes = []
231 for n in itertools.chain(outgoing.missing, outgoing.excluded):
232 if any(oldmatch(f) and not newmatch(f) for f in unfi[n].files()):
233 localnodes.append(n)
236 with progress:
237 for n in itertools.chain(outgoing.missing, outgoing.excluded):
238 progress.increment()
239 if any(oldmatch(f) and not newmatch(f) for f in unfi[n].files()):
240 localnodes.append(n)
234 241 revstostrip = unfi.revs(b'descendants(%ln)', localnodes)
235 242 hiddenrevs = repoview.filterrevs(repo, b'visible')
236 243 visibletostrip = list(
237 244 repo.changelog.node(r) for r in (revstostrip - hiddenrevs)
238 245 )
239 246 if visibletostrip:
240 247 ui.status(
241 248 _(
242 249 b'The following changeset(s) or their ancestors have '
243 250 b'local changes not on the remote:\n'
244 251 )
245 252 )
246 253 maxnodes = 10
247 254 if ui.verbose or len(visibletostrip) <= maxnodes:
248 255 for n in visibletostrip:
249 256 ui.status(b'%s\n' % short(n))
250 257 else:
251 258 for n in visibletostrip[:maxnodes]:
252 259 ui.status(b'%s\n' % short(n))
253 260 ui.status(
254 261 _(b'...and %d more, use --verbose to list all\n')
255 262 % (len(visibletostrip) - maxnodes)
256 263 )
257 264 if not force:
258 265 raise error.StateError(
259 266 _(b'local changes found'),
260 267 hint=_(b'use --force-delete-local-changes to ignore'),
261 268 )
262 269
263 270 with ui.uninterruptible():
264 271 if revstostrip:
265 272 tostrip = [unfi.changelog.node(r) for r in revstostrip]
266 273 if repo[b'.'].node() in tostrip:
267 274 # stripping working copy, so move to a different commit first
268 275 urev = max(
269 276 repo.revs(
270 277 b'(::%n) - %ln + null',
271 278 repo[b'.'].node(),
272 279 visibletostrip,
273 280 )
274 281 )
275 282 hg.clean(repo, urev)
276 283 overrides = {(b'devel', b'strip-obsmarkers'): False}
277 284 with ui.configoverride(overrides, b'narrow'):
278 285 repair.strip(ui, unfi, tostrip, topic=b'narrow', backup=backup)
279 286
280 287 todelete = []
281 288 for t, f, f2, size in repo.store.datafiles():
282 289 if f.startswith(b'data/'):
283 290 file = f[5:-2]
284 291 if not newmatch(file):
285 292 todelete.append(f)
286 293 elif f.startswith(b'meta/'):
287 294 dir = f[5:-13]
288 295 dirs = sorted(pathutil.dirs({dir})) + [dir]
289 296 include = True
290 297 for d in dirs:
291 298 visit = newmatch.visitdir(d)
292 299 if not visit:
293 300 include = False
294 301 break
295 302 if visit == b'all':
296 303 break
297 304 if not include:
298 305 todelete.append(f)
299 306
300 307 repo.destroying()
301 308
302 309 with repo.transaction(b'narrowing'):
303 310 # Update narrowspec before removing revlogs, so repo won't be
304 311 # corrupt in case of crash
305 312 repo.setnarrowpats(newincludes, newexcludes)
306 313
307 314 for f in todelete:
308 315 ui.status(_(b'deleting %s\n') % f)
309 316 util.unlinkpath(repo.svfs.join(f))
310 317 repo.store.markremoved(f)
311 318
312 319 narrowspec.updateworkingcopy(repo, assumeclean=True)
313 320 narrowspec.copytoworkingcopy(repo)
314 321
315 322 repo.destroyed()
316 323
317 324
318 325 def _widen(
319 326 ui,
320 327 repo,
321 328 remote,
322 329 commoninc,
323 330 oldincludes,
324 331 oldexcludes,
325 332 newincludes,
326 333 newexcludes,
327 334 ):
328 335 # for now we assume that if a server has ellipses enabled, we will be
329 336 # exchanging ellipses nodes. In future we should add ellipses as a client
330 337 # side requirement (maybe) to distinguish a client is shallow or not and
331 338 # then send that information to server whether we want ellipses or not.
332 339 # Theoretically a non-ellipses repo should be able to use narrow
333 340 # functionality from an ellipses enabled server
334 341 remotecap = remote.capabilities()
335 342 ellipsesremote = any(
336 343 cap in remotecap for cap in wireprototypes.SUPPORTED_ELLIPSESCAP
337 344 )
338 345
339 346 # check whether we are talking to a server which supports old version of
340 347 # ellipses capabilities
341 348 isoldellipses = (
342 349 ellipsesremote
343 350 and wireprototypes.ELLIPSESCAP1 in remotecap
344 351 and wireprototypes.ELLIPSESCAP not in remotecap
345 352 )
346 353
347 354 def pullbundle2extraprepare_widen(orig, pullop, kwargs):
348 355 orig(pullop, kwargs)
349 356 # The old{in,ex}cludepats have already been set by orig()
350 357 kwargs[b'includepats'] = newincludes
351 358 kwargs[b'excludepats'] = newexcludes
352 359
353 360 wrappedextraprepare = extensions.wrappedfunction(
354 361 exchange, b'_pullbundle2extraprepare', pullbundle2extraprepare_widen
355 362 )
356 363
357 364 # define a function that narrowbundle2 can call after creating the
358 365 # backup bundle, but before applying the bundle from the server
359 366 def setnewnarrowpats():
360 367 repo.setnarrowpats(newincludes, newexcludes)
361 368
362 369 repo.setnewnarrowpats = setnewnarrowpats
363 370 # silence the devel-warning of applying an empty changegroup
364 371 overrides = {(b'devel', b'all-warnings'): False}
365 372
366 373 common = commoninc[0]
367 374 with ui.uninterruptible():
368 375 if ellipsesremote:
369 376 ds = repo.dirstate
370 377 p1, p2 = ds.p1(), ds.p2()
371 378 with ds.parentchange():
372 379 ds.setparents(repo.nullid, repo.nullid)
373 380 if isoldellipses:
374 381 with wrappedextraprepare:
375 382 exchange.pull(repo, remote, heads=common)
376 383 else:
377 384 known = []
378 385 if ellipsesremote:
379 386 known = [
380 387 ctx.node()
381 388 for ctx in repo.set(b'::%ln', common)
382 389 if ctx.node() != repo.nullid
383 390 ]
384 391 with remote.commandexecutor() as e:
385 392 bundle = e.callcommand(
386 393 b'narrow_widen',
387 394 {
388 395 b'oldincludes': oldincludes,
389 396 b'oldexcludes': oldexcludes,
390 397 b'newincludes': newincludes,
391 398 b'newexcludes': newexcludes,
392 399 b'cgversion': b'03',
393 400 b'commonheads': common,
394 401 b'known': known,
395 402 b'ellipses': ellipsesremote,
396 403 },
397 404 ).result()
398 405
399 406 trmanager = exchange.transactionmanager(
400 407 repo, b'widen', remote.url()
401 408 )
402 409 with trmanager, repo.ui.configoverride(overrides, b'widen'):
403 410 op = bundle2.bundleoperation(
404 411 repo, trmanager.transaction, source=b'widen'
405 412 )
406 413 # TODO: we should catch error.Abort here
407 414 bundle2.processbundle(repo, bundle, op=op)
408 415
409 416 if ellipsesremote:
410 417 with ds.parentchange():
411 418 ds.setparents(p1, p2)
412 419
413 420 with repo.transaction(b'widening'):
414 421 repo.setnewnarrowpats()
415 422 narrowspec.updateworkingcopy(repo)
416 423 narrowspec.copytoworkingcopy(repo)
417 424
418 425
419 426 # TODO(rdamazio): Make new matcher format and update description
420 427 @command(
421 428 b'tracked',
422 429 [
423 430 (b'', b'addinclude', [], _(b'new paths to include')),
424 431 (b'', b'removeinclude', [], _(b'old paths to no longer include')),
425 432 (
426 433 b'',
427 434 b'auto-remove-includes',
428 435 False,
429 436 _(b'automatically choose unused includes to remove'),
430 437 ),
431 438 (b'', b'addexclude', [], _(b'new paths to exclude')),
432 439 (b'', b'import-rules', b'', _(b'import narrowspecs from a file')),
433 440 (b'', b'removeexclude', [], _(b'old paths to no longer exclude')),
434 441 (
435 442 b'',
436 443 b'clear',
437 444 False,
438 445 _(b'whether to replace the existing narrowspec'),
439 446 ),
440 447 (
441 448 b'',
442 449 b'force-delete-local-changes',
443 450 False,
444 451 _(b'forces deletion of local changes when narrowing'),
445 452 ),
446 453 (
447 454 b'',
448 455 b'backup',
449 456 True,
450 457 _(b'back up local changes when narrowing'),
451 458 ),
452 459 (
453 460 b'',
454 461 b'update-working-copy',
455 462 False,
456 463 _(b'update working copy when the store has changed'),
457 464 ),
458 465 ]
459 466 + commands.remoteopts,
460 467 _(b'[OPTIONS]... [REMOTE]'),
461 468 inferrepo=True,
462 469 helpcategory=command.CATEGORY_MAINTENANCE,
463 470 )
464 471 def trackedcmd(ui, repo, remotepath=None, *pats, **opts):
465 472 """show or change the current narrowspec
466 473
467 474 With no argument, shows the current narrowspec entries, one per line. Each
468 475 line will be prefixed with 'I' or 'X' for included or excluded patterns,
469 476 respectively.
470 477
471 478 The narrowspec is comprised of expressions to match remote files and/or
472 479 directories that should be pulled into your client.
473 480 The narrowspec has *include* and *exclude* expressions, with excludes always
474 481 trumping includes: that is, if a file matches an exclude expression, it will
475 482 be excluded even if it also matches an include expression.
476 483 Excluding files that were never included has no effect.
477 484
478 485 Each included or excluded entry is in the format described by
479 486 'hg help patterns'.
480 487
481 488 The options allow you to add or remove included and excluded expressions.
482 489
483 490 If --clear is specified, then all previous includes and excludes are DROPPED
484 491 and replaced by the new ones specified to --addinclude and --addexclude.
485 492 If --clear is specified without any further options, the narrowspec will be
486 493 empty and will not match any files.
487 494
488 495 If --auto-remove-includes is specified, then those includes that don't match
489 496 any files modified by currently visible local commits (those not shared by
490 497 the remote) will be added to the set of explicitly specified includes to
491 498 remove.
492 499
493 500 --import-rules accepts a path to a file containing rules, allowing you to
494 501 add --addinclude, --addexclude rules in bulk. Like the other include and
495 502 exclude switches, the changes are applied immediately.
496 503 """
497 504 opts = pycompat.byteskwargs(opts)
498 505 if requirements.NARROW_REQUIREMENT not in repo.requirements:
499 506 raise error.InputError(
500 507 _(
501 508 b'the tracked command is only supported on '
502 509 b'repositories cloned with --narrow'
503 510 )
504 511 )
505 512
506 513 # Before supporting, decide whether it "hg tracked --clear" should mean
507 514 # tracking no paths or all paths.
508 515 if opts[b'clear']:
509 516 raise error.InputError(_(b'the --clear option is not yet supported'))
510 517
511 518 # import rules from a file
512 519 newrules = opts.get(b'import_rules')
513 520 if newrules:
514 521 try:
515 522 filepath = os.path.join(encoding.getcwd(), newrules)
516 523 fdata = util.readfile(filepath)
517 524 except IOError as inst:
518 525 raise error.StorageError(
519 526 _(b"cannot read narrowspecs from '%s': %s")
520 527 % (filepath, encoding.strtolocal(inst.strerror))
521 528 )
522 529 includepats, excludepats, profiles = sparse.parseconfig(
523 530 ui, fdata, b'narrow'
524 531 )
525 532 if profiles:
526 533 raise error.InputError(
527 534 _(
528 535 b"including other spec files using '%include' "
529 536 b"is not supported in narrowspec"
530 537 )
531 538 )
532 539 opts[b'addinclude'].extend(includepats)
533 540 opts[b'addexclude'].extend(excludepats)
534 541
535 542 addedincludes = narrowspec.parsepatterns(opts[b'addinclude'])
536 543 removedincludes = narrowspec.parsepatterns(opts[b'removeinclude'])
537 544 addedexcludes = narrowspec.parsepatterns(opts[b'addexclude'])
538 545 removedexcludes = narrowspec.parsepatterns(opts[b'removeexclude'])
539 546 autoremoveincludes = opts[b'auto_remove_includes']
540 547
541 548 update_working_copy = opts[b'update_working_copy']
542 549 only_show = not (
543 550 addedincludes
544 551 or removedincludes
545 552 or addedexcludes
546 553 or removedexcludes
547 554 or newrules
548 555 or autoremoveincludes
549 556 or update_working_copy
550 557 )
551 558
552 559 oldincludes, oldexcludes = repo.narrowpats
553 560
554 561 # filter the user passed additions and deletions into actual additions and
555 562 # deletions of excludes and includes
556 563 addedincludes -= oldincludes
557 564 removedincludes &= oldincludes
558 565 addedexcludes -= oldexcludes
559 566 removedexcludes &= oldexcludes
560 567
561 568 widening = addedincludes or removedexcludes
562 569 narrowing = removedincludes or addedexcludes
563 570
564 571 # Only print the current narrowspec.
565 572 if only_show:
566 573 ui.pager(b'tracked')
567 574 fm = ui.formatter(b'narrow', opts)
568 575 for i in sorted(oldincludes):
569 576 fm.startitem()
570 577 fm.write(b'status', b'%s ', b'I', label=b'narrow.included')
571 578 fm.write(b'pat', b'%s\n', i, label=b'narrow.included')
572 579 for i in sorted(oldexcludes):
573 580 fm.startitem()
574 581 fm.write(b'status', b'%s ', b'X', label=b'narrow.excluded')
575 582 fm.write(b'pat', b'%s\n', i, label=b'narrow.excluded')
576 583 fm.end()
577 584 return 0
578 585
579 586 if update_working_copy:
580 587 with repo.wlock(), repo.lock(), repo.transaction(b'narrow-wc'):
581 588 narrowspec.updateworkingcopy(repo)
582 589 narrowspec.copytoworkingcopy(repo)
583 590 return 0
584 591
585 592 if not (widening or narrowing or autoremoveincludes):
586 593 ui.status(_(b"nothing to widen or narrow\n"))
587 594 return 0
588 595
589 596 with repo.wlock(), repo.lock():
590 597 cmdutil.bailifchanged(repo)
591 598
592 599 # Find the revisions we have in common with the remote. These will
593 600 # be used for finding local-only changes for narrowing. They will
594 601 # also define the set of revisions to update for widening.
595 602 r = urlutil.get_unique_pull_path(b'tracked', repo, ui, remotepath)
596 603 url, branches = r
597 604 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(url))
598 605 remote = hg.peer(repo, opts, url)
599 606
600 607 try:
601 608 # check narrow support before doing anything if widening needs to be
602 609 # performed. In future we should also abort if client is ellipses and
603 610 # server does not support ellipses
604 611 if (
605 612 widening
606 613 and wireprototypes.NARROWCAP not in remote.capabilities()
607 614 ):
608 615 raise error.Abort(_(b"server does not support narrow clones"))
609 616
610 617 commoninc = discovery.findcommonincoming(repo, remote)
611 618
612 619 if autoremoveincludes:
613 620 outgoing = discovery.findcommonoutgoing(
614 621 repo, remote, commoninc=commoninc
615 622 )
616 623 ui.status(_(b'looking for unused includes to remove\n'))
617 624 localfiles = set()
618 625 for n in itertools.chain(outgoing.missing, outgoing.excluded):
619 626 localfiles.update(repo[n].files())
620 627 suggestedremovals = []
621 628 for include in sorted(oldincludes):
622 629 match = narrowspec.match(repo.root, [include], oldexcludes)
623 630 if not any(match(f) for f in localfiles):
624 631 suggestedremovals.append(include)
625 632 if suggestedremovals:
626 633 for s in suggestedremovals:
627 634 ui.status(b'%s\n' % s)
628 635 if (
629 636 ui.promptchoice(
630 637 _(
631 638 b'remove these unused includes (yn)?'
632 639 b'$$ &Yes $$ &No'
633 640 )
634 641 )
635 642 == 0
636 643 ):
637 644 removedincludes.update(suggestedremovals)
638 645 narrowing = True
639 646 else:
640 647 ui.status(_(b'found no unused includes\n'))
641 648
642 649 if narrowing:
643 650 newincludes = oldincludes - removedincludes
644 651 newexcludes = oldexcludes | addedexcludes
645 652 _narrow(
646 653 ui,
647 654 repo,
648 655 remote,
649 656 commoninc,
650 657 oldincludes,
651 658 oldexcludes,
652 659 newincludes,
653 660 newexcludes,
654 661 opts[b'force_delete_local_changes'],
655 662 opts[b'backup'],
656 663 )
657 664 # _narrow() updated the narrowspec and _widen() below needs to
658 665 # use the updated values as its base (otherwise removed includes
659 666 # and addedexcludes will be lost in the resulting narrowspec)
660 667 oldincludes = newincludes
661 668 oldexcludes = newexcludes
662 669
663 670 if widening:
664 671 newincludes = oldincludes | addedincludes
665 672 newexcludes = oldexcludes - removedexcludes
666 673 _widen(
667 674 ui,
668 675 repo,
669 676 remote,
670 677 commoninc,
671 678 oldincludes,
672 679 oldexcludes,
673 680 newincludes,
674 681 newexcludes,
675 682 )
676 683 finally:
677 684 remote.close()
678 685
679 686 return 0
General Comments 0
You need to be logged in to leave comments. Login now