]>
Commit | Line | Data |
---|---|---|
66bf85a4 LT |
1 | #include "cache.h" |
2 | #include "refs.h" | |
3 | ||
4 | static const char git_update_ref_usage[] = "git-update-ref <refname> <value> [<oldval>]"; | |
5 | ||
152da3df JH |
6 | static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1) |
7 | { | |
8 | char buf[40]; | |
9 | int fd = open(path, O_RDONLY), nr; | |
10 | if (fd < 0) | |
11 | return -1; | |
12 | nr = read(fd, buf, 40); | |
13 | close(fd); | |
14 | if (nr != 40 || get_sha1_hex(buf, currsha1) < 0) | |
15 | return -1; | |
16 | return memcmp(oldsha1, currsha1, 20) ? -1 : 0; | |
17 | } | |
18 | ||
66bf85a4 LT |
19 | int main(int argc, char **argv) |
20 | { | |
21 | char *hex; | |
08db81a9 AR |
22 | const char *refname, *value, *oldval, *path; |
23 | char *lockpath; | |
66bf85a4 LT |
24 | unsigned char sha1[20], oldsha1[20], currsha1[20]; |
25 | int fd, written; | |
26 | ||
27 | setup_git_directory(); | |
28 | if (argc < 3 || argc > 4) | |
29 | usage(git_update_ref_usage); | |
30 | ||
31 | refname = argv[1]; | |
32 | value = argv[2]; | |
33 | oldval = argv[3]; | |
34 | if (get_sha1(value, sha1) < 0) | |
35 | die("%s: not a valid SHA1", value); | |
36 | memset(oldsha1, 0, 20); | |
37 | if (oldval && get_sha1(oldval, oldsha1) < 0) | |
38 | die("%s: not a valid old SHA1", oldval); | |
39 | ||
a876ed83 | 40 | path = resolve_ref(git_path("%s", refname), currsha1, !!oldval); |
66bf85a4 LT |
41 | if (!path) |
42 | die("No such ref: %s", refname); | |
43 | ||
44 | if (oldval) { | |
45 | if (memcmp(currsha1, oldsha1, 20)) | |
ad7db621 | 46 | die("Ref %s is at %s but expected %s", refname, sha1_to_hex(currsha1), sha1_to_hex(oldsha1)); |
66bf85a4 LT |
47 | /* Nothing to do? */ |
48 | if (!memcmp(oldsha1, sha1, 20)) | |
49 | exit(0); | |
50 | } | |
51 | path = strdup(path); | |
52 | lockpath = mkpath("%s.lock", path); | |
08db81a9 AR |
53 | if (safe_create_leading_directories(lockpath) < 0) |
54 | die("Unable to create all of %s", lockpath); | |
66bf85a4 LT |
55 | |
56 | fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666); | |
57 | if (fd < 0) | |
58 | die("Unable to create %s", lockpath); | |
59 | hex = sha1_to_hex(sha1); | |
60 | hex[40] = '\n'; | |
61 | written = write(fd, hex, 41); | |
62 | close(fd); | |
63 | if (written != 41) { | |
64 | unlink(lockpath); | |
65 | die("Unable to write to %s", lockpath); | |
66 | } | |
67 | ||
68 | /* | |
152da3df | 69 | * Re-read the ref after getting the lock to verify |
66bf85a4 | 70 | */ |
152da3df JH |
71 | if (oldval && re_verify(path, oldsha1, currsha1) < 0) { |
72 | unlink(lockpath); | |
73 | die("Ref lock failed"); | |
74 | } | |
66bf85a4 | 75 | |
152da3df JH |
76 | /* |
77 | * Finally, replace the old ref with the new one | |
78 | */ | |
66bf85a4 LT |
79 | if (rename(lockpath, path) < 0) { |
80 | unlink(lockpath); | |
81 | die("Unable to create %s", path); | |
82 | } | |
83 | return 0; | |
84 | } |