return -1;
}
-/*
- * Read a raw ref from the filesystem or packed refs file.
- *
- * If the ref is a sha1, fill in sha1 and return 0.
- *
- * If the ref is symbolic, fill in *symref with the referrent
- * (e.g. "refs/heads/master") and return 0. The caller is responsible
- * for validating the referrent. Set REF_ISSYMREF in flags.
- *
- * If the ref doesn't exist, set errno to ENOENT and return -1.
- *
- * If the ref exists but is neither a symbolic ref nor a sha1, it is
- * broken. Set REF_ISBROKEN in flags, set errno to EINVAL, and return
- * -1.
- *
- * If there is another error reading the ref, set errno appropriately and
- * return -1.
- *
- * Backend-specific flags might be set in flags as well, regardless of
- * outcome.
- *
- * sb_path is workspace: the caller should allocate and free it.
- *
- * It is OK for refname to point into symref. In this case:
- * - if the function succeeds with REF_ISSYMREF, symref will be
- * overwritten and the memory pointed to by refname might be changed
- * or even freed.
- * - in all other cases, symref will be untouched, and therefore
- * refname will still be valid and unchanged.
- */
int read_raw_ref(const char *refname, unsigned char *sha1,
- struct strbuf *symref, unsigned int *flags)
+ struct strbuf *referent, unsigned int *type)
{
struct strbuf sb_contents = STRBUF_INIT;
struct strbuf sb_path = STRBUF_INIT;
int ret = -1;
int save_errno;
+ *type = 0;
strbuf_reset(&sb_path);
strbuf_git_path(&sb_path, "%s", refname);
path = sb_path.buf;
if (lstat(path, &st) < 0) {
if (errno != ENOENT)
goto out;
- if (resolve_missing_loose_ref(refname, sha1, flags)) {
+ if (resolve_missing_loose_ref(refname, sha1, type)) {
errno = ENOENT;
goto out;
}
}
if (starts_with(sb_contents.buf, "refs/") &&
!check_refname_format(sb_contents.buf, 0)) {
- strbuf_swap(&sb_contents, symref);
- *flags |= REF_ISSYMREF;
+ strbuf_swap(&sb_contents, referent);
+ *type |= REF_ISSYMREF;
ret = 0;
goto out;
}
* ref is supposed to be, there could still be a
* packed ref:
*/
- if (resolve_missing_loose_ref(refname, sha1, flags)) {
+ if (resolve_missing_loose_ref(refname, sha1, type)) {
errno = EISDIR;
goto out;
}
while (isspace(*buf))
buf++;
- strbuf_reset(symref);
- strbuf_addstr(symref, buf);
- *flags |= REF_ISSYMREF;
+ strbuf_reset(referent);
+ strbuf_addstr(referent, buf);
+ *type |= REF_ISSYMREF;
ret = 0;
goto out;
}
*/
if (get_sha1_hex(buf, sha1) ||
(buf[40] != '\0' && !isspace(buf[40]))) {
- *flags |= REF_ISBROKEN;
+ *type |= REF_ISBROKEN;
errno = EINVAL;
goto out;
}
lock->old_oid.hash, NULL)) {
if (old_sha1) {
int save_errno = errno;
- strbuf_addf(err, "can't verify ref %s", lock->ref_name);
+ strbuf_addf(err, "can't verify ref '%s'", lock->ref_name);
errno = save_errno;
return -1;
} else {
}
}
if (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) {
- strbuf_addf(err, "ref %s is at %s but expected %s",
+ strbuf_addf(err, "ref '%s' is at %s but expected %s",
lock->ref_name,
sha1_to_hex(lock->old_oid.hash),
sha1_to_hex(old_sha1));
const unsigned char *old_sha1,
const struct string_list *extras,
const struct string_list *skip,
- unsigned int flags, int *type_p,
+ unsigned int flags, int *type,
struct strbuf *err)
{
struct strbuf ref_file = STRBUF_INIT;
const char *orig_refname = refname;
struct ref_lock *lock;
int last_errno = 0;
- int type;
int lflags = 0;
int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
int resolve_flags = 0;
}
refname = resolve_ref_unsafe(refname, resolve_flags,
- lock->old_oid.hash, &type);
+ lock->old_oid.hash, type);
if (!refname && errno == EISDIR) {
/*
* we are trying to lock foo but we used to
goto error_return;
}
refname = resolve_ref_unsafe(orig_refname, resolve_flags,
- lock->old_oid.hash, &type);
+ lock->old_oid.hash, type);
}
- if (type_p)
- *type_p = type;
if (!refname) {
last_errno = errno;
if (last_errno != ENOTDIR ||
!verify_refname_available_dir(orig_refname, extras, skip,
get_loose_refs(&ref_cache), err))
- strbuf_addf(err, "unable to resolve reference %s: %s",
+ strbuf_addf(err, "unable to resolve reference '%s': %s",
orig_refname, strerror(last_errno));
goto error_return;
/* fall through */
default:
last_errno = errno;
- strbuf_addf(err, "unable to create directory for %s",
+ strbuf_addf(err, "unable to create directory for '%s'",
ref_file.buf);
goto error_return;
}
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, r->name, r->sha1,
- REF_ISPRUNING, NULL, &err) ||
+ REF_ISPRUNING | REF_NODEREF, NULL, &err) ||
ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
}
int verify_refname_available(const char *newname,
- struct string_list *extras,
- struct string_list *skip,
+ const struct string_list *extras,
+ const struct string_list *skip,
struct strbuf *err)
{
struct ref_dir *packed_refs = get_packed_refs(&ref_cache);
if (log && S_ISLNK(loginfo.st_mode))
return error("reflog for %s is a symlink", oldrefname);
- if (!resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING, orig_sha1, &flag))
+ if (!resolve_ref_unsafe(oldrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ orig_sha1, &flag))
return error("refname %s not found", oldrefname);
if (flag & REF_ISSYMREF)
goto rollback;
}
- if (!read_ref_full(newrefname, RESOLVE_REF_READING, sha1, NULL) &&
- delete_ref(newrefname, sha1, REF_NODEREF)) {
+ /*
+ * Since we are doing a shallow lookup, sha1 is not the
+ * correct value to pass to delete_ref as old_sha1. But that
+ * doesn't matter, because an old_sha1 check wouldn't add to
+ * the safety anyway; we want to delete the reference whatever
+ * its current value.
+ */
+ if (!read_ref_full(newrefname, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ sha1, NULL) &&
+ delete_ref(newrefname, NULL, REF_NODEREF)) {
if (errno==EISDIR) {
struct strbuf path = STRBUF_INIT;
int result;
logmoved = log;
- lock = lock_ref_sha1_basic(newrefname, NULL, NULL, NULL, 0, NULL, &err);
+ lock = lock_ref_sha1_basic(newrefname, NULL, NULL, NULL, REF_NODEREF,
+ NULL, &err);
if (!lock) {
error("unable to rename '%s' to '%s': %s", oldrefname, newrefname, err.buf);
strbuf_release(&err);
return 0;
rollback:
- lock = lock_ref_sha1_basic(oldrefname, NULL, NULL, NULL, 0, NULL, &err);
+ lock = lock_ref_sha1_basic(oldrefname, NULL, NULL, NULL, REF_NODEREF,
+ NULL, &err);
if (!lock) {
error("unable to lock %s for rollback: %s", oldrefname, err.buf);
strbuf_release(&err);
strbuf_git_path(logfile, "logs/%s", refname);
if (force_create || should_autocreate_reflog(refname)) {
if (safe_create_leading_directories(logfile->buf) < 0) {
- strbuf_addf(err, "unable to create directory for %s: "
+ strbuf_addf(err, "unable to create directory for '%s': "
"%s", logfile->buf, strerror(errno));
return -1;
}
if (errno == EISDIR) {
if (remove_empty_directories(logfile)) {
- strbuf_addf(err, "There are still logs under "
+ strbuf_addf(err, "there are still logs under "
"'%s'", logfile->buf);
return -1;
}
}
if (logfd < 0) {
- strbuf_addf(err, "unable to append to %s: %s",
+ strbuf_addf(err, "unable to append to '%s': %s",
logfile->buf, strerror(errno));
return -1;
}
result = log_ref_write_fd(logfd, old_sha1, new_sha1,
git_committer_info(0), msg);
if (result) {
- strbuf_addf(err, "unable to append to %s: %s", logfile->buf,
+ strbuf_addf(err, "unable to append to '%s': %s", logfile->buf,
strerror(errno));
close(logfd);
return -1;
}
if (close(logfd)) {
- strbuf_addf(err, "unable to append to %s: %s", logfile->buf,
+ strbuf_addf(err, "unable to append to '%s': %s", logfile->buf,
strerror(errno));
return -1;
}
o = parse_object(sha1);
if (!o) {
strbuf_addf(err,
- "Trying to write ref %s with nonexistent object %s",
+ "trying to write ref '%s' with nonexistent object %s",
lock->ref_name, sha1_to_hex(sha1));
unlock_ref(lock);
return -1;
}
if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) {
strbuf_addf(err,
- "Trying to write non-commit object %s to branch %s",
+ "trying to write non-commit object %s to branch '%s'",
sha1_to_hex(sha1), lock->ref_name);
unlock_ref(lock);
return -1;
write_in_full(fd, &term, 1) != 1 ||
close_ref(lock) < 0) {
strbuf_addf(err,
- "Couldn't write %s", get_lock_file_path(lock->lk));
+ "couldn't write '%s'", get_lock_file_path(lock->lk));
unlock_ref(lock);
return -1;
}
(strcmp(lock->ref_name, lock->orig_ref_name) &&
log_ref_write(lock->orig_ref_name, lock->old_oid.hash, sha1, logmsg, flags, err) < 0)) {
char *old_msg = strbuf_detach(err, NULL);
- strbuf_addf(err, "Cannot update the ref '%s': %s",
+ strbuf_addf(err, "cannot update the ref '%s': %s",
lock->ref_name, old_msg);
free(old_msg);
unlock_ref(lock);
}
}
}
- if (commit_ref(lock)) {
- strbuf_addf(err, "Couldn't set %s", lock->ref_name);
+ if (!(flags & REF_LOG_ONLY) && commit_ref(lock)) {
+ strbuf_addf(err, "couldn't set '%s'", lock->ref_name);
unlock_ref(lock);
return -1;
}
for (i = 1; i < n; i++)
if (!strcmp(refnames->items[i - 1].string, refnames->items[i].string)) {
strbuf_addf(err,
- "Multiple updates for ref '%s' not allowed.",
+ "multiple updates for ref '%s' not allowed.",
refnames->items[i].string);
return 1;
}
goto cleanup;
}
if ((update->flags & REF_HAVE_NEW) &&
- !(update->flags & REF_DELETING)) {
+ !(update->flags & REF_DELETING) &&
+ !(update->flags & REF_LOG_ONLY)) {
int overwriting_symref = ((update->type & REF_ISSYMREF) &&
(update->flags & REF_NODEREF));
}
if (!(update->flags & REF_NEEDS_COMMIT)) {
/*
- * We didn't have to write anything to the lockfile.
- * Close it to free up the file descriptor:
+ * We didn't call write_ref_to_lockfile(), so
+ * the lockfile is still open. Close it to
+ * free up the file descriptor:
*/
if (close_ref(update->lock)) {
- strbuf_addf(err, "Couldn't close %s.lock",
+ strbuf_addf(err, "couldn't close '%s.lock'",
update->refname);
+ ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;
}
}
for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i];
- if (update->flags & REF_NEEDS_COMMIT) {
+ if (update->flags & REF_NEEDS_COMMIT ||
+ update->flags & REF_LOG_ONLY) {
if (commit_ref_update(update->lock,
update->new_sha1, update->msg,
update->flags, err)) {
for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i];
- if (update->flags & REF_DELETING) {
+ if (update->flags & REF_DELETING &&
+ !(update->flags & REF_LOG_ONLY)) {
if (delete_ref_loose(update->lock, update->type, err)) {
ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;