зеркало из https://github.com/microsoft/git.git
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:
Родитель
4bd18c43d9
Коммит
5b16b09021
|
@ -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
|
||||
-----------
|
||||
|
|
103
update-ref.c
103
update-ref.c
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче