691 revspec = attr.ib() # type: List[bytes] |
691 revspec = attr.ib() # type: List[bytes] |
692 |
692 |
693 # 0: no follow, 1: follow first, 2: follow both parents |
693 # 0: no follow, 1: follow first, 2: follow both parents |
694 follow = attr.ib(default=0) # type: int |
694 follow = attr.ib(default=0) # type: int |
695 |
695 |
|
696 # do not attempt filelog-based traversal, which may be fast but cannot |
|
697 # include revisions where files were removed |
|
698 force_changelog_traversal = attr.ib(default=False) # type: bool |
|
699 |
696 # limit number of changes displayed; None means unlimited |
700 # limit number of changes displayed; None means unlimited |
697 limit = attr.ib(default=None) # type: Optional[int] |
701 limit = attr.ib(default=None) # type: Optional[int] |
698 |
702 |
699 |
703 |
700 def parseopts(ui, pats, opts): |
704 def parseopts(ui, pats, opts): |
713 return walkopts( |
717 return walkopts( |
714 pats=pats, |
718 pats=pats, |
715 opts=opts, |
719 opts=opts, |
716 revspec=opts.get(b'rev', []), |
720 revspec=opts.get(b'rev', []), |
717 follow=follow, |
721 follow=follow, |
|
722 force_changelog_traversal=bool(opts.get(b'removed')), |
718 limit=getlimit(opts), |
723 limit=getlimit(opts), |
719 ) |
724 ) |
720 |
725 |
721 |
726 |
722 def _makematcher(repo, revs, wopts): |
727 def _makematcher(repo, revs, wopts): |
734 # scmutil.match(). The difference is input pats are globbed on |
739 # scmutil.match(). The difference is input pats are globbed on |
735 # platforms without shell expansion (windows). |
740 # platforms without shell expansion (windows). |
736 wctx = repo[None] |
741 wctx = repo[None] |
737 match, pats = scmutil.matchandpats(wctx, wopts.pats, wopts.opts) |
742 match, pats = scmutil.matchandpats(wctx, wopts.pats, wopts.opts) |
738 slowpath = match.anypats() or ( |
743 slowpath = match.anypats() or ( |
739 not match.always() and wopts.opts.get(b'removed') |
744 not match.always() and wopts.force_changelog_traversal |
740 ) |
745 ) |
741 if not slowpath: |
746 if not slowpath: |
742 if wopts.follow and wopts.revspec: |
747 if wopts.follow and wopts.revspec: |
743 # There may be the case that a path doesn't exist in some (but |
748 # There may be the case that a path doesn't exist in some (but |
744 # not all) of the specified start revisions, but let's consider |
749 # not all) of the specified start revisions, but let's consider |
921 differ is a changesetdiffer with pre-configured file matcher. |
926 differ is a changesetdiffer with pre-configured file matcher. |
922 """ |
927 """ |
923 revs = _initialrevs(repo, wopts) |
928 revs = _initialrevs(repo, wopts) |
924 if not revs: |
929 if not revs: |
925 return smartset.baseset(), None |
930 return smartset.baseset(), None |
|
931 # TODO: might want to merge slowpath with wopts.force_changelog_traversal |
926 match, pats, slowpath = _makematcher(repo, revs, wopts) |
932 match, pats, slowpath = _makematcher(repo, revs, wopts) |
927 wopts = attr.evolve(wopts, pats=pats) |
933 wopts = attr.evolve(wopts, pats=pats) |
928 |
934 |
929 filematcher = None |
935 filematcher = None |
930 if wopts.follow: |
936 if wopts.follow: |
931 if slowpath or match.always(): |
937 if slowpath or match.always(): |
932 revs = dagop.revancestors(repo, revs, followfirst=wopts.follow == 1) |
938 revs = dagop.revancestors(repo, revs, followfirst=wopts.follow == 1) |
933 else: |
939 else: |
|
940 assert not wopts.force_changelog_traversal |
934 revs, filematcher = _fileancestors( |
941 revs, filematcher = _fileancestors( |
935 repo, revs, match, followfirst=wopts.follow == 1 |
942 repo, revs, match, followfirst=wopts.follow == 1 |
936 ) |
943 ) |
937 revs.reverse() |
944 revs.reverse() |
938 if filematcher is None: |
945 if filematcher is None: |