aboutsummaryrefslogtreecommitdiff
path: root/receive-pack.c
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2007-09-14 03:31:16 -0400
committerJunio C Hamano <gitster@pobox.com>2007-09-19 03:22:30 -0700
commit106764e6515dd0fb9fda8bb8cab523932ae903b3 (patch)
tree498d678d97b6c1a4aabdb3ddc1cb6854382ef8be /receive-pack.c
parent425b1393139d99d89c7a95906686d9b041f2ee3d (diff)
downloadgit-106764e6515dd0fb9fda8bb8cab523932ae903b3.tar.gz
git-106764e6515dd0fb9fda8bb8cab523932ae903b3.tar.xz
Refactor index-pack "keep $sha1" handling for reuse
There is a subtle (but important) linkage between receive-pack and index-pack that allows index-pack to create a packfile but protect it from being deleted by a concurrent `git repack -a -d` operation. The linkage works by having index-pack mark the newly created pack with a ".keep" file and then it passes the SHA-1 name of that new packfile to receive-pack along its stdout channel. The receive-pack process must unkeep the packfile by deleting the .keep file, but can it can only do so after all elgible refs have been updated in the receiving repository. This ensures that the packfile is either kept or its objects are reachable, preventing a concurrent repacker from deleting the packfile before it can determine that its objects are actually needed by the repository. The new builtin-fetch code needs to perform the same actions if it choose to run index-pack rather than unpack-objects, so I am moving this code out to its own function where both receive-pack and fetch-pack are able to invoke it when necessary. The caller is responsible for deleting the returned ".keep" and freeing the path if the returned path is not NULL. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'receive-pack.c')
-rw-r--r--receive-pack.c24
1 files changed, 2 insertions, 22 deletions
diff --git a/receive-pack.c b/receive-pack.c
index d3c422be5..61e992976 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -382,9 +382,8 @@ static const char *unpack(void)
}
} else {
const char *keeper[6];
- int s, len, status;
+ int s, status;
char keep_arg[256];
- char packname[46];
struct child_process ip;
s = sprintf(keep_arg, "--keep=receive-pack %i on ", getpid());
@@ -403,26 +402,7 @@ static const char *unpack(void)
ip.git_cmd = 1;
if (start_command(&ip))
return "index-pack fork failed";
-
- /*
- * The first thing we expects from index-pack's output
- * is "pack\t%40s\n" or "keep\t%40s\n" (46 bytes) where
- * %40s is the newly created pack SHA1 name. In the "keep"
- * case, we need it to remove the corresponding .keep file
- * later on. If we don't get that then tough luck with it.
- */
- for (len = 0;
- len < 46 && (s = xread(ip.out, packname+len, 46-len)) > 0;
- len += s);
- if (len == 46 && packname[45] == '\n' &&
- memcmp(packname, "keep\t", 5) == 0) {
- char path[PATH_MAX];
- packname[45] = 0;
- snprintf(path, sizeof(path), "%s/pack/pack-%s.keep",
- get_object_directory(), packname + 5);
- pack_lockfile = xstrdup(path);
- }
-
+ pack_lockfile = index_pack_lockfile(ip.out);
status = finish_command(&ip);
if (!status) {
reprepare_packed_git();