Teach git-index-pack how to keep a pack file.
To prevent a race condition between `index-pack --stdin` and
`repack -a -d` where the repack deletes the newly created pack
file before any refs are updated to reference objects contained
within it we mark the pack file as one that should be kept. This
removes it from the list of packs that `repack -a -d` will consider
for removal.
Callers such as `receive-pack` which want to invoke `index-pack`
should use this new --keep option to prevent the newly created pack
and index file pair from being deleted before they have finished any
related ref updates. Only after all ref updates have been finished
should the associated .keep file be removed.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
diff --git a/index-pack.c b/index-pack.c
index 866a054..b37dd78 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -10,7 +10,7 @@
#include <signal.h>
static const char index_pack_usage[] =
-"git-index-pack [-v] [-o <index-file>] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
struct object_entry
{
@@ -754,6 +754,7 @@
static void final(const char *final_pack_name, const char *curr_pack_name,
const char *final_index_name, const char *curr_index_name,
+ const char *keep_name, const char *keep_msg,
unsigned char *sha1)
{
char name[PATH_MAX];
@@ -780,6 +781,23 @@
}
}
+ if (keep_msg) {
+ int keep_fd, keep_msg_len = strlen(keep_msg);
+ if (!keep_name) {
+ snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
+ get_object_directory(), sha1_to_hex(sha1));
+ keep_name = name;
+ }
+ keep_fd = open(keep_name, O_RDWR | O_CREAT, 0600);
+ if (keep_fd < 0)
+ die("cannot write keep file");
+ if (keep_msg_len > 0) {
+ write_or_die(keep_fd, keep_msg, keep_msg_len);
+ write_or_die(keep_fd, "\n", 1);
+ }
+ close(keep_fd);
+ }
+
if (final_pack_name != curr_pack_name) {
if (!final_pack_name) {
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
@@ -807,7 +825,8 @@
int i, fix_thin_pack = 0;
const char *curr_pack, *pack_name = NULL;
const char *curr_index, *index_name = NULL;
- char *index_name_buf = NULL;
+ const char *keep_name = NULL, *keep_msg = NULL;
+ char *index_name_buf = NULL, *keep_name_buf = NULL;
unsigned char sha1[20];
for (i = 1; i < argc; i++) {
@@ -818,6 +837,10 @@
from_stdin = 1;
} else if (!strcmp(arg, "--fix-thin")) {
fix_thin_pack = 1;
+ } else if (!strcmp(arg, "--keep")) {
+ keep_msg = "";
+ } else if (!strncmp(arg, "--keep=", 7)) {
+ keep_msg = arg + 7;
} else if (!strcmp(arg, "-v")) {
verbose = 1;
} else if (!strcmp(arg, "-o")) {
@@ -848,6 +871,16 @@
strcpy(index_name_buf + len - 5, ".idx");
index_name = index_name_buf;
}
+ if (keep_msg && !keep_name && pack_name) {
+ int len = strlen(pack_name);
+ if (!has_extension(pack_name, ".pack"))
+ die("packfile name '%s' does not end with '.pack'",
+ pack_name);
+ keep_name_buf = xmalloc(len);
+ memcpy(keep_name_buf, pack_name, len - 5);
+ strcpy(keep_name_buf + len - 5, ".keep");
+ keep_name = keep_name_buf;
+ }
curr_pack = open_pack_file(pack_name);
parse_pack_header();
@@ -880,9 +913,13 @@
}
free(deltas);
curr_index = write_index_file(index_name, sha1);
- final(pack_name, curr_pack, index_name, curr_index, sha1);
+ final(pack_name, curr_pack,
+ index_name, curr_index,
+ keep_name, keep_msg,
+ sha1);
free(objects);
free(index_name_buf);
+ free(keep_name_buf);
if (!from_stdin)
printf("%s\n", sha1_to_hex(sha1));