##// END OF EJS Templates
narrow: migrate `opts` to native kwargs
Matt Harbison -
r51774:4803cea1 default
parent child Browse files
Show More
@@ -1,698 +1,697 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 opts = pycompat.byteskwargs(opts)
91 90 wrappedextraprepare = util.nullcontextmanager()
92 narrowspecfile = opts[b'narrowspec']
91 narrowspecfile = opts['narrowspec']
93 92
94 93 if narrowspecfile:
95 94 filepath = os.path.join(encoding.getcwd(), narrowspecfile)
96 95 ui.status(_(b"reading narrowspec from '%s'\n") % filepath)
97 96 try:
98 97 fdata = util.readfile(filepath)
99 98 except IOError as inst:
100 99 raise error.Abort(
101 100 _(b"cannot read narrowspecs from '%s': %s")
102 101 % (filepath, encoding.strtolocal(inst.strerror))
103 102 )
104 103
105 104 includes, excludes, profiles = sparse.parseconfig(ui, fdata, b'narrow')
106 105 if profiles:
107 106 raise error.ConfigError(
108 107 _(
109 108 b"cannot specify other files using '%include' in"
110 109 b" narrowspec"
111 110 )
112 111 )
113 112
114 113 narrowspec.validatepatterns(includes)
115 114 narrowspec.validatepatterns(excludes)
116 115
117 116 # narrowspec is passed so we should assume that user wants narrow clone
118 opts[b'narrow'] = True
119 opts[b'include'].extend(includes)
120 opts[b'exclude'].extend(excludes)
117 opts['narrow'] = True
118 opts['include'].extend(includes)
119 opts['exclude'].extend(excludes)
121 120
122 if opts[b'narrow']:
121 if opts['narrow']:
123 122
124 123 def pullbundle2extraprepare_widen(orig, pullop, kwargs):
125 124 orig(pullop, kwargs)
126 125
127 if opts.get(b'depth'):
128 kwargs[b'depth'] = opts[b'depth']
126 if opts.get('depth'):
127 # TODO: fix exchange._pullbundle2extraprepare()
128 kwargs[b'depth'] = opts['depth']
129 129
130 130 wrappedextraprepare = extensions.wrappedfunction(
131 131 exchange, '_pullbundle2extraprepare', pullbundle2extraprepare_widen
132 132 )
133 133
134 134 with wrappedextraprepare:
135 return orig(ui, repo, *args, **pycompat.strkwargs(opts))
135 return orig(ui, repo, *args, **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, '_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, '_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 entry in repo.store.data_entries():
292 292 if not entry.is_revlog:
293 293 continue
294 294 if entry.is_filelog:
295 295 if not newmatch(entry.target_id):
296 296 for file_ in entry.files():
297 297 todelete.append(file_.unencoded_path)
298 298 elif entry.is_manifestlog:
299 299 dir = entry.target_id
300 300 dirs = sorted(pathutil.dirs({dir})) + [dir]
301 301 include = True
302 302 for d in dirs:
303 303 visit = newmatch.visitdir(d)
304 304 if not visit:
305 305 include = False
306 306 break
307 307 if visit == b'all':
308 308 break
309 309 if not include:
310 310 for file_ in entry.files():
311 311 todelete.append(file_.unencoded_path)
312 312
313 313 repo.destroying()
314 314
315 315 with repo.transaction(b'narrowing'):
316 316 # Update narrowspec before removing revlogs, so repo won't be
317 317 # corrupt in case of crash
318 318 repo.setnarrowpats(newincludes, newexcludes)
319 319
320 320 for f in todelete:
321 321 ui.status(_(b'deleting %s\n') % f)
322 322 util.unlinkpath(repo.svfs.join(f))
323 323 repo.store.markremoved(f)
324 324
325 325 ui.status(_(b'deleting unwanted files from working copy\n'))
326 326 with repo.dirstate.changing_parents(repo):
327 327 narrowspec.updateworkingcopy(repo, assumeclean=True)
328 328 narrowspec.copytoworkingcopy(repo)
329 329
330 330 repo.destroyed()
331 331
332 332
333 333 def _widen(
334 334 ui,
335 335 repo,
336 336 remote,
337 337 commoninc,
338 338 oldincludes,
339 339 oldexcludes,
340 340 newincludes,
341 341 newexcludes,
342 342 ):
343 343 # for now we assume that if a server has ellipses enabled, we will be
344 344 # exchanging ellipses nodes. In future we should add ellipses as a client
345 345 # side requirement (maybe) to distinguish a client is shallow or not and
346 346 # then send that information to server whether we want ellipses or not.
347 347 # Theoretically a non-ellipses repo should be able to use narrow
348 348 # functionality from an ellipses enabled server
349 349 remotecap = remote.capabilities()
350 350 ellipsesremote = any(
351 351 cap in remotecap for cap in wireprototypes.SUPPORTED_ELLIPSESCAP
352 352 )
353 353
354 354 # check whether we are talking to a server which supports old version of
355 355 # ellipses capabilities
356 356 isoldellipses = (
357 357 ellipsesremote
358 358 and wireprototypes.ELLIPSESCAP1 in remotecap
359 359 and wireprototypes.ELLIPSESCAP not in remotecap
360 360 )
361 361
362 362 def pullbundle2extraprepare_widen(orig, pullop, kwargs):
363 363 orig(pullop, kwargs)
364 364 # The old{in,ex}cludepats have already been set by orig()
365 365 kwargs[b'includepats'] = newincludes
366 366 kwargs[b'excludepats'] = newexcludes
367 367
368 368 wrappedextraprepare = extensions.wrappedfunction(
369 369 exchange, '_pullbundle2extraprepare', pullbundle2extraprepare_widen
370 370 )
371 371
372 372 # define a function that narrowbundle2 can call after creating the
373 373 # backup bundle, but before applying the bundle from the server
374 374 def setnewnarrowpats():
375 375 repo.setnarrowpats(newincludes, newexcludes)
376 376
377 377 repo.setnewnarrowpats = setnewnarrowpats
378 378 # silence the devel-warning of applying an empty changegroup
379 379 overrides = {(b'devel', b'all-warnings'): False}
380 380
381 381 common = commoninc[0]
382 382 with ui.uninterruptible():
383 383 if ellipsesremote:
384 384 ds = repo.dirstate
385 385 p1, p2 = ds.p1(), ds.p2()
386 386 with ds.changing_parents(repo):
387 387 ds.setparents(repo.nullid, repo.nullid)
388 388 if isoldellipses:
389 389 with wrappedextraprepare:
390 390 exchange.pull(repo, remote, heads=common)
391 391 else:
392 392 known = []
393 393 if ellipsesremote:
394 394 known = [
395 395 ctx.node()
396 396 for ctx in repo.set(b'::%ln', common)
397 397 if ctx.node() != repo.nullid
398 398 ]
399 399 with remote.commandexecutor() as e:
400 400 bundle = e.callcommand(
401 401 b'narrow_widen',
402 402 {
403 403 b'oldincludes': oldincludes,
404 404 b'oldexcludes': oldexcludes,
405 405 b'newincludes': newincludes,
406 406 b'newexcludes': newexcludes,
407 407 b'cgversion': b'03',
408 408 b'commonheads': common,
409 409 b'known': known,
410 410 b'ellipses': ellipsesremote,
411 411 },
412 412 ).result()
413 413
414 414 trmanager = exchange.transactionmanager(
415 415 repo, b'widen', remote.url()
416 416 )
417 417 with trmanager, repo.ui.configoverride(overrides, b'widen'):
418 418 op = bundle2.bundleoperation(
419 419 repo, trmanager.transaction, source=b'widen'
420 420 )
421 421 # TODO: we should catch error.Abort here
422 422 bundle2.processbundle(repo, bundle, op=op, remote=remote)
423 423
424 424 if ellipsesremote:
425 425 with ds.changing_parents(repo):
426 426 ds.setparents(p1, p2)
427 427
428 428 with repo.transaction(b'widening'), repo.dirstate.changing_parents(
429 429 repo
430 430 ):
431 431 repo.setnewnarrowpats()
432 432 narrowspec.updateworkingcopy(repo)
433 433 narrowspec.copytoworkingcopy(repo)
434 434
435 435
436 436 # TODO(rdamazio): Make new matcher format and update description
437 437 @command(
438 438 b'tracked',
439 439 [
440 440 (b'', b'addinclude', [], _(b'new paths to include')),
441 441 (b'', b'removeinclude', [], _(b'old paths to no longer include')),
442 442 (
443 443 b'',
444 444 b'auto-remove-includes',
445 445 False,
446 446 _(b'automatically choose unused includes to remove'),
447 447 ),
448 448 (b'', b'addexclude', [], _(b'new paths to exclude')),
449 449 (b'', b'import-rules', b'', _(b'import narrowspecs from a file')),
450 450 (b'', b'removeexclude', [], _(b'old paths to no longer exclude')),
451 451 (
452 452 b'',
453 453 b'clear',
454 454 False,
455 455 _(b'whether to replace the existing narrowspec'),
456 456 ),
457 457 (
458 458 b'',
459 459 b'force-delete-local-changes',
460 460 False,
461 461 _(b'forces deletion of local changes when narrowing'),
462 462 ),
463 463 (
464 464 b'',
465 465 b'backup',
466 466 True,
467 467 _(b'back up local changes when narrowing'),
468 468 ),
469 469 (
470 470 b'',
471 471 b'update-working-copy',
472 472 False,
473 473 _(b'update working copy when the store has changed'),
474 474 ),
475 475 ]
476 476 + commands.remoteopts,
477 477 _(b'[OPTIONS]... [REMOTE]'),
478 478 inferrepo=True,
479 479 helpcategory=command.CATEGORY_MAINTENANCE,
480 480 )
481 481 def trackedcmd(ui, repo, remotepath=None, *pats, **opts):
482 482 """show or change the current narrowspec
483 483
484 484 With no argument, shows the current narrowspec entries, one per line. Each
485 485 line will be prefixed with 'I' or 'X' for included or excluded patterns,
486 486 respectively.
487 487
488 488 The narrowspec is comprised of expressions to match remote files and/or
489 489 directories that should be pulled into your client.
490 490 The narrowspec has *include* and *exclude* expressions, with excludes always
491 491 trumping includes: that is, if a file matches an exclude expression, it will
492 492 be excluded even if it also matches an include expression.
493 493 Excluding files that were never included has no effect.
494 494
495 495 Each included or excluded entry is in the format described by
496 496 'hg help patterns'.
497 497
498 498 The options allow you to add or remove included and excluded expressions.
499 499
500 500 If --clear is specified, then all previous includes and excludes are DROPPED
501 501 and replaced by the new ones specified to --addinclude and --addexclude.
502 502 If --clear is specified without any further options, the narrowspec will be
503 503 empty and will not match any files.
504 504
505 505 If --auto-remove-includes is specified, then those includes that don't match
506 506 any files modified by currently visible local commits (those not shared by
507 507 the remote) will be added to the set of explicitly specified includes to
508 508 remove.
509 509
510 510 --import-rules accepts a path to a file containing rules, allowing you to
511 511 add --addinclude, --addexclude rules in bulk. Like the other include and
512 512 exclude switches, the changes are applied immediately.
513 513 """
514 opts = pycompat.byteskwargs(opts)
515 514 if requirements.NARROW_REQUIREMENT not in repo.requirements:
516 515 raise error.InputError(
517 516 _(
518 517 b'the tracked command is only supported on '
519 518 b'repositories cloned with --narrow'
520 519 )
521 520 )
522 521
523 522 # Before supporting, decide whether it "hg tracked --clear" should mean
524 523 # tracking no paths or all paths.
525 if opts[b'clear']:
524 if opts['clear']:
526 525 raise error.InputError(_(b'the --clear option is not yet supported'))
527 526
528 527 # import rules from a file
529 newrules = opts.get(b'import_rules')
528 newrules = opts.get('import_rules')
530 529 if newrules:
531 530 try:
532 531 filepath = os.path.join(encoding.getcwd(), newrules)
533 532 fdata = util.readfile(filepath)
534 533 except IOError as inst:
535 534 raise error.StorageError(
536 535 _(b"cannot read narrowspecs from '%s': %s")
537 536 % (filepath, encoding.strtolocal(inst.strerror))
538 537 )
539 538 includepats, excludepats, profiles = sparse.parseconfig(
540 539 ui, fdata, b'narrow'
541 540 )
542 541 if profiles:
543 542 raise error.InputError(
544 543 _(
545 544 b"including other spec files using '%include' "
546 545 b"is not supported in narrowspec"
547 546 )
548 547 )
549 opts[b'addinclude'].extend(includepats)
550 opts[b'addexclude'].extend(excludepats)
548 opts['addinclude'].extend(includepats)
549 opts['addexclude'].extend(excludepats)
551 550
552 addedincludes = narrowspec.parsepatterns(opts[b'addinclude'])
553 removedincludes = narrowspec.parsepatterns(opts[b'removeinclude'])
554 addedexcludes = narrowspec.parsepatterns(opts[b'addexclude'])
555 removedexcludes = narrowspec.parsepatterns(opts[b'removeexclude'])
556 autoremoveincludes = opts[b'auto_remove_includes']
551 addedincludes = narrowspec.parsepatterns(opts['addinclude'])
552 removedincludes = narrowspec.parsepatterns(opts['removeinclude'])
553 addedexcludes = narrowspec.parsepatterns(opts['addexclude'])
554 removedexcludes = narrowspec.parsepatterns(opts['removeexclude'])
555 autoremoveincludes = opts['auto_remove_includes']
557 556
558 update_working_copy = opts[b'update_working_copy']
557 update_working_copy = opts['update_working_copy']
559 558 only_show = not (
560 559 addedincludes
561 560 or removedincludes
562 561 or addedexcludes
563 562 or removedexcludes
564 563 or newrules
565 564 or autoremoveincludes
566 565 or update_working_copy
567 566 )
568 567
569 568 # Only print the current narrowspec.
570 569 if only_show:
571 570 oldincludes, oldexcludes = repo.narrowpats
572 571 ui.pager(b'tracked')
573 fm = ui.formatter(b'narrow', opts)
572 fm = ui.formatter(b'narrow', pycompat.byteskwargs(opts))
574 573 for i in sorted(oldincludes):
575 574 fm.startitem()
576 575 fm.write(b'status', b'%s ', b'I', label=b'narrow.included')
577 576 fm.write(b'pat', b'%s\n', i, label=b'narrow.included')
578 577 for i in sorted(oldexcludes):
579 578 fm.startitem()
580 579 fm.write(b'status', b'%s ', b'X', label=b'narrow.excluded')
581 580 fm.write(b'pat', b'%s\n', i, label=b'narrow.excluded')
582 581 fm.end()
583 582 return 0
584 583
585 584 with repo.wlock(), repo.lock():
586 585 oldincludes, oldexcludes = repo.narrowpats
587 586
588 587 # filter the user passed additions and deletions into actual additions and
589 588 # deletions of excludes and includes
590 589 addedincludes -= oldincludes
591 590 removedincludes &= oldincludes
592 591 addedexcludes -= oldexcludes
593 592 removedexcludes &= oldexcludes
594 593
595 594 widening = addedincludes or removedexcludes
596 595 narrowing = removedincludes or addedexcludes
597 596
598 597 if update_working_copy:
599 598 with repo.transaction(b'narrow-wc'), repo.dirstate.changing_parents(
600 599 repo
601 600 ):
602 601 narrowspec.updateworkingcopy(repo)
603 602 narrowspec.copytoworkingcopy(repo)
604 603 return 0
605 604
606 605 if not (widening or narrowing or autoremoveincludes):
607 606 ui.status(_(b"nothing to widen or narrow\n"))
608 607 return 0
609 608
610 609 cmdutil.bailifchanged(repo)
611 610
612 611 # Find the revisions we have in common with the remote. These will
613 612 # be used for finding local-only changes for narrowing. They will
614 613 # also define the set of revisions to update for widening.
615 614 path = urlutil.get_unique_pull_path_obj(b'tracked', ui, remotepath)
616 615 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
617 remote = hg.peer(repo, opts, path)
616 remote = hg.peer(repo, pycompat.byteskwargs(opts), path)
618 617
619 618 try:
620 619 # check narrow support before doing anything if widening needs to be
621 620 # performed. In future we should also abort if client is ellipses and
622 621 # server does not support ellipses
623 622 if (
624 623 widening
625 624 and wireprototypes.NARROWCAP not in remote.capabilities()
626 625 ):
627 626 raise error.Abort(_(b"server does not support narrow clones"))
628 627
629 628 commoninc = discovery.findcommonincoming(repo, remote)
630 629
631 630 if autoremoveincludes:
632 631 outgoing = discovery.findcommonoutgoing(
633 632 repo, remote, commoninc=commoninc
634 633 )
635 634 ui.status(_(b'looking for unused includes to remove\n'))
636 635 localfiles = set()
637 636 for n in itertools.chain(outgoing.missing, outgoing.excluded):
638 637 localfiles.update(repo[n].files())
639 638 suggestedremovals = []
640 639 for include in sorted(oldincludes):
641 640 match = narrowspec.match(repo.root, [include], oldexcludes)
642 641 if not any(match(f) for f in localfiles):
643 642 suggestedremovals.append(include)
644 643 if suggestedremovals:
645 644 for s in suggestedremovals:
646 645 ui.status(b'%s\n' % s)
647 646 if (
648 647 ui.promptchoice(
649 648 _(
650 649 b'remove these unused includes (Yn)?'
651 650 b'$$ &Yes $$ &No'
652 651 )
653 652 )
654 653 == 0
655 654 ):
656 655 removedincludes.update(suggestedremovals)
657 656 narrowing = True
658 657 else:
659 658 ui.status(_(b'found no unused includes\n'))
660 659
661 660 if narrowing:
662 661 newincludes = oldincludes - removedincludes
663 662 newexcludes = oldexcludes | addedexcludes
664 663 _narrow(
665 664 ui,
666 665 repo,
667 666 remote,
668 667 commoninc,
669 668 oldincludes,
670 669 oldexcludes,
671 670 newincludes,
672 671 newexcludes,
673 opts[b'force_delete_local_changes'],
674 opts[b'backup'],
672 opts['force_delete_local_changes'],
673 opts['backup'],
675 674 )
676 675 # _narrow() updated the narrowspec and _widen() below needs to
677 676 # use the updated values as its base (otherwise removed includes
678 677 # and addedexcludes will be lost in the resulting narrowspec)
679 678 oldincludes = newincludes
680 679 oldexcludes = newexcludes
681 680
682 681 if widening:
683 682 newincludes = oldincludes | addedincludes
684 683 newexcludes = oldexcludes - removedexcludes
685 684 _widen(
686 685 ui,
687 686 repo,
688 687 remote,
689 688 commoninc,
690 689 oldincludes,
691 690 oldexcludes,
692 691 newincludes,
693 692 newexcludes,
694 693 )
695 694 finally:
696 695 remote.close()
697 696
698 697 return 0
General Comments 0
You need to be logged in to leave comments. Login now