提交 a157400c 编写于 作者: J Junio C Hamano

Merge branch 'jc/maint-co-track'

* jc/maint-co-track:
  Enhance hold_lock_file_for_{update,append}() API
  demonstrate breakage of detached checkout with symbolic link HEAD
  Fix "checkout --track -b newbranch" on detached HEAD

Conflicts:
	builtin-commit.c
......@@ -129,7 +129,9 @@ void create_branch(const char *head,
die("Cannot setup tracking information; starting point is not a branch.");
break;
case 1:
/* Unique completion -- good */
/* Unique completion -- good, only if it is a real ref */
if (track == BRANCH_TRACK_EXPLICIT && !strcmp(real_ref, "HEAD"))
die("Cannot setup tracking information; starting point is not a branch.");
break;
default:
die("Ambiguous object name: '%s'.", start_name);
......
......@@ -320,7 +320,9 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
die("unable to write new_index file");
fd = hold_lock_file_for_update(&false_lock,
git_path("next-index-%"PRIuMAX, (uintmax_t) getpid()), 1);
git_path("next-index-%"PRIuMAX,
(uintmax_t) getpid()),
LOCK_DIE_ON_ERROR);
create_base_index();
add_remove_files(&partial);
......
......@@ -813,7 +813,8 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
)
die("shallow file was changed during fetch");
fd = hold_lock_file_for_update(&lock, shallow, 1);
fd = hold_lock_file_for_update(&lock, shallow,
LOCK_DIE_ON_ERROR);
if (!write_shallow_commits(fd, 0)) {
unlink(shallow);
rollback_lock_file(&lock);
......
......@@ -329,7 +329,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)
* reverse of it if we are revert.
*/
msg_fd = hold_lock_file_for_update(&msg_file, defmsg, 1);
msg_fd = hold_lock_file_for_update(&msg_file, defmsg,
LOCK_DIE_ON_ERROR);
encoding = get_encoding(message);
if (!encoding)
......
......@@ -186,7 +186,8 @@ int create_bundle(struct bundle_header *header, const char *path,
if (bundle_to_stdout)
bundle_fd = 1;
else
bundle_fd = hold_lock_file_for_update(&lock, path, 1);
bundle_fd = hold_lock_file_for_update(&lock, path,
LOCK_DIE_ON_ERROR);
/* write signature */
write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
......
......@@ -423,6 +423,8 @@ struct lock_file {
char on_list;
char filename[PATH_MAX];
};
#define LOCK_DIE_ON_ERROR 1
#define LOCK_NODEREF 2
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
extern int commit_lock_file(struct lock_file *);
......
......@@ -121,15 +121,17 @@ static char *resolve_symlink(char *p, size_t s)
}
static int lock_file(struct lock_file *lk, const char *path)
static int lock_file(struct lock_file *lk, const char *path, int flags)
{
if (strlen(path) >= sizeof(lk->filename)) return -1;
if (strlen(path) >= sizeof(lk->filename))
return -1;
strcpy(lk->filename, path);
/*
* subtract 5 from size to make sure there's room for adding
* ".lock" for the lock file name
*/
resolve_symlink(lk->filename, sizeof(lk->filename)-5);
if (!(flags & LOCK_NODEREF))
resolve_symlink(lk->filename, sizeof(lk->filename)-5);
strcat(lk->filename, ".lock");
lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= lk->fd) {
......@@ -155,21 +157,21 @@ static int lock_file(struct lock_file *lk, const char *path)
return lk->fd;
}
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
{
int fd = lock_file(lk, path);
if (fd < 0 && die_on_error)
int fd = lock_file(lk, path, flags);
if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
die("unable to create '%s.lock': %s", path, strerror(errno));
return fd;
}
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error)
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
{
int fd, orig_fd;
fd = lock_file(lk, path);
fd = lock_file(lk, path, flags);
if (fd < 0) {
if (die_on_error)
if (flags & LOCK_DIE_ON_ERROR)
die("unable to create '%s.lock': %s", path, strerror(errno));
return fd;
}
......@@ -177,13 +179,13 @@ int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on
orig_fd = open(path, O_RDONLY);
if (orig_fd < 0) {
if (errno != ENOENT) {
if (die_on_error)
if (flags & LOCK_DIE_ON_ERROR)
die("cannot open '%s' for copying", path);
close(fd);
return error("cannot open '%s' for copying", path);
}
} else if (copy_fd(orig_fd, fd)) {
if (die_on_error)
if (flags & LOCK_DIE_ON_ERROR)
exit(128);
close(fd);
return -1;
......@@ -215,7 +217,10 @@ int commit_lock_file(struct lock_file *lk)
int hold_locked_index(struct lock_file *lk, int die_on_error)
{
return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
return hold_lock_file_for_update(lk, get_index_file(),
die_on_error
? LOCK_DIE_ON_ERROR
: 0);
}
void set_alternate_index_output(const char *name)
......
......@@ -89,7 +89,8 @@ int pack_refs(unsigned int flags)
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
fd = hold_lock_file_for_update(&packed, git_path("packed-refs"),
LOCK_DIE_ON_ERROR);
cbdata.refs_file = fdopen(fd, "w");
if (!cbdata.refs_file)
die("unable to create ref-pack file structure (%s)",
......
......@@ -796,7 +796,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
struct ref_lock *lock;
struct stat st;
int last_errno = 0;
int type;
int type, lflags;
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
lock = xcalloc(1, sizeof(struct ref_lock));
......@@ -836,8 +836,11 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
lock->lk = xcalloc(1, sizeof(struct lock_file));
if (flags & REF_NODEREF)
lflags = LOCK_DIE_ON_ERROR;
if (flags & REF_NODEREF) {
ref = orig_ref;
lflags |= LOCK_NODEREF;
}
lock->ref_name = xstrdup(ref);
lock->orig_ref_name = xstrdup(orig_ref);
ref_file = git_path("%s", ref);
......@@ -851,8 +854,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
error("unable to create directory for %s", ref_file);
goto error_return;
}
lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
error_return:
......
......@@ -352,7 +352,8 @@ int setup_rerere(struct string_list *merge_rr)
return -1;
merge_rr_path = xstrdup(git_path("MERGE_RR"));
fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
LOCK_DIE_ON_ERROR);
read_rr(merge_rr);
return fd;
}
......
......@@ -388,7 +388,7 @@ static void read_info_alternates(const char * relative_base, int depth)
void add_to_alternates_file(const char *reference)
{
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), 1);
int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), LOCK_DIE_ON_ERROR);
char *alt = mkpath("%s/objects\n", reference);
write_or_die(fd, alt, strlen(alt));
if (commit_lock_file(lock))
......
......@@ -330,12 +330,26 @@ test_expect_success \
test "$(git config branch.track2.merge)"
git config branch.autosetupmerge false'
test_expect_success \
'checkout w/--track from non-branch HEAD fails' '
git checkout -b delete-me master &&
rm .git/refs/heads/delete-me &&
test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
test_must_fail git checkout --track -b track'
test_expect_success 'checkout w/--track from non-branch HEAD fails' '
git checkout master^0 &&
test_must_fail git symbolic-ref HEAD &&
test_must_fail git checkout --track -b track &&
test_must_fail git rev-parse --verify track &&
test_must_fail git symbolic-ref HEAD &&
test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
'
test_expect_success 'detach a symbolic link HEAD' '
git checkout master &&
git config --bool core.prefersymlinkrefs yes &&
git checkout side &&
git checkout master &&
it=$(git symbolic-ref HEAD) &&
test "z$it" = zrefs/heads/master &&
here=$(git rev-parse --verify refs/heads/master) &&
git checkout side^ &&
test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
'
test_expect_success \
'checkout with --track fakes a sensible -b <name>' '
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册