4 static const char git_update_ref_usage
[] = "git-update-ref <refname> <value> [<oldval>]";
8 const char *resolve_ref(const char *path
, unsigned char *sha1
)
10 int depth
= MAXDEPTH
, len
;
20 /* Special case: non-existing file */
21 if (lstat(path
, &st
) < 0) {
28 /* Follow "normalized" - ie "refs/.." symlinks by hand */
29 if (S_ISLNK(st
.st_mode
)) {
30 len
= readlink(path
, buffer
, sizeof(buffer
)-1);
31 if (len
>= 5 && !memcmp("refs/", buffer
, 5)) {
32 path
= git_path("%.*s", len
, buffer
);
38 * Anything else, just open it and try to use it as
41 fd
= open(path
, O_RDONLY
);
44 len
= read(fd
, buffer
, sizeof(buffer
)-1);
48 if (len
< 40 || get_sha1_hex(buffer
, sha1
))
53 int main(int argc
, char **argv
)
56 const char *refname
, *value
, *oldval
, *path
, *lockpath
;
57 unsigned char sha1
[20], oldsha1
[20], currsha1
[20];
60 setup_git_directory();
61 if (argc
< 3 || argc
> 4)
62 usage(git_update_ref_usage
);
67 if (get_sha1(value
, sha1
) < 0)
68 die("%s: not a valid SHA1", value
);
69 memset(oldsha1
, 0, 20);
70 if (oldval
&& get_sha1(oldval
, oldsha1
) < 0)
71 die("%s: not a valid old SHA1", oldval
);
73 path
= resolve_ref(git_path("%s", refname
), currsha1
);
75 die("No such ref: %s", refname
);
78 if (memcmp(currsha1
, oldsha1
, 20))
79 die("Ref %s changed to %s", refname
, sha1_to_hex(currsha1
));
81 if (!memcmp(oldsha1
, sha1
, 20))
85 lockpath
= mkpath("%s.lock", path
);
87 fd
= open(lockpath
, O_CREAT
| O_EXCL
| O_WRONLY
, 0666);
89 die("Unable to create %s", lockpath
);
90 hex
= sha1_to_hex(sha1
);
92 written
= write(fd
, hex
, 41);
96 die("Unable to write to %s", lockpath
);
102 * We should re-read the old ref here, and re-verify that it
103 * matches "oldsha1". Otherwise there's a small race.
106 if (rename(lockpath
, path
) < 0) {
108 die("Unable to create %s", path
);