repo-settings: create feature.experimental setting

The 'feature.experimental' setting includes config options that are not committed to become defaults, but could use additional testing. Update the following config settings to take new defaults, and to use the repo_settings struct if not already using them: * 'pack.useSparse=true' * 'fetch.negotiationAlgorithm=skipping' In the case of fetch.negotiationAlgorithm, the existing logic would load the config option only when about to use the setting, so had a die() statement on an unknown string value. This is removed as now the config is parsed under prepare_repo_settings(). In general, this die() is probably misplaced and not valuable. A test was removed that checked this die() statement executed. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Aug 13, 2019 at 11:37 UTC aaf633c2ad10b47af7623c130ddfe7231658c7e4
9 files changed +60 -45
Documentation/config/feature.txt
+14
@@ -4,6 +4,20 @@ feature.*::
4 developer community as recommended defaults and are subject to change.
5 In particular, new config options may be added with different defaults.
6
7 +feature.experimental::
8 + Enable config options that are new to Git, and are being considered for
9 + future defaults. Config settings included here may be added or removed
10 + with each release, including minor version updates. These settings may
11 + have unintended interactions since they are so new. Please enable this
12 + setting if you are interested in providing feedback on experimental
13 + features. The new default values are:
14 ++
15 +* `pack.useSparse=true` uses a new algorithm when constructing a pack-file
16 +which can improve `git push` performance in repos with many files.
17 ++
18 +* `fetch.negotiationAlgorithm=skipping` may improve fetch negotiation times by
19 +skipping more commits at a time, reducing the number of round trips.
20 +
21 feature.manyFiles::
22 Enable config options that optimize for repos with many files in the
23 working directory. With many files, commands such as `git status` and
Documentation/config/fetch.txt
+2 -1
@@ -59,7 +59,8 @@ fetch.negotiationAlgorithm::
59 effort to converge faster, but may result in a larger-than-necessary
60 packfile; The default is "default" which instructs Git to use the default algorithm
61 that never skips commits (unless the server has acknowledged it or one
62 - of its descendants).
62 + of its descendants). If `feature.experimental` is enabled, then this
63 + setting defaults to "skipping".
64 Unknown values will cause 'git fetch' to error out.
65 +
66 See also the `--negotiation-tip` option for linkgit:git-fetch[1].
Documentation/config/pack.txt
+2 -1
@@ -112,7 +112,8 @@ pack.useSparse::
112 objects. This can have significant performance benefits when
113 computing a pack to send a small change. However, it is possible
114 that extra objects are added to the pack-file if the included
115 - commits contain certain types of direct renames.
115 + commits contain certain types of direct renames. Default is `false`
116 + unless `feature.experimental` is enabled.
117
118 pack.writeBitmaps (deprecated)::
119 This is a deprecated synonym for `repack.writeBitmaps`.
fetch-negotiator.c
+13 -12
@@ -2,19 +2,20 @@
2 #include "fetch-negotiator.h"
3 #include "negotiator/default.h"
4 #include "negotiator/skipping.h"
5 +#include "repository.h"
6
6 -void fetch_negotiator_init(struct fetch_negotiator *negotiator,
7 - const char *algorithm)
7 +void fetch_negotiator_init(struct repository *r,
8 + struct fetch_negotiator *negotiator)
9 {
9 - if (algorithm) {
10 - if (!strcmp(algorithm, "skipping")) {
11 - skipping_negotiator_init(negotiator);
12 - return;
13 - } else if (!strcmp(algorithm, "default")) {
14 - /* Fall through to default initialization */
15 - } else {
16 - die("unknown fetch negotiation algorithm '%s'", algorithm);
17 - }
10 + prepare_repo_settings(r);
11 + switch(r->settings.fetch_negotiation_algorithm) {
12 + case FETCH_NEGOTIATION_SKIPPING:
13 + skipping_negotiator_init(negotiator);
14 + return;
15 +
16 + case FETCH_NEGOTIATION_DEFAULT:
17 + default:
18 + default_negotiator_init(negotiator);
19 + return;
20 }
19 - default_negotiator_init(negotiator);
21 }
fetch-negotiator.h
+3 -2
@@ -2,6 +2,7 @@
2 #define FETCH_NEGOTIATOR_H
3
4 struct commit;
5 +struct repository;
6
7 /*
8 * An object that supplies the information needed to negotiate the contents of
@@ -52,7 +53,7 @@ struct fetch_negotiator {
53 void *data;
54 };
55
55 -void fetch_negotiator_init(struct fetch_negotiator *negotiator,
56 - const char *algorithm);
56 +void fetch_negotiator_init(struct repository *r,
57 + struct fetch_negotiator *negotiator);
58
59 #endif
fetch-pack.c
+5 -6
@@ -36,7 +36,6 @@ static int agent_supported;
36 static int server_supports_filtering;
37 static struct lock_file shallow_lock;
38 static const char *alternate_shallow_file;
39 -static char *negotiation_algorithm;
39 static struct strbuf fsck_msg_types = STRBUF_INIT;
40
41 /* Remember to update object flag allocation in object.h */
@@ -892,12 +891,13 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
891 struct shallow_info *si,
892 char **pack_lockfile)
893 {
894 + struct repository *r = the_repository;
895 struct ref *ref = copy_ref_list(orig_ref);
896 struct object_id oid;
897 const char *agent_feature;
898 int agent_len;
899 struct fetch_negotiator negotiator;
900 - fetch_negotiator_init(&negotiator, negotiation_algorithm);
900 + fetch_negotiator_init(r, &negotiator);
901
902 sort_ref_list(&ref, ref_compare_name);
903 QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -911,7 +911,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
911
912 if (server_supports("shallow"))
913 print_verbose(args, _("Server supports %s"), "shallow");
914 - else if (args->depth > 0 || is_repository_shallow(the_repository))
914 + else if (args->depth > 0 || is_repository_shallow(r))
915 die(_("Server does not support shallow clients"));
916 if (args->depth > 0 || args->deepen_since || args->deepen_not)
917 args->deepen = 1;
@@ -1379,6 +1379,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1379 struct shallow_info *si,
1380 char **pack_lockfile)
1381 {
1382 + struct repository *r = the_repository;
1383 struct ref *ref = copy_ref_list(orig_ref);
1384 enum fetch_state state = FETCH_CHECK_LOCAL;
1385 struct oidset common = OIDSET_INIT;
@@ -1386,7 +1387,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
1387 int in_vain = 0;
1388 int haves_to_send = INITIAL_FLUSH;
1389 struct fetch_negotiator negotiator;
1389 - fetch_negotiator_init(&negotiator, negotiation_algorithm);
1390 + fetch_negotiator_init(r, &negotiator);
1391 packet_reader_init(&reader, fd[0], NULL, 0,
1392 PACKET_READ_CHOMP_NEWLINE |
1393 PACKET_READ_DIE_ON_ERR_PACKET);
@@ -1505,8 +1506,6 @@ static void fetch_pack_config(void)
1506 git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
1507 git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
1508 git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
1508 - git_config_get_string("fetch.negotiationalgorithm",
1509 - &negotiation_algorithm);
1509
1510 git_config(fetch_pack_config_cb, NULL);
1511 }
repo-settings.c
+13
@@ -36,16 +36,29 @@ void prepare_repo_settings(struct repository *r)
36 free(strval);
37 }
38
39 + if (!repo_config_get_string(r, "fetch.negotiationalgorithm", &strval)) {
40 + if (!strcasecmp(strval, "skipping"))
41 + r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING;
42 + else
43 + r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_DEFAULT;
44 + }
45 +
46 if (!repo_config_get_bool(r, "pack.usesparse", &value))
47 r->settings.pack_use_sparse = value;
48 if (!repo_config_get_bool(r, "feature.manyfiles", &value) && value) {
49 UPDATE_DEFAULT_BOOL(r->settings.index_version, 4);
50 UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_WRITE);
51 }
52 + if (!repo_config_get_bool(r, "feature.experimental", &value) && value) {
53 + UPDATE_DEFAULT_BOOL(r->settings.pack_use_sparse, 1);
54 + UPDATE_DEFAULT_BOOL(r->settings.fetch_negotiation_algorithm, FETCH_NEGOTIATION_SKIPPING);
55 + }
56
57 /* Hack for test programs like test-dump-untracked-cache */
58 if (ignore_untracked_cache_config)
59 r->settings.core_untracked_cache = UNTRACKED_CACHE_KEEP;
60 else
61 UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_KEEP);
62 +
63 + UPDATE_DEFAULT_BOOL(r->settings.fetch_negotiation_algorithm, FETCH_NEGOTIATION_DEFAULT);
64 }
repository.h
+8
@@ -18,6 +18,13 @@ enum untracked_cache_setting {
18 UNTRACKED_CACHE_WRITE = 2
19 };
20
21 +enum fetch_negotiation_setting {
22 + FETCH_NEGOTIATION_UNSET = -1,
23 + FETCH_NEGOTIATION_NONE = 0,
24 + FETCH_NEGOTIATION_DEFAULT = 1,
25 + FETCH_NEGOTIATION_SKIPPING = 2,
26 +};
27 +
28 struct repo_settings {
29 int initialized;
30
@@ -28,6 +35,7 @@ struct repo_settings {
35 enum untracked_cache_setting core_untracked_cache;
36
37 int pack_use_sparse;
38 + enum fetch_negotiation_setting fetch_negotiation_algorithm;
39 };
40
41 struct repository {
t/t5552-skipping-fetch-negotiator.sh
-23
@@ -60,29 +60,6 @@ test_expect_success 'commits with no parents are sent regardless of skip distanc
60 have_not_sent c6 c4 c3
61 '
62
63 -test_expect_success 'unknown fetch.negotiationAlgorithm values error out' '
64 - rm -rf server client trace &&
65 - git init server &&
66 - test_commit -C server to_fetch &&
67 -
68 - git init client &&
69 - test_commit -C client on_client &&
70 - git -C client checkout on_client &&
71 -
72 - test_config -C client fetch.negotiationAlgorithm invalid &&
73 - test_must_fail git -C client fetch "$(pwd)/server" 2>err &&
74 - test_i18ngrep "unknown fetch negotiation algorithm" err &&
75 -
76 - # Explicit "default" value
77 - test_config -C client fetch.negotiationAlgorithm default &&
78 - git -C client -c fetch.negotiationAlgorithm=default fetch "$(pwd)/server" &&
79 -
80 - # Implementation detail: If there is nothing to fetch, we will not error out
81 - test_config -C client fetch.negotiationAlgorithm invalid &&
82 - git -C client fetch "$(pwd)/server" 2>err &&
83 - test_i18ngrep ! "unknown fetch negotiation algorithm" err
84 -'
85 -
63 test_expect_success 'when two skips collide, favor the larger one' '
64 rm -rf server client trace &&
65 git init server &&