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']: