519 origsparsematch = matcher(repo) |
519 origsparsematch = matcher(repo) |
520 refreshwdir(repo, origstatus, origsparsematch, force=True) |
520 refreshwdir(repo, origstatus, origsparsematch, force=True) |
521 |
521 |
522 prunetemporaryincludes(repo) |
522 prunetemporaryincludes(repo) |
523 |
523 |
|
524 def _updateconfigandrefreshwdir(repo, includes, excludes, profiles, |
|
525 force=False): |
|
526 """Update the sparse config and working directory state.""" |
|
527 raw = repo.vfs.tryread('sparse') |
|
528 oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw) |
|
529 |
|
530 oldstatus = repo.status() |
|
531 oldmatch = matcher(repo) |
|
532 |
|
533 # TODO remove this try..except once the matcher integrates better |
|
534 # with dirstate. We currently have to write the updated config |
|
535 # because that will invalidate the matcher cache and force a |
|
536 # re-read. We ideally want to update the cached matcher on the |
|
537 # repo instance then flush the new config to disk once wdir is |
|
538 # updated. But this requires massive rework to matcher() and its |
|
539 # consumers. |
|
540 |
|
541 writeconfig(repo, includes, excludes, profiles) |
|
542 |
|
543 try: |
|
544 return refreshwdir(repo, oldstatus, oldmatch, force=force) |
|
545 except Exception: |
|
546 writeconfig(repo, oldincludes, oldexcludes, oldprofiles) |
|
547 raise |
|
548 |
524 def clearrules(repo, force=False): |
549 def clearrules(repo, force=False): |
525 """Clears include/exclude rules from the sparse config. |
550 """Clears include/exclude rules from the sparse config. |
526 |
551 |
527 The remaining sparse config only has profiles, if defined. The working |
552 The remaining sparse config only has profiles, if defined. The working |
528 directory is refreshed, as needed. |
553 directory is refreshed, as needed. |
532 includes, excludes, profiles = parseconfig(repo.ui, raw) |
557 includes, excludes, profiles = parseconfig(repo.ui, raw) |
533 |
558 |
534 if not includes and not excludes: |
559 if not includes and not excludes: |
535 return |
560 return |
536 |
561 |
537 oldstatus = repo.status() |
562 _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force) |
538 oldmatch = matcher(repo) |
|
539 writeconfig(repo, set(), set(), profiles) |
|
540 refreshwdir(repo, oldstatus, oldmatch, force=force) |
|
541 |
563 |
542 def importfromfiles(repo, opts, paths, force=False): |
564 def importfromfiles(repo, opts, paths, force=False): |
543 """Import sparse config rules from files. |
565 """Import sparse config rules from files. |
544 |
566 |
545 The updated sparse config is written out and the working directory |
567 The updated sparse config is written out and the working directory |
546 is refreshed, as needed. |
568 is refreshed, as needed. |
547 """ |
569 """ |
548 with repo.wlock(): |
570 with repo.wlock(): |
549 # read current configuration |
571 # read current configuration |
550 raw = repo.vfs.tryread('sparse') |
572 raw = repo.vfs.tryread('sparse') |
551 oincludes, oexcludes, oprofiles = parseconfig(repo.ui, raw) |
573 includes, excludes, profiles = parseconfig(repo.ui, raw) |
552 includes, excludes, profiles = map( |
|
553 set, (oincludes, oexcludes, oprofiles)) |
|
554 |
|
555 aincludes, aexcludes, aprofiles = activeconfig(repo) |
574 aincludes, aexcludes, aprofiles = activeconfig(repo) |
556 |
575 |
557 # Import rules on top; only take in rules that are not yet |
576 # Import rules on top; only take in rules that are not yet |
558 # part of the active rules. |
577 # part of the active rules. |
559 changed = False |
578 changed = False |
575 if changed: |
594 if changed: |
576 profilecount = len(profiles - aprofiles) |
595 profilecount = len(profiles - aprofiles) |
577 includecount = len(includes - aincludes) |
596 includecount = len(includes - aincludes) |
578 excludecount = len(excludes - aexcludes) |
597 excludecount = len(excludes - aexcludes) |
579 |
598 |
580 oldstatus = repo.status() |
599 fcounts = map(len, _updateconfigandrefreshwdir( |
581 oldsparsematch = matcher(repo) |
600 repo, includes, excludes, profiles, force=force)) |
582 |
|
583 # TODO remove this try..except once the matcher integrates better |
|
584 # with dirstate. We currently have to write the updated config |
|
585 # because that will invalidate the matcher cache and force a |
|
586 # re-read. We ideally want to update the cached matcher on the |
|
587 # repo instance then flush the new config to disk once wdir is |
|
588 # updated. But this requires massive rework to matcher() and its |
|
589 # consumers. |
|
590 writeconfig(repo, includes, excludes, profiles) |
|
591 |
|
592 try: |
|
593 fcounts = map( |
|
594 len, |
|
595 refreshwdir(repo, oldstatus, oldsparsematch, force=force)) |
|
596 except Exception: |
|
597 writeconfig(repo, oincludes, oexcludes, oprofiles) |
|
598 raise |
|
599 |
601 |
600 printchanges(repo.ui, opts, profilecount, includecount, excludecount, |
602 printchanges(repo.ui, opts, profilecount, includecount, excludecount, |
601 *fcounts) |
603 *fcounts) |
602 |
604 |
603 def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False, |
605 def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False, |
608 Only one of the actions may be performed. |
610 Only one of the actions may be performed. |
609 |
611 |
610 The new config is written out and a working directory refresh is performed. |
612 The new config is written out and a working directory refresh is performed. |
611 """ |
613 """ |
612 with repo.wlock(): |
614 with repo.wlock(): |
613 oldmatcher = matcher(repo) |
|
614 |
|
615 raw = repo.vfs.tryread('sparse') |
615 raw = repo.vfs.tryread('sparse') |
616 oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw) |
616 oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw) |
617 |
617 |
618 if reset: |
618 if reset: |
619 newinclude = set() |
619 newinclude = set() |
621 newprofiles = set() |
621 newprofiles = set() |
622 else: |
622 else: |
623 newinclude = set(oldinclude) |
623 newinclude = set(oldinclude) |
624 newexclude = set(oldexclude) |
624 newexclude = set(oldexclude) |
625 newprofiles = set(oldprofiles) |
625 newprofiles = set(oldprofiles) |
626 |
|
627 oldstatus = repo.status() |
|
628 |
626 |
629 if any(pat.startswith('/') for pat in pats): |
627 if any(pat.startswith('/') for pat in pats): |
630 repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n') |
628 repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n') |
631 % ([pat for pat in pats if pat.startswith('/')])) |
629 % ([pat for pat in pats if pat.startswith('/')])) |
632 elif include: |
630 elif include: |
646 includecount = (len(newinclude - oldinclude) - |
644 includecount = (len(newinclude - oldinclude) - |
647 len(oldinclude - newinclude)) |
645 len(oldinclude - newinclude)) |
648 excludecount = (len(newexclude - oldexclude) - |
646 excludecount = (len(newexclude - oldexclude) - |
649 len(oldexclude - newexclude)) |
647 len(oldexclude - newexclude)) |
650 |
648 |
651 # TODO clean up this writeconfig() + try..except pattern once we can. |
649 fcounts = map(len, _updateconfigandrefreshwdir( |
652 # See comment in importfromfiles() explaining it. |
650 repo, newinclude, newexclude, newprofiles, force=force)) |
653 writeconfig(repo, newinclude, newexclude, newprofiles) |
651 |
654 |
652 printchanges(repo.ui, opts, profilecount, includecount, |
655 try: |
653 excludecount, *fcounts) |
656 fcounts = map( |
|
657 len, |
|
658 refreshwdir(repo, oldstatus, oldmatcher, force=force)) |
|
659 |
|
660 printchanges(repo.ui, opts, profilecount, includecount, |
|
661 excludecount, *fcounts) |
|
662 except Exception: |
|
663 writeconfig(repo, oldinclude, oldexclude, oldprofiles) |
|
664 raise |
|
665 |
654 |
666 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0, |
655 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0, |
667 added=0, dropped=0, conflicting=0): |
656 added=0, dropped=0, conflicting=0): |
668 """Print output summarizing sparse config changes.""" |
657 """Print output summarizing sparse config changes.""" |
669 with ui.formatter('sparse', opts) as fm: |
658 with ui.formatter('sparse', opts) as fm: |