verify_refname_available(): adjust constness in declaration
[gitweb.git] / refs / files-backend.c
index 814e230fa323851d6def5fcd89b0bee7a9d0f8bc..1d1b72d57d1c895280e54e79d0e52192a70094de 100644 (file)
@@ -1388,38 +1388,8 @@ static int resolve_missing_loose_ref(const char *refname,
        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;
@@ -1430,6 +1400,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
        int ret = -1;
        int save_errno;
 
+       *type = 0;
        strbuf_reset(&sb_path);
        strbuf_git_path(&sb_path, "%s", refname);
        path = sb_path.buf;
@@ -1448,7 +1419,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
        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;
                }
@@ -1468,8 +1439,8 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
                }
                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;
                }
@@ -1482,7 +1453,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
                 * 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;
                }
@@ -1517,9 +1488,9 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
                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;
        }
@@ -1530,7 +1501,7 @@ int read_raw_ref(const char *refname, unsigned char *sha1,
         */
        if (get_sha1_hex(buf, sha1) ||
            (buf[40] != '\0' && !isspace(buf[40]))) {
-               *flags |= REF_ISBROKEN;
+               *type |= REF_ISBROKEN;
                errno = EINVAL;
                goto out;
        }
@@ -1730,7 +1701,7 @@ static int verify_lock(struct ref_lock *lock,
                          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 {
@@ -1739,7 +1710,7 @@ static int verify_lock(struct ref_lock *lock,
                }
        }
        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));
@@ -1767,7 +1738,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                                            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;
@@ -1775,7 +1746,6 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        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;
@@ -1795,7 +1765,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        }
 
        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
@@ -1813,16 +1783,14 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                        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;
@@ -1860,7 +1828,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                /* 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;
        }
@@ -2119,7 +2087,7 @@ static void prune_ref(struct ref_to_prune *r)
        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);
@@ -2331,8 +2299,8 @@ static int rename_tmp_log(const char *newrefname)
 }
 
 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);
@@ -2365,7 +2333,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        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)
@@ -2383,8 +2352,16 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
                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;
@@ -2408,7 +2385,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
 
        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);
@@ -2426,7 +2404,8 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
        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);
@@ -2505,7 +2484,7 @@ static int log_ref_setup(const char *refname, struct strbuf *logfile, struct str
        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;
                }
@@ -2519,7 +2498,7 @@ static int log_ref_setup(const char *refname, struct strbuf *logfile, struct str
 
                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;
                        }
@@ -2527,7 +2506,7 @@ static int log_ref_setup(const char *refname, struct strbuf *logfile, struct str
                }
 
                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;
                }
@@ -2596,13 +2575,13 @@ static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
        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;
        }
@@ -2643,14 +2622,14 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
        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;
@@ -2660,7 +2639,7 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
            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;
        }
@@ -2681,7 +2660,7 @@ static int commit_ref_update(struct ref_lock *lock,
            (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);
@@ -2715,8 +2694,8 @@ static int commit_ref_update(struct ref_lock *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;
        }
@@ -3065,7 +3044,7 @@ static int ref_update_reject_duplicates(struct string_list *refnames,
        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;
                }
@@ -3133,7 +3112,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                        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));
 
@@ -3165,12 +3145,14 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                }
                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;
                        }
                }
@@ -3180,7 +3162,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        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)) {
@@ -3199,7 +3182,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        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;