comparison mercurial/cmdutil.py @ 9667:8743f2e1bc54

merge changes from mpm
author Dirkjan Ochtman <dirkjan@ochtman.nl>
date Fri, 30 Oct 2009 09:53:39 +0100
parents 71e081b88f3e 1de5ebfa5585
children 2c24471d478c
comparison
equal deleted inserted replaced
9666:71e081b88f3e 9667:8743f2e1bc54
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)
1091 1087
1092 if not slowpath and not match.files(): 1088 if not slowpath and not match.files():
1093 # No files, no patterns. Display all revs. 1089 # No files, no patterns. Display all revs.
1094 wanted = set(revs) 1090 wanted = set(revs)
1095 copies = [] 1091 copies = []
1092
1096 if not slowpath: 1093 if not slowpath:
1097 # Only files, no patterns. Check the history of each file. 1094 # Only files, no patterns. Check the history of each file.
1098 def filerevgen(filelog, node): 1095 def filerevgen(filelog, node):
1099 cl_count = len(repo) 1096 cl_count = len(repo)
1100 if node is None: 1097 if node is None:
1127 if follow: 1124 if follow:
1128 raise util.Abort(_('cannot follow nonexistent file: "%s"') % file_) 1125 raise util.Abort(_('cannot follow nonexistent file: "%s"') % file_)
1129 slowpath = True 1126 slowpath = True
1130 break 1127 break
1131 else: 1128 else:
1132 ui.warn(_('%s:%s copy source revision cannot be found!\n')
1133 % (file_, short(node)))
1134 continue 1129 continue
1135 for rev, copied in filerevgen(filelog, node): 1130 for rev, copied in filerevgen(filelog, node):
1136 if rev <= maxrev: 1131 if rev <= maxrev:
1137 if rev < minrev: 1132 if rev < minrev:
1138 break 1133 break
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')