git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mark Levedahl <mdl123@verizon.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Git Mailing List <git@vger.kernel.org>,
	Mark Levedahl <mdl123@verizon.net>
Subject: [PATCH] builtin-bundle create - use lock_file
Date: Sun, 12 Aug 2007 10:14:09 -0400	[thread overview]
Message-ID: <11869280491451-git-send-email-mdl123@verizon.net> (raw)
In-Reply-To: <11869231822803-git-send-email-mdl123@verizon.net>

git bundle create would leave an invalid, partially written bundle if
an error occured during creation. Fix that using lock_file.

Signed-off-by: Mark Levedahl <mdl123@verizon.net>
---
 struct lock_file is now static.
 *caller* closes the lock file before commiting / rolling back.

 builtin-bundle.c |   57 +++++++++++++++++++++++++++++++++++------------------
 1 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/builtin-bundle.c b/builtin-bundle.c
index f4b4f03..e5a2859 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -186,10 +186,21 @@ static int list_heads(struct bundle_header *header, int argc, const char **argv)
 	return list_refs(&header->references, argc, argv);
 }

+/* create_bundle uses lock_file, delete if write fails */
+static inline void lwrite_or_die(int fd, const void *buf, size_t count, struct lock_file *lock)
+{
+	if (write_in_full(fd, buf, count) != count) {
+		close(fd);
+		rollback_lock_file(lock);
+		die("Unable to write bundle");
+	}
+}
+
 static int create_bundle(struct bundle_header *header, const char *path,
 		int argc, const char **argv)
 {
 	int bundle_fd = -1;
+	static struct lock_file lock;
 	const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
 	const char **argv_pack = xmalloc(5 * sizeof(const char *));
 	int i, ref_count = 0;
@@ -198,17 +209,9 @@ static int create_bundle(struct bundle_header *header, const char *path,
 	struct child_process rls;
 	FILE *rls_fout;

-	/*
-	 * NEEDSWORK: this should use something like lock-file
-	 * to create temporary that is cleaned up upon error.
-	 */
-	bundle_fd = (!strcmp(path, "-") ? 1 :
-			open(path, O_CREAT | O_EXCL | O_WRONLY, 0666));
-	if (bundle_fd < 0)
-		return error("Could not create '%s': %s", path, strerror(errno));
-
 	/* write signature */
-	write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
+	bundle_fd = hold_lock_file_for_update(&lock, path, 1);
+	lwrite_or_die(bundle_fd, bundle_signature, strlen(bundle_signature), &lock);

 	/* init revs to list objects for pack-objects later */
 	save_commit_buffer = 0;
@@ -230,7 +233,7 @@ static int create_bundle(struct bundle_header *header, const char *path,
 	while (fgets(buffer, sizeof(buffer), rls_fout)) {
 		unsigned char sha1[20];
 		if (buffer[0] == '-') {
-			write_or_die(bundle_fd, buffer, strlen(buffer));
+			lwrite_or_die(bundle_fd, buffer, strlen(buffer), &lock);
 			if (!get_sha1_hex(buffer + 1, sha1)) {
 				struct object *object = parse_object(sha1);
 				object->flags |= UNINTERESTING;
@@ -242,13 +245,19 @@ static int create_bundle(struct bundle_header *header, const char *path,
 		}
 	}
 	fclose(rls_fout);
-	if (finish_command(&rls))
+	if (finish_command(&rls)) {
+		close(bundle_fd);
+		rollback_lock_file(&lock);
 		return error("rev-list died");
+	}

 	/* write references */
 	argc = setup_revisions(argc, argv, &revs, NULL);
-	if (argc > 1)
+	if (argc > 1) {
+		close(bundle_fd);
+		rollback_lock_file(&lock);
 		return error("unrecognized argument: %s'", argv[1]);
+	}

 	for (i = 0; i < revs.pending.nr; i++) {
 		struct object_array_entry *e = revs.pending.objects + i;
@@ -307,17 +316,20 @@ static int create_bundle(struct bundle_header *header, const char *path,
 		}

 		ref_count++;
-		write_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40);
-		write_or_die(bundle_fd, " ", 1);
-		write_or_die(bundle_fd, ref, strlen(ref));
-		write_or_die(bundle_fd, "\n", 1);
+		lwrite_or_die(bundle_fd, sha1_to_hex(e->item->sha1), 40, &lock);
+		lwrite_or_die(bundle_fd, " ", 1, &lock);
+		lwrite_or_die(bundle_fd, ref, strlen(ref), &lock);
+		lwrite_or_die(bundle_fd, "\n", 1, &lock);
 		free(ref);
 	}
-	if (!ref_count)
+	if (!ref_count) {
+		close(bundle_fd);
+		rollback_lock_file(&lock);
 		die ("Refusing to create empty bundle.");
+	}

 	/* end header */
-	write_or_die(bundle_fd, "\n", 1);
+	lwrite_or_die(bundle_fd, "\n", 1, &lock);

 	/* write pack */
 	argv_pack[0] = "pack-objects";
@@ -339,8 +351,13 @@ static int create_bundle(struct bundle_header *header, const char *path,
 		write(rls.in, sha1_to_hex(object->sha1), 40);
 		write(rls.in, "\n", 1);
 	}
-	if (finish_command(&rls))
+	if (finish_command(&rls)) {
+		close(bundle_fd);
+		rollback_lock_file(&lock);
 		return error ("pack-objects died");
+	}
+	close(bundle_fd);
+	commit_lock_file(&lock);
 	return 0;
 }

--
1.5.3.rc4.79.gb5c7e-dirty

  reply	other threads:[~2007-08-12 14:14 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-12 12:53 [PATCH] builtin-bundle create - use lock_file semantics Mark Levedahl
2007-08-12 14:14 ` Mark Levedahl [this message]
2007-08-12 17:44   ` [PATCH] builtin-bundle create - use lock_file Junio C Hamano
2007-08-12 18:22     ` Mark Levedahl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11869280491451-git-send-email-mdl123@verizon.net \
    --to=mdl123@verizon.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).