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