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 semantics
Date: Sun, 12 Aug 2007 08:53:02 -0400 [thread overview]
Message-ID: <11869231822803-git-send-email-mdl123@verizon.net> (raw)
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>
---
builtin-bundle.c | 51 +++++++++++++++++++++++++++++++--------------------
1 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/builtin-bundle.c b/builtin-bundle.c
index f4b4f03..82e00f5 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -186,10 +186,20 @@ 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) {
+ 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;
+ 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 +208,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 +232,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 +244,17 @@ static int create_bundle(struct bundle_header *header, const char *path,
}
}
fclose(rls_fout);
- if (finish_command(&rls))
+ if (finish_command(&rls)) {
+ rollback_lock_file(&lock);
return error("rev-list died");
+ }
/* write references */
argc = setup_revisions(argc, argv, &revs, NULL);
- if (argc > 1)
+ if (argc > 1) {
+ 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 +313,19 @@ 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) {
+ 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 +347,11 @@ 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)) {
+ rollback_lock_file(&lock);
return error ("pack-objects died");
+ }
+ commit_lock_file(&lock);
return 0;
}
--
1.5.3.rc4.78.g5acb3-dirty
next reply other threads:[~2007-08-12 12:53 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-12 12:53 Mark Levedahl [this message]
2007-08-12 14:14 ` [PATCH] builtin-bundle create - use lock_file Mark Levedahl
2007-08-12 17:44 ` 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=11869231822803-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).