git/update-ref.c
Junio C Hamano 84a9b58c42 sha1_name: warning ambiguous refs.
This makes sure that many commands that take refs on the command
line to honor core.warnambiguousrefs configuration.  Earlier,
the commands affected by this patch did not read the
configuration file.

Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-03-23 23:41:18 -08:00

86 lines
2.0 KiB
C

#include "cache.h"
#include "refs.h"
static const char git_update_ref_usage[] = "git-update-ref <refname> <value> [<oldval>]";
static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1)
{
char buf[40];
int fd = open(path, O_RDONLY), nr;
if (fd < 0)
return -1;
nr = read(fd, buf, 40);
close(fd);
if (nr != 40 || get_sha1_hex(buf, currsha1) < 0)
return -1;
return memcmp(oldsha1, currsha1, 20) ? -1 : 0;
}
int main(int argc, char **argv)
{
char *hex;
const char *refname, *value, *oldval, *path;
char *lockpath;
unsigned char sha1[20], oldsha1[20], currsha1[20];
int fd, written;
setup_git_directory();
git_config(git_default_config);
if (argc < 3 || argc > 4)
usage(git_update_ref_usage);
refname = argv[1];
value = argv[2];
oldval = argv[3];
if (get_sha1(value, sha1) < 0)
die("%s: not a valid SHA1", value);
memset(oldsha1, 0, 20);
if (oldval && get_sha1(oldval, oldsha1) < 0)
die("%s: not a valid old SHA1", oldval);
path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
if (!path)
die("No such ref: %s", refname);
if (oldval) {
if (memcmp(currsha1, oldsha1, 20))
die("Ref %s is at %s but expected %s", refname, sha1_to_hex(currsha1), sha1_to_hex(oldsha1));
/* Nothing to do? */
if (!memcmp(oldsha1, sha1, 20))
exit(0);
}
path = strdup(path);
lockpath = mkpath("%s.lock", path);
if (safe_create_leading_directories(lockpath) < 0)
die("Unable to create all of %s", lockpath);
fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd < 0)
die("Unable to create %s", lockpath);
hex = sha1_to_hex(sha1);
hex[40] = '\n';
written = write(fd, hex, 41);
close(fd);
if (written != 41) {
unlink(lockpath);
die("Unable to write to %s", lockpath);
}
/*
* Re-read the ref after getting the lock to verify
*/
if (oldval && re_verify(path, oldsha1, currsha1) < 0) {
unlink(lockpath);
die("Ref lock failed");
}
/*
* Finally, replace the old ref with the new one
*/
if (rename(lockpath, path) < 0) {
unlink(lockpath);
die("Unable to create %s", path);
}
return 0;
}