mercurial/cmdutil.py
changeset 35683 ea3320015d54
parent 35682 8273c1a47282
child 35684 1c929b4942a3
equal deleted inserted replaced
35682:8273c1a47282 35683:ea3320015d54
  2357 _opt2logrevset = {
  2357 _opt2logrevset = {
  2358     'no_merges':        ('not merge()', None),
  2358     'no_merges':        ('not merge()', None),
  2359     'only_merges':      ('merge()', None),
  2359     'only_merges':      ('merge()', None),
  2360     '_ancestors':       ('ancestors(%r)', None),
  2360     '_ancestors':       ('ancestors(%r)', None),
  2361     '_fancestors':      ('_firstancestors(%r)', None),
  2361     '_fancestors':      ('_firstancestors(%r)', None),
  2362     '_descendants':     ('descendants(%r)', None),
       
  2363     '_fdescendants':    ('_firstdescendants(%r)', None),
       
  2364     '_matchfiles':      (None, '_matchfiles(%ps)'),
  2362     '_matchfiles':      (None, '_matchfiles(%ps)'),
  2365     'date':             ('date(%s)', None),
  2363     'date':             ('date(%s)', None),
  2366     'branch':           ('branch(%s)', '%lr'),
  2364     'branch':           ('branch(%s)', '%lr'),
  2367     '_patslog':         ('filelog(%s)', '%lr'),
  2365     '_patslog':         ('filelog(%s)', '%lr'),
  2368     '_patsfollow':      ('follow(%s)', '%lr'),
  2366     '_patsfollow':      ('follow(%s)', '%lr'),
  2370     'keyword':          ('keyword(%s)', '%lr'),
  2368     'keyword':          ('keyword(%s)', '%lr'),
  2371     'prune':            ('ancestors(%s)', 'not %lr'),
  2369     'prune':            ('ancestors(%s)', 'not %lr'),
  2372     'user':             ('user(%s)', '%lr'),
  2370     'user':             ('user(%s)', '%lr'),
  2373 }
  2371 }
  2374 
  2372 
  2375 def _makelogrevset(repo, pats, opts, revs):
  2373 def _makelogrevset(repo, pats, opts):
  2376     """Return (expr, filematcher) where expr is a revset string built
  2374     """Return (expr, filematcher) where expr is a revset string built
  2377     from log options and file patterns or None. If --stat or --patch
  2375     from log options and file patterns or None. If --stat or --patch
  2378     are not passed filematcher is None. Otherwise it is a callable
  2376     are not passed filematcher is None. Otherwise it is a callable
  2379     taking a revision number and returning a match objects filtering
  2377     taking a revision number and returning a match objects filtering
  2380     the files to be detailed when displaying the revision.
  2378     the files to be detailed when displaying the revision.
  2384     follow = opts.get('follow') or opts.get('follow_first')
  2382     follow = opts.get('follow') or opts.get('follow_first')
  2385     if opts.get('follow_first'):
  2383     if opts.get('follow_first'):
  2386         followfirst = 1
  2384         followfirst = 1
  2387     else:
  2385     else:
  2388         followfirst = 0
  2386         followfirst = 0
  2389     # --follow with FILE behavior depends on revs...
       
  2390     it = iter(revs)
       
  2391     startrev = next(it)
       
  2392     followdescendants = startrev < next(it, startrev)
       
  2393 
  2387 
  2394     # branch and only_branch are really aliases and must be handled at
  2388     # branch and only_branch are really aliases and must be handled at
  2395     # the same time
  2389     # the same time
  2396     opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
  2390     opts['branch'] = opts.get('branch', []) + opts.get('only_branch', [])
  2397     opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
  2391     opts['branch'] = [repo.lookupbranch(b) for b in opts['branch']]
  2432                     break
  2426                     break
  2433             else:
  2427             else:
  2434                 slowpath = False
  2428                 slowpath = False
  2435 
  2429 
  2436     fpats = ('_patsfollow', '_patsfollowfirst')
  2430     fpats = ('_patsfollow', '_patsfollowfirst')
  2437     fnopats = (('_ancestors', '_fancestors'),
  2431     fnopats = ('_ancestors', '_fancestors')
  2438                ('_descendants', '_fdescendants'))
  2432 
  2439     if slowpath:
  2433     if slowpath:
  2440         # See walkchangerevs() slow path.
  2434         # See walkchangerevs() slow path.
  2441         #
  2435         #
  2442         # pats/include/exclude cannot be represented as separate
  2436         # pats/include/exclude cannot be represented as separate
  2443         # revset expressions as their filtering logic applies at file
  2437         # revset expressions as their filtering logic applies at file
  2452             matchargs.append('i:' + p)
  2446             matchargs.append('i:' + p)
  2453         for p in opts.get('exclude', []):
  2447         for p in opts.get('exclude', []):
  2454             matchargs.append('x:' + p)
  2448             matchargs.append('x:' + p)
  2455         opts['_matchfiles'] = matchargs
  2449         opts['_matchfiles'] = matchargs
  2456         if follow:
  2450         if follow:
  2457             opts[fnopats[0][followfirst]] = '.'
  2451             opts[fnopats[followfirst]] = '.'
  2458     else:
  2452     else:
  2459         if follow:
  2453         if follow:
  2460             if pats:
  2454             if pats:
  2461                 # follow() revset interprets its file argument as a
  2455                 # follow() revset interprets its file argument as a
  2462                 # manifest entry, so use match.files(), not pats.
  2456                 # manifest entry, so use match.files(), not pats.
  2463                 opts[fpats[followfirst]] = list(match.files())
  2457                 opts[fpats[followfirst]] = list(match.files())
  2464             else:
  2458             else:
  2465                 op = fnopats[followdescendants][followfirst]
  2459                 op = fnopats[followfirst]
  2466                 opts[op] = 'rev(%d)' % startrev
  2460                 opts[op] = '.'
  2467         else:
  2461         else:
  2468             opts['_patslog'] = list(pats)
  2462             opts['_patslog'] = list(pats)
  2469 
  2463 
  2470     filematcher = None
  2464     filematcher = None
  2471     if opts.get('patch') or opts.get('stat'):
  2465     if opts.get('patch') or opts.get('stat'):
  2503     else:
  2497     else:
  2504         expr = None
  2498         expr = None
  2505     return expr, filematcher
  2499     return expr, filematcher
  2506 
  2500 
  2507 def _logrevs(repo, opts):
  2501 def _logrevs(repo, opts):
  2508     # Default --rev value depends on --follow but --follow behavior
       
  2509     # depends on revisions resolved from --rev...
       
  2510     follow = opts.get('follow') or opts.get('follow_first')
  2502     follow = opts.get('follow') or opts.get('follow_first')
  2511     if opts.get('rev'):
  2503     if opts.get('rev'):
  2512         revs = scmutil.revrange(repo, opts['rev'])
  2504         revs = scmutil.revrange(repo, opts['rev'])
  2513     elif follow and repo.dirstate.p1() == nullid:
  2505     elif follow and repo.dirstate.p1() == nullid:
  2514         revs = smartset.baseset()
  2506         revs = smartset.baseset()
  2528     """
  2520     """
  2529     limit = loglimit(opts)
  2521     limit = loglimit(opts)
  2530     revs = _logrevs(repo, opts)
  2522     revs = _logrevs(repo, opts)
  2531     if not revs:
  2523     if not revs:
  2532         return smartset.baseset(), None
  2524         return smartset.baseset(), None
  2533     expr, filematcher = _makelogrevset(repo, pats, opts, revs)
  2525     expr, filematcher = _makelogrevset(repo, pats, opts)
  2534     if opts.get('graph') and opts.get('rev'):
  2526     if opts.get('graph') and opts.get('rev'):
  2535         # User-specified revs might be unsorted, but don't sort before
  2527         # User-specified revs might be unsorted, but don't sort before
  2536         # _makelogrevset because it might depend on the order of revs
  2528         # _makelogrevset because it might depend on the order of revs
  2537         if not (revs.isdescending() or revs.istopo()):
  2529         if not (revs.isdescending() or revs.istopo()):
  2538             revs.sort(reverse=True)
  2530             revs.sort(reverse=True)