Merge branch 'jn/per-repo-object-store-fixes'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:06 +0000 (15:24 +0900)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Sep 2017 06:24:07 +0000 (15:24 +0900)
Step #0 of a planned & larger series to make the in-core object
store per in-core repository object.

* jn/per-repo-object-store-fixes:
replace-objects: evaluate replacement refs without using the object store
push, fetch: error out for submodule entries not pointing to commits
pack: make packed_git_mru global a value instead of a pointer

builtin/pack-objects.c
cache.h
packfile.c
refs.c
submodule.c
t/t5531-deep-submodule-push.sh
index a57b4f058dff3ceec80355560bf6a856f130b8c0..f721137eaf88143aa2ae3f8c67b97fbceccbb6cf 100644 (file)
@@ -1012,7 +1012,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        return want;
        }
 
-       for (entry = packed_git_mru->head; entry; entry = entry->next) {
+       for (entry = packed_git_mru.head; entry; entry = entry->next) {
                struct packed_git *p = entry->item;
                off_t offset;
 
@@ -1030,7 +1030,7 @@ static int want_object_in_pack(const unsigned char *sha1,
                        }
                        want = want_found_object(exclude, p);
                        if (!exclude && want > 0)
-                               mru_mark(packed_git_mru, entry);
+                               mru_mark(&packed_git_mru, entry);
                        if (want != -1)
                                return want;
                }
diff --git a/cache.h b/cache.h
index a916bc79e3c1a77f55764f34f6357478e83b6cb0..49b083ee0a10ea379f271e141ccee0fa852a1954 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -4,6 +4,7 @@
 #include "git-compat-util.h"
 #include "strbuf.h"
 #include "hashmap.h"
+#include "mru.h"
 #include "advice.h"
 #include "gettext.h"
 #include "convert.h"
@@ -1589,8 +1590,7 @@ extern struct packed_git {
  * A most-recently-used ordered version of the packed_git list, which can
  * be iterated instead of packed_git (and marked via mru_mark).
  */
-struct mru;
-extern struct mru *packed_git_mru;
+extern struct mru packed_git_mru;
 
 struct pack_entry {
        off_t offset;
index f86fa051c9e67def994b8b487ad34f200967d5e9..f69a5c8d607af191fa8ba04e84da8f02c40823ef 100644 (file)
@@ -40,9 +40,7 @@ static unsigned int pack_max_fds;
 static size_t peak_pack_mapped;
 static size_t pack_mapped;
 struct packed_git *packed_git;
-
-static struct mru packed_git_mru_storage;
-struct mru *packed_git_mru = &packed_git_mru_storage;
+struct mru packed_git_mru;
 
 #define SZ_FMT PRIuMAX
 static inline uintmax_t sz_fmt(size_t s) { return s; }
@@ -861,9 +859,9 @@ static void prepare_packed_git_mru(void)
 {
        struct packed_git *p;
 
-       mru_clear(packed_git_mru);
+       mru_clear(&packed_git_mru);
        for (p = packed_git; p; p = p->next)
-               mru_append(packed_git_mru, p);
+               mru_append(&packed_git_mru, p);
 }
 
 static int prepare_packed_git_run_once = 0;
@@ -1832,9 +1830,9 @@ int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
        if (!packed_git)
                return 0;
 
-       for (p = packed_git_mru->head; p; p = p->next) {
+       for (p = packed_git_mru.head; p; p = p->next) {
                if (fill_pack_entry(sha1, e, p->item)) {
-                       mru_mark(packed_git_mru, p);
+                       mru_mark(&packed_git_mru, p);
                        return 1;
                }
        }
diff --git a/refs.c b/refs.c
index e8b67ddce80c83f8ec0dbfb3adc6d6c10b2f4b2d..0d5fe7442ae98e5bdc9641b6891cf508e2605453 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1357,7 +1357,7 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
        return do_for_each_ref(get_main_ref_store(),
                               git_replace_ref_base, fn,
                               strlen(git_replace_ref_base),
-                              0, cb_data);
+                              DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
 int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
index 075c55f3ca8101e06731ef3b45e51d11ec00c7f6..b12600fc798f4427c8ad3bff1384c6fb5a6f4bc5 100644 (file)
@@ -774,19 +774,36 @@ static int append_oid_to_argv(const struct object_id *oid, void *data)
        return 0;
 }
 
+struct has_commit_data {
+       int result;
+       const char *path;
+};
+
 static int check_has_commit(const struct object_id *oid, void *data)
 {
-       int *has_commit = data;
+       struct has_commit_data *cb = data;
 
-       if (!lookup_commit_reference(oid))
-               *has_commit = 0;
+       enum object_type type = sha1_object_info(oid->hash, NULL);
 
-       return 0;
+       switch (type) {
+       case OBJ_COMMIT:
+               return 0;
+       case OBJ_BAD:
+               /*
+                * Object is missing or invalid. If invalid, an error message
+                * has already been printed.
+                */
+               cb->result = 0;
+               return 0;
+       default:
+               die(_("submodule entry '%s' (%s) is a %s, not a commit"),
+                   cb->path, oid_to_hex(oid), typename(type));
+       }
 }
 
 static int submodule_has_commits(const char *path, struct oid_array *commits)
 {
-       int has_commit = 1;
+       struct has_commit_data has_commit = { 1, path };
 
        /*
         * Perform a cheap, but incorrect check for the existence of 'commits'.
@@ -802,7 +819,7 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
 
        oid_array_for_each_unique(commits, check_has_commit, &has_commit);
 
-       if (has_commit) {
+       if (has_commit.result) {
                /*
                 * Even if the submodule is checked out and the commit is
                 * present, make sure it exists in the submodule's object store
@@ -821,12 +838,12 @@ static int submodule_has_commits(const char *path, struct oid_array *commits)
                cp.dir = path;
 
                if (capture_command(&cp, &out, GIT_MAX_HEXSZ + 1) || out.len)
-                       has_commit = 0;
+                       has_commit.result = 0;
 
                strbuf_release(&out);
        }
 
-       return has_commit;
+       return has_commit.result;
 }
 
 static int submodule_needs_pushing(const char *path, struct oid_array *commits)
index 0f84a53146f3bac1bded4d2b11212b8ddef1bf2c..39cb2c1c3489c25545ab3cd69706c0a21378c6b7 100755 (executable)
@@ -298,6 +298,16 @@ test_expect_success 'push succeeds if submodule commit disabling recursion from
        )
 '
 
+test_expect_success 'submodule entry pointing at a tag is error' '
+       git -C work/gar/bage tag -a test1 -m "tag" &&
+       tag=$(git -C work/gar/bage rev-parse test1^{tag}) &&
+       git -C work update-index --cacheinfo 160000 "$tag" gar/bage &&
+       git -C work commit -m "bad commit" &&
+       test_when_finished "git -C work reset --hard HEAD^" &&
+       test_must_fail git -C work push --recurse-submodules=on-demand ../pub.git master 2>err &&
+       test_i18ngrep "is a tag, not a commit" err
+'
+
 test_expect_success 'push fails if recurse submodules option passed as yes' '
        (
                cd work/gar/bage &&