Mercurial > hg
changeset 535:fba26990604a
Deal with failed clone/transaction interaction
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Deal with failed clone/transaction interaction
> What is happening is that something in the transaction machinery is
> causing the directory to be completely recreated.
The transaction gets rolled back by its destructor. This is critical
so it happens whenever an exception occurs that unwinds the stack.
Unfortunately, what's happening with clone is we're trying to delete
the directory during exception propagation. And a reference to the
transaction is held in the exception backtrace stack frames so it
still exists until the exception is completely resolved.
So there's no way to do the directory delete inside the exception
handling cleanly.
But we can handle it similarly to the transaction itself: use an
object with a destructor.
manifest hash: fc38550a20d64d08333f256bbedc312493c1390b
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCxDT2ywK+sNU5EO8RAjikAJ0Tej56rAutxQDfYzVbFGtT1sEC5ACgmVds
/fwdQyHn+FwshugqXLemUaM=
=3f78
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Thu, 30 Jun 2005 10:07:50 -0800 |
parents | ab0d1bfeee7c |
children | c15b4bc0a11c eda4c32c167a |
files | mercurial/commands.py |
diffstat | 1 files changed, 38 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/commands.py Thu Jun 30 09:22:59 2005 -0800 +++ b/mercurial/commands.py Thu Jun 30 10:07:50 2005 -0800 @@ -272,8 +272,6 @@ """make a copy of an existing repository""" source = ui.expandpath(source) - success = False - if dest is None: dest = os.path.basename(os.path.normpath(source)) @@ -281,45 +279,50 @@ ui.warn("abort: destination '%s' already exists\n" % dest) return 1 - os.mkdir(dest) - - try: - link = 0 - if not source.startswith("http://"): - d1 = os.stat(dest).st_dev - d2 = os.stat(source).st_dev - if d1 == d2: link = 1 + class dircleanup: + def __init__(self, dir): + self.dir = dir + os.mkdir(dir) + def close(self): + self.dir = None + def __del__(self): + if self.dir: + import shutil + shutil.rmtree(self.dir, True) - if link: - ui.note("copying by hardlink\n") - util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) - try: - os.remove(os.path.join(dest, ".hg", "dirstate")) - except: pass + d = dircleanup(dest) - repo = hg.repository(ui, dest) + link = 0 + if not source.startswith("http://"): + d1 = os.stat(dest).st_dev + d2 = os.stat(source).st_dev + if d1 == d2: link = 1 - else: - repo = hg.repository(ui, dest, create=1) - other = hg.repository(ui, source) - fetch = repo.findincoming(other) - if fetch: - cg = other.changegroup(fetch) - repo.addchangegroup(cg) + if link: + ui.note("copying by hardlink\n") + util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) + try: + os.remove(os.path.join(dest, ".hg", "dirstate")) + except: pass + + repo = hg.repository(ui, dest) - f = repo.opener("hgrc", "w") - f.write("[paths]\n") - f.write("default = %s\n" % source) - - if not opts['noupdate']: - update(ui, repo) + else: + repo = hg.repository(ui, dest, create=1) + other = hg.repository(ui, source) + fetch = repo.findincoming(other) + if fetch: + cg = other.changegroup(fetch) + repo.addchangegroup(cg) - success = True + f = repo.opener("hgrc", "w") + f.write("[paths]\n") + f.write("default = %s\n" % source) - finally: - if not success: - import shutil - shutil.rmtree(dest, True) + if not opts['noupdate']: + update(ui, repo) + + d.close() def commit(ui, repo, *files, **opts): """commit the specified files or all outstanding changes"""