Merge branch 'dl/complete-cherry-pick-revert-skip'
[gitweb.git] / sha1-name.c
index 6b53ea2eeb7cd62790aaba8c72afa4afe00e23c6..c665e3f96d5b67db3a3079483bbd28044fbbe120 100644 (file)
@@ -12,6 +12,7 @@
 #include "packfile.h"
 #include "object-store.h"
 #include "repository.h"
+#include "submodule.h"
 #include "midx.h"
 #include "commit-reach.h"
 
@@ -156,6 +157,9 @@ static void unique_in_pack(struct packed_git *p,
        uint32_t num, i, first = 0;
        const struct object_id *current = NULL;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
@@ -399,9 +403,9 @@ static int repo_collect_ambiguous(struct repository *r,
        return collect_ambiguous(oid, data);
 }
 
-static struct repository *sort_ambiguous_repo;
-static int sort_ambiguous(const void *a, const void *b)
+static int sort_ambiguous(const void *a, const void *b, void *ctx)
 {
+       struct repository *sort_ambiguous_repo = ctx;
        int a_type = oid_object_info(sort_ambiguous_repo, a, NULL);
        int b_type = oid_object_info(sort_ambiguous_repo, b, NULL);
        int a_type_sort;
@@ -430,10 +434,7 @@ static int sort_ambiguous(const void *a, const void *b)
 
 static void sort_ambiguous_oid_array(struct repository *r, struct oid_array *a)
 {
-       /* mutex will be needed if this code is to be made thread safe */
-       sort_ambiguous_repo = r;
-       QSORT(a->oid, a->nr, sort_ambiguous);
-       sort_ambiguous_repo = NULL;
+       QSORT_S(a->oid, a->nr, sort_ambiguous, r);
 }
 
 static enum get_oid_result get_short_oid(struct repository *r,
@@ -468,6 +469,18 @@ static enum get_oid_result get_short_oid(struct repository *r,
        find_short_packed_object(&ds);
        status = finish_object_disambiguation(&ds, oid);
 
+       /*
+        * If we didn't find it, do the usual reprepare() slow-path,
+        * since the object may have recently been added to the repository
+        * or migrated from loose to packed.
+        */
+       if (status == MISSING_OBJECT) {
+               reprepare_packed_git(r);
+               find_short_object_filename(&ds);
+               find_short_packed_object(&ds);
+               status = finish_object_disambiguation(&ds, oid);
+       }
+
        if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
                struct oid_array collect = OID_ARRAY_INIT;
 
@@ -612,6 +625,9 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
        struct object_id oid;
        const struct object_id *mad_oid;
 
+       if (p->multi_pack_index)
+               return;
+
        if (open_pack_index(p) || !p->num_objects)
                return;
 
@@ -782,7 +798,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
        "because it will be ignored when you just specify 40-hex. These refs\n"
        "may be created by mistake. For example,\n"
        "\n"
-       "  git checkout -b $br $(git rev-parse ...)\n"
+       "  git switch -c $br $(git rev-parse ...)\n"
        "\n"
        "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
        "examine these refs and maybe delete them. Turn this message off by\n"
@@ -1337,7 +1353,9 @@ static int interpret_nth_prior_checkout(struct repository *r,
        return retval;
 }
 
-int get_oid_mb(const char *name, struct object_id *oid)
+int repo_get_oid_mb(struct repository *r,
+                   const char *name,
+                   struct object_id *oid)
 {
        struct commit *one, *two;
        struct commit_list *mbs;
@@ -1347,28 +1365,28 @@ int get_oid_mb(const char *name, struct object_id *oid)
 
        dots = strstr(name, "...");
        if (!dots)
-               return get_oid(name, oid);
+               return repo_get_oid(r, name, oid);
        if (dots == name)
-               st = get_oid("HEAD", &oid_tmp);
+               st = repo_get_oid(r, "HEAD", &oid_tmp);
        else {
                struct strbuf sb;
                strbuf_init(&sb, dots - name);
                strbuf_add(&sb, name, dots - name);
-               st = get_oid_committish(sb.buf, &oid_tmp);
+               st = repo_get_oid_committish(r, sb.buf, &oid_tmp);
                strbuf_release(&sb);
        }
        if (st)
                return st;
-       one = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
+       one = lookup_commit_reference_gently(r, &oid_tmp, 0);
        if (!one)
                return -1;
 
-       if (get_oid_committish(dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
+       if (repo_get_oid_committish(r, dots[3] ? (dots + 3) : "HEAD", &oid_tmp))
                return -1;
-       two = lookup_commit_reference_gently(the_repository, &oid_tmp, 0);
+       two = lookup_commit_reference_gently(r, &oid_tmp, 0);
        if (!two)
                return -1;
-       mbs = get_merge_bases(one, two);
+       mbs = repo_get_merge_bases(r, one, two);
        if (!mbs || mbs->next)
                st = -1;
        else {
@@ -1572,12 +1590,31 @@ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
  * This is like "get_oid_basic()", except it allows "object ID expressions",
  * notably "xyz^" for "parent of xyz"
  */
-int get_oid(const char *name, struct object_id *oid)
+int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository, name, 0, oid, &unused);
+       return get_oid_with_context(r, name, 0, oid, &unused);
 }
 
+/*
+ * This returns a non-zero value if the string (built using printf
+ * format and the given arguments) is not a valid object.
+ */
+int get_oidf(struct object_id *oid, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+       struct strbuf sb = STRBUF_INIT;
+
+       va_start(ap, fmt);
+       strbuf_vaddf(&sb, fmt, ap);
+       va_end(ap);
+
+       ret = get_oid(sb.buf, oid);
+       strbuf_release(&sb);
+
+       return ret;
+}
 
 /*
  * Many callers know that the user meant to name a commit-ish by
@@ -1589,55 +1626,61 @@ int get_oid(const char *name, struct object_id *oid)
  * commit-ish. It is merely to give a hint to the disambiguation
  * machinery.
  */
-int get_oid_committish(const char *name, struct object_id *oid)
+int repo_get_oid_committish(struct repository *r,
+                           const char *name,
+                           struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository,
-                                   name, GET_OID_COMMITTISH,
+       return get_oid_with_context(r, name, GET_OID_COMMITTISH,
                                    oid, &unused);
 }
 
-int get_oid_treeish(const char *name, struct object_id *oid)
+int repo_get_oid_treeish(struct repository *r,
+                        const char *name,
+                        struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository,
-                                   name, GET_OID_TREEISH,
+       return get_oid_with_context(r, name, GET_OID_TREEISH,
                                    oid, &unused);
 }
 
-int get_oid_commit(const char *name, struct object_id *oid)
+int repo_get_oid_commit(struct repository *r,
+                       const char *name,
+                       struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository,
-                                   name, GET_OID_COMMIT,
+       return get_oid_with_context(r, name, GET_OID_COMMIT,
                                    oid, &unused);
 }
 
-int get_oid_tree(const char *name, struct object_id *oid)
+int repo_get_oid_tree(struct repository *r,
+                     const char *name,
+                     struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository,
-                                   name, GET_OID_TREE,
+       return get_oid_with_context(r, name, GET_OID_TREE,
                                    oid, &unused);
 }
 
-int get_oid_blob(const char *name, struct object_id *oid)
+int repo_get_oid_blob(struct repository *r,
+                     const char *name,
+                     struct object_id *oid)
 {
        struct object_context unused;
-       return get_oid_with_context(the_repository,
-                                   name, GET_OID_BLOB,
+       return get_oid_with_context(r, name, GET_OID_BLOB,
                                    oid, &unused);
 }
 
 /* Must be called only when object_name:filename doesn't exist. */
-static void diagnose_invalid_oid_path(const char *prefix,
+static void diagnose_invalid_oid_path(struct repository *r,
+                                     const char *prefix,
                                      const char *filename,
                                      const struct object_id *tree_oid,
                                      const char *object_name,
                                      int object_name_len)
 {
        struct object_id oid;
-       unsigned mode;
+       unsigned short mode;
 
        if (!prefix)
                prefix = "";
@@ -1648,7 +1691,7 @@ static void diagnose_invalid_oid_path(const char *prefix,
        if (is_missing_file_error(errno)) {
                char *fullname = xstrfmt("%s%s", prefix, filename);
 
-               if (!get_tree_entry(tree_oid, fullname, &oid, &mode)) {
+               if (!get_tree_entry(r, tree_oid, fullname, &oid, &mode)) {
                        die("Path '%s' exists, but not '%s'.\n"
                            "Did you mean '%.*s:%s' aka '%.*s:./%s'?",
                            fullname,
@@ -1796,8 +1839,8 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
                if (flags & GET_OID_RECORD_PATH)
                        oc->path = xstrdup(cp);
 
-               if (!repo->index->cache)
-                       repo_read_index(the_repository);
+               if (!repo->index || !repo->index->cache)
+                       repo_read_index(repo);
                pos = index_name_pos(repo->index, cp, namelen);
                if (pos < 0)
                        pos = -pos - 1;
@@ -1843,14 +1886,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
                        if (new_filename)
                                filename = new_filename;
                        if (flags & GET_OID_FOLLOW_SYMLINKS) {
-                               ret = get_tree_entry_follow_symlinks(&tree_oid,
+                               ret = get_tree_entry_follow_symlinks(repo, &tree_oid,
                                        filename, oid, &oc->symlink_path,
                                        &oc->mode);
                        } else {
-                               ret = get_tree_entry(&tree_oid, filename, oid,
+                               ret = get_tree_entry(repo, &tree_oid, filename, oid,
                                                     &oc->mode);
                                if (ret && only_to_die) {
-                                       diagnose_invalid_oid_path(prefix,
+                                       diagnose_invalid_oid_path(repo, prefix,
                                                                   filename,
                                                                   &tree_oid,
                                                                   name, len);
@@ -1876,11 +1919,13 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
  * exist in 'HEAD'" when given "HEAD:doc", or it may return in which case
  * you have a chance to diagnose the error further.
  */
-void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)
+void maybe_die_on_misspelt_object_name(struct repository *r,
+                                      const char *name,
+                                      const char *prefix)
 {
        struct object_context oc;
        struct object_id oid;
-       get_oid_with_context_1(the_repository, name, GET_OID_ONLY_TO_DIE,
+       get_oid_with_context_1(r, name, GET_OID_ONLY_TO_DIE,
                               prefix, &oid, &oc);
 }