Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/cmdutil.py @ 9652:2cb0cab10d2e
walkchangerevs: pull out matchfn
* * *
imported patch mercurial/commands.py
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 25 Oct 2009 18:43:56 -0500 |
parents | f57640bf10d4 |
children | e4de75343743 |
comparison
equal
deleted
inserted
replaced
9632:16698d87ad20 | 9652:2cb0cab10d2e |
---|---|
1022 | 1022 |
1023 def finddate(ui, repo, date): | 1023 def finddate(ui, repo, date): |
1024 """Find the tipmost changeset that matches the given date spec""" | 1024 """Find the tipmost changeset that matches the given date spec""" |
1025 df = util.matchdate(date) | 1025 df = util.matchdate(date) |
1026 get = util.cachefunc(lambda r: repo[r]) | 1026 get = util.cachefunc(lambda r: repo[r]) |
1027 changeiter, matchfn = walkchangerevs(ui, repo, [], get, {'rev':None}) | 1027 m = matchall(repo) |
1028 results = {} | 1028 results = {} |
1029 for st, rev, fns in changeiter: | 1029 for st, rev, fns in walkchangerevs(ui, repo, m, get, {'rev':None}): |
1030 if st == 'add': | 1030 if st == 'add': |
1031 d = get(rev).date() | 1031 d = get(rev).date() |
1032 if df(d[0]): | 1032 if df(d[0]): |
1033 results[rev] = d | 1033 results[rev] = d |
1034 elif st == 'iter': | 1034 elif st == 'iter': |
1037 (rev, util.datestr(results[rev]))) | 1037 (rev, util.datestr(results[rev]))) |
1038 return str(rev) | 1038 return str(rev) |
1039 | 1039 |
1040 raise util.Abort(_("revision matching date not found")) | 1040 raise util.Abort(_("revision matching date not found")) |
1041 | 1041 |
1042 def walkchangerevs(ui, repo, pats, change, opts): | 1042 def walkchangerevs(ui, repo, match, change, opts): |
1043 '''Iterate over files and the revs in which they changed. | 1043 '''Iterate over files and the revs in which they changed. |
1044 | 1044 |
1045 Callers most commonly need to iterate backwards over the history | 1045 Callers most commonly need to iterate backwards over the history |
1046 in which they are interested. Doing so has awful (quadratic-looking) | 1046 in which they are interested. Doing so has awful (quadratic-looking) |
1047 performance, so we use iterators in a "windowed" way. | 1047 performance, so we use iterators in a "windowed" way. |
1048 | 1048 |
1049 We walk a window of revisions in the desired order. Within the | 1049 We walk a window of revisions in the desired order. Within the |
1050 window, we first walk forwards to gather data, then in the desired | 1050 window, we first walk forwards to gather data, then in the desired |
1051 order (usually backwards) to display it. | 1051 order (usually backwards) to display it. |
1052 | 1052 |
1053 This function returns an (iterator, matchfn) tuple. The iterator | 1053 This function returns an iterator. The iterator yields 3-tuples. |
1054 yields 3-tuples. They will be of one of the following forms: | 1054 They will be of one of the following forms: |
1055 | 1055 |
1056 "window", incrementing, lastrev: stepping through a window, | 1056 "window", incrementing, lastrev: stepping through a window, |
1057 positive if walking forwards through revs, last rev in the | 1057 positive if walking forwards through revs, last rev in the |
1058 sequence iterated over - use to reset state for the current window | 1058 sequence iterated over - use to reset state for the current window |
1059 | 1059 |
1076 yield start, min(windowsize, start-end-1) | 1076 yield start, min(windowsize, start-end-1) |
1077 start -= windowsize | 1077 start -= windowsize |
1078 if windowsize < sizelimit: | 1078 if windowsize < sizelimit: |
1079 windowsize *= 2 | 1079 windowsize *= 2 |
1080 | 1080 |
1081 m = match(repo, pats, opts) | |
1082 follow = opts.get('follow') or opts.get('follow_first') | 1081 follow = opts.get('follow') or opts.get('follow_first') |
1083 | 1082 |
1084 if not len(repo): | 1083 if not len(repo): |
1085 return [], m | 1084 return [] |
1086 | 1085 |
1087 if follow: | 1086 if follow: |
1088 defrange = '%s:0' % repo['.'].rev() | 1087 defrange = '%s:0' % repo['.'].rev() |
1089 else: | 1088 else: |
1090 defrange = '-1:0' | 1089 defrange = '-1:0' |
1091 revs = revrange(repo, opts['rev'] or [defrange]) | 1090 revs = revrange(repo, opts['rev'] or [defrange]) |
1092 wanted = set() | 1091 wanted = set() |
1093 slowpath = m.anypats() or (m.files() and opts.get('removed')) | 1092 slowpath = match.anypats() or (match.files() and opts.get('removed')) |
1094 fncache = {} | 1093 fncache = {} |
1095 | 1094 |
1096 if not slowpath and not m.files(): | 1095 if not slowpath and not match.files(): |
1097 # No files, no patterns. Display all revs. | 1096 # No files, no patterns. Display all revs. |
1098 wanted = set(revs) | 1097 wanted = set(revs) |
1099 copies = [] | 1098 copies = [] |
1100 if not slowpath: | 1099 if not slowpath: |
1101 # Only files, no patterns. Check the history of each file. | 1100 # Only files, no patterns. Check the history of each file. |
1115 # only yield rev for which we have the changelog, it can | 1114 # only yield rev for which we have the changelog, it can |
1116 # happen while doing "hg log" during a pull or commit | 1115 # happen while doing "hg log" during a pull or commit |
1117 if rev[0] < cl_count: | 1116 if rev[0] < cl_count: |
1118 yield rev | 1117 yield rev |
1119 def iterfiles(): | 1118 def iterfiles(): |
1120 for filename in m.files(): | 1119 for filename in match.files(): |
1121 yield filename, None | 1120 yield filename, None |
1122 for filename_node in copies: | 1121 for filename_node in copies: |
1123 yield filename_node | 1122 yield filename_node |
1124 minrev, maxrev = min(revs), max(revs) | 1123 minrev, maxrev = min(revs), max(revs) |
1125 for file_, node in iterfiles(): | 1124 for file_, node in iterfiles(): |
1155 for i, window in increasing_windows(len(repo) - 1, nullrev): | 1154 for i, window in increasing_windows(len(repo) - 1, nullrev): |
1156 for j in xrange(i - window, i + 1): | 1155 for j in xrange(i - window, i + 1): |
1157 yield change(j) | 1156 yield change(j) |
1158 | 1157 |
1159 for ctx in changerevgen(): | 1158 for ctx in changerevgen(): |
1160 matches = filter(m, ctx.files()) | 1159 matches = filter(match, ctx.files()) |
1161 if matches: | 1160 if matches: |
1162 fncache[ctx.rev()] = matches | 1161 fncache[ctx.rev()] = matches |
1163 wanted.add(ctx.rev()) | 1162 wanted.add(ctx.rev()) |
1164 | 1163 |
1165 class followfilter(object): | 1164 class followfilter(object): |
1208 for x in xrange(rev, stop-1, -1): | 1207 for x in xrange(rev, stop-1, -1): |
1209 if ff.match(x): | 1208 if ff.match(x): |
1210 wanted.discard(x) | 1209 wanted.discard(x) |
1211 | 1210 |
1212 def iterate(): | 1211 def iterate(): |
1213 if follow and not m.files(): | 1212 if follow and not match.files(): |
1214 ff = followfilter(onlyfirst=opts.get('follow_first')) | 1213 ff = followfilter(onlyfirst=opts.get('follow_first')) |
1215 def want(rev): | 1214 def want(rev): |
1216 return ff.match(rev) and rev in wanted | 1215 return ff.match(rev) and rev in wanted |
1217 else: | 1216 else: |
1218 def want(rev): | 1217 def want(rev): |
1224 for rev in sorted(nrevs): | 1223 for rev in sorted(nrevs): |
1225 fns = fncache.get(rev) | 1224 fns = fncache.get(rev) |
1226 if not fns: | 1225 if not fns: |
1227 def fns_generator(): | 1226 def fns_generator(): |
1228 for f in change(rev).files(): | 1227 for f in change(rev).files(): |
1229 if m(f): | 1228 if match(f): |
1230 yield f | 1229 yield f |
1231 fns = fns_generator() | 1230 fns = fns_generator() |
1232 yield 'add', rev, fns | 1231 yield 'add', rev, fns |
1233 for rev in nrevs: | 1232 for rev in nrevs: |
1234 yield 'iter', rev, None | 1233 yield 'iter', rev, None |
1235 return iterate(), m | 1234 return iterate() |
1236 | 1235 |
1237 def commit(ui, repo, commitfunc, pats, opts): | 1236 def commit(ui, repo, commitfunc, pats, opts): |
1238 '''commit the specified files or all outstanding changes''' | 1237 '''commit the specified files or all outstanding changes''' |
1239 date = opts.get('date') | 1238 date = opts.get('date') |
1240 if date: | 1239 if date: |