Skip to content

Commit b807770

Browse files
spearceJunio C Hamano
authored and
Junio C Hamano
committed
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>
1 parent 01cff2d commit b807770

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

Documentation/git-index-pack.txt

+21-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ git-index-pack - Build pack index file for an existing packed archive
99
SYNOPSIS
1010
--------
1111
'git-index-pack' [-v] [-o <index-file>] <pack-file>
12-
'git-index-pack' --stdin [--fix-thin] [-v] [-o <index-file>] [<pack-file>]
12+
'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>] [<pack-file>]
1313

1414

1515
DESCRIPTION
@@ -38,7 +38,10 @@ OPTIONS
3838
instead and a copy is then written to <pack-file>. If
3939
<pack-file> is not specified, the pack is written to
4040
objects/pack/ directory of the current git repository with
41-
a default name determined from the pack content.
41+
a default name determined from the pack content. If
42+
<pack-file> is not specified consider using --keep to
43+
prevent a race condition between this process and
44+
gitlink::git-repack[1] .
4245

4346
--fix-thin::
4447
It is possible for gitlink:git-pack-objects[1] to build
@@ -48,7 +51,22 @@ OPTIONS
4851
and they must be included in the pack for that pack to be self
4952
contained and indexable. Without this option any attempt to
5053
index a thin pack will fail. This option only makes sense in
51-
conjonction with --stdin.
54+
conjunction with --stdin.
55+
56+
--keep::
57+
Before moving the index into its final destination
58+
create an empty .keep file for the associated pack file.
59+
This option is usually necessary with --stdin to prevent a
60+
simultaneous gitlink:git-repack[1] process from deleting
61+
the newly constructed pack and index before refs can be
62+
updated to use objects contained in the pack.
63+
64+
--keep='why'::
65+
Like --keep create a .keep file before moving the index into
66+
its final destination, but rather than creating an empty file
67+
place 'why' followed by an LF into the .keep file. The 'why'
68+
message can later be searched for within all .keep files to
69+
locate any which have outlived their usefulness.
5270

5371

5472
Author

index-pack.c

+40-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <signal.h>
1111

1212
static const char index_pack_usage[] =
13-
"git-index-pack [-v] [-o <index-file>] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
13+
"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
1414

1515
struct object_entry
1616
{
@@ -754,6 +754,7 @@ static const char *write_index_file(const char *index_name, unsigned char *sha1)
754754

755755
static void final(const char *final_pack_name, const char *curr_pack_name,
756756
const char *final_index_name, const char *curr_index_name,
757+
const char *keep_name, const char *keep_msg,
757758
unsigned char *sha1)
758759
{
759760
char name[PATH_MAX];
@@ -780,6 +781,23 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
780781
}
781782
}
782783

784+
if (keep_msg) {
785+
int keep_fd, keep_msg_len = strlen(keep_msg);
786+
if (!keep_name) {
787+
snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
788+
get_object_directory(), sha1_to_hex(sha1));
789+
keep_name = name;
790+
}
791+
keep_fd = open(keep_name, O_RDWR | O_CREAT, 0600);
792+
if (keep_fd < 0)
793+
die("cannot write keep file");
794+
if (keep_msg_len > 0) {
795+
write_or_die(keep_fd, keep_msg, keep_msg_len);
796+
write_or_die(keep_fd, "\n", 1);
797+
}
798+
close(keep_fd);
799+
}
800+
783801
if (final_pack_name != curr_pack_name) {
784802
if (!final_pack_name) {
785803
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
@@ -807,7 +825,8 @@ int main(int argc, char **argv)
807825
int i, fix_thin_pack = 0;
808826
const char *curr_pack, *pack_name = NULL;
809827
const char *curr_index, *index_name = NULL;
810-
char *index_name_buf = NULL;
828+
const char *keep_name = NULL, *keep_msg = NULL;
829+
char *index_name_buf = NULL, *keep_name_buf = NULL;
811830
unsigned char sha1[20];
812831

813832
for (i = 1; i < argc; i++) {
@@ -818,6 +837,10 @@ int main(int argc, char **argv)
818837
from_stdin = 1;
819838
} else if (!strcmp(arg, "--fix-thin")) {
820839
fix_thin_pack = 1;
840+
} else if (!strcmp(arg, "--keep")) {
841+
keep_msg = "";
842+
} else if (!strncmp(arg, "--keep=", 7)) {
843+
keep_msg = arg + 7;
821844
} else if (!strcmp(arg, "-v")) {
822845
verbose = 1;
823846
} else if (!strcmp(arg, "-o")) {
@@ -848,6 +871,16 @@ int main(int argc, char **argv)
848871
strcpy(index_name_buf + len - 5, ".idx");
849872
index_name = index_name_buf;
850873
}
874+
if (keep_msg && !keep_name && pack_name) {
875+
int len = strlen(pack_name);
876+
if (!has_extension(pack_name, ".pack"))
877+
die("packfile name '%s' does not end with '.pack'",
878+
pack_name);
879+
keep_name_buf = xmalloc(len);
880+
memcpy(keep_name_buf, pack_name, len - 5);
881+
strcpy(keep_name_buf + len - 5, ".keep");
882+
keep_name = keep_name_buf;
883+
}
851884

852885
curr_pack = open_pack_file(pack_name);
853886
parse_pack_header();
@@ -880,9 +913,13 @@ int main(int argc, char **argv)
880913
}
881914
free(deltas);
882915
curr_index = write_index_file(index_name, sha1);
883-
final(pack_name, curr_pack, index_name, curr_index, sha1);
916+
final(pack_name, curr_pack,
917+
index_name, curr_index,
918+
keep_name, keep_msg,
919+
sha1);
884920
free(objects);
885921
free(index_name_buf);
922+
free(keep_name_buf);
886923

887924
if (!from_stdin)
888925
printf("%s\n", sha1_to_hex(sha1));

0 commit comments

Comments
 (0)