summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 56b6ed8)
raw | patch | inline | side by side (parent: 56b6ed8)
author | Linus Torvalds <torvalds@ppc970.osdl.org> | |
Thu, 30 Jun 2005 17:15:22 +0000 (10:15 -0700) | ||
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | |
Thu, 30 Jun 2005 17:15:22 +0000 (10:15 -0700) |
After unpacking the object pack successfully, we go through the list of
refs, and verify that they still contain their expected values. Then we
replace them with the new ones.
refs, and verify that they still contain their expected values. Then we
replace them with the new ones.
receive-pack.c | patch | blob | history |
diff --git a/receive-pack.c b/receive-pack.c
index fb43107d82bc795383b743490e522887f389589e..7ce5f1e24a57f673e614c6bb3d75480e272d37da 100644 (file)
--- a/receive-pack.c
+++ b/receive-pack.c
}
if (read_ref(path, sha1) < 0)
continue;
+ if (!has_sha1_file(sha1))
+ continue;
if (nr && !path_match(path, nr, match))
continue;
show_ref(path, sha1);
struct command *commands = NULL;
+static int verify_old_ref(const char *name, char *hex_contents)
+{
+ int fd, ret;
+ char buffer[60];
+
+ fd = open(name, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ ret = read(fd, buffer, 40);
+ close(fd);
+ if (ret != 40)
+ return -1;
+ if (memcmp(buffer, hex_contents, 40))
+ return -1;
+ return 0;
+}
+
+static void update(const char *name, unsigned char *old_sha1, unsigned char *new_sha1)
+{
+ char new_hex[60], *old_hex, *lock_name;
+ int newfd, namelen, written;
+
+ namelen = strlen(name);
+ lock_name = xmalloc(namelen + 10);
+ memcpy(lock_name, name, namelen);
+ memcpy(lock_name + namelen, ".lock", 6);
+
+ strcpy(new_hex, sha1_to_hex(new_sha1));
+ new_hex[40] = '\n';
+ new_hex[41] = 0;
+ old_hex = sha1_to_hex(old_sha1);
+ if (!has_sha1_file(new_sha1))
+ die("unpack should have generated %s, but I can't find it!", new_hex);
+
+ newfd = open(lock_name, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (newfd < 0)
+ die("unable to create %s (%s)", lock_name, strerror(errno));
+ written = write(newfd, new_hex, 41);
+ close(newfd);
+ if (written != 41) {
+ unlink(lock_name);
+ die("unable to write %s", lock_name);
+ }
+ if (verify_old_ref(name, old_hex) < 0) {
+ unlink(lock_name);
+ die("%s changed during push", name);
+ }
+ if (rename(lock_name, name) < 0) {
+ unlink(lock_name);
+ die("unable to replace %s", name);
+ }
+ fprintf(stderr, "%s: %s -> %s\n", name, old_hex, new_hex);
+}
+
+
/*
* This gets called after(if) we've successfully
* unpacked the data payload.
struct command *cmd = commands;
while (cmd) {
- char old_hex[60], *new_hex;
- strcpy(old_hex, sha1_to_hex(cmd->old_sha1));
- new_hex = sha1_to_hex(cmd->new_sha1);
- fprintf(stderr, "%s: %s -> %s\n", cmd->ref_name, old_hex, new_hex);
+ update(cmd->ref_name, cmd->old_sha1, cmd->new_sha1);
cmd = cmd->next;
}
}
if (pid < 0)
die("unpack fork failed");
if (!pid) {
- setenv("GIT_DIR", ".", 1);
execlp(unpacker, unpacker, NULL);
die("unpack execute failed");
}
/* If we have a ".git" directory, chdir to it */
chdir(".git");
+ setenv("GIT_DIR", ".", 1);
if (access("objects", X_OK) < 0 || access("refs/heads", X_OK) < 0)
die("%s doesn't appear to be a git directory", dir);