Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 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 |
comparison
equal
deleted
inserted
replaced
534:ab0d1bfeee7c | 535:fba26990604a |
---|---|
270 | 270 |
271 def clone(ui, source, dest = None, **opts): | 271 def clone(ui, source, dest = None, **opts): |
272 """make a copy of an existing repository""" | 272 """make a copy of an existing repository""" |
273 source = ui.expandpath(source) | 273 source = ui.expandpath(source) |
274 | 274 |
275 success = False | |
276 | |
277 if dest is None: | 275 if dest is None: |
278 dest = os.path.basename(os.path.normpath(source)) | 276 dest = os.path.basename(os.path.normpath(source)) |
279 | 277 |
280 if os.path.exists(dest): | 278 if os.path.exists(dest): |
281 ui.warn("abort: destination '%s' already exists\n" % dest) | 279 ui.warn("abort: destination '%s' already exists\n" % dest) |
282 return 1 | 280 return 1 |
283 | 281 |
284 os.mkdir(dest) | 282 class dircleanup: |
285 | 283 def __init__(self, dir): |
286 try: | 284 self.dir = dir |
287 link = 0 | 285 os.mkdir(dir) |
288 if not source.startswith("http://"): | 286 def close(self): |
289 d1 = os.stat(dest).st_dev | 287 self.dir = None |
290 d2 = os.stat(source).st_dev | 288 def __del__(self): |
291 if d1 == d2: link = 1 | 289 if self.dir: |
292 | 290 import shutil |
293 if link: | 291 shutil.rmtree(self.dir, True) |
294 ui.note("copying by hardlink\n") | 292 |
295 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) | 293 d = dircleanup(dest) |
296 try: | 294 |
297 os.remove(os.path.join(dest, ".hg", "dirstate")) | 295 link = 0 |
298 except: pass | 296 if not source.startswith("http://"): |
299 | 297 d1 = os.stat(dest).st_dev |
300 repo = hg.repository(ui, dest) | 298 d2 = os.stat(source).st_dev |
301 | 299 if d1 == d2: link = 1 |
302 else: | 300 |
303 repo = hg.repository(ui, dest, create=1) | 301 if link: |
304 other = hg.repository(ui, source) | 302 ui.note("copying by hardlink\n") |
305 fetch = repo.findincoming(other) | 303 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) |
306 if fetch: | 304 try: |
307 cg = other.changegroup(fetch) | 305 os.remove(os.path.join(dest, ".hg", "dirstate")) |
308 repo.addchangegroup(cg) | 306 except: pass |
309 | 307 |
310 f = repo.opener("hgrc", "w") | 308 repo = hg.repository(ui, dest) |
311 f.write("[paths]\n") | 309 |
312 f.write("default = %s\n" % source) | 310 else: |
313 | 311 repo = hg.repository(ui, dest, create=1) |
314 if not opts['noupdate']: | 312 other = hg.repository(ui, source) |
315 update(ui, repo) | 313 fetch = repo.findincoming(other) |
316 | 314 if fetch: |
317 success = True | 315 cg = other.changegroup(fetch) |
318 | 316 repo.addchangegroup(cg) |
319 finally: | 317 |
320 if not success: | 318 f = repo.opener("hgrc", "w") |
321 import shutil | 319 f.write("[paths]\n") |
322 shutil.rmtree(dest, True) | 320 f.write("default = %s\n" % source) |
321 | |
322 if not opts['noupdate']: | |
323 update(ui, repo) | |
324 | |
325 d.close() | |
323 | 326 |
324 def commit(ui, repo, *files, **opts): | 327 def commit(ui, repo, *files, **opts): |
325 """commit the specified files or all outstanding changes""" | 328 """commit the specified files or all outstanding changes""" |
326 text = opts['text'] | 329 text = opts['text'] |
327 if not text and opts['logfile']: | 330 if not text and opts['logfile']: |