This patch separates submodule odb sources from ordinary alternate
sources. The new sources can be accessed with ODB_EXTALT (e.g. via
read_sha1_file_extended).

ODB_EXTALT is only added to odb_default in certain cases. Basically:

 - External commands do not access submodule odb by default
 - unpack-objects, index-pack and rev-list do not
 - All other builtin commands do

unpack-objects, index-pack and rev-list take new objects from outside
and have to make sure the repository is still in good state. They
should not pay attention to submodule's odb, especially rev-list
because it does connectivity check.

External commands also do not have default access to submodule odb,
simply because I see no reasons why the should. They don't usually
play a big role in the user front, where submodule integration happens
and requires looking into submodule odb.

The die() in add_submodule_odb() may be too strong. There might be a
use case where somebody wants to add_submodule_odb() and look some up
with read_sha1_file_extended() even if odb_default does not contain
ODB_EXTALT. Right now such a use case may need to work around die() by
temporarily adding ODB_EXTALT to odb_default. Not nice, but as no such
use case exists yet to worry about.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 cache.h     |  1 +
 git.c       | 10 +++++++---
 sha1_file.c | 24 +++++++++++++++++-------
 submodule.c |  3 +++
 4 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/cache.h b/cache.h
index b8d8e03..bc3ccd8 100644
--- a/cache.h
+++ b/cache.h
@@ -759,6 +759,7 @@ int offset_1st_component(const char *path);
  * function cals explicitly.
  */
 #define ODB_DEFAULT    8
+#define ODB_EXTALT     16
 
 extern unsigned int odb_default;
 
diff --git a/git.c b/git.c
index 1ada169..49a66fa 100644
--- a/git.c
+++ b/git.c
@@ -242,6 +242,7 @@ static int handle_alias(int *argcp, const char ***argv)
  * RUN_SETUP for reading from the configuration file.
  */
 #define NEED_WORK_TREE         (1<<3)
+#define NO_ODB_EXTALT          (1<<4)
 
 struct cmd_struct {
        const char *cmd;
@@ -258,6 +259,9 @@ static int run_builtin(struct cmd_struct *p, int argc, 
const char **argv)
        prefix = NULL;
        help = argc == 2 && !strcmp(argv[1], "-h");
        if (!help) {
+               if (!(p->option & NO_ODB_EXTALT))
+                       odb_default |= ODB_EXTALT;
+
                if (p->option & RUN_SETUP)
                        prefix = setup_git_directory();
                if (p->option & RUN_SETUP_GENTLY) {
@@ -349,7 +353,7 @@ static void handle_internal_command(int argc, const char 
**argv)
                { "grep", cmd_grep, RUN_SETUP_GENTLY },
                { "hash-object", cmd_hash_object },
                { "help", cmd_help },
-               { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
+               { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY | 
NO_ODB_EXTALT },
                { "init", cmd_init_db },
                { "init-db", cmd_init_db },
                { "log", cmd_log, RUN_SETUP },
@@ -392,7 +396,7 @@ static void handle_internal_command(int argc, const char 
**argv)
                { "repo-config", cmd_repo_config, RUN_SETUP_GENTLY },
                { "rerere", cmd_rerere, RUN_SETUP },
                { "reset", cmd_reset, RUN_SETUP },
-               { "rev-list", cmd_rev_list, RUN_SETUP },
+               { "rev-list", cmd_rev_list, RUN_SETUP | NO_ODB_EXTALT },
                { "rev-parse", cmd_rev_parse },
                { "revert", cmd_revert, RUN_SETUP | NEED_WORK_TREE },
                { "rm", cmd_rm, RUN_SETUP },
@@ -408,7 +412,7 @@ static void handle_internal_command(int argc, const char 
**argv)
                { "tag", cmd_tag, RUN_SETUP },
                { "tar-tree", cmd_tar_tree },
                { "unpack-file", cmd_unpack_file, RUN_SETUP },
-               { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
+               { "unpack-objects", cmd_unpack_objects, RUN_SETUP | 
NO_ODB_EXTALT },
                { "update-index", cmd_update_index, RUN_SETUP },
                { "update-ref", cmd_update_ref, RUN_SETUP },
                { "update-server-info", cmd_update_server_info, RUN_SETUP },
diff --git a/sha1_file.c b/sha1_file.c
index eb682b3..53f93ab 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -37,6 +37,10 @@ static inline uintmax_t sz_fmt(size_t s) { return s; }
 const unsigned char null_sha1[20];
 
 /*
+ * Some commands may not want to touch ODB_EXTALT at all. So
+ * ODB_EXTALT is only enabled later, not now, when we know which
+ * command is running.
+ *
  * clear_delta_base_cache() may be needed if odb_default is changed to
  * a narrower origin set.
  */
@@ -433,10 +437,12 @@ void foreach_alt_odb(alt_odb_fn fn, void *cb)
                        return;
 }
 
-static inline int match_origin(unsigned int origin, int pack_local)
+static inline int match_origin(unsigned int origin,
+                              struct alternate_object_database *alt)
 {
-       return (pack_local && (origin & ODB_LOCAL)) ||
-               (!pack_local && (origin & ODB_ALT));
+       return (!alt && (origin & ODB_LOCAL)) ||
+               (alt && (origin & ODB_ALT)    && !alt->external) ||
+               (alt && (origin & ODB_EXTALT) &&  alt->external);
 }
 
 void prepare_alt_odb(void)
@@ -464,10 +470,12 @@ static int has_loose_object_extended(const unsigned char 
*sha1,
                        return 1;
        }
 
-       if (origin & ODB_ALT) {
+       if (origin & (ODB_ALT | ODB_EXTALT)) {
                struct alternate_object_database *alt;
                prepare_alt_odb();
                for (alt = alt_odb_list; alt; alt = alt->next) {
+                       if (!match_origin(origin, alt))
+                               continue;
                        fill_sha1_path(alt->name, sha1);
                        if (!access(alt->base, F_OK))
                                return 1;
@@ -478,7 +486,7 @@ static int has_loose_object_extended(const unsigned char 
*sha1,
 
 int has_loose_object_nonlocal(const unsigned char *sha1)
 {
-       unsigned int origin = ODB_ALT;
+       unsigned int origin = ODB_ALT | ODB_EXTALT;
        return has_loose_object_extended(sha1, origin);
 }
 
@@ -1354,7 +1362,7 @@ static int open_sha1_file(const unsigned char *sha1, 
unsigned int origin)
            (fd = git_open_noatime(name)) >= 0)
                return fd;
 
-       if (!(origin & ODB_ALT)) {
+       if (!(origin & (ODB_ALT | ODB_EXTALT))) {
                errno = ENOENT;
                return -1;
        }
@@ -1362,6 +1370,8 @@ static int open_sha1_file(const unsigned char *sha1, 
unsigned int origin)
        prepare_alt_odb();
        errno = ENOENT;
        for (alt = alt_odb_list; alt; alt = alt->next) {
+               if (!match_origin(origin, alt))
+                       continue;
                name = alt->name;
                fill_sha1_path(name, sha1);
                fd = git_open_noatime(alt->base);
@@ -2336,7 +2346,7 @@ static int fill_pack_entry(const unsigned char *sha1,
 {
        off_t offset;
 
-       if (!match_origin(origin, p->pack_local))
+       if (!match_origin(origin, p->alt))
                return 0;
 
        if (p->num_bad_objects) {
diff --git a/submodule.c b/submodule.c
index 3cb63f7..1271366 100644
--- a/submodule.c
+++ b/submodule.c
@@ -37,6 +37,9 @@ static int add_submodule_odb(const char *path)
        int ret = 0;
        const char *git_dir;
 
+       if (!(odb_default & ODB_EXTALT))
+               die("BUG: this command does not support submodule odb");
+
        strbuf_addf(&objects_directory, "%s/.git", path);
        git_dir = read_gitfile(objects_directory.buf);
        if (git_dir) {
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to