Merge branch 'ds/feature-macros'
authorJunio C Hamano <gitster@pobox.com>
Mon, 9 Sep 2019 19:26:36 +0000 (12:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Sep 2019 19:26:36 +0000 (12:26 -0700)
A mechanism to affect the default setting for a (related) group of
configuration variables is introduced.

* ds/feature-macros:
repo-settings: create feature.experimental setting
repo-settings: create feature.manyFiles setting
repo-settings: parse core.untrackedCache
commit-graph: turn on commit-graph by default
t6501: use 'git gc' in quiet mode
repo-settings: consolidate some config settings

26 files changed:
Documentation/config.txt
Documentation/config/core.txt
Documentation/config/feature.txt [new file with mode: 0644]
Documentation/config/fetch.txt
Documentation/config/gc.txt
Documentation/config/index.txt
Documentation/config/pack.txt
Makefile
builtin/gc.c
builtin/pack-objects.c
builtin/update-index.c
commit-graph.c
config.c
fetch-negotiator.c
fetch-negotiator.h
fetch-pack.c
read-cache.c
repo-settings.c [new file with mode: 0644]
repository.h
t/t0410-partial-clone.sh
t/t1600-index.sh
t/t5307-pack-missing-commit.sh
t/t5324-split-commit-graph.sh
t/t5552-skipping-fetch-negotiator.sh
t/t6011-rev-list-with-bad-commit.sh
t/t6501-freshen-objects.sh
index e3f5bc3396d0c7502f16eed989220c8e2010bcc1..77f3b1486b78ab81e1248e1a6cfb651c9e17fd85 100644 (file)
@@ -345,6 +345,8 @@ include::config/difftool.txt[]
 
 include::config/fastimport.txt[]
 
+include::config/feature.txt[]
+
 include::config/fetch.txt[]
 
 include::config/format.txt[]
index 75538d27e7e06b2041f556dc5e3fcd4aef1abf20..852d2ba37a1204e0e210e9abf671d7f0c9c850d8 100644 (file)
@@ -86,7 +86,9 @@ core.untrackedCache::
        it will automatically be removed, if set to `false`. Before
        setting it to `true`, you should check that mtime is working
        properly on your system.
-       See linkgit:git-update-index[1]. `keep` by default.
+       See linkgit:git-update-index[1]. `keep` by default, unless
+       `feature.manyFiles` is enabled which sets this setting to
+       `true` by default.
 
 core.checkStat::
        When missing or is set to `default`, many fields in the stat
@@ -577,7 +579,7 @@ the `GIT_NOTES_REF` environment variable.  See linkgit:git-notes[1].
 
 core.commitGraph::
        If true, then git will read the commit-graph file (if it exists)
-       to parse the graph structure of commits. Defaults to false. See
+       to parse the graph structure of commits. Defaults to true. See
        linkgit:git-commit-graph[1] for more information.
 
 core.useReplaceRefs::
diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
new file mode 100644 (file)
index 0000000..545522f
--- /dev/null
@@ -0,0 +1,29 @@
+feature.*::
+       The config settings that start with `feature.` modify the defaults of
+       a group of other config settings. These groups are created by the Git
+       developer community as recommended defaults and are subject to change.
+       In particular, new config options may be added with different defaults.
+
+feature.experimental::
+       Enable config options that are new to Git, and are being considered for
+       future defaults. Config settings included here may be added or removed
+       with each release, including minor version updates. These settings may
+       have unintended interactions since they are so new. Please enable this
+       setting if you are interested in providing feedback on experimental
+       features. The new default values are:
++
+* `pack.useSparse=true` uses a new algorithm when constructing a pack-file
+which can improve `git push` performance in repos with many files.
++
+* `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
+skipping more commits at a time, reducing the number of round trips.
+
+feature.manyFiles::
+       Enable config options that optimize for repos with many files in the
+       working directory. With many files, commands such as `git status` and
+       `git checkout` may be slow and these new defaults improve performance:
++
+* `index.version=4` enables path-prefix compression in the index.
++
+* `core.untrackedCache=true` enables the untracked cache. This setting assumes
+that mtime is working on your machine.
index ba890b5884fc3496e6529cb8e1f41ad7dd9748f4..d402110638b4e465075bf1a59885563d15f190e1 100644 (file)
@@ -59,7 +59,8 @@ fetch.negotiationAlgorithm::
        effort to converge faster, but may result in a larger-than-necessary
        packfile; The default is "default" which instructs Git to use the default algorithm
        that never skips commits (unless the server has acknowledged it or one
-       of its descendants).
+       of its descendants). If `feature.experimental` is enabled, then this
+       setting defaults to "skipping".
        Unknown values will cause 'git fetch' to error out.
 +
 See also the `--negotiation-tip` option for linkgit:git-fetch[1].
index 02b92b18b5c2cf6f9d509483a4bb995f3677d519..00ea0a678ee214f86cc91b27389572698d35bece 100644 (file)
@@ -63,7 +63,7 @@ gc.writeCommitGraph::
        If true, then gc will rewrite the commit-graph file when
        linkgit:git-gc[1] is run. When using `git gc --auto`
        the commit-graph will be updated if housekeeping is
-       required. Default is false. See linkgit:git-commit-graph[1]
+       required. Default is true. See linkgit:git-commit-graph[1]
        for details.
 
 gc.logExpiry::
index f18150304106891ad388a7620594937b43e7615e..7cb50b37e98dba813886adb4578435495be8e78c 100644 (file)
@@ -24,3 +24,4 @@ index.threads::
 index.version::
        Specify the version with which new index files should be
        initialized.  This does not affect existing repositories.
+       If `feature.manyFiles` is enabled, then the default is 4.
index 9cdcfa7324784299f431d94b5237cc136aa585d1..1d66f0c992c38237dfa7def97d9b62c9803c7fc8 100644 (file)
@@ -112,7 +112,8 @@ pack.useSparse::
        objects. This can have significant performance benefits when
        computing a pack to send a small change. However, it is possible
        that extra objects are added to the pack-file if the included
-       commits contain certain types of direct renames.
+       commits contain certain types of direct renames. Default is `false`
+       unless `feature.experimental` is enabled.
 
 pack.writeBitmaps (deprecated)::
        This is a deprecated synonym for `repack.writeBitmaps`.
index f9255344ae5009a192ab83a332be749632d94531..ad71ae12194e1d27f2adcd4014d0048ee4a5ebcd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -965,6 +965,7 @@ LIB_OBJS += refspec.o
 LIB_OBJS += ref-filter.o
 LIB_OBJS += remote.o
 LIB_OBJS += replace-object.o
+LIB_OBJS += repo-settings.o
 LIB_OBJS += repository.o
 LIB_OBJS += rerere.o
 LIB_OBJS += resolve-undo.o
index 305fb0f45af3bdfc32e15bcc18acdcaa6af205cb..a22b6ff683465a3addeb059c89775e080197f155 100644 (file)
@@ -41,7 +41,6 @@ static int aggressive_depth = 50;
 static int aggressive_window = 250;
 static int gc_auto_threshold = 6700;
 static int gc_auto_pack_limit = 50;
-static int gc_write_commit_graph;
 static int detach_auto = 1;
 static timestamp_t gc_log_expire_time;
 static const char *gc_log_expire = "1.day.ago";
@@ -148,7 +147,6 @@ static void gc_config(void)
        git_config_get_int("gc.aggressivedepth", &aggressive_depth);
        git_config_get_int("gc.auto", &gc_auto_threshold);
        git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
-       git_config_get_bool("gc.writecommitgraph", &gc_write_commit_graph);
        git_config_get_bool("gc.autodetach", &detach_auto);
        git_config_get_expiry("gc.pruneexpire", &prune_expire);
        git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
@@ -685,11 +683,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                clean_pack_garbage();
        }
 
-       if (gc_write_commit_graph &&
-           write_commit_graph_reachable(get_object_directory(),
-                                        !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
-                                        NULL))
-               return 1;
+       prepare_repo_settings(the_repository);
+       if (the_repository->settings.gc_write_commit_graph == 1)
+               write_commit_graph_reachable(get_object_directory(),
+                                            !quiet && !daemonized ? COMMIT_GRAPH_WRITE_PROGRESS : 0,
+                                            NULL);
 
        if (auto_gc && too_many_loose_objects())
                warning(_("There are too many unreachable loose objects; "
index 76ce9069467e06545652a70040b79316f0a87fb9..b410801edb6b8a18ffff17b6c720db98d4238106 100644 (file)
@@ -2715,10 +2715,6 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                use_bitmap_index_default = git_config_bool(k, v);
                return 0;
        }
-       if (!strcmp(k, "pack.usesparse")) {
-               sparse = git_config_bool(k, v);
-               return 0;
-       }
        if (!strcmp(k, "pack.threads")) {
                delta_search_threads = git_config_int(k, v);
                if (delta_search_threads < 0)
@@ -3343,6 +3339,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        read_replace_refs = 0;
 
        sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0);
+       prepare_repo_settings(the_repository);
+       if (!sparse && the_repository->settings.pack_use_sparse != -1)
+               sparse = the_repository->settings.pack_use_sparse;
+
        reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
 
index dff2f4b837208deebeb34f4af687c18df7dbfe76..49302d98c55d19651cacef7b36197de65d805e50 100644 (file)
@@ -966,6 +966,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        struct parse_opt_ctx_t ctx;
        strbuf_getline_fn getline_fn;
        int parseopt_state = PARSE_OPT_UNKNOWN;
+       struct repository *r = the_repository;
        struct option options[] = {
                OPT_BIT('q', NULL, &refresh_args.flags,
                        N_("continue refresh even when index needs update"),
@@ -1180,11 +1181,12 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                remove_split_index(&the_index);
        }
 
+       prepare_repo_settings(r);
        switch (untracked_cache) {
        case UC_UNSPECIFIED:
                break;
        case UC_DISABLE:
-               if (git_config_get_untracked_cache() == 1)
+               if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE)
                        warning(_("core.untrackedCache is set to true; "
                                  "remove or change it, if you really want to "
                                  "disable the untracked cache"));
@@ -1196,7 +1198,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                return !test_if_untracked_cache_is_supported();
        case UC_ENABLE:
        case UC_FORCE:
-               if (git_config_get_untracked_cache() == 0)
+               if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE)
                        warning(_("core.untrackedCache is set to false; "
                                  "remove or change it, if you really want to "
                                  "enable the untracked cache"));
index f2888c203b677a8a0091f7f63129efe282899172..9b02d2c42657b4cef247fee6aa4240dead0ae776 100644 (file)
@@ -467,7 +467,6 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
 static int prepare_commit_graph(struct repository *r)
 {
        struct object_directory *odb;
-       int config_value;
 
        if (git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD, 0))
                die("dying as requested by the '%s' variable on commit-graph load!",
@@ -477,9 +476,10 @@ static int prepare_commit_graph(struct repository *r)
                return !!r->objects->commit_graph;
        r->objects->commit_graph_attempted = 1;
 
+       prepare_repo_settings(r);
+
        if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
-           (repo_config_get_bool(r, "core.commitgraph", &config_value) ||
-           !config_value))
+           r->settings.core_commit_graph != 1)
                /*
                 * This repository is not configured to use commit graphs, so
                 * do not load one. (But report commit_graph_attempted anyway
index cc637363bbae10f1b87b5b7ab0bd015e49cb56b8..b61c258d6da5266a66caa55ef821de0f8e0d75aa 100644 (file)
--- a/config.c
+++ b/config.c
@@ -2288,30 +2288,6 @@ int git_config_get_expiry_in_days(const char *key, timestamp_t *expiry, timestam
        return -1; /* thing exists but cannot be parsed */
 }
 
-int git_config_get_untracked_cache(void)
-{
-       int val = -1;
-       const char *v;
-
-       /* Hack for test programs like test-dump-untracked-cache */
-       if (ignore_untracked_cache_config)
-               return -1;
-
-       if (!git_config_get_maybe_bool("core.untrackedcache", &val))
-               return val;
-
-       if (!git_config_get_value("core.untrackedcache", &v)) {
-               if (!strcasecmp(v, "keep"))
-                       return -1;
-
-               error(_("unknown core.untrackedCache value '%s'; "
-                       "using 'keep' default value"), v);
-               return -1;
-       }
-
-       return -1; /* default value */
-}
-
 int git_config_get_split_index(void)
 {
        int val;
index d6d685cba012d6765b3998fde14b5c40fff82a96..0a1357dc9d55b34992ff5a6f65e3bdf77375465e 100644 (file)
@@ -2,19 +2,20 @@
 #include "fetch-negotiator.h"
 #include "negotiator/default.h"
 #include "negotiator/skipping.h"
+#include "repository.h"
 
-void fetch_negotiator_init(struct fetch_negotiator *negotiator,
-                          const char *algorithm)
+void fetch_negotiator_init(struct repository *r,
+                          struct fetch_negotiator *negotiator)
 {
-       if (algorithm) {
-               if (!strcmp(algorithm, "skipping")) {
-                       skipping_negotiator_init(negotiator);
-                       return;
-               } else if (!strcmp(algorithm, "default")) {
-                       /* Fall through to default initialization */
-               } else {
-                       die("unknown fetch negotiation algorithm '%s'", algorithm);
-               }
+       prepare_repo_settings(r);
+       switch(r->settings.fetch_negotiation_algorithm) {
+       case FETCH_NEGOTIATION_SKIPPING:
+               skipping_negotiator_init(negotiator);
+               return;
+
+       case FETCH_NEGOTIATION_DEFAULT:
+       default:
+               default_negotiator_init(negotiator);
+               return;
        }
-       default_negotiator_init(negotiator);
 }
index 9e3967ce6626be459ad7d8a0590240b06e7056e3..ea78868504bdcff0121c40cd40b6857df1680cfc 100644 (file)
@@ -2,6 +2,7 @@
 #define FETCH_NEGOTIATOR_H
 
 struct commit;
+struct repository;
 
 /*
  * An object that supplies the information needed to negotiate the contents of
@@ -52,7 +53,7 @@ struct fetch_negotiator {
        void *data;
 };
 
-void fetch_negotiator_init(struct fetch_negotiator *negotiator,
-                          const char *algorithm);
+void fetch_negotiator_init(struct repository *r,
+                          struct fetch_negotiator *negotiator);
 
 #endif
index 65be043f2afafdb37b4ce4d6fe8fbd3ac0eb2eaf..d81f47c07b36de586fda0840093ff259eb29650d 100644 (file)
@@ -36,7 +36,6 @@ static int agent_supported;
 static int server_supports_filtering;
 static struct lock_file shallow_lock;
 static const char *alternate_shallow_file;
-static char *negotiation_algorithm;
 static struct strbuf fsck_msg_types = STRBUF_INIT;
 
 /* Remember to update object flag allocation in object.h */
@@ -892,12 +891,13 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                                 struct shallow_info *si,
                                 char **pack_lockfile)
 {
+       struct repository *r = the_repository;
        struct ref *ref = copy_ref_list(orig_ref);
        struct object_id oid;
        const char *agent_feature;
        int agent_len;
        struct fetch_negotiator negotiator;
-       fetch_negotiator_init(&negotiator, negotiation_algorithm);
+       fetch_negotiator_init(r, &negotiator);
 
        sort_ref_list(&ref, ref_compare_name);
        QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -911,7 +911,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 
        if (server_supports("shallow"))
                print_verbose(args, _("Server supports %s"), "shallow");
-       else if (args->depth > 0 || is_repository_shallow(the_repository))
+       else if (args->depth > 0 || is_repository_shallow(r))
                die(_("Server does not support shallow clients"));
        if (args->depth > 0 || args->deepen_since || args->deepen_not)
                args->deepen = 1;
@@ -1379,6 +1379,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
                                    struct shallow_info *si,
                                    char **pack_lockfile)
 {
+       struct repository *r = the_repository;
        struct ref *ref = copy_ref_list(orig_ref);
        enum fetch_state state = FETCH_CHECK_LOCAL;
        struct oidset common = OIDSET_INIT;
@@ -1386,7 +1387,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
        int in_vain = 0;
        int haves_to_send = INITIAL_FLUSH;
        struct fetch_negotiator negotiator;
-       fetch_negotiator_init(&negotiator, negotiation_algorithm);
+       fetch_negotiator_init(r, &negotiator);
        packet_reader_init(&reader, fd[0], NULL, 0,
                           PACKET_READ_CHOMP_NEWLINE |
                           PACKET_READ_DIE_ON_ERR_PACKET);
@@ -1505,8 +1506,6 @@ static void fetch_pack_config(void)
        git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
        git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
        git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
-       git_config_get_string("fetch.negotiationalgorithm",
-                             &negotiation_algorithm);
 
        git_config(fetch_pack_config_cb, NULL);
 }
index 52ffa8a3139f2e427fadb7d233fb4910819becc9..cff1280975b5d400844916083c070b9ee861d1cf 100644 (file)
@@ -1599,16 +1599,17 @@ struct cache_entry *refresh_cache_entry(struct index_state *istate,
 
 #define INDEX_FORMAT_DEFAULT 3
 
-static unsigned int get_index_format_default(void)
+static unsigned int get_index_format_default(struct repository *r)
 {
        char *envversion = getenv("GIT_INDEX_VERSION");
        char *endp;
-       int value;
        unsigned int version = INDEX_FORMAT_DEFAULT;
 
        if (!envversion) {
-               if (!git_config_get_int("index.version", &value))
-                       version = value;
+               prepare_repo_settings(r);
+
+               if (r->settings.index_version >= 0)
+                       version = r->settings.index_version;
                if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
                        warning(_("index.version set, but the value is invalid.\n"
                                  "Using version %i"), INDEX_FORMAT_DEFAULT);
@@ -1844,18 +1845,17 @@ static void check_ce_order(struct index_state *istate)
 
 static void tweak_untracked_cache(struct index_state *istate)
 {
-       switch (git_config_get_untracked_cache()) {
-       case -1: /* keep: do nothing */
-               break;
-       case 0: /* false */
+       struct repository *r = the_repository;
+
+       prepare_repo_settings(r);
+
+       if (r->settings.core_untracked_cache  == UNTRACKED_CACHE_REMOVE) {
                remove_untracked_cache(istate);
-               break;
-       case 1: /* true */
-               add_untracked_cache(istate);
-               break;
-       default: /* unknown value: do nothing */
-               break;
+               return;
        }
+
+       if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE)
+               add_untracked_cache(istate);
 }
 
 static void tweak_split_index(struct index_state *istate)
@@ -2765,7 +2765,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
        }
 
        if (!istate->version) {
-               istate->version = get_index_format_default();
+               istate->version = get_index_format_default(the_repository);
                if (git_env_bool("GIT_TEST_SPLIT_INDEX", 0))
                        init_split_index(istate);
        }
diff --git a/repo-settings.c b/repo-settings.c
new file mode 100644 (file)
index 0000000..3779b85
--- /dev/null
@@ -0,0 +1,64 @@
+#include "cache.h"
+#include "config.h"
+#include "repository.h"
+
+#define UPDATE_DEFAULT_BOOL(s,v) do { if (s == -1) { s = v; } } while(0)
+
+void prepare_repo_settings(struct repository *r)
+{
+       int value;
+       char *strval;
+
+       if (r->settings.initialized)
+               return;
+
+       /* Defaults */
+       memset(&r->settings, -1, sizeof(r->settings));
+
+       if (!repo_config_get_bool(r, "core.commitgraph", &value))
+               r->settings.core_commit_graph = value;
+       if (!repo_config_get_bool(r, "gc.writecommitgraph", &value))
+               r->settings.gc_write_commit_graph = value;
+       UPDATE_DEFAULT_BOOL(r->settings.core_commit_graph, 1);
+       UPDATE_DEFAULT_BOOL(r->settings.gc_write_commit_graph, 1);
+
+       if (!repo_config_get_bool(r, "index.version", &value))
+               r->settings.index_version = value;
+       if (!repo_config_get_maybe_bool(r, "core.untrackedcache", &value)) {
+               if (value == 0)
+                       r->settings.core_untracked_cache = UNTRACKED_CACHE_REMOVE;
+               else
+                       r->settings.core_untracked_cache = UNTRACKED_CACHE_WRITE;
+       } else if (!repo_config_get_string(r, "core.untrackedcache", &strval)) {
+               if (!strcasecmp(strval, "keep"))
+                       r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;
+
+               free(strval);
+       }
+
+       if (!repo_config_get_string(r, "fetch.negotiationalgorithm", &strval)) {
+               if (!strcasecmp(strval, "skipping"))
+                       r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING;
+               else
+                       r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_DEFAULT;
+       }
+
+       if (!repo_config_get_bool(r, "pack.usesparse", &value))
+               r->settings.pack_use_sparse = value;
+       if (!repo_config_get_bool(r, "feature.manyfiles", &value) && value) {
+               UPDATE_DEFAULT_BOOL(r->settings.index_version, 4);
+               UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_WRITE);
+       }
+       if (!repo_config_get_bool(r, "feature.experimental", &value) && value) {
+               UPDATE_DEFAULT_BOOL(r->settings.pack_use_sparse, 1);
+               UPDATE_DEFAULT_BOOL(r->settings.fetch_negotiation_algorithm, FETCH_NEGOTIATION_SKIPPING);
+       }
+
+       /* Hack for test programs like test-dump-untracked-cache */
+       if (ignore_untracked_cache_config)
+               r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;
+       else
+               UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_KEEP);
+
+       UPDATE_DEFAULT_BOOL(r->settings.fetch_negotiation_algorithm, FETCH_NEGOTIATION_DEFAULT);
+}
index 4fb6a5885f794dea9ff7a1ecf37f27bc34e4d218..4da275e73fac1a97c39109b7bf31ae01f20e0730 100644 (file)
@@ -11,6 +11,33 @@ struct pathspec;
 struct raw_object_store;
 struct submodule_cache;
 
+enum untracked_cache_setting {
+       UNTRACKED_CACHE_UNSET = -1,
+       UNTRACKED_CACHE_REMOVE = 0,
+       UNTRACKED_CACHE_KEEP = 1,
+       UNTRACKED_CACHE_WRITE = 2
+};
+
+enum fetch_negotiation_setting {
+       FETCH_NEGOTIATION_UNSET = -1,
+       FETCH_NEGOTIATION_NONE = 0,
+       FETCH_NEGOTIATION_DEFAULT = 1,
+       FETCH_NEGOTIATION_SKIPPING = 2,
+};
+
+struct repo_settings {
+       int initialized;
+
+       int core_commit_graph;
+       int gc_write_commit_graph;
+
+       int index_version;
+       enum untracked_cache_setting core_untracked_cache;
+
+       int pack_use_sparse;
+       enum fetch_negotiation_setting fetch_negotiation_algorithm;
+};
+
 struct repository {
        /* Environment */
        /*
@@ -72,6 +99,8 @@ struct repository {
         */
        char *submodule_prefix;
 
+       struct repo_settings settings;
+
        /* Subsystems */
        /*
         * Repository's config which contains key-value pairs from the usual
@@ -157,5 +186,6 @@ int repo_read_index_unmerged(struct repository *);
  */
 void repo_update_index_if_able(struct repository *, struct lock_file *);
 
+void prepare_repo_settings(struct repository *r);
 
 #endif /* REPOSITORY_H */
index 6415063980b49985b25d351f5c0079f44ad92533..33e0aa4a896575f14442e5b1a9029640d4d7ac50 100755 (executable)
@@ -234,7 +234,7 @@ test_expect_success 'rev-list stops traversal at missing and promised commit' '
 
        git -C repo config core.repositoryformatversion 1 &&
        git -C repo config extensions.partialclone "arbitrary string" &&
-       GIT_TEST_COMMIT_GRAPH=0 git -C repo rev-list --exclude-promisor-objects --objects bar >out &&
+       GIT_TEST_COMMIT_GRAPH=0 git -C repo -c core.commitGraph=false rev-list --exclude-promisor-objects --objects bar >out &&
        grep $(git -C repo rev-parse bar) out &&
        ! grep $FOO out
 '
index 42962ed7d46f6dafa09c7b276942c32da130e300..c77721b580c1535de33f3bd109c95bb52200a691 100755 (executable)
@@ -59,17 +59,38 @@ test_expect_success 'out of bounds index.version issues warning' '
        )
 '
 
-test_expect_success 'GIT_INDEX_VERSION takes precedence over config' '
+test_index_version () {
+       INDEX_VERSION_CONFIG=$1 &&
+       FEATURE_MANY_FILES=$2 &&
+       ENV_VAR_VERSION=$3
+       EXPECTED_OUTPUT_VERSION=$4 &&
        (
                rm -f .git/index &&
-               GIT_INDEX_VERSION=4 &&
-               export GIT_INDEX_VERSION &&
-               git config --add index.version 2 &&
+               rm -f .git/config &&
+               if test "$INDEX_VERSION_CONFIG" -ne 0
+               then
+                       git config --add index.version $INDEX_VERSION_CONFIG
+               fi &&
+               git config --add feature.manyFiles $FEATURE_MANY_FILES
+               if test "$ENV_VAR_VERSION" -ne 0
+               then
+                       GIT_INDEX_VERSION=$ENV_VAR_VERSION &&
+                       export GIT_INDEX_VERSION
+               else
+                       unset GIT_INDEX_VERSION
+               fi &&
                git add a 2>&1 &&
-               echo 4 >expect &&
+               echo $EXPECTED_OUTPUT_VERSION >expect &&
                test-tool index-version <.git/index >actual &&
                test_cmp expect actual
        )
+}
+
+test_expect_success 'index version config precedence' '
+       test_index_version 2 false 4 4 &&
+       test_index_version 2 true 0 2 &&
+       test_index_version 0 true 0 4 &&
+       test_index_version 0 true 2 2
 '
 
 test_done
index dacb440b2750e40b393a200229a9ee968f12ccd3..f4338abb78a83967a1bdc6b264600262a0f94d65 100755 (executable)
@@ -24,11 +24,11 @@ test_expect_success 'check corruption' '
 '
 
 test_expect_success 'rev-list notices corruption (1)' '
-       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list HEAD
+       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list HEAD
 '
 
 test_expect_success 'rev-list notices corruption (2)' '
-       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list --objects HEAD
+       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list --objects HEAD
 '
 
 test_expect_success 'pack-objects notices corruption' '
index 99f4ef4c19dff028facac6da810c973b3a82a4fc..e2c39533d3f8ce292f151d82f19dd753b564b882 100755 (executable)
@@ -8,6 +8,7 @@ GIT_TEST_COMMIT_GRAPH=0
 test_expect_success 'setup repo' '
        git init &&
        git config core.commitGraph true &&
+       git config gc.writeCommitGraph false &&
        infodir=".git/objects/info" &&
        graphdir="$infodir/commit-graphs" &&
        test_oid_init
@@ -334,6 +335,7 @@ test_expect_success 'split across alternate where alternate is not split' '
        git clone --no-hardlinks . alt-split &&
        (
                cd alt-split &&
+               rm -f .git/objects/info/commit-graph &&
                echo "$(pwd)"/../.git/objects >.git/objects/info/alternates &&
                test_commit 18 &&
                git commit-graph write --reachable --split &&
index 8a14be51a13280d3fccd340c027cd5f20bb941a5..f70cbcc9cabf6499de57529cbfa095ed9eff73e3 100755 (executable)
@@ -60,29 +60,6 @@ test_expect_success 'commits with no parents are sent regardless of skip distanc
        have_not_sent c6 c4 c3
 '
 
-test_expect_success 'unknown fetch.negotiationAlgorithm values error out' '
-       rm -rf server client trace &&
-       git init server &&
-       test_commit -C server to_fetch &&
-
-       git init client &&
-       test_commit -C client on_client &&
-       git -C client checkout on_client &&
-
-       test_config -C client fetch.negotiationAlgorithm invalid &&
-       test_must_fail git -C client fetch "$(pwd)/server" 2>err &&
-       test_i18ngrep "unknown fetch negotiation algorithm" err &&
-
-       # Explicit "default" value
-       test_config -C client fetch.negotiationAlgorithm default &&
-       git -C client -c fetch.negotiationAlgorithm=default fetch "$(pwd)/server" &&
-
-       # Implementation detail: If there is nothing to fetch, we will not error out
-       test_config -C client fetch.negotiationAlgorithm invalid &&
-       git -C client fetch "$(pwd)/server" 2>err &&
-       test_i18ngrep ! "unknown fetch negotiation algorithm" err
-'
-
 test_expect_success 'when two skips collide, favor the larger one' '
        rm -rf server client trace &&
        git init server &&
index 545b461e51d4fd5df39c7d27953fb0f26f73e052..bad02cf5b83dbc014c23cc8ac66135e0cf095138 100755 (executable)
@@ -42,7 +42,7 @@ test_expect_success 'corrupt second commit object' \
    '
 
 test_expect_success 'rev-list should fail' '
-       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list --all > /dev/null
+       test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list --all > /dev/null
 '
 
 test_expect_success 'git repack _MUST_ fail' \
index 033871ee5f35c1a143aec6d2b30c5116bf3f94f5..f30b4849b64ea8bd79a82117333b0f7f225def63 100755 (executable)
@@ -137,7 +137,7 @@ test_expect_success 'do not complain about existing broken links (commit)' '
        some message
        EOF
        commit=$(git hash-object -t commit -w broken-commit) &&
-       git gc 2>stderr &&
+       git gc -q 2>stderr &&
        verbose git cat-file -e $commit &&
        test_must_be_empty stderr
 '
@@ -147,7 +147,7 @@ test_expect_success 'do not complain about existing broken links (tree)' '
        100644 blob 0000000000000000000000000000000000000003    foo
        EOF
        tree=$(git mktree --missing <broken-tree) &&
-       git gc 2>stderr &&
+       git gc -q 2>stderr &&
        git cat-file -e $tree &&
        test_must_be_empty stderr
 '
@@ -162,7 +162,7 @@ test_expect_success 'do not complain about existing broken links (tag)' '
        this is a broken tag
        EOF
        tag=$(git hash-object -t tag -w broken-tag) &&
-       git gc 2>stderr &&
+       git gc -q 2>stderr &&
        git cat-file -e $tag &&
        test_must_be_empty stderr
 '