147 |
146 |
148 # profiles will only have data if sparse is enabled. |
147 # profiles will only have data if sparse is enabled. |
149 if set(profiles) & set(ctx.files()): |
148 if set(profiles) & set(ctx.files()): |
150 origstatus = repo.status() |
149 origstatus = repo.status() |
151 origsparsematch = sparse.matcher(repo) |
150 origsparsematch = sparse.matcher(repo) |
152 _refresh(repo.ui, repo, origstatus, origsparsematch, True) |
151 sparse.refreshwdir(repo, origstatus, origsparsematch, force=True) |
153 |
152 |
154 sparse.prunetemporaryincludes(repo) |
153 sparse.prunetemporaryincludes(repo) |
155 |
154 |
156 extensions.wrapfunction(context.committablectx, 'markcommitted', |
155 extensions.wrapfunction(context.committablectx, 'markcommitted', |
157 _refreshoncommit) |
156 _refreshoncommit) |
396 if refresh: |
395 if refresh: |
397 try: |
396 try: |
398 wlock = repo.wlock() |
397 wlock = repo.wlock() |
399 fcounts = map( |
398 fcounts = map( |
400 len, |
399 len, |
401 _refresh(ui, repo, repo.status(), sparse.matcher(repo), force)) |
400 sparse.refreshwdir(repo, repo.status(), sparse.matcher(repo), |
|
401 force=force)) |
402 _verbose_output(ui, opts, 0, 0, 0, *fcounts) |
402 _verbose_output(ui, opts, 0, 0, 0, *fcounts) |
403 finally: |
403 finally: |
404 wlock.release() |
404 wlock.release() |
405 |
405 |
406 def _config(ui, repo, pats, opts, include=False, exclude=False, reset=False, |
406 def _config(ui, repo, pats, opts, include=False, exclude=False, reset=False, |
450 newexclude.difference_update(pats) |
450 newexclude.difference_update(pats) |
451 |
451 |
452 sparse.writeconfig(repo, newinclude, newexclude, newprofiles) |
452 sparse.writeconfig(repo, newinclude, newexclude, newprofiles) |
453 |
453 |
454 fcounts = map( |
454 fcounts = map( |
455 len, _refresh(ui, repo, oldstatus, oldsparsematch, force)) |
455 len, |
|
456 sparse.refreshwdir(repo, oldstatus, oldsparsematch, |
|
457 force=force)) |
456 |
458 |
457 profilecount = (len(newprofiles - oldprofiles) - |
459 profilecount = (len(newprofiles - oldprofiles) - |
458 len(oldprofiles - newprofiles)) |
460 len(oldprofiles - newprofiles)) |
459 includecount = (len(newinclude - oldinclude) - |
461 includecount = (len(newinclude - oldinclude) - |
460 len(oldinclude - newinclude)) |
462 len(oldinclude - newinclude)) |
514 oldsparsematch = sparse.matcher(repo) |
516 oldsparsematch = sparse.matcher(repo) |
515 sparse.writeconfig(repo, includes, excludes, profiles) |
517 sparse.writeconfig(repo, includes, excludes, profiles) |
516 |
518 |
517 try: |
519 try: |
518 fcounts = map( |
520 fcounts = map( |
519 len, _refresh(ui, repo, oldstatus, oldsparsematch, force)) |
521 len, |
|
522 sparse.refreshwdir(repo, oldstatus, oldsparsematch, |
|
523 force=force)) |
520 except Exception: |
524 except Exception: |
521 sparse.writeconfig(repo, oincludes, oexcludes, oprofiles) |
525 sparse.writeconfig(repo, oincludes, oexcludes, oprofiles) |
522 raise |
526 raise |
523 |
527 |
524 _verbose_output(ui, opts, profilecount, includecount, excludecount, |
528 _verbose_output(ui, opts, profilecount, includecount, excludecount, |
531 |
535 |
532 if includes or excludes: |
536 if includes or excludes: |
533 oldstatus = repo.status() |
537 oldstatus = repo.status() |
534 oldsparsematch = sparse.matcher(repo) |
538 oldsparsematch = sparse.matcher(repo) |
535 sparse.writeconfig(repo, set(), set(), profiles) |
539 sparse.writeconfig(repo, set(), set(), profiles) |
536 _refresh(ui, repo, oldstatus, oldsparsematch, force) |
540 sparse.refreshwdir(repo, oldstatus, oldsparsematch, force) |
537 |
|
538 def _refresh(ui, repo, origstatus, origsparsematch, force): |
|
539 """Refreshes which files are on disk by comparing the old status and |
|
540 sparsematch with the new sparsematch. |
|
541 |
|
542 Will raise an exception if a file with pending changes is being excluded |
|
543 or included (unless force=True). |
|
544 """ |
|
545 modified, added, removed, deleted, unknown, ignored, clean = origstatus |
|
546 |
|
547 # Verify there are no pending changes |
|
548 pending = set() |
|
549 pending.update(modified) |
|
550 pending.update(added) |
|
551 pending.update(removed) |
|
552 sparsematch = sparse.matcher(repo) |
|
553 abort = False |
|
554 for file in pending: |
|
555 if not sparsematch(file): |
|
556 ui.warn(_("pending changes to '%s'\n") % file) |
|
557 abort = not force |
|
558 if abort: |
|
559 raise error.Abort(_("could not update sparseness due to " + |
|
560 "pending changes")) |
|
561 |
|
562 # Calculate actions |
|
563 dirstate = repo.dirstate |
|
564 ctx = repo['.'] |
|
565 added = [] |
|
566 lookup = [] |
|
567 dropped = [] |
|
568 mf = ctx.manifest() |
|
569 files = set(mf) |
|
570 |
|
571 actions = {} |
|
572 |
|
573 for file in files: |
|
574 old = origsparsematch(file) |
|
575 new = sparsematch(file) |
|
576 # Add files that are newly included, or that don't exist in |
|
577 # the dirstate yet. |
|
578 if (new and not old) or (old and new and not file in dirstate): |
|
579 fl = mf.flags(file) |
|
580 if repo.wvfs.exists(file): |
|
581 actions[file] = ('e', (fl,), '') |
|
582 lookup.append(file) |
|
583 else: |
|
584 actions[file] = ('g', (fl, False), '') |
|
585 added.append(file) |
|
586 # Drop files that are newly excluded, or that still exist in |
|
587 # the dirstate. |
|
588 elif (old and not new) or (not old and not new and file in dirstate): |
|
589 dropped.append(file) |
|
590 if file not in pending: |
|
591 actions[file] = ('r', [], '') |
|
592 |
|
593 # Verify there are no pending changes in newly included files |
|
594 abort = False |
|
595 for file in lookup: |
|
596 ui.warn(_("pending changes to '%s'\n") % file) |
|
597 abort = not force |
|
598 if abort: |
|
599 raise error.Abort(_("cannot change sparseness due to " + |
|
600 "pending changes (delete the files or use --force " + |
|
601 "to bring them back dirty)")) |
|
602 |
|
603 # Check for files that were only in the dirstate. |
|
604 for file, state in dirstate.iteritems(): |
|
605 if not file in files: |
|
606 old = origsparsematch(file) |
|
607 new = sparsematch(file) |
|
608 if old and not new: |
|
609 dropped.append(file) |
|
610 |
|
611 # Apply changes to disk |
|
612 typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split()) |
|
613 for f, (m, args, msg) in actions.iteritems(): |
|
614 if m not in typeactions: |
|
615 typeactions[m] = [] |
|
616 typeactions[m].append((f, args, msg)) |
|
617 mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False) |
|
618 |
|
619 # Fix dirstate |
|
620 for file in added: |
|
621 dirstate.normal(file) |
|
622 |
|
623 for file in dropped: |
|
624 dirstate.drop(file) |
|
625 |
|
626 for file in lookup: |
|
627 # File exists on disk, and we're bringing it back in an unknown state. |
|
628 dirstate.normallookup(file) |
|
629 |
|
630 return added, dropped, lookup |
|
631 |
541 |
632 def _verbose_output(ui, opts, profilecount, includecount, excludecount, added, |
542 def _verbose_output(ui, opts, profilecount, includecount, excludecount, added, |
633 dropped, lookup): |
543 dropped, lookup): |
634 """Produce --verbose and templatable output |
544 """Produce --verbose and templatable output |
635 |
545 |