comparison mercurial/scmutil.py @ 23259:9f4778027bc2

addremove: add back forgotten files (BC) After running "hg forget README && hg addremove", README will still be reported as removed, while "hg forget README && hg add README" adds it back so it gets reported as clean. It seems like they should behave the same. Furthermore, it seems like no files should remain untracked after 'hg addremove && hg commit' (or 'hg commit -A'). For these reasons, change the behavior of addremove so it does add forgotten files back. The problem is with scmutil._interestingfiles(), which reports the file as removed, so scmutil.addremove() does not add it. Fix by teaching _interestingfiles() to report forgotten files separately from removed files and make addremove() add forgotten files back. However, do not treat forgotten files as sources for rename detection. Note that since removed and forgotten files are treated the same before this change, forgotten files were considered sources for rename detection. Also update the other caller, marktouched(), in the same way as addremove().
author Martin von Zweigbergk <martinvonz@google.com>
date Sat, 08 Nov 2014 23:13:39 -0800
parents c4ce077588d0
children bf8c3172255c
comparison
equal deleted inserted replaced
23258:10697f29af2b 23259:9f4778027bc2
684 # we'd use status here, except handling of symlinks and ignore is tricky 684 # we'd use status here, except handling of symlinks and ignore is tricky
685 m = match(repo[None], pats, opts) 685 m = match(repo[None], pats, opts)
686 rejected = [] 686 rejected = []
687 m.bad = lambda x, y: rejected.append(x) 687 m.bad = lambda x, y: rejected.append(x)
688 688
689 added, unknown, deleted, removed = _interestingfiles(repo, m) 689 added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m)
690 690
691 unknownset = set(unknown) 691 unknownset = set(unknown + forgotten)
692 toprint = unknownset.copy() 692 toprint = unknownset.copy()
693 toprint.update(deleted) 693 toprint.update(deleted)
694 for abs in sorted(toprint): 694 for abs in sorted(toprint):
695 if repo.ui.verbose or not m.exact(abs): 695 if repo.ui.verbose or not m.exact(abs):
696 rel = m.rel(abs) 696 rel = m.rel(abs)
702 702
703 renames = _findrenames(repo, m, added + unknown, removed + deleted, 703 renames = _findrenames(repo, m, added + unknown, removed + deleted,
704 similarity) 704 similarity)
705 705
706 if not dry_run: 706 if not dry_run:
707 _markchanges(repo, unknown, deleted, renames) 707 _markchanges(repo, unknown + forgotten, deleted, renames)
708 708
709 for f in rejected: 709 for f in rejected:
710 if f in m.files(): 710 if f in m.files():
711 return 1 711 return 1
712 return 0 712 return 0
716 the repo root.''' 716 the repo root.'''
717 m = matchfiles(repo, files) 717 m = matchfiles(repo, files)
718 rejected = [] 718 rejected = []
719 m.bad = lambda x, y: rejected.append(x) 719 m.bad = lambda x, y: rejected.append(x)
720 720
721 added, unknown, deleted, removed = _interestingfiles(repo, m) 721 added, unknown, deleted, removed, forgotten = _interestingfiles(repo, m)
722 722
723 if repo.ui.verbose: 723 if repo.ui.verbose:
724 unknownset = set(unknown) 724 unknownset = set(unknown + forgotten)
725 toprint = unknownset.copy() 725 toprint = unknownset.copy()
726 toprint.update(deleted) 726 toprint.update(deleted)
727 for abs in sorted(toprint): 727 for abs in sorted(toprint):
728 if abs in unknownset: 728 if abs in unknownset:
729 status = _('adding %s\n') % abs 729 status = _('adding %s\n') % abs
732 repo.ui.status(status) 732 repo.ui.status(status)
733 733
734 renames = _findrenames(repo, m, added + unknown, removed + deleted, 734 renames = _findrenames(repo, m, added + unknown, removed + deleted,
735 similarity) 735 similarity)
736 736
737 _markchanges(repo, unknown, deleted, renames) 737 _markchanges(repo, unknown + forgotten, deleted, renames)
738 738
739 for f in rejected: 739 for f in rejected:
740 if f in m.files(): 740 if f in m.files():
741 return 1 741 return 1
742 return 0 742 return 0
745 '''Walk dirstate with matcher, looking for files that addremove would care 745 '''Walk dirstate with matcher, looking for files that addremove would care
746 about. 746 about.
747 747
748 This is different from dirstate.status because it doesn't care about 748 This is different from dirstate.status because it doesn't care about
749 whether files are modified or clean.''' 749 whether files are modified or clean.'''
750 added, unknown, deleted, removed = [], [], [], [] 750 added, unknown, deleted, removed, forgotten = [], [], [], [], []
751 audit_path = pathutil.pathauditor(repo.root) 751 audit_path = pathutil.pathauditor(repo.root)
752 752
753 ctx = repo[None] 753 ctx = repo[None]
754 dirstate = repo.dirstate 754 dirstate = repo.dirstate
755 walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False, 755 walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False,
758 dstate = dirstate[abs] 758 dstate = dirstate[abs]
759 if dstate == '?' and audit_path.check(abs): 759 if dstate == '?' and audit_path.check(abs):
760 unknown.append(abs) 760 unknown.append(abs)
761 elif dstate != 'r' and not st: 761 elif dstate != 'r' and not st:
762 deleted.append(abs) 762 deleted.append(abs)
763 elif dstate == 'r' and st:
764 forgotten.append(abs)
763 # for finding renames 765 # for finding renames
764 elif dstate == 'r': 766 elif dstate == 'r' and not st:
765 removed.append(abs) 767 removed.append(abs)
766 elif dstate == 'a': 768 elif dstate == 'a':
767 added.append(abs) 769 added.append(abs)
768 770
769 return added, unknown, deleted, removed 771 return added, unknown, deleted, removed, forgotten
770 772
771 def _findrenames(repo, matcher, added, removed, similarity): 773 def _findrenames(repo, matcher, added, removed, similarity):
772 '''Find renames from removed files to added ones.''' 774 '''Find renames from removed files to added ones.'''
773 renames = {} 775 renames = {}
774 if similarity > 0: 776 if similarity > 0: