Delete bundle file of hg incoming in case of errors, preserve existing files.
authorThomas Arendsen Hein <thomas@intevation.de>
Sat, 18 Mar 2006 14:36:45 +0100
changeset 1974 0d54675cd566
parent 1973 9103902a5a8d
child 1975 6e1a8ea5d717
Delete bundle file of hg incoming in case of errors, preserve existing files. Let write_bundle always create the bundle file, check if target doesn't exist and delete it in case of errors. This way incoming only has to delete the bundle file if it was meant to be a temporary file.
mercurial/commands.py
--- a/mercurial/commands.py	Sat Mar 18 11:24:19 2006 +0100
+++ b/mercurial/commands.py	Sat Mar 18 14:36:45 2006 +0100
@@ -274,20 +274,32 @@
                               pathname),
                 mode)
 
-def write_bundle(cg, filename, compress=True, fh=None):
-    """Write a bundle file, optionally without bz2 compression.
-
-    A file handle (fh) may be passed and is guaranteed to be closed.
+def write_bundle(cg, filename=None, compress=True):
+    """Write a bundle file and return its filename.
+
+    Existing files will not be overwritten.
+    If no filename is specified, a temporary file is created.
+    bz2 compression can be turned off.
+    The bundle file will be deleted in case of errors.
     """
-    if fh is None:
-        fh = open(filename, "wb")
-
     class nocompress(object):
         def compress(self, x):
             return x
         def flush(self):
             return ""
+
+    fh = None
+    cleanup = None
     try:
+        if filename:
+            if os.path.exists(filename):
+                raise util.Abort(_("file '%s' already exists"), filename)
+            fh = open(filename, "wb")
+        else:
+            fd, filename = tempfile.mkstemp(suffix=".hg", prefix="hg-bundle-")
+            fh = os.fdopen(fd, "wb")
+        cleanup = filename
+
         if compress:
             fh.write("HG10")
             z = bz2.BZ2Compressor(9)
@@ -300,11 +312,13 @@
                 break
             fh.write(z.compress(chunk))
         fh.write(z.flush())
-    except:
-        fh.close()
-        os.unlink(filename)
-        raise
-    fh.close()
+        cleanup = None
+        return filename
+    finally:
+        if fh is not None:
+            fh.close()
+        if cleanup is not None:
+            os.unlink(cleanup)
 
 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
            changes=None, text=False, opts={}):
@@ -1782,41 +1796,37 @@
         return
 
     cleanup = None
-    fname = opts["bundle"]
-    if fname:
-        # create a bundle (uncompressed if other repo is not local)
-        f = open(fname, "wb")
-    elif not other.local():
-        # create an uncompressed temporary bundle
-        fd, fname = tempfile.mkstemp(suffix=".hg", prefix="hg-incoming-")
-        f = os.fdopen(fd, "wb")
-        cleanup = fname
-
-    if fname:
-        cg = other.changegroup(incoming, "incoming")
-        write_bundle(cg, fname, compress=other.local(), fh=f)
-        # write_bundle closed f for us.
-        if not other.local():
-            # use the created uncompressed bundlerepo
-            other = bundlerepo.bundlerepository(ui, repo.root, fname)
-
-    o = other.changelog.nodesbetween(incoming)[0]
-    if opts['newest_first']:
-        o.reverse()
-    displayer = show_changeset(ui, other, opts)
-    for n in o:
-        parents = [p for p in other.changelog.parents(n) if p != nullid]
-        if opts['no_merges'] and len(parents) == 2:
-            continue
-        displayer.show(changenode=n)
-        if opts['patch']:
-            prev = (parents and parents[0]) or nullid
-            dodiff(ui, ui, other, prev, n)
-            ui.write("\n")
-
-    if cleanup:
-        other.close()                   # explicit close for unlink
-        os.unlink(cleanup)
+    try:
+        fname = opts["bundle"]
+        if fname or not other.local():
+            # create a bundle (uncompressed if other repo is not local)
+            cg = other.changegroup(incoming, "incoming")
+            fname = cleanup = write_bundle(cg, fname, compress=other.local())
+            # keep written bundle?
+            if opts["bundle"]:
+                cleanup = None
+            if not other.local():
+                # use the created uncompressed bundlerepo
+                other = bundlerepo.bundlerepository(ui, repo.root, fname)
+
+        o = other.changelog.nodesbetween(incoming)[0]
+        if opts['newest_first']:
+            o.reverse()
+        displayer = show_changeset(ui, other, opts)
+        for n in o:
+            parents = [p for p in other.changelog.parents(n) if p != nullid]
+            if opts['no_merges'] and len(parents) == 2:
+                continue
+            displayer.show(changenode=n)
+            if opts['patch']:
+                prev = (parents and parents[0]) or nullid
+                dodiff(ui, ui, other, prev, n)
+                ui.write("\n")
+    finally:
+        if hasattr(other, 'close'):
+            other.close()
+        if cleanup:
+            os.unlink(cleanup)
 
 def init(ui, dest="."):
     """create a new repository in the given directory