1020 if tmpl: t.use_template(tmpl) |
1020 if tmpl: t.use_template(tmpl) |
1021 return t |
1021 return t |
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 |
1025 df = util.matchdate(date) |
1026 df = util.matchdate(date) |
1026 m = matchall(repo) |
1027 m = matchall(repo) |
1027 results = {} |
1028 results = {} |
1028 for st, ctx, fns in walkchangerevs(ui, repo, m, {'rev': None}): |
1029 |
|
1030 def prep(ctx, fns): |
|
1031 d = ctx.date() |
|
1032 if df(d[0]): |
|
1033 results[rev] = d |
|
1034 |
|
1035 for ctx in walkchangerevs(repo, m, {'rev': None}, prep): |
1029 rev = ctx.rev() |
1036 rev = ctx.rev() |
1030 if st == 'add': |
1037 if rev in results: |
1031 d = ctx.date() |
1038 ui.status(_("Found revision %s from %s\n") % |
1032 if df(d[0]): |
1039 (rev, util.datestr(results[rev]))) |
1033 results[rev] = d |
1040 return str(rev) |
1034 elif st == 'iter': |
|
1035 if rev in results: |
|
1036 ui.status(_("Found revision %s from %s\n") % |
|
1037 (rev, util.datestr(results[rev]))) |
|
1038 return str(rev) |
|
1039 |
1041 |
1040 raise util.Abort(_("revision matching date not found")) |
1042 raise util.Abort(_("revision matching date not found")) |
1041 |
1043 |
1042 def walkchangerevs(ui, repo, match, opts): |
1044 def walkchangerevs(repo, match, opts, prepare): |
1043 '''Iterate over files and the revs in which they changed. |
1045 '''Iterate over files and the revs in which they changed. |
1044 |
1046 |
1045 Callers most commonly need to iterate backwards over the history |
1047 Callers most commonly need to iterate backwards over the history |
1046 in which they are interested. Doing so has awful (quadratic-looking) |
1048 in which they are interested. Doing so has awful (quadratic-looking) |
1047 performance, so we use iterators in a "windowed" way. |
1049 performance, so we use iterators in a "windowed" way. |
1048 |
1050 |
1049 We walk a window of revisions in the desired order. Within the |
1051 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 |
1052 window, we first walk forwards to gather data, then in the desired |
1051 order (usually backwards) to display it. |
1053 order (usually backwards) to display it. |
1052 |
1054 |
1053 This function returns an iterator. The iterator yields 3-tuples. |
1055 This function returns an iterator yielding contexts. Before |
1054 They will be of one of the following forms: |
1056 yielding each context, the iterator will first call the prepare |
1055 |
1057 function on each context in the window in forward order.''' |
1056 "add", rev, fns: out-of-order traversal of the given filenames |
|
1057 fns, which changed during revision rev - use to gather data for |
|
1058 possible display |
|
1059 |
|
1060 "iter", rev, None: in-order traversal of the revs earlier iterated |
|
1061 over with "add" - use to display data''' |
|
1062 |
1058 |
1063 def increasing_windows(start, end, windowsize=8, sizelimit=512): |
1059 def increasing_windows(start, end, windowsize=8, sizelimit=512): |
1064 if start < end: |
1060 if start < end: |
1065 while start < end: |
1061 while start < end: |
1066 yield start, min(windowsize, end-start) |
1062 yield start, min(windowsize, end-start) |
1213 else: |
1208 else: |
1214 def want(rev): |
1209 def want(rev): |
1215 return rev in wanted |
1210 return rev in wanted |
1216 |
1211 |
1217 for i, window in increasing_windows(0, len(revs)): |
1212 for i, window in increasing_windows(0, len(revs)): |
|
1213 change = util.cachefunc(repo.changectx) |
1218 nrevs = [rev for rev in revs[i:i+window] if want(rev)] |
1214 nrevs = [rev for rev in revs[i:i+window] if want(rev)] |
1219 for rev in sorted(nrevs): |
1215 for rev in sorted(nrevs): |
1220 fns = fncache.get(rev) |
1216 fns = fncache.get(rev) |
1221 ctx = change(rev) |
1217 ctx = change(rev) |
1222 if not fns: |
1218 if not fns: |
1223 def fns_generator(): |
1219 def fns_generator(): |
1224 for f in ctx.files(): |
1220 for f in ctx.files(): |
1225 if match(f): |
1221 if match(f): |
1226 yield f |
1222 yield f |
1227 fns = fns_generator() |
1223 fns = fns_generator() |
1228 yield 'add', ctx, fns |
1224 prepare(ctx, fns) |
1229 for rev in nrevs: |
1225 for rev in nrevs: |
1230 yield 'iter', change(rev), None |
1226 yield change(rev) |
1231 return iterate() |
1227 return iterate() |
1232 |
1228 |
1233 def commit(ui, repo, commitfunc, pats, opts): |
1229 def commit(ui, repo, commitfunc, pats, opts): |
1234 '''commit the specified files or all outstanding changes''' |
1230 '''commit the specified files or all outstanding changes''' |
1235 date = opts.get('date') |
1231 date = opts.get('date') |