refs.c: log_ref_write should try to return meaningful errno
Making errno from write_ref_sha1() meaningful, which should fix * a bug in "git checkout -b" where it prints strerror(errno) despite errno possibly being zero or clobbered * a bug in "git fetch"'s s_update_ref, which trusts the result of an errno == ENOTDIR check to detect D/F conflicts Signed-off-by: Ronnie Sahlberg <sahlberg@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com> Acked-by: Michael Haggerty <mhagger@alum.mit.edu>
This commit is contained in:
parent
76d70dc0c6
commit
dc615de861
28
refs.c
28
refs.c
@ -2859,8 +2859,19 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
|
|||||||
len += copy_msg(logrec + len - 1, msg) - 1;
|
len += copy_msg(logrec + len - 1, msg) - 1;
|
||||||
written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
|
written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
|
||||||
free(logrec);
|
free(logrec);
|
||||||
if (close(logfd) != 0 || written != len)
|
if (written != len) {
|
||||||
return error("Unable to append to %s", log_file);
|
int save_errno = errno;
|
||||||
|
close(logfd);
|
||||||
|
error("Unable to append to %s", log_file);
|
||||||
|
errno = save_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (close(logfd)) {
|
||||||
|
int save_errno = errno;
|
||||||
|
error("Unable to append to %s", log_file);
|
||||||
|
errno = save_errno;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2869,14 +2880,17 @@ static int is_branch(const char *refname)
|
|||||||
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
|
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function must return a meaningful errno */
|
||||||
int write_ref_sha1(struct ref_lock *lock,
|
int write_ref_sha1(struct ref_lock *lock,
|
||||||
const unsigned char *sha1, const char *logmsg)
|
const unsigned char *sha1, const char *logmsg)
|
||||||
{
|
{
|
||||||
static char term = '\n';
|
static char term = '\n';
|
||||||
struct object *o;
|
struct object *o;
|
||||||
|
|
||||||
if (!lock)
|
if (!lock) {
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
|
if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
|
||||||
unlock_ref(lock);
|
unlock_ref(lock);
|
||||||
return 0;
|
return 0;
|
||||||
@ -2886,19 +2900,23 @@ int write_ref_sha1(struct ref_lock *lock,
|
|||||||
error("Trying to write ref %s with nonexistent object %s",
|
error("Trying to write ref %s with nonexistent object %s",
|
||||||
lock->ref_name, sha1_to_hex(sha1));
|
lock->ref_name, sha1_to_hex(sha1));
|
||||||
unlock_ref(lock);
|
unlock_ref(lock);
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
|
if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
|
||||||
error("Trying to write non-commit object %s to branch %s",
|
error("Trying to write non-commit object %s to branch %s",
|
||||||
sha1_to_hex(sha1), lock->ref_name);
|
sha1_to_hex(sha1), lock->ref_name);
|
||||||
unlock_ref(lock);
|
unlock_ref(lock);
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
|
if (write_in_full(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
|
||||||
write_in_full(lock->lock_fd, &term, 1) != 1
|
write_in_full(lock->lock_fd, &term, 1) != 1 ||
|
||||||
|| close_ref(lock) < 0) {
|
close_ref(lock) < 0) {
|
||||||
|
int save_errno = errno;
|
||||||
error("Couldn't write %s", lock->lk->filename);
|
error("Couldn't write %s", lock->lk->filename);
|
||||||
unlock_ref(lock);
|
unlock_ref(lock);
|
||||||
|
errno = save_errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
clear_loose_ref_cache(&ref_cache);
|
clear_loose_ref_cache(&ref_cache);
|
||||||
|
Loading…
Reference in New Issue
Block a user