##// END OF EJS Templates
log: introduce struct that carries log traversal options...
Yuya Nishihara -
r46139:c1d0f83d default
parent child Browse files
Show More
@@ -137,9 +137,9 b' def _setuplog(ui):'
137 )
137 )
138 )
138 )
139
139
140 def _initialrevs(orig, repo, opts):
140 def _initialrevs(orig, repo, wopts):
141 revs = orig(repo, opts)
141 revs = orig(repo, wopts)
142 if opts.get(b'sparse'):
142 if wopts.opts.get(b'sparse'):
143 sparsematch = sparse.matcher(repo)
143 sparsematch = sparse.matcher(repo)
144
144
145 def ctxmatch(rev):
145 def ctxmatch(rev):
@@ -4734,7 +4734,9 b' def log(ui, repo, *pats, **opts):'
4734 )
4734 )
4735
4735
4736 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4736 repo = scmutil.unhidehashlikerevs(repo, opts.get(b'rev'), b'nowarn')
4737 revs, differ = logcmdutil.getrevs(repo, pats, opts)
4737 revs, differ = logcmdutil.getrevs(
4738 repo, logcmdutil.parseopts(ui, pats, opts)
4739 )
4738 if linerange:
4740 if linerange:
4739 # TODO: should follow file history from logcmdutil._initialrevs(),
4741 # TODO: should follow file history from logcmdutil._initialrevs(),
4740 # then filter the result by logcmdutil._makerevset() and --limit
4742 # then filter the result by logcmdutil._makerevset() and --limit
@@ -18,6 +18,8 b' from .node import ('
18 wdirrev,
18 wdirrev,
19 )
19 )
20
20
21 from .thirdparty import attr
22
21 from . import (
23 from . import (
22 dagop,
24 dagop,
23 error,
25 error,
@@ -45,11 +47,13 b' from .utils import ('
45 if pycompat.TYPE_CHECKING:
47 if pycompat.TYPE_CHECKING:
46 from typing import (
48 from typing import (
47 Any,
49 Any,
50 Dict,
51 List,
48 Optional,
52 Optional,
49 Tuple,
53 Tuple,
50 )
54 )
51
55
52 for t in (Any, Optional, Tuple):
56 for t in (Any, Dict, List, Optional, Tuple):
53 assert t
57 assert t
54
58
55
59
@@ -672,7 +676,27 b' def changesetdisplayer(ui, repo, opts, d'
672 return changesettemplater(ui, repo, spec, *postargs)
676 return changesettemplater(ui, repo, spec, *postargs)
673
677
674
678
675 def _makematcher(repo, revs, pats, opts):
679 @attr.s
680 class walkopts(object):
681 """Options to configure a set of revisions and file matcher factory
682 to scan revision/file history
683 """
684
685 # raw command-line parameters, which a matcher will be built from
686 pats = attr.ib() # type: List[bytes]
687 opts = attr.ib() # type: Dict[bytes, Any]
688
689
690 def parseopts(ui, pats, opts):
691 # type: (Any, List[bytes], Dict[bytes, Any]) -> walkopts
692 """Parse log command options into walkopts
693
694 The returned walkopts will be passed in to getrevs().
695 """
696 return walkopts(pats=pats, opts=opts)
697
698
699 def _makematcher(repo, revs, wopts):
676 """Build matcher and expanded patterns from log options
700 """Build matcher and expanded patterns from log options
677
701
678 If --follow, revs are the revisions to follow from.
702 If --follow, revs are the revisions to follow from.
@@ -687,11 +711,13 b' def _makematcher(repo, revs, pats, opts)'
687 # scmutil.match(). The difference is input pats are globbed on
711 # scmutil.match(). The difference is input pats are globbed on
688 # platforms without shell expansion (windows).
712 # platforms without shell expansion (windows).
689 wctx = repo[None]
713 wctx = repo[None]
690 match, pats = scmutil.matchandpats(wctx, pats, opts)
714 match, pats = scmutil.matchandpats(wctx, wopts.pats, wopts.opts)
691 slowpath = match.anypats() or (not match.always() and opts.get(b'removed'))
715 slowpath = match.anypats() or (
716 not match.always() and wopts.opts.get(b'removed')
717 )
692 if not slowpath:
718 if not slowpath:
693 follow = opts.get(b'follow') or opts.get(b'follow_first')
719 follow = wopts.opts.get(b'follow') or wopts.opts.get(b'follow_first')
694 if follow and opts.get(b'rev'):
720 if follow and wopts.opts.get(b'rev'):
695 # There may be the case that a path doesn't exist in some (but
721 # There may be the case that a path doesn't exist in some (but
696 # not all) of the specified start revisions, but let's consider
722 # not all) of the specified start revisions, but let's consider
697 # the path is valid. Missing files will be warned by the matcher.
723 # the path is valid. Missing files will be warned by the matcher.
@@ -800,9 +826,9 b' def _makenofollowfilematcher(repo, pats,'
800 }
826 }
801
827
802
828
803 def _makerevset(repo, pats, slowpath, opts):
829 def _makerevset(repo, wopts, slowpath):
804 """Return a revset string built from log options and file patterns"""
830 """Return a revset string built from log options and file patterns"""
805 opts = dict(opts)
831 opts = dict(wopts.opts)
806 # follow or not follow?
832 # follow or not follow?
807 follow = opts.get(b'follow') or opts.get(b'follow_first')
833 follow = opts.get(b'follow') or opts.get(b'follow_first')
808
834
@@ -821,7 +847,7 b' def _makerevset(repo, pats, slowpath, op'
821 # not. Besides, filesets are evaluated against the working
847 # not. Besides, filesets are evaluated against the working
822 # directory.
848 # directory.
823 matchargs = [b'r:', b'd:relpath']
849 matchargs = [b'r:', b'd:relpath']
824 for p in pats:
850 for p in wopts.pats:
825 matchargs.append(b'p:' + p)
851 matchargs.append(b'p:' + p)
826 for p in opts.get(b'include', []):
852 for p in opts.get(b'include', []):
827 matchargs.append(b'i:' + p)
853 matchargs.append(b'i:' + p)
@@ -829,7 +855,7 b' def _makerevset(repo, pats, slowpath, op'
829 matchargs.append(b'x:' + p)
855 matchargs.append(b'x:' + p)
830 opts[b'_matchfiles'] = matchargs
856 opts[b'_matchfiles'] = matchargs
831 elif not follow:
857 elif not follow:
832 opts[b'_patslog'] = list(pats)
858 opts[b'_patslog'] = list(wopts.pats)
833
859
834 expr = []
860 expr = []
835 for op, val in sorted(pycompat.iteritems(opts)):
861 for op, val in sorted(pycompat.iteritems(opts)):
@@ -854,11 +880,11 b' def _makerevset(repo, pats, slowpath, op'
854 return expr
880 return expr
855
881
856
882
857 def _initialrevs(repo, opts):
883 def _initialrevs(repo, wopts):
858 """Return the initial set of revisions to be filtered or followed"""
884 """Return the initial set of revisions to be filtered or followed"""
859 follow = opts.get(b'follow') or opts.get(b'follow_first')
885 follow = wopts.opts.get(b'follow') or wopts.opts.get(b'follow_first')
860 if opts.get(b'rev'):
886 if wopts.opts.get(b'rev'):
861 revs = scmutil.revrange(repo, opts[b'rev'])
887 revs = scmutil.revrange(repo, wopts.opts[b'rev'])
862 elif follow and repo.dirstate.p1() == nullid:
888 elif follow and repo.dirstate.p1() == nullid:
863 revs = smartset.baseset()
889 revs = smartset.baseset()
864 elif follow:
890 elif follow:
@@ -869,19 +895,21 b' def _initialrevs(repo, opts):'
869 return revs
895 return revs
870
896
871
897
872 def getrevs(repo, pats, opts):
898 def getrevs(repo, wopts):
873 # type: (Any, Any, Any) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]
899 # type: (Any, walkopts) -> Tuple[smartset.abstractsmartset, Optional[changesetdiffer]]
874 """Return (revs, differ) where revs is a smartset
900 """Return (revs, differ) where revs is a smartset
875
901
876 differ is a changesetdiffer with pre-configured file matcher.
902 differ is a changesetdiffer with pre-configured file matcher.
877 """
903 """
878 follow = opts.get(b'follow') or opts.get(b'follow_first')
904 follow = wopts.opts.get(b'follow') or wopts.opts.get(b'follow_first')
879 followfirst = opts.get(b'follow_first')
905 followfirst = wopts.opts.get(b'follow_first')
880 limit = getlimit(opts)
906 limit = getlimit(wopts.opts)
881 revs = _initialrevs(repo, opts)
907 revs = _initialrevs(repo, wopts)
882 if not revs:
908 if not revs:
883 return smartset.baseset(), None
909 return smartset.baseset(), None
884 match, pats, slowpath = _makematcher(repo, revs, pats, opts)
910 match, pats, slowpath = _makematcher(repo, revs, wopts)
911 wopts = attr.evolve(wopts, pats=pats)
912
885 filematcher = None
913 filematcher = None
886 if follow:
914 if follow:
887 if slowpath or match.always():
915 if slowpath or match.always():
@@ -890,14 +918,14 b' def getrevs(repo, pats, opts):'
890 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
918 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
891 revs.reverse()
919 revs.reverse()
892 if filematcher is None:
920 if filematcher is None:
893 filematcher = _makenofollowfilematcher(repo, pats, opts)
921 filematcher = _makenofollowfilematcher(repo, wopts.pats, wopts.opts)
894 if filematcher is None:
922 if filematcher is None:
895
923
896 def filematcher(ctx):
924 def filematcher(ctx):
897 return match
925 return match
898
926
899 expr = _makerevset(repo, pats, slowpath, opts)
927 expr = _makerevset(repo, wopts, slowpath)
900 if opts.get(b'graph'):
928 if wopts.opts.get(b'graph'):
901 if repo.ui.configbool(b'experimental', b'log.topo'):
929 if repo.ui.configbool(b'experimental', b'log.topo'):
902 if not revs.istopo():
930 if not revs.istopo():
903 revs = dagop.toposort(revs, repo.changelog.parentrevs)
931 revs = dagop.toposort(revs, repo.changelog.parentrevs)
@@ -1,4 +1,5 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2 from mercurial.thirdparty import attr
2 from mercurial import (
3 from mercurial import (
3 cmdutil,
4 cmdutil,
4 commands,
5 commands,
@@ -11,26 +12,27 b' from mercurial import ('
11 from mercurial.utils import stringutil
12 from mercurial.utils import stringutil
12
13
13
14
14 def logrevset(repo, pats, opts):
15 def logrevset(repo, wopts):
15 revs = logcmdutil._initialrevs(repo, opts)
16 revs = logcmdutil._initialrevs(repo, wopts)
16 if not revs:
17 if not revs:
17 return None
18 return None
18 match, pats, slowpath = logcmdutil._makematcher(repo, revs, pats, opts)
19 match, pats, slowpath = logcmdutil._makematcher(repo, revs, wopts)
19 return logcmdutil._makerevset(repo, pats, slowpath, opts)
20 wopts = attr.evolve(wopts, pats=pats)
21 return logcmdutil._makerevset(repo, wopts, slowpath)
20
22
21
23
22 def uisetup(ui):
24 def uisetup(ui):
23 def printrevset(orig, repo, pats, opts):
25 def printrevset(orig, repo, wopts):
24 revs, filematcher = orig(repo, pats, opts)
26 revs, filematcher = orig(repo, wopts)
25 if opts.get(b'print_revset'):
27 if wopts.opts.get(b'print_revset'):
26 expr = logrevset(repo, pats, opts)
28 expr = logrevset(repo, wopts)
27 if expr:
29 if expr:
28 tree = revsetlang.parse(expr)
30 tree = revsetlang.parse(expr)
29 tree = revsetlang.analyze(tree)
31 tree = revsetlang.analyze(tree)
30 else:
32 else:
31 tree = []
33 tree = []
32 ui = repo.ui
34 ui = repo.ui
33 ui.write(b'%s\n' % stringutil.pprint(opts.get(b'rev', [])))
35 ui.write(b'%s\n' % stringutil.pprint(wopts.opts.get(b'rev', [])))
34 ui.write(revsetlang.prettyformat(tree) + b'\n')
36 ui.write(revsetlang.prettyformat(tree) + b'\n')
35 ui.write(stringutil.prettyrepr(revs) + b'\n')
37 ui.write(stringutil.prettyrepr(revs) + b'\n')
36 revs = smartset.baseset() # display no revisions
38 revs = smartset.baseset() # display no revisions
General Comments 0
You need to be logged in to leave comments. Login now