##// 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 for r in revs:
2388 for r in revs:
2389 ctx = repo[r]
2389 ctx = repo[r]
2390 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
2390 fctxs.extend(ctx[f].introfilectx() for f in ctx.walk(match))
2391 return dagop.filerevancestors(fctxs, followfirst=followfirst)
2391
2392
2393 def _makefollowlogfilematcher(repo, files, followfirst):
2394 # When displaying a revision with --patch --follow FILE, we have
2392 # When displaying a revision with --patch --follow FILE, we have
2395 # to know which file of the revision must be diffed. With
2393 # to know which file of the revision must be diffed. With
2396 # --follow, we want the names of the ancestors of FILE in the
2394 # --follow, we want the names of the ancestors of FILE in the
2397 # revision, stored in "fcache". "fcache" is populated by
2395 # revision, stored in "fcache". "fcache" is populated as a side effect
2398 # reproducing the graph traversal already done by --follow revset
2396 # of the graph traversal.
2399 # and relating revs to file names (which is not "correct" but
2400 # good enough).
2401 fcache = {}
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 def filematcher(rev):
2398 def filematcher(rev):
2413 if not fcacheready[0]:
2414 # Lazy initialization
2415 fcacheready[0] = True
2416 populate()
2417 return scmutil.matchfiles(repo, fcache.get(rev, []))
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 def _makenofollowlogfilematcher(repo, pats, opts):
2407 def _makenofollowlogfilematcher(repo, pats, opts):
2422 '''hook for extensions to override the filematcher for non-follow cases'''
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 def _makelogrevset(repo, match, pats, slowpath, opts):
2423 def _makelogrevset(repo, match, pats, slowpath, opts):
2438 """Return (expr, filematcher) where expr is a revset string built
2424 """Return a revset string built from log options and file patterns"""
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 """
2444 opts = dict(opts)
2425 opts = dict(opts)
2445 # follow or not follow?
2426 # follow or not follow?
2446 follow = opts.get('follow') or opts.get('follow_first')
2427 follow = opts.get('follow') or opts.get('follow_first')
@@ -2470,21 +2451,6 b' def _makelogrevset(repo, match, pats, sl'
2470 elif not follow:
2451 elif not follow:
2471 opts['_patslog'] = list(pats)
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 expr = []
2454 expr = []
2489 for op, val in sorted(opts.iteritems()):
2455 for op, val in sorted(opts.iteritems()):
2490 if not val:
2456 if not val:
@@ -2505,7 +2471,7 b' def _makelogrevset(repo, match, pats, sl'
2505 expr = '(' + ' and '.join(expr) + ')'
2471 expr = '(' + ' and '.join(expr) + ')'
2506 else:
2472 else:
2507 expr = None
2473 expr = None
2508 return expr, filematcher
2474 return expr
2509
2475
2510 def _logrevs(repo, opts):
2476 def _logrevs(repo, opts):
2511 """Return the initial set of revisions to be filtered or followed"""
2477 """Return the initial set of revisions to be filtered or followed"""
@@ -2524,9 +2490,8 b' def _logrevs(repo, opts):'
2524 def getlogrevs(repo, pats, opts):
2490 def getlogrevs(repo, pats, opts):
2525 """Return (revs, filematcher) where revs is a smartset
2491 """Return (revs, filematcher) where revs is a smartset
2526
2492
2527 If --stat or --patch is not passed, filematcher is None. Otherwise it
2493 filematcher is a callable taking a revision number and returning a match
2528 is a callable taking a revision number and returning a match objects
2494 objects filtering the files to be detailed when displaying the revision.
2529 filtering the files to be detailed when displaying the revision.
2530 """
2495 """
2531 follow = opts.get('follow') or opts.get('follow_first')
2496 follow = opts.get('follow') or opts.get('follow_first')
2532 followfirst = opts.get('follow_first')
2497 followfirst = opts.get('follow_first')
@@ -2535,13 +2500,20 b' def getlogrevs(repo, pats, opts):'
2535 if not revs:
2500 if not revs:
2536 return smartset.baseset(), None
2501 return smartset.baseset(), None
2537 match, pats, slowpath = _makelogmatcher(repo, revs, pats, opts)
2502 match, pats, slowpath = _makelogmatcher(repo, revs, pats, opts)
2503 filematcher = None
2538 if follow:
2504 if follow:
2539 if slowpath or match.always():
2505 if slowpath or match.always():
2540 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
2506 revs = dagop.revancestors(repo, revs, followfirst=followfirst)
2541 else:
2507 else:
2542 revs = _fileancestors(repo, revs, match, followfirst)
2508 revs, filematcher = _fileancestors(repo, revs, match, followfirst)
2543 revs.reverse()
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 if opts.get('graph') and opts.get('rev'):
2517 if opts.get('graph') and opts.get('rev'):
2546 # User-specified revs might be unsorted, but don't sort before
2518 # User-specified revs might be unsorted, but don't sort before
2547 # _makelogrevset because it might depend on the order of revs
2519 # _makelogrevset because it might depend on the order of revs
@@ -96,7 +96,7 b' o (0) root'
96 > if not revs:
96 > if not revs:
97 > return None
97 > return None
98 > match, pats, slowpath = cmdutil._makelogmatcher(repo, revs, pats, opts)
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 > def uisetup(ui):
101 > def uisetup(ui):
102 > def printrevset(orig, repo, pats, opts):
102 > def printrevset(orig, repo, pats, opts):
General Comments 0
You need to be logged in to leave comments. Login now