comparison mercurial/cmdutil.py @ 22573:f528bfb25b45

revert: special case 'hg revert --all' On large repos, hg revert --all can take over 13 seconds. This is mainly due to it walking the tree three times: once to find the list of files in the dirstate, once to find the list of files in the target, and once to compute the status from the dirstate to the target. This optimizes the hg revert --all case to only require the final status. This speeds it up to 1.3 seconds or so (with hgwatchman enabled). Further optimizations could be done for the -r NODE and pattern cases, but they are significantly more complex.
author Durham Goode <durham@fb.com>
date Fri, 19 Sep 2014 18:43:53 -0700
parents 8d707da26f9b
children cd1b43226b34
comparison
equal deleted inserted replaced
22572:cc3d9f776632 22573:f528bfb25b45
2478 try: 2478 try:
2479 ## filling of the `names` mapping 2479 ## filling of the `names` mapping
2480 # walk dirstate to fill `names` 2480 # walk dirstate to fill `names`
2481 2481
2482 m = scmutil.match(repo[None], pats, opts) 2482 m = scmutil.match(repo[None], pats, opts)
2483 m.bad = lambda x, y: False 2483 if not m.always() or node != parent:
2484 for abs in repo.walk(m): 2484 m.bad = lambda x, y: False
2485 names[abs] = m.rel(abs), m.exact(abs) 2485 for abs in repo.walk(m):
2486 2486 names[abs] = m.rel(abs), m.exact(abs)
2487 # walk target manifest to fill `names` 2487
2488 2488 # walk target manifest to fill `names`
2489 def badfn(path, msg): 2489
2490 if path in names: 2490 def badfn(path, msg):
2491 return 2491 if path in names:
2492 if path in ctx.substate:
2493 return
2494 path_ = path + '/'
2495 for f in names:
2496 if f.startswith(path_):
2497 return 2492 return
2498 ui.warn("%s: %s\n" % (m.rel(path), msg)) 2493 if path in ctx.substate:
2499 2494 return
2500 m = scmutil.match(ctx, pats, opts) 2495 path_ = path + '/'
2501 m.bad = badfn 2496 for f in names:
2502 for abs in ctx.walk(m): 2497 if f.startswith(path_):
2503 if abs not in names: 2498 return
2504 names[abs] = m.rel(abs), m.exact(abs) 2499 ui.warn("%s: %s\n" % (m.rel(path), msg))
2505 2500
2506 # Find status of all file in `names`. 2501 m = scmutil.match(ctx, pats, opts)
2507 m = scmutil.matchfiles(repo, names) 2502 m.bad = badfn
2508 2503 for abs in ctx.walk(m):
2509 changes = repo.status(node1=node, match=m, 2504 if abs not in names:
2510 unknown=True, ignored=True, clean=True) 2505 names[abs] = m.rel(abs), m.exact(abs)
2506
2507 # Find status of all file in `names`.
2508 m = scmutil.matchfiles(repo, names)
2509
2510 changes = repo.status(node1=node, match=m,
2511 unknown=True, ignored=True, clean=True)
2512 else:
2513 changes = repo.status(match=m)
2514 for kind in changes:
2515 for abs in kind:
2516 names[abs] = m.rel(abs), m.exact(abs)
2517
2518 m = scmutil.matchfiles(repo, names)
2519
2511 modified = set(changes[0]) 2520 modified = set(changes[0])
2512 added = set(changes[1]) 2521 added = set(changes[1])
2513 removed = set(changes[2]) 2522 removed = set(changes[2])
2514 _deleted = set(changes[3]) 2523 _deleted = set(changes[3])
2515 unknown = set(changes[4]) 2524 unknown = set(changes[4])