Convert update-ref to use ref_lock API.

This conversion also adds the '-m' switch to update-ref allowing
the caller to record why the ref is changing.  At present this is
merely copied down into the ref_lock API.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Shawn Pearce 2006-05-17 05:55:19 -04:00 коммит произвёл Junio C Hamano
Родитель 4bd18c43d9
Коммит 5b16b09021
2 изменённых файлов: 38 добавлений и 67 удалений

Просмотреть файл

@ -7,7 +7,7 @@ git-update-ref - update the object name stored in a ref safely
SYNOPSIS
--------
'git-update-ref' <ref> <newvalue> [<oldvalue>]
'git-update-ref' <ref> <newvalue> [<oldvalue>] [-m <reason>]
DESCRIPTION
-----------

Просмотреть файл

@ -1,85 +1,56 @@
#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;
}
static const char git_update_ref_usage[] =
"git-update-ref <refname> <value> [<oldval>] [-m <reason>]";
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;
const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;
struct ref_lock *lock;
unsigned char sha1[20], oldsha1[20];
int i;
setup_git_directory();
git_config(git_default_config);
if (argc < 3 || argc > 4)
for (i = 1; i < argc; i++) {
if (!strcmp("-m", argv[i])) {
if (i+1 >= argc)
usage(git_update_ref_usage);
msg = argv[++i];
if (!*msg)
die("Refusing to perform update with empty message.");
if (strchr(msg, '\n'))
die("Refusing to perform update with \\n in message.");
continue;
}
if (!refname) {
refname = argv[i];
continue;
}
if (!value) {
value = argv[i];
continue;
}
if (!oldval) {
oldval = argv[i];
continue;
}
}
if (!refname || !value)
usage(git_update_ref_usage);
refname = argv[1];
value = argv[2];
oldval = argv[3];
if (get_sha1(value, sha1))
die("%s: not a valid SHA1", value);
memset(oldsha1, 0, 20);
if (oldval && get_sha1(oldval, oldsha1))
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);
}
lock = lock_any_ref_for_update(refname, oldval ? oldsha1 : NULL, 0);
if (!lock)
return 1;
if (write_ref_sha1(lock, sha1, msg) < 0)
return 1;
return 0;
}