##// END OF EJS Templates
log: build follow-log filematcher at once...
Yuya Nishihara -
r35708:3e394e05 default
parent child Browse files
Show More
@@ -2388,35 +2388,21 b' def _fileancestors(repo, revs, match, fo'
2388 2388 for r in revs:
2389 2389 ctx = repo[r]
2390 2390 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
2391 return dagop.filerevancestors(fctxs, followfirst=followfirst)
2392
2393 def _makefollowlogfilematcher(repo, files, followfirst):
2391
2394 2392 # When displaying a revision with --patch --follow FILE, we have
2395 2393 # to know which file of the revision must be diffed. With
2396 2394 # --follow, we want the names of the ancestors of FILE in the
2397 # revision, stored in "fcache". "fcache" is populated by
2398 # reproducing the graph traversal already done by --follow revset
2399 # and relating revs to file names (which is not "correct" but
2400 # good enough).
2395 # revision, stored in "fcache". "fcache" is populated as a side effect
2396 # of the graph traversal.
2401 2397 fcache = {}
2402 fcacheready = [False]
2403 pctx = repo['.']
2404
2405 def populate():
2406 for fn in files:
2407 fctx = pctx[fn]
2408 fcache.setdefault(fctx.introrev(), set()).add(fctx.path())
2409 for c in fctx.ancestors(followfirst=followfirst):
2410 fcache.setdefault(c.rev(), set()).add(c.path())
2411
2412 2398 def filematcher(rev):
2413 if not fcacheready[0]:
2414 # Lazy initialization
2415 fcacheready[0] = True
2416 populate()
2417 2399 return scmutil.matchfiles(repo, fcache.get(rev, []))
2418 2400
2419 return filematcher
2401 def revgen():
2402 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
2403 fcache[rev] = [c.path() for c in cs]
2404 yield rev
2405 return smartset.generatorset(revgen(), iterasc=False), filematcher
2420 2406
2421 2407 def _makenofollowlogfilematcher(repo, pats, opts):
2422 2408 '''hook for extensions to override the filematcher for non-follow cases'''
@@ -2435,12 +2421,7 b' def _makenofollowlogfilematcher(repo, pa'
2435 2421 }
2436 2422
2437 2423 def _makelogrevset(repo, match, pats, slowpath, opts):
2438 """Return (expr, filematcher) where expr is a revset string built
2439 from log options and file patterns or None. If --stat or --patch
2440 are not passed filematcher is None. Otherwise it is a callable
2441 taking a revision number and returning a match objects filtering
2442 the files to be detailed when displaying the revision.
2443 """
2424 """Return a revset string built from log options and file patterns"""
2444 2425 opts = dict(opts)
2445 2426 # follow or not follow?
2446 2427 follow = opts.get('follow') or opts.get('follow_first')
@@ -2470,21 +2451,6 b' def _makelogrevset(repo, match, pats, sl'
2470 2451 elif not follow:
2471 2452 opts['_patslog'] = list(pats)
2472 2453
2473 filematcher = None
2474 if opts.get('patch') or opts.get('stat'):
2475 # When following files, track renames via a special matcher.
2476 # If we're forced to take the slowpath it means we're following
2477 # at least one pattern/directory, so don't bother with rename tracking.
2478 if follow and not match.always() and not slowpath:
2479 # _makefollowlogfilematcher expects its files argument to be
2480 # relative to the repo root, so use match.files(), not pats.
2481 filematcher = _makefollowlogfilematcher(repo, match.files(),
2482 opts.get('follow_first'))
2483 else:
2484 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
2485 if filematcher is None:
2486 filematcher = lambda rev: match
2487
2488 2454 expr = []
2489 2455 for op, val in sorted(opts.iteritems()):
2490 2456 if not val:
@@ -2505,7 +2471,7 b' def _makelogrevset(repo, match, pats, sl'
2505 2471 expr = '(' + ' and '.join(expr) + ')'
2506 2472 else:
2507 2473 expr = None
2508 return expr, filematcher
2474 return expr
2509 2475
2510 2476 def _logrevs(repo, opts):
2511 2477 """Return the initial set of revisions to be filtered or followed"""
@@ -2524,9 +2490,8 b' def _logrevs(repo, opts):'
2524 2490 def getlogrevs(repo, pats, opts):
2525 2491 """Return (revs, filematcher) where revs is a smartset
2526 2492
2527 If --stat or --patch is not passed, filematcher is None. Otherwise it
2528 is a callable taking a revision number and returning a match objects
2529 filtering the files to be detailed when displaying the revision.
2493 filematcher is a callable taking a revision number and returning a match
2494 objects filtering the files to be detailed when displaying the revision.
2530 2495 """
2531 2496 follow = opts.get('follow') or opts.get('follow_first')
2532 2497 followfirst = opts.get('follow_first')
@@ -2535,13 +2500,20 b' def getlogrevs(repo, pats, opts):'
2535 2500 if not revs:
2536 2501 return smartset.baseset(), None
2537 2502 match, pats, slowpath = _makelogmatcher(repo, revs, pats, opts)
2503 filematcher = None
2538 2504 if follow:
2539 2505 if slowpath or match.always():
2540 2506 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
2541 2507 else:
2542 revs = _fileancestors(repo, revs, match, followfirst)
2508 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
2543 2509 revs.reverse()
2544 expr, filematcher = _makelogrevset(repo, match, pats, slowpath, opts)
2510 if filematcher is None:
2511 filematcher = _makenofollowlogfilematcher(repo, pats, opts)
2512 if filematcher is None:
2513 def filematcher(rev):
2514 return match
2515
2516 expr = _makelogrevset(repo, match, pats, slowpath, opts)
2545 2517 if opts.get('graph') and opts.get('rev'):
2546 2518 # User-specified revs might be unsorted, but don't sort before
2547 2519 # _makelogrevset because it might depend on the order of revs
@@ -96,7 +96,7 b' o (0) root'
96 96 > if not revs:
97 97 > return None
98 98 > match, pats, slowpath = cmdutil._makelogmatcher(repo, revs, pats, opts)
99 > return cmdutil._makelogrevset(repo, match, pats, slowpath, opts)[0]
99 > return cmdutil._makelogrevset(repo, match, pats, slowpath, opts)
100 100 >
101 101 > def uisetup(ui):
102 102 > def printrevset(orig, repo, pats, opts):
General Comments 0
You need to be logged in to leave comments. Login now