Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 8849:80cc4b1a62d0
compare grep result between target and its parent
I found that typical case is that grep target is added at (*) revision
in the tree shown below.
+--- 1(*) --- 3
0
+--- 2 ------ 4
Now, I expect 'hg grep --all' to show only rev:1 which is first
appearance of target line.
But 'hg grep --all' will tell:
target line dis-appeared at 3 => 4
target line appeared at 2 => 3
target line dis-appeared at 1 => 2
target line appeared at 0 => 1
because current 'hg grep' implementation compares not between target
revision and its parent, but between neighbor revisions in walkthrough
order.
I checked performance of this patch by "hg grep --follow --all
walkchangerevs" on whole Mercurial repo, and patched version could
complete as fast as un-patched one.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Tue, 19 May 2009 16:49:54 +0900 |
parents | 6d36fc70754e |
children | f331de880cbb |
comparison
equal
deleted
inserted
replaced
8848:89b71acdac9a | 8849:80cc4b1a62d0 |
---|---|
1228 for i in xrange(alo, ahi): | 1228 for i in xrange(alo, ahi): |
1229 yield ('-', a[i]) | 1229 yield ('-', a[i]) |
1230 for i in xrange(blo, bhi): | 1230 for i in xrange(blo, bhi): |
1231 yield ('+', b[i]) | 1231 yield ('+', b[i]) |
1232 | 1232 |
1233 prev = {} | 1233 def display(fn, r, pstates, states): |
1234 def display(fn, rev, states, prevstates): | |
1235 datefunc = ui.quiet and util.shortdate or util.datestr | 1234 datefunc = ui.quiet and util.shortdate or util.datestr |
1236 found = False | 1235 found = False |
1237 filerevmatches = {} | 1236 filerevmatches = {} |
1238 r = prev.get(fn, -1) | |
1239 if opts.get('all'): | 1237 if opts.get('all'): |
1240 iter = difflinestates(states, prevstates) | 1238 iter = difflinestates(pstates, states) |
1241 else: | 1239 else: |
1242 iter = [('', l) for l in prevstates] | 1240 iter = [('', l) for l in states] |
1243 for change, l in iter: | 1241 for change, l in iter: |
1244 cols = [fn, str(r)] | 1242 cols = [fn, str(r)] |
1245 if opts.get('line_number'): | 1243 if opts.get('line_number'): |
1246 cols.append(str(l.linenum)) | 1244 cols.append(str(l.linenum)) |
1247 if opts.get('all'): | 1245 if opts.get('all'): |
1259 cols.append(l.line) | 1257 cols.append(l.line) |
1260 ui.write(sep.join(cols), eol) | 1258 ui.write(sep.join(cols), eol) |
1261 found = True | 1259 found = True |
1262 return found | 1260 return found |
1263 | 1261 |
1264 fstate = {} | |
1265 skip = {} | 1262 skip = {} |
1263 revfiles = {} | |
1266 get = util.cachefunc(lambda r: repo[r].changeset()) | 1264 get = util.cachefunc(lambda r: repo[r].changeset()) |
1267 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) | 1265 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts) |
1268 found = False | 1266 found = False |
1269 follow = opts.get('follow') | 1267 follow = opts.get('follow') |
1270 for st, rev, fns in changeiter: | 1268 for st, rev, fns in changeiter: |
1271 if st == 'window': | 1269 if st == 'window': |
1272 matches.clear() | 1270 matches.clear() |
1271 revfiles.clear() | |
1273 elif st == 'add': | 1272 elif st == 'add': |
1274 ctx = repo[rev] | 1273 ctx = repo[rev] |
1275 matches[rev] = {} | 1274 pctx = ctx.parents()[0] |
1275 parent = pctx.rev() | |
1276 matches.setdefault(rev, {}) | |
1277 matches.setdefault(parent, {}) | |
1278 files = revfiles.setdefault(rev, []) | |
1276 for fn in fns: | 1279 for fn in fns: |
1280 flog = getfile(fn) | |
1281 try: | |
1282 fnode = ctx.filenode(fn) | |
1283 except error.LookupError: | |
1284 continue | |
1285 | |
1286 copied = flog.renamed(fnode) | |
1287 copy = follow and copied and copied[0] | |
1288 if copy: | |
1289 copies.setdefault(rev, {})[fn] = copy | |
1277 if fn in skip: | 1290 if fn in skip: |
1291 if copy: | |
1292 skip[copy] = True | |
1278 continue | 1293 continue |
1279 try: | 1294 files.append(fn) |
1280 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn))) | 1295 |
1281 fstate.setdefault(fn, []) | 1296 if not matches[rev].has_key(fn): |
1282 if follow: | 1297 grepbody(fn, rev, flog.read(fnode)) |
1283 copied = getfile(fn).renamed(ctx.filenode(fn)) | 1298 |
1284 if copied: | 1299 pfn = copy or fn |
1285 copies.setdefault(rev, {})[fn] = copied[0] | 1300 if not matches[parent].has_key(pfn): |
1286 except error.LookupError: | 1301 try: |
1287 pass | 1302 fnode = pctx.filenode(pfn) |
1303 grepbody(pfn, parent, flog.read(fnode)) | |
1304 except error.LookupError: | |
1305 pass | |
1288 elif st == 'iter': | 1306 elif st == 'iter': |
1289 for fn, m in sorted(matches[rev].items()): | 1307 parent = repo[rev].parents()[0].rev() |
1308 for fn in sorted(revfiles.get(rev, [])): | |
1309 states = matches[rev][fn] | |
1290 copy = copies.get(rev, {}).get(fn) | 1310 copy = copies.get(rev, {}).get(fn) |
1291 if fn in skip: | 1311 if fn in skip: |
1292 if copy: | 1312 if copy: |
1293 skip[copy] = True | 1313 skip[copy] = True |
1294 continue | 1314 continue |
1295 if fn in prev or fstate[fn]: | 1315 pstates = matches.get(parent, {}).get(copy or fn, []) |
1296 r = display(fn, rev, m, fstate[fn]) | 1316 if pstates or states: |
1317 r = display(fn, rev, pstates, states) | |
1297 found = found or r | 1318 found = found or r |
1298 if r and not opts.get('all'): | 1319 if r and not opts.get('all'): |
1299 skip[fn] = True | 1320 skip[fn] = True |
1300 if copy: | 1321 if copy: |
1301 skip[copy] = True | 1322 skip[copy] = True |
1302 fstate[fn] = m | |
1303 if copy: | |
1304 fstate[copy] = m | |
1305 prev[fn] = rev | |
1306 | |
1307 for fn, state in sorted(fstate.items()): | |
1308 if fn in skip: | |
1309 continue | |
1310 if fn not in copies.get(prev[fn], {}): | |
1311 found = display(fn, rev, {}, state) or found | |
1312 return (not found and 1) or 0 | |
1313 | 1323 |
1314 def heads(ui, repo, *branchrevs, **opts): | 1324 def heads(ui, repo, *branchrevs, **opts): |
1315 """show current repository heads or show branch heads | 1325 """show current repository heads or show branch heads |
1316 | 1326 |
1317 With no arguments, show all repository head changesets. | 1327 With no arguments, show all repository head changesets. |