midx: sort and deduplicate objects from packfiles
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 2e4a42f45963c5f8725b339cdab7b6a52e685e4d..0eb379f9312fd9f167fea2e0f148c85c47cd2ff0 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -303,7 +303,7 @@ enum peel_status peel_object(const struct object_id *name, struct object_id *oid
        struct object *o = lookup_unknown_object(name->hash);
 
        if (o->type == OBJ_NONE) {
-               int type = oid_object_info(name, NULL);
+               int type = oid_object_info(the_repository, name, NULL);
                if (type < 0 || !object_as_type(o, type, 0))
                        return PEEL_INVALID;
        }
@@ -615,7 +615,8 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **log)
 static int is_per_worktree_ref(const char *refname)
 {
        return !strcmp(refname, "HEAD") ||
-               starts_with(refname, "refs/bisect/");
+               starts_with(refname, "refs/bisect/") ||
+               starts_with(refname, "refs/rewritten/");
 }
 
 static int is_pseudoref_syntax(const char *refname)
@@ -659,7 +660,7 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
 {
        const char *filename;
        int fd;
-       static struct lock_file lock;
+       struct lock_file lock = LOCK_INIT;
        struct strbuf buf = STRBUF_INIT;
        int ret = -1;
 
@@ -669,8 +670,7 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
        strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
 
        filename = git_path("%s", pseudoref);
-       fd = hold_lock_file_for_update_timeout(&lock, filename,
-                                              LOCK_DIE_ON_ERROR,
+       fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
                                               get_files_ref_lock_timeout_ms());
        if (fd < 0) {
                strbuf_addf(err, "could not open '%s' for writing: %s",
@@ -681,10 +681,21 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
        if (old_oid) {
                struct object_id actual_old_oid;
 
-               if (read_ref(pseudoref, &actual_old_oid))
-                       die("could not read ref '%s'", pseudoref);
-               if (oidcmp(&actual_old_oid, old_oid)) {
-                       strbuf_addf(err, "unexpected sha1 when writing '%s'", pseudoref);
+               if (read_ref(pseudoref, &actual_old_oid)) {
+                       if (!is_null_oid(old_oid)) {
+                               strbuf_addf(err, "could not read ref '%s'",
+                                           pseudoref);
+                               rollback_lock_file(&lock);
+                               goto done;
+                       }
+               } else if (is_null_oid(old_oid)) {
+                       strbuf_addf(err, "ref '%s' already exists",
+                                   pseudoref);
+                       rollback_lock_file(&lock);
+                       goto done;
+               } else if (oidcmp(&actual_old_oid, old_oid)) {
+                       strbuf_addf(err, "unexpected object ID when writing '%s'",
+                                   pseudoref);
                        rollback_lock_file(&lock);
                        goto done;
                }
@@ -705,24 +716,28 @@ static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
 
 static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
 {
-       static struct lock_file lock;
        const char *filename;
 
        filename = git_path("%s", pseudoref);
 
        if (old_oid && !is_null_oid(old_oid)) {
+               struct lock_file lock = LOCK_INIT;
                int fd;
                struct object_id actual_old_oid;
 
                fd = hold_lock_file_for_update_timeout(
-                               &lock, filename, LOCK_DIE_ON_ERROR,
+                               &lock, filename, 0,
                                get_files_ref_lock_timeout_ms());
-               if (fd < 0)
-                       die_errno(_("Could not open '%s' for writing"), filename);
+               if (fd < 0) {
+                       error_errno(_("could not open '%s' for writing"),
+                                   filename);
+                       return -1;
+               }
                if (read_ref(pseudoref, &actual_old_oid))
                        die("could not read ref '%s'", pseudoref);
                if (oidcmp(&actual_old_oid, old_oid)) {
-                       warning("Unexpected sha1 when deleting %s", pseudoref);
+                       error("unexpected object ID when deleting '%s'",
+                             pseudoref);
                        rollback_lock_file(&lock);
                        return -1;
                }
@@ -959,10 +974,10 @@ void ref_transaction_free(struct ref_transaction *transaction)
                /* OK */
                break;
        case REF_TRANSACTION_PREPARED:
-               die("BUG: free called on a prepared reference transaction");
+               BUG("free called on a prepared reference transaction");
                break;
        default:
-               die("BUG: unexpected reference transaction state");
+               BUG("unexpected reference transaction state");
                break;
        }
 
@@ -984,7 +999,7 @@ struct ref_update *ref_transaction_add_update(
        struct ref_update *update;
 
        if (transaction->state != REF_TRANSACTION_OPEN)
-               die("BUG: update called for transaction that is not open");
+               BUG("update called for transaction that is not open");
 
        FLEX_ALLOC_STR(update, refname, refname);
        ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
@@ -1034,7 +1049,7 @@ int ref_transaction_create(struct ref_transaction *transaction,
                           struct strbuf *err)
 {
        if (!new_oid || is_null_oid(new_oid))
-               die("BUG: create called without valid new_oid");
+               BUG("create called without valid new_oid");
        return ref_transaction_update(transaction, refname, new_oid,
                                      &null_oid, flags, msg, err);
 }
@@ -1046,7 +1061,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,
                           struct strbuf *err)
 {
        if (old_oid && is_null_oid(old_oid))
-               die("BUG: delete called with old_oid set to zeros");
+               BUG("delete called with old_oid set to zeros");
        return ref_transaction_update(transaction, refname,
                                      &null_oid, old_oid,
                                      flags, msg, err);
@@ -1059,7 +1074,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
                           struct strbuf *err)
 {
        if (!old_oid)
-               die("BUG: verify called with old_oid set to NULL");
+               BUG("verify called with old_oid set to NULL");
        return ref_transaction_update(transaction, refname,
                                      NULL, old_oid,
                                      flags, NULL, err);
@@ -1147,8 +1162,8 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
                for (i = 0; i < nr_rules; i++) {
                        assert(offset < total_len);
                        scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
-                       offset += snprintf(scanf_fmts[i], total_len - offset,
-                                          ref_rev_parse_rules[i], 2, "%s") + 1;
+                       offset += xsnprintf(scanf_fmts[i], total_len - offset,
+                                           ref_rev_parse_rules[i], 2, "%s") + 1;
                }
        }
 
@@ -1657,7 +1672,7 @@ static struct ref_store *ref_store_init(const char *gitdir,
        struct ref_store *refs;
 
        if (!be)
-               die("BUG: reference backend %s is unknown", be_name);
+               BUG("reference backend %s is unknown", be_name);
 
        refs = be->init(gitdir, flags);
        return refs;
@@ -1688,7 +1703,7 @@ static void register_ref_store_map(struct hashmap *map,
                hashmap_init(map, ref_store_hash_cmp, NULL, 0);
 
        if (hashmap_put(map, alloc_ref_store_hash_entry(name, refs)))
-               die("BUG: %s ref_store '%s' initialized twice", type, name);
+               BUG("%s ref_store '%s' initialized twice", type, name);
 }
 
 struct ref_store *get_submodule_ref_store(const char *submodule)
@@ -1834,7 +1849,7 @@ int ref_update_reject_duplicates(struct string_list *refnames,
                                    refnames->items[i].string);
                        return 1;
                } else if (cmp > 0) {
-                       die("BUG: ref_update_reject_duplicates() received unsorted list");
+                       BUG("ref_update_reject_duplicates() received unsorted list");
                }
        }
        return 0;
@@ -1850,13 +1865,13 @@ int ref_transaction_prepare(struct ref_transaction *transaction,
                /* Good. */
                break;
        case REF_TRANSACTION_PREPARED:
-               die("BUG: prepare called twice on reference transaction");
+               BUG("prepare called twice on reference transaction");
                break;
        case REF_TRANSACTION_CLOSED:
-               die("BUG: prepare called on a closed reference transaction");
+               BUG("prepare called on a closed reference transaction");
                break;
        default:
-               die("BUG: unexpected reference transaction state");
+               BUG("unexpected reference transaction state");
                break;
        }
 
@@ -1883,10 +1898,10 @@ int ref_transaction_abort(struct ref_transaction *transaction,
                ret = refs->be->transaction_abort(refs, transaction, err);
                break;
        case REF_TRANSACTION_CLOSED:
-               die("BUG: abort called on a closed reference transaction");
+               BUG("abort called on a closed reference transaction");
                break;
        default:
-               die("BUG: unexpected reference transaction state");
+               BUG("unexpected reference transaction state");
                break;
        }
 
@@ -1911,10 +1926,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                /* Fall through to finish. */
                break;
        case REF_TRANSACTION_CLOSED:
-               die("BUG: commit called on a closed reference transaction");
+               BUG("commit called on a closed reference transaction");
                break;
        default:
-               die("BUG: unexpected reference transaction state");
+               BUG("unexpected reference transaction state");
                break;
        }
 
@@ -1995,7 +2010,7 @@ int refs_verify_refname_available(struct ref_store *refs,
        }
 
        if (ok != ITER_DONE)
-               die("BUG: error while iterating over references");
+               BUG("error while iterating over references");
 
        extra_refname = find_descendant_ref(dirname.buf, extras, skip);
        if (extra_refname)