Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/commands.py @ 4959:97b734fb9c6f
Use try/finally pattern to cleanup locks and transactions
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 21 Jul 2007 16:02:10 -0500 |
parents | 9a2a73ea6135 |
children | 126f527b3ba3 |
comparison
equal
deleted
inserted
replaced
4958:9a2a73ea6135 | 4959:97b734fb9c6f |
---|---|
674 | 674 |
675 This command takes effect in the next commit. To undo a copy | 675 This command takes effect in the next commit. To undo a copy |
676 before that, see hg revert. | 676 before that, see hg revert. |
677 """ | 677 """ |
678 wlock = repo.wlock(False) | 678 wlock = repo.wlock(False) |
679 errs, copied = docopy(ui, repo, pats, opts, wlock) | 679 try: |
680 errs, copied = docopy(ui, repo, pats, opts, wlock) | |
681 finally: | |
682 del wlock | |
680 return errs | 683 return errs |
681 | 684 |
682 def debugancestor(ui, index, rev1, rev2): | 685 def debugancestor(ui, index, rev1, rev2): |
683 """find the ancestor revision of two revisions in a given index""" | 686 """find the ancestor revision of two revisions in a given index""" |
684 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index) | 687 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index) |
711 if rev == "": | 714 if rev == "": |
712 rev = repo.changelog.tip() | 715 rev = repo.changelog.tip() |
713 ctx = repo.changectx(rev) | 716 ctx = repo.changectx(rev) |
714 files = ctx.manifest() | 717 files = ctx.manifest() |
715 wlock = repo.wlock() | 718 wlock = repo.wlock() |
716 repo.dirstate.rebuild(rev, files) | 719 try: |
720 repo.dirstate.rebuild(rev, files) | |
721 finally: | |
722 del wlock | |
717 | 723 |
718 def debugcheckstate(ui, repo): | 724 def debugcheckstate(ui, repo): |
719 """validate the correctness of the current dirstate""" | 725 """validate the correctness of the current dirstate""" |
720 parent1, parent2 = repo.dirstate.parents() | 726 parent1, parent2 = repo.dirstate.parents() |
721 m1 = repo.changectx(parent1).manifest() | 727 m1 = repo.changectx(parent1).manifest() |
780 | 786 |
781 wlock = repo.wlock() | 787 wlock = repo.wlock() |
782 try: | 788 try: |
783 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2)) | 789 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2)) |
784 finally: | 790 finally: |
785 wlock.release() | 791 del wlock |
786 | 792 |
787 def debugstate(ui, repo): | 793 def debugstate(ui, repo): |
788 """show the contents of the current dirstate""" | 794 """show the contents of the current dirstate""" |
789 dc = repo.dirstate._map | 795 dc = repo.dirstate._map |
790 k = dc.keys() | 796 k = dc.keys() |
1579 if opts.get('exact') or not opts['force']: | 1585 if opts.get('exact') or not opts['force']: |
1580 cmdutil.bail_if_changed(repo) | 1586 cmdutil.bail_if_changed(repo) |
1581 | 1587 |
1582 d = opts["base"] | 1588 d = opts["base"] |
1583 strip = opts["strip"] | 1589 strip = opts["strip"] |
1584 | 1590 wlock = lock = None |
1585 wlock = repo.wlock() | 1591 try: |
1586 lock = repo.lock() | 1592 wlock = repo.wlock() |
1587 | 1593 lock = repo.lock() |
1588 for p in patches: | 1594 for p in patches: |
1589 pf = os.path.join(d, p) | 1595 pf = os.path.join(d, p) |
1590 | 1596 |
1591 if pf == '-': | 1597 if pf == '-': |
1592 ui.status(_("applying patch from stdin\n")) | 1598 ui.status(_("applying patch from stdin\n")) |
1593 tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, sys.stdin) | 1599 data = patch.extract(ui, sys.stdin) |
1594 else: | |
1595 ui.status(_("applying %s\n") % p) | |
1596 tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, file(pf, 'rb')) | |
1597 | |
1598 if tmpname is None: | |
1599 raise util.Abort(_('no diffs found')) | |
1600 | |
1601 try: | |
1602 cmdline_message = cmdutil.logmessage(opts) | |
1603 if cmdline_message: | |
1604 # pickup the cmdline msg | |
1605 message = cmdline_message | |
1606 elif message: | |
1607 # pickup the patch msg | |
1608 message = message.strip() | |
1609 else: | 1600 else: |
1610 # launch the editor | 1601 ui.status(_("applying %s\n") % p) |
1611 message = None | 1602 data = patch.extract(ui, file(pf, 'rb')) |
1612 ui.debug(_('message:\n%s\n') % message) | 1603 |
1613 | 1604 tmpname, message, user, date, branch, nodeid, p1, p2 = data |
1614 wp = repo.workingctx().parents() | 1605 |
1615 if opts.get('exact'): | 1606 if tmpname is None: |
1616 if not nodeid or not p1: | 1607 raise util.Abort(_('no diffs found')) |
1617 raise util.Abort(_('not a mercurial patch')) | 1608 |
1618 p1 = repo.lookup(p1) | 1609 try: |
1619 p2 = repo.lookup(p2 or hex(nullid)) | 1610 cmdline_message = cmdutil.logmessage(opts) |
1620 | 1611 if cmdline_message: |
1621 if p1 != wp[0].node(): | 1612 # pickup the cmdline msg |
1622 hg.clean(repo, p1, wlock=wlock) | 1613 message = cmdline_message |
1623 repo.dirstate.setparents(p1, p2) | 1614 elif message: |
1624 elif p2: | 1615 # pickup the patch msg |
1616 message = message.strip() | |
1617 else: | |
1618 # launch the editor | |
1619 message = None | |
1620 ui.debug(_('message:\n%s\n') % message) | |
1621 | |
1622 wp = repo.workingctx().parents() | |
1623 if opts.get('exact'): | |
1624 if not nodeid or not p1: | |
1625 raise util.Abort(_('not a mercurial patch')) | |
1626 p1 = repo.lookup(p1) | |
1627 p2 = repo.lookup(p2 or hex(nullid)) | |
1628 | |
1629 if p1 != wp[0].node(): | |
1630 hg.clean(repo, p1, wlock=wlock) | |
1631 repo.dirstate.setparents(p1, p2) | |
1632 elif p2: | |
1633 try: | |
1634 p1 = repo.lookup(p1) | |
1635 p2 = repo.lookup(p2) | |
1636 if p1 == wp[0].node(): | |
1637 repo.dirstate.setparents(p1, p2) | |
1638 except hg.RepoError: | |
1639 pass | |
1640 if opts.get('exact') or opts.get('import_branch'): | |
1641 repo.dirstate.setbranch(branch or 'default') | |
1642 | |
1643 files = {} | |
1625 try: | 1644 try: |
1626 p1 = repo.lookup(p1) | 1645 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, |
1627 p2 = repo.lookup(p2) | 1646 files=files) |
1628 if p1 == wp[0].node(): | 1647 finally: |
1629 repo.dirstate.setparents(p1, p2) | 1648 files = patch.updatedir(ui, repo, files, wlock=wlock) |
1630 except hg.RepoError: | 1649 n = repo.commit(files, message, user, date, wlock=wlock, |
1631 pass | 1650 lock=lock) |
1632 if opts.get('exact') or opts.get('import_branch'): | 1651 if opts.get('exact'): |
1633 repo.dirstate.setbranch(branch or 'default') | 1652 if hex(n) != nodeid: |
1634 | 1653 repo.rollback(wlock=wlock, lock=lock) |
1635 files = {} | 1654 raise util.Abort(_('patch is damaged' + |
1636 try: | 1655 ' or loses information')) |
1637 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root, | |
1638 files=files) | |
1639 finally: | 1656 finally: |
1640 files = patch.updatedir(ui, repo, files, wlock=wlock) | 1657 os.unlink(tmpname) |
1641 n = repo.commit(files, message, user, date, wlock=wlock, lock=lock) | 1658 finally: |
1642 if opts.get('exact'): | 1659 del wlock, lock |
1643 if hex(n) != nodeid: | |
1644 repo.rollback(wlock=wlock, lock=lock) | |
1645 raise util.Abort(_('patch is damaged or loses information')) | |
1646 finally: | |
1647 os.unlink(tmpname) | |
1648 | 1660 |
1649 def incoming(ui, repo, source="default", **opts): | 1661 def incoming(ui, repo, source="default", **opts): |
1650 """show new changesets found in source | 1662 """show new changesets found in source |
1651 | 1663 |
1652 Show new changesets found in the specified path/URL or the default | 1664 Show new changesets found in the specified path/URL or the default |
2246 | 2258 |
2247 This command takes effect in the next commit. To undo a rename | 2259 This command takes effect in the next commit. To undo a rename |
2248 before that, see hg revert. | 2260 before that, see hg revert. |
2249 """ | 2261 """ |
2250 wlock = repo.wlock(False) | 2262 wlock = repo.wlock(False) |
2251 errs, copied = docopy(ui, repo, pats, opts, wlock) | 2263 try: |
2252 names = [] | 2264 errs, copied = docopy(ui, repo, pats, opts, wlock) |
2253 for abs, rel, exact in copied: | 2265 names = [] |
2254 if ui.verbose or not exact: | 2266 for abs, rel, exact in copied: |
2255 ui.status(_('removing %s\n') % rel) | 2267 if ui.verbose or not exact: |
2256 names.append(abs) | 2268 ui.status(_('removing %s\n') % rel) |
2257 if not opts.get('dry_run'): | 2269 names.append(abs) |
2258 repo.remove(names, True, wlock=wlock) | 2270 if not opts.get('dry_run'): |
2259 return errs | 2271 repo.remove(names, True, wlock=wlock) |
2272 return errs | |
2273 finally: | |
2274 del wlock | |
2260 | 2275 |
2261 def revert(ui, repo, *pats, **opts): | 2276 def revert(ui, repo, *pats, **opts): |
2262 """revert files or dirs to their states as of some revision | 2277 """revert files or dirs to their states as of some revision |
2263 | 2278 |
2264 With no revision specified, revert the named files or directories | 2279 With no revision specified, revert the named files or directories |
2308 if node == parent: | 2323 if node == parent: |
2309 pmf = mf | 2324 pmf = mf |
2310 else: | 2325 else: |
2311 pmf = None | 2326 pmf = None |
2312 | 2327 |
2313 wlock = repo.wlock() | |
2314 | |
2315 # need all matching names in dirstate and manifest of target rev, | 2328 # need all matching names in dirstate and manifest of target rev, |
2316 # so have to walk both. do not print errors if files exist in one | 2329 # so have to walk both. do not print errors if files exist in one |
2317 # but not other. | 2330 # but not other. |
2318 | 2331 |
2319 names = {} | 2332 names = {} |
2320 target_only = {} | 2333 target_only = {} |
2321 | 2334 |
2322 # walk dirstate. | 2335 wlock = repo.wlock() |
2323 | 2336 try: |
2324 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, | 2337 # walk dirstate. |
2325 badmatch=mf.has_key): | 2338 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, |
2326 names[abs] = (rel, exact) | 2339 badmatch=mf.has_key): |
2327 if src == 'b': | 2340 names[abs] = (rel, exact) |
2341 if src == 'b': | |
2342 target_only[abs] = True | |
2343 | |
2344 # walk target manifest. | |
2345 | |
2346 def badmatch(path): | |
2347 if path in names: | |
2348 return True | |
2349 path_ = path + '/' | |
2350 for f in names: | |
2351 if f.startswith(path_): | |
2352 return True | |
2353 return False | |
2354 | |
2355 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node, | |
2356 badmatch=badmatch): | |
2357 if abs in names or src == 'b': | |
2358 continue | |
2359 names[abs] = (rel, exact) | |
2328 target_only[abs] = True | 2360 target_only[abs] = True |
2329 | 2361 |
2330 # walk target manifest. | 2362 changes = repo.status(match=names.has_key, wlock=wlock)[:5] |
2331 | 2363 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes) |
2332 def badmatch(path): | 2364 |
2333 if path in names: | 2365 revert = ([], _('reverting %s\n')) |
2334 return True | 2366 add = ([], _('adding %s\n')) |
2335 path_ = path + '/' | 2367 remove = ([], _('removing %s\n')) |
2336 for f in names: | 2368 forget = ([], _('forgetting %s\n')) |
2337 if f.startswith(path_): | 2369 undelete = ([], _('undeleting %s\n')) |
2338 return True | 2370 update = {} |
2339 return False | 2371 |
2340 | 2372 disptable = ( |
2341 for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node, | 2373 # dispatch table: |
2342 badmatch=badmatch): | 2374 # file state |
2343 if abs in names or src == 'b': | 2375 # action if in target manifest |
2344 continue | 2376 # action if not in target manifest |
2345 names[abs] = (rel, exact) | 2377 # make backup if in target manifest |
2346 target_only[abs] = True | 2378 # make backup if not in target manifest |
2347 | 2379 (modified, revert, remove, True, True), |
2348 changes = repo.status(match=names.has_key, wlock=wlock)[:5] | 2380 (added, revert, forget, True, False), |
2349 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes) | 2381 (removed, undelete, None, False, False), |
2350 | 2382 (deleted, revert, remove, False, False), |
2351 revert = ([], _('reverting %s\n')) | 2383 (unknown, add, None, True, False), |
2352 add = ([], _('adding %s\n')) | 2384 (target_only, add, None, False, False), |
2353 remove = ([], _('removing %s\n')) | 2385 ) |
2354 forget = ([], _('forgetting %s\n')) | 2386 |
2355 undelete = ([], _('undeleting %s\n')) | 2387 entries = names.items() |
2356 update = {} | 2388 entries.sort() |
2357 | 2389 |
2358 disptable = ( | 2390 for abs, (rel, exact) in entries: |
2359 # dispatch table: | 2391 mfentry = mf.get(abs) |
2360 # file state | 2392 target = repo.wjoin(abs) |
2361 # action if in target manifest | 2393 def handle(xlist, dobackup): |
2362 # action if not in target manifest | 2394 xlist[0].append(abs) |
2363 # make backup if in target manifest | 2395 update[abs] = 1 |
2364 # make backup if not in target manifest | 2396 if dobackup and not opts['no_backup'] and util.lexists(target): |
2365 (modified, revert, remove, True, True), | 2397 bakname = "%s.orig" % rel |
2366 (added, revert, forget, True, False), | 2398 ui.note(_('saving current version of %s as %s\n') % |
2367 (removed, undelete, None, False, False), | 2399 (rel, bakname)) |
2368 (deleted, revert, remove, False, False), | 2400 if not opts.get('dry_run'): |
2369 (unknown, add, None, True, False), | 2401 util.copyfile(target, bakname) |
2370 (target_only, add, None, False, False), | 2402 if ui.verbose or not exact: |
2371 ) | 2403 ui.status(xlist[1] % rel) |
2372 | 2404 for table, hitlist, misslist, backuphit, backupmiss in disptable: |
2373 entries = names.items() | 2405 if abs not in table: continue |
2374 entries.sort() | 2406 # file has changed in dirstate |
2375 | 2407 if mfentry: |
2376 for abs, (rel, exact) in entries: | 2408 handle(hitlist, backuphit) |
2377 mfentry = mf.get(abs) | 2409 elif misslist is not None: |
2378 target = repo.wjoin(abs) | 2410 handle(misslist, backupmiss) |
2379 def handle(xlist, dobackup): | 2411 else: |
2380 xlist[0].append(abs) | 2412 if exact: ui.warn(_('file not managed: %s\n') % rel) |
2381 update[abs] = 1 | 2413 break |
2382 if dobackup and not opts['no_backup'] and util.lexists(target): | |
2383 bakname = "%s.orig" % rel | |
2384 ui.note(_('saving current version of %s as %s\n') % | |
2385 (rel, bakname)) | |
2386 if not opts.get('dry_run'): | |
2387 util.copyfile(target, bakname) | |
2388 if ui.verbose or not exact: | |
2389 ui.status(xlist[1] % rel) | |
2390 for table, hitlist, misslist, backuphit, backupmiss in disptable: | |
2391 if abs not in table: continue | |
2392 # file has changed in dirstate | |
2393 if mfentry: | |
2394 handle(hitlist, backuphit) | |
2395 elif misslist is not None: | |
2396 handle(misslist, backupmiss) | |
2397 else: | 2414 else: |
2398 if exact: ui.warn(_('file not managed: %s\n') % rel) | 2415 # file has not changed in dirstate |
2399 break | 2416 if node == parent: |
2400 else: | 2417 if exact: ui.warn(_('no changes needed to %s\n') % rel) |
2401 # file has not changed in dirstate | 2418 continue |
2402 if node == parent: | 2419 if pmf is None: |
2403 if exact: ui.warn(_('no changes needed to %s\n') % rel) | 2420 # only need parent manifest in this unlikely case, |
2404 continue | 2421 # so do not read by default |
2405 if pmf is None: | 2422 pmf = repo.changectx(parent).manifest() |
2406 # only need parent manifest in this unlikely case, | 2423 if abs in pmf: |
2407 # so do not read by default | 2424 if mfentry: |
2408 pmf = repo.changectx(parent).manifest() | 2425 # if version of file is same in parent and target |
2409 if abs in pmf: | 2426 # manifests, do nothing |
2410 if mfentry: | 2427 if pmf[abs] != mfentry: |
2411 # if version of file is same in parent and target | 2428 handle(revert, False) |
2412 # manifests, do nothing | 2429 else: |
2413 if pmf[abs] != mfentry: | 2430 handle(remove, False) |
2414 handle(revert, False) | 2431 |
2415 else: | 2432 if not opts.get('dry_run'): |
2416 handle(remove, False) | 2433 for f in forget[0]: |
2417 | 2434 repo.dirstate.forget(f) |
2418 if not opts.get('dry_run'): | 2435 r = hg.revert(repo, node, update.has_key, wlock) |
2419 for f in forget[0]: | 2436 for f in add[0]: |
2420 repo.dirstate.forget(f) | 2437 repo.dirstate.add(f) |
2421 r = hg.revert(repo, node, update.has_key, wlock) | 2438 for f in undelete[0]: |
2422 for f in add[0]: | 2439 repo.dirstate.normal(f) |
2423 repo.dirstate.add(f) | 2440 for f in remove[0]: |
2424 for f in undelete[0]: | 2441 repo.dirstate.remove(f) |
2425 repo.dirstate.normal(f) | 2442 return r |
2426 for f in remove[0]: | 2443 finally: |
2427 repo.dirstate.remove(f) | 2444 del wlock |
2428 return r | |
2429 | 2445 |
2430 def rollback(ui, repo): | 2446 def rollback(ui, repo): |
2431 """roll back the last transaction in this repository | 2447 """roll back the last transaction in this repository |
2432 | 2448 |
2433 Roll back the last transaction in this repository, restoring the | 2449 Roll back the last transaction in this repository, restoring the |