sequencer (rebase -i): the todo can be empty when continuing
[gitweb.git] / refs / files-backend.c
index 82b3ac0dbc1c7b4665515e6b04ce2689674253b0..f9023939d5884e0f975d5997336313695e407ca1 100644 (file)
@@ -501,7 +501,7 @@ static void sort_ref_dir(struct ref_dir *dir)
        if (dir->sorted == dir->nr)
                return;
 
-       qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
+       QSORT(dir->entries, dir->nr, ref_entry_cmp);
 
        /* Remove any duplicates: */
        for (i = 0, j = 0; j < dir->nr; j++) {
@@ -1201,13 +1201,19 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
        struct strbuf refname;
        struct strbuf path = STRBUF_INIT;
        size_t path_baselen;
+       int err = 0;
 
        if (*refs->base.submodule)
-               strbuf_git_path_submodule(&path, refs->base.submodule, "%s", dirname);
+               err = strbuf_git_path_submodule(&path, refs->base.submodule, "%s", dirname);
        else
                strbuf_git_path(&path, "%s", dirname);
        path_baselen = path.len;
 
+       if (err) {
+               strbuf_release(&path);
+               return;
+       }
+
        d = opendir(path.buf);
        if (!d) {
                strbuf_release(&path);
@@ -1347,6 +1353,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
        int fd;
        int ret = -1;
        int save_errno;
+       int remaining_retries = 3;
 
        *type = 0;
        strbuf_reset(&sb_path);
@@ -1367,8 +1374,14 @@ static int files_read_raw_ref(struct ref_store *ref_store,
         * <-> symlink) between the lstat() and reading, then
         * we don't want to report that as an error but rather
         * try again starting with the lstat().
+        *
+        * We'll keep a count of the retries, though, just to avoid
+        * any confusing situation sending us into an infinite loop.
         */
 
+       if (remaining_retries-- <= 0)
+               goto out;
+
        if (lstat(path, &st) < 0) {
                if (errno != ENOENT)
                        goto out;
@@ -1397,6 +1410,11 @@ static int files_read_raw_ref(struct ref_store *ref_store,
                        ret = 0;
                        goto out;
                }
+               /*
+                * It doesn't look like a refname; fall through to just
+                * treating it like a non-symlink, and reading whatever it
+                * points to.
+                */
        }
 
        /* Is it a directory? */
@@ -1420,7 +1438,7 @@ static int files_read_raw_ref(struct ref_store *ref_store,
         */
        fd = open(path, O_RDONLY);
        if (fd < 0) {
-               if (errno == ENOENT)
+               if (errno == ENOENT && !S_ISLNK(st.st_mode))
                        /* inconsistent with lstat; retry */
                        goto stat_ref;
                else
@@ -1798,6 +1816,10 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
        int ok;
 
        while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
+               if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
+                   ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
+                       continue;
+
                if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
                    !ref_resolves_to_object(iter->iter0->refname,
                                            iter->iter0->oid,
@@ -1938,14 +1960,14 @@ static int verify_lock(struct ref_lock *lock,
                        errno = save_errno;
                        return -1;
                } else {
-                       hashclr(lock->old_oid.hash);
+                       oidclr(&lock->old_oid);
                        return 0;
                }
        }
        if (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) {
                strbuf_addf(err, "ref '%s' is at %s but expected %s",
                            lock->ref_name,
-                           sha1_to_hex(lock->old_oid.hash),
+                           oid_to_hex(&lock->old_oid),
                            sha1_to_hex(old_sha1));
                errno = EBUSY;
                return -1;
@@ -3480,6 +3502,38 @@ static const char *original_update_refname(struct ref_update *update)
        return update->refname;
 }
 
+/*
+ * Check whether the REF_HAVE_OLD and old_oid values stored in update
+ * are consistent with oid, which is the reference's current value. If
+ * everything is OK, return 0; otherwise, write an error message to
+ * err and return -1.
+ */
+static int check_old_oid(struct ref_update *update, struct object_id *oid,
+                        struct strbuf *err)
+{
+       if (!(update->flags & REF_HAVE_OLD) ||
+                  !hashcmp(oid->hash, update->old_sha1))
+               return 0;
+
+       if (is_null_sha1(update->old_sha1))
+               strbuf_addf(err, "cannot lock ref '%s': "
+                           "reference already exists",
+                           original_update_refname(update));
+       else if (is_null_oid(oid))
+               strbuf_addf(err, "cannot lock ref '%s': "
+                           "reference is missing but expected %s",
+                           original_update_refname(update),
+                           sha1_to_hex(update->old_sha1));
+       else
+               strbuf_addf(err, "cannot lock ref '%s': "
+                           "is at %s but expected %s",
+                           original_update_refname(update),
+                           oid_to_hex(oid),
+                           sha1_to_hex(update->old_sha1));
+
+       return -1;
+}
+
 /*
  * Prepare for carrying out update:
  * - Lock the reference referred to by update.
@@ -3527,7 +3581,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
 
                reason = strbuf_detach(err, NULL);
                strbuf_addf(err, "cannot lock ref '%s': %s",
-                           update->refname, reason);
+                           original_update_refname(update), reason);
                free(reason);
                return ret;
        }
@@ -3541,28 +3595,17 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                         * the transaction, so we have to read it here
                         * to record and possibly check old_sha1:
                         */
-                       if (read_ref_full(update->refname,
-                                         mustexist ? RESOLVE_REF_READING : 0,
+                       if (read_ref_full(referent.buf, 0,
                                          lock->old_oid.hash, NULL)) {
                                if (update->flags & REF_HAVE_OLD) {
                                        strbuf_addf(err, "cannot lock ref '%s': "
-                                                   "can't resolve old value",
-                                                   update->refname);
-                                       return TRANSACTION_GENERIC_ERROR;
-                               } else {
-                                       hashclr(lock->old_oid.hash);
+                                                   "error reading reference",
+                                                   original_update_refname(update));
+                                       return -1;
                                }
-                       }
-                       if ((update->flags & REF_HAVE_OLD) &&
-                           hashcmp(lock->old_oid.hash, update->old_sha1)) {
-                               strbuf_addf(err, "cannot lock ref '%s': "
-                                           "is at %s but expected %s",
-                                           update->refname,
-                                           sha1_to_hex(lock->old_oid.hash),
-                                           sha1_to_hex(update->old_sha1));
+                       } else if (check_old_oid(update, &lock->old_oid, err)) {
                                return TRANSACTION_GENERIC_ERROR;
                        }
-
                } else {
                        /*
                         * Create a new update for the reference this
@@ -3580,6 +3623,9 @@ static int lock_ref_for_update(struct files_ref_store *refs,
        } else {
                struct ref_update *parent_update;
 
+               if (check_old_oid(update, &lock->old_oid, err))
+                       return TRANSACTION_GENERIC_ERROR;
+
                /*
                 * If this update is happening indirectly because of a
                 * symref update, record the old SHA-1 in the parent
@@ -3591,20 +3637,6 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                        struct ref_lock *parent_lock = parent_update->backend_data;
                        oidcpy(&parent_lock->old_oid, &lock->old_oid);
                }
-
-               if ((update->flags & REF_HAVE_OLD) &&
-                   hashcmp(lock->old_oid.hash, update->old_sha1)) {
-                       if (is_null_sha1(update->old_sha1))
-                               strbuf_addf(err, "cannot lock ref '%s': reference already exists",
-                                           original_update_refname(update));
-                       else
-                               strbuf_addf(err, "cannot lock ref '%s': is at %s but expected %s",
-                                           original_update_refname(update),
-                                           sha1_to_hex(lock->old_oid.hash),
-                                           sha1_to_hex(update->old_sha1));
-
-                       return TRANSACTION_GENERIC_ERROR;
-               }
        }
 
        if ((update->flags & REF_HAVE_NEW) &&
@@ -3626,7 +3658,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                         */
                        update->backend_data = NULL;
                        strbuf_addf(err,
-                                   "cannot update the ref '%s': %s",
+                                   "cannot update ref '%s': %s",
                                    update->refname, write_err);
                        free(write_err);
                        return TRANSACTION_GENERIC_ERROR;