]> git.ipfire.org Git - thirdparty/git.git/blobdiff - refs.c
Merge branch 'jc/test-i18ngrep'
[thirdparty/git.git] / refs.c
diff --git a/refs.c b/refs.c
index 6b826b002e3b15db0889cf06b54eeccf6ea532ba..55d2e0b2cb9e959443e98eb329fdf97eff9073a9 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -35,6 +35,7 @@
  */
 static const struct ref_storage_be *refs_backends[] = {
        [REF_STORAGE_FORMAT_FILES] = &refs_be_files,
+       [REF_STORAGE_FORMAT_REFTABLE] = &refs_be_reftable,
 };
 
 static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format)
@@ -859,6 +860,47 @@ static int is_pseudoref_syntax(const char *refname)
        return 1;
 }
 
+int is_pseudoref(struct ref_store *refs, const char *refname)
+{
+       static const char *const irregular_pseudorefs[] = {
+               "AUTO_MERGE",
+               "BISECT_EXPECTED_REV",
+               "NOTES_MERGE_PARTIAL",
+               "NOTES_MERGE_REF",
+               "MERGE_AUTOSTASH",
+       };
+       struct object_id oid;
+       size_t i;
+
+       if (!is_pseudoref_syntax(refname))
+               return 0;
+
+       if (ends_with(refname, "_HEAD")) {
+               refs_resolve_ref_unsafe(refs, refname,
+                                       RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+                                       &oid, NULL);
+               return !is_null_oid(&oid);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
+               if (!strcmp(refname, irregular_pseudorefs[i])) {
+                       refs_resolve_ref_unsafe(refs, refname,
+                                               RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+                                               &oid, NULL);
+                       return !is_null_oid(&oid);
+               }
+
+       return 0;
+}
+
+int is_headref(struct ref_store *refs, const char *refname)
+{
+       if (!strcmp(refname, "HEAD"))
+               return refs_ref_exists(refs, refname);
+
+       return 0;
+}
+
 static int is_current_worktree_ref(const char *ref) {
        return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
 }
@@ -1109,6 +1151,21 @@ int read_ref_at(struct ref_store *refs, const char *refname,
        refs_for_each_reflog_ent_reverse(refs, refname, read_ref_at_ent, &cb);
 
        if (!cb.reccnt) {
+               if (cnt == 0) {
+                       /*
+                        * The caller asked for ref@{0}, and we had no entries.
+                        * It's a bit subtle, but in practice all callers have
+                        * prepped the "oid" field with the current value of
+                        * the ref, which is the most reasonable fallback.
+                        *
+                        * We'll put dummy values into the out-parameters (so
+                        * they're not just uninitialized garbage), and the
+                        * caller can take our return value as a hint that
+                        * we did not find any such reflog.
+                        */
+                       set_read_ref_cutoffs(&cb, 0, 0, "empty reflog");
+                       return 1;
+               }
                if (flags & GET_OID_QUIETLY)
                        exit(128);
                else
@@ -1573,10 +1630,6 @@ struct ref_iterator *refs_ref_iterator_begin(
        if (trim)
                iter = prefix_ref_iterator_begin(iter, "", trim);
 
-       /* Sanity check for subclasses: */
-       if (!iter->ordered)
-               BUG("reference iterator is not ordered");
-
        return iter;
 }
 
@@ -1703,6 +1756,13 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
        return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
 }
 
+int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
+                                   void *cb_data)
+{
+       return do_for_each_ref(refs, "", NULL, fn, 0,
+                              DO_FOR_EACH_INCLUDE_ROOT_REFS, cb_data);
+}
+
 static int qsort_strcmp(const void *va, const void *vb)
 {
        const char *a = *(const char **)va;
@@ -2495,18 +2555,33 @@ cleanup:
        return ret;
 }
 
-int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
+struct do_for_each_reflog_help {
+       each_reflog_fn *fn;
+       void *cb_data;
+};
+
+static int do_for_each_reflog_helper(struct repository *r UNUSED,
+                                    const char *refname,
+                                    const struct object_id *oid UNUSED,
+                                    int flags,
+                                    void *cb_data)
+{
+       struct do_for_each_reflog_help *hp = cb_data;
+       return hp->fn(refname, hp->cb_data);
+}
+
+int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data)
 {
        struct ref_iterator *iter;
-       struct do_for_each_ref_help hp = { fn, cb_data };
+       struct do_for_each_reflog_help hp = { fn, cb_data };
 
        iter = refs->be->reflog_iterator_begin(refs);
 
        return do_for_each_repo_ref_iterator(the_repository, iter,
-                                            do_for_each_ref_helper, &hp);
+                                            do_for_each_reflog_helper, &hp);
 }
 
-int for_each_reflog(each_ref_fn fn, void *cb_data)
+int for_each_reflog(each_reflog_fn fn, void *cb_data)
 {
        return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
 }