688 |
688 |
689 # a list of revset expressions to be traversed; if follow, it specifies |
689 # a list of revset expressions to be traversed; if follow, it specifies |
690 # the start revisions |
690 # the start revisions |
691 revspec = attr.ib() # type: List[bytes] |
691 revspec = attr.ib() # type: List[bytes] |
692 |
692 |
|
693 # miscellaneous queries to filter revisions (see "hg help log" for details) |
|
694 branches = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
695 date = attr.ib(default=None) # type: Optional[bytes] |
|
696 keywords = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
697 no_merges = attr.ib(default=False) # type: bool |
|
698 only_merges = attr.ib(default=False) # type: bool |
|
699 prune_ancestors = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
700 users = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
701 |
|
702 # miscellaneous matcher arguments |
|
703 include_pats = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
704 exclude_pats = attr.ib(default=attr.Factory(list)) # type: List[bytes] |
|
705 |
693 # 0: no follow, 1: follow first, 2: follow both parents |
706 # 0: no follow, 1: follow first, 2: follow both parents |
694 follow = attr.ib(default=0) # type: int |
707 follow = attr.ib(default=0) # type: int |
695 |
708 |
696 # do not attempt filelog-based traversal, which may be fast but cannot |
709 # do not attempt filelog-based traversal, which may be fast but cannot |
697 # include revisions where files were removed |
710 # include revisions where files were removed |
716 |
729 |
717 return walkopts( |
730 return walkopts( |
718 pats=pats, |
731 pats=pats, |
719 opts=opts, |
732 opts=opts, |
720 revspec=opts.get(b'rev', []), |
733 revspec=opts.get(b'rev', []), |
|
734 # branch and only_branch are really aliases and must be handled at |
|
735 # the same time |
|
736 branches=opts.get(b'branch', []) + opts.get(b'only_branch', []), |
|
737 date=opts.get(b'date'), |
|
738 keywords=opts.get(b'keyword', []), |
|
739 no_merges=bool(opts.get(b'no_merges')), |
|
740 only_merges=bool(opts.get(b'only_merges')), |
|
741 prune_ancestors=opts.get(b'prune', []), |
|
742 users=opts.get(b'user', []), |
|
743 include_pats=opts.get(b'include', []), |
|
744 exclude_pats=opts.get(b'exclude', []), |
721 follow=follow, |
745 follow=follow, |
722 force_changelog_traversal=bool(opts.get(b'removed')), |
746 force_changelog_traversal=bool(opts.get(b'removed')), |
723 limit=getlimit(opts), |
747 limit=getlimit(opts), |
724 ) |
748 ) |
725 |
749 |
853 } |
877 } |
854 |
878 |
855 |
879 |
856 def _makerevset(repo, wopts, slowpath): |
880 def _makerevset(repo, wopts, slowpath): |
857 """Return a revset string built from log options and file patterns""" |
881 """Return a revset string built from log options and file patterns""" |
858 opts = dict(wopts.opts) |
882 opts = { |
859 |
883 b'branch': [repo.lookupbranch(b) for b in wopts.branches], |
860 # branch and only_branch are really aliases and must be handled at |
884 b'date': wopts.date, |
861 # the same time |
885 b'keyword': wopts.keywords, |
862 opts[b'branch'] = opts.get(b'branch', []) + opts.get(b'only_branch', []) |
886 b'no_merges': wopts.no_merges, |
863 opts[b'branch'] = [repo.lookupbranch(b) for b in opts[b'branch']] |
887 b'only_merges': wopts.only_merges, |
|
888 b'prune': wopts.prune_ancestors, |
|
889 b'user': wopts.users, |
|
890 } |
864 |
891 |
865 if slowpath: |
892 if slowpath: |
866 # See walkchangerevs() slow path. |
893 # See walkchangerevs() slow path. |
867 # |
894 # |
868 # pats/include/exclude cannot be represented as separate |
895 # pats/include/exclude cannot be represented as separate |
872 # not. Besides, filesets are evaluated against the working |
899 # not. Besides, filesets are evaluated against the working |
873 # directory. |
900 # directory. |
874 matchargs = [b'r:', b'd:relpath'] |
901 matchargs = [b'r:', b'd:relpath'] |
875 for p in wopts.pats: |
902 for p in wopts.pats: |
876 matchargs.append(b'p:' + p) |
903 matchargs.append(b'p:' + p) |
877 for p in opts.get(b'include', []): |
904 for p in wopts.include_pats: |
878 matchargs.append(b'i:' + p) |
905 matchargs.append(b'i:' + p) |
879 for p in opts.get(b'exclude', []): |
906 for p in wopts.exclude_pats: |
880 matchargs.append(b'x:' + p) |
907 matchargs.append(b'x:' + p) |
881 opts[b'_matchfiles'] = matchargs |
908 opts[b'_matchfiles'] = matchargs |
882 elif not wopts.follow: |
909 elif not wopts.follow: |
883 opts[b'_patslog'] = list(wopts.pats) |
910 opts[b'_patslog'] = list(wopts.pats) |
884 |
911 |
885 expr = [] |
912 expr = [] |
886 for op, val in sorted(pycompat.iteritems(opts)): |
913 for op, val in sorted(pycompat.iteritems(opts)): |
887 if not val: |
914 if not val: |
888 continue |
|
889 if op not in _opt2logrevset: |
|
890 continue |
915 continue |
891 revop, listop = _opt2logrevset[op] |
916 revop, listop = _opt2logrevset[op] |
892 if revop and b'%' not in revop: |
917 if revop and b'%' not in revop: |
893 expr.append(revop) |
918 expr.append(revop) |
894 elif not listop: |
919 elif not listop: |