Skip to content

Commit af5be84

Browse files
committed
Merge branch 'ds/early-access' into jch
A mechanism to enable newish configuration settings in bulk has been invented. The model may need to be rethought. A linear scale with "early adoption" mindset may not match diverse use cases of the tool. * ds/early-access: repo-settings: pack.useSparse=true repo-settings: use index.version=4 by default repo-settings: create core.featureAdoptionRate setting
2 parents b23eebc + bbd04cf commit af5be84

13 files changed

+164
-24
lines changed

Documentation/config/core.txt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,8 @@ the `GIT_NOTES_REF` environment variable. See linkgit:git-notes[1].
577577

578578
core.commitGraph::
579579
If true, then git will read the commit-graph file (if it exists)
580-
to parse the graph structure of commits. Defaults to false. See
580+
to parse the graph structure of commits. Defaults to false, unless
581+
`core.featureAdoptionRate` is at least three. See
581582
linkgit:git-commit-graph[1] for more information.
582583

583584
core.useReplaceRefs::
@@ -601,3 +602,34 @@ core.abbrev::
601602
in your repository, which hopefully is enough for
602603
abbreviated object names to stay unique for some time.
603604
The minimum length is 4.
605+
606+
core.featureAdoptionRate::
607+
Set an integer value on a scale from 0 to 10 describing your
608+
desire to adopt new performance features. Defaults to 0. As
609+
the value increases, features are enabled by changing the
610+
default values of other config settings. If a config variable
611+
is specified explicitly, the explicit value will override these
612+
defaults:
613+
+
614+
If the value is at least 3, then the following defaults are modified.
615+
These represent relatively new features that have existed for multiple
616+
major releases, and may present performance benefits. These benefits
617+
depend on the amount and kind of data in your repo and how you use it.
618+
The settings do not modify the user-facing output of porcelain commands.
619+
+
620+
* `core.commitGraph=true` enables reading commit-graph files.
621+
+
622+
* `gc.writeCommitGraph=true` eneables writing commit-graph files during
623+
`git gc`.
624+
+
625+
* `index.version=4` uses prefix-compression to reduce the size of the
626+
.git/index file.
627+
+
628+
If the value is at least 5, then all of the defaults above are included,
629+
plus the defaults below. These represent new features that present
630+
significant performance benefits, but may not have been released for
631+
multiple major versions.
632+
+
633+
* `pack.useSparse=true` uses the sparse tree-walk algorithm, which is
634+
optimized for enumerating objects during linkgit:git-push[1] from a
635+
client machine.

Documentation/config/gc.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ gc.writeCommitGraph::
6363
If true, then gc will rewrite the commit-graph file when
6464
linkgit:git-gc[1] is run. When using `git gc --auto`
6565
the commit-graph will be updated if housekeeping is
66-
required. Default is false. See linkgit:git-commit-graph[1]
67-
for details.
66+
required. Default is false, unless `core.featureAdoptionRage`
67+
is at least three. See linkgit:git-commit-graph[1] for details.
6868

6969
gc.logExpiry::
7070
If the file gc.log exists, then `git gc --auto` will print

Documentation/config/index.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ index.threads::
2424
index.version::
2525
Specify the version with which new index files should be
2626
initialized. This does not affect existing repositories.
27+
If `core.featureAdoptionRate` is at least three, then the
28+
default value is 4.

Documentation/config/pack.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ pack.useSparse::
112112
objects. This can have significant performance benefits when
113113
computing a pack to send a small change. However, it is possible
114114
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. Defaults to
116+
false, unless `core.featureAdoptionRate` is at least five.
116117

117118
pack.writeBitmaps (deprecated)::
118119
This is a deprecated synonym for `repack.writeBitmaps`.

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ LIB_OBJS += refspec.o
965965
LIB_OBJS += ref-filter.o
966966
LIB_OBJS += remote.o
967967
LIB_OBJS += replace-object.o
968+
LIB_OBJS += repo-settings.o
968969
LIB_OBJS += repository.o
969970
LIB_OBJS += rerere.o
970971
LIB_OBJS += resolve-undo.o

builtin/gc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "pack-objects.h"
2828
#include "blob.h"
2929
#include "tree.h"
30+
#include "repo-settings.h"
3031

3132
#define FAILED_RUN "failed to run %s"
3233

@@ -41,7 +42,6 @@ static int aggressive_depth = 50;
4142
static int aggressive_window = 250;
4243
static int gc_auto_threshold = 6700;
4344
static int gc_auto_pack_limit = 50;
44-
static int gc_write_commit_graph;
4545
static int detach_auto = 1;
4646
static timestamp_t gc_log_expire_time;
4747
static const char *gc_log_expire = "1.day.ago";
@@ -148,7 +148,6 @@ static void gc_config(void)
148148
git_config_get_int("gc.aggressivedepth", &aggressive_depth);
149149
git_config_get_int("gc.auto", &gc_auto_threshold);
150150
git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
151-
git_config_get_bool("gc.writecommitgraph", &gc_write_commit_graph);
152151
git_config_get_bool("gc.autodetach", &detach_auto);
153152
git_config_get_expiry("gc.pruneexpire", &prune_expire);
154153
git_config_get_expiry("gc.worktreepruneexpire", &prune_worktrees_expire);
@@ -685,7 +684,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
685684
clean_pack_garbage();
686685
}
687686

688-
if (gc_write_commit_graph &&
687+
prepare_repo_settings(the_repository);
688+
if (the_repository->settings->gc_write_commit_graph == 1 &&
689689
write_commit_graph_reachable(get_object_directory(),
690690
!quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0,
691691
NULL))

builtin/pack-objects.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "dir.h"
3535
#include "midx.h"
3636
#include "trace2.h"
37+
#include "repo-settings.h"
3738

3839
#define IN_PACK(obj) oe_in_pack(&to_pack, obj)
3940
#define SIZE(obj) oe_size(&to_pack, obj)
@@ -2709,10 +2710,6 @@ static int git_pack_config(const char *k, const char *v, void *cb)
27092710
use_bitmap_index_default = git_config_bool(k, v);
27102711
return 0;
27112712
}
2712-
if (!strcmp(k, "pack.usesparse")) {
2713-
sparse = git_config_bool(k, v);
2714-
return 0;
2715-
}
27162713
if (!strcmp(k, "pack.threads")) {
27172714
delta_search_threads = git_config_int(k, v);
27182715
if (delta_search_threads < 0)
@@ -3332,6 +3329,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
33323329
read_replace_refs = 0;
33333330

33343331
sparse = git_env_bool("GIT_TEST_PACK_SPARSE", 0);
3332+
prepare_repo_settings(the_repository);
3333+
if (!sparse && the_repository->settings->pack_use_sparse != -1)
3334+
sparse = the_repository->settings->pack_use_sparse;
3335+
33353336
reset_pack_idx_option(&pack_idx_opts);
33363337
git_config(git_pack_config, NULL);
33373338

commit-graph.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "hashmap.h"
1717
#include "replace-object.h"
1818
#include "progress.h"
19+
#include "repo-settings.h"
1920

2021
#define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
2122
#define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
@@ -466,7 +467,6 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
466467
static int prepare_commit_graph(struct repository *r)
467468
{
468469
struct object_directory *odb;
469-
int config_value;
470470

471471
if (git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD, 0))
472472
die("dying as requested by the '%s' variable on commit-graph load!",
@@ -476,9 +476,10 @@ static int prepare_commit_graph(struct repository *r)
476476
return !!r->objects->commit_graph;
477477
r->objects->commit_graph_attempted = 1;
478478

479+
prepare_repo_settings(r);
480+
479481
if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
480-
(repo_config_get_bool(r, "core.commitgraph", &config_value) ||
481-
!config_value))
482+
r->settings->core_commit_graph != 1)
482483
/*
483484
* This repository is not configured to use commit graphs, so
484485
* do not load one. (But report commit_graph_attempted anyway

read-cache.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "fsmonitor.h"
2626
#include "thread-utils.h"
2727
#include "progress.h"
28+
#include "repo-settings.h"
2829
#include "json-writer.h"
2930

3031
/* Mask for the name length in ce_flags in the on-disk index */
@@ -1600,16 +1601,17 @@ struct cache_entry *refresh_cache_entry(struct index_state *istate,
16001601

16011602
#define INDEX_FORMAT_DEFAULT 3
16021603

1603-
static unsigned int get_index_format_default(void)
1604+
static unsigned int get_index_format_default(struct repository *r)
16041605
{
16051606
char *envversion = getenv("GIT_INDEX_VERSION");
16061607
char *endp;
1607-
int value;
16081608
unsigned int version = INDEX_FORMAT_DEFAULT;
16091609

16101610
if (!envversion) {
1611-
if (!git_config_get_int("index.version", &value))
1612-
version = value;
1611+
prepare_repo_settings(r);
1612+
1613+
if (r->settings->index_version >= 0)
1614+
version = r->settings->index_version;
16131615
if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
16141616
warning(_("index.version set, but the value is invalid.\n"
16151617
"Using version %i"), INDEX_FORMAT_DEFAULT);
@@ -2876,7 +2878,7 @@ static int do_write_index(struct index_state *istate, struct tempfile *tempfile,
28762878
}
28772879

28782880
if (!istate->version) {
2879-
istate->version = get_index_format_default();
2881+
istate->version = get_index_format_default(the_repository);
28802882
if (git_env_bool("GIT_TEST_SPLIT_INDEX", 0))
28812883
init_split_index(istate);
28822884
}

repo-settings.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "cache.h"
2+
#include "repository.h"
3+
#include "config.h"
4+
#include "repo-settings.h"
5+
6+
#define UPDATE_DEFAULT(s,v) do { if (s == -1) { s = v; } } while(0)
7+
8+
static int git_repo_config(const char *key, const char *value, void *cb)
9+
{
10+
struct repo_settings *rs = (struct repo_settings *)cb;
11+
12+
if (!strcmp(key, "core.featureadoptionrate")) {
13+
int rate = git_config_int(key, value);
14+
if (rate >= 3) {
15+
UPDATE_DEFAULT(rs->core_commit_graph, 1);
16+
UPDATE_DEFAULT(rs->gc_write_commit_graph, 1);
17+
UPDATE_DEFAULT(rs->index_version, 4);
18+
}
19+
if (rate >= 5) {
20+
UPDATE_DEFAULT(rs->pack_use_sparse, 1);
21+
}
22+
return 0;
23+
}
24+
if (!strcmp(key, "core.commitgraph")) {
25+
rs->core_commit_graph = git_config_bool(key, value);
26+
return 0;
27+
}
28+
if (!strcmp(key, "gc.writecommitgraph")) {
29+
rs->gc_write_commit_graph = git_config_bool(key, value);
30+
return 0;
31+
}
32+
if (!strcmp(key, "pack.usesparse")) {
33+
rs->pack_use_sparse = git_config_bool(key, value);
34+
return 0;
35+
}
36+
if (!strcmp(key, "index.version")) {
37+
rs->index_version = git_config_int(key, value);
38+
return 0;
39+
}
40+
41+
return 1;
42+
}
43+
44+
void prepare_repo_settings(struct repository *r)
45+
{
46+
if (r->settings)
47+
return;
48+
49+
r->settings = xmalloc(sizeof(*r->settings));
50+
51+
/* Defaults */
52+
r->settings->core_commit_graph = -1;
53+
r->settings->gc_write_commit_graph = -1;
54+
r->settings->pack_use_sparse = -1;
55+
r->settings->index_version = -1;
56+
57+
repo_config(r, git_repo_config, r->settings);
58+
}

repo-settings.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef REPO_SETTINGS_H
2+
#define REPO_SETTINGS_H
3+
4+
struct repo_settings {
5+
int core_commit_graph;
6+
int gc_write_commit_graph;
7+
int pack_use_sparse;
8+
int index_version;
9+
};
10+
11+
struct repository;
12+
13+
void prepare_repo_settings(struct repository *r);
14+
15+
#endif /* REPO_SETTINGS_H */

repository.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "path.h"
55

66
struct config_set;
7+
struct repo_settings;
78
struct git_hash_algo;
89
struct index_state;
910
struct lock_file;
@@ -72,6 +73,8 @@ struct repository {
7273
*/
7374
char *submodule_prefix;
7475

76+
struct repo_settings *settings;
77+
7578
/* Subsystems */
7679
/*
7780
* Repository's config which contains key-value pairs from the usual

t/t1600-index.sh

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,41 @@ test_expect_success 'out of bounds index.version issues warning' '
5959
)
6060
'
6161

62-
test_expect_success 'GIT_INDEX_VERSION takes precedence over config' '
62+
test_index_version () {
63+
INDEX_VERSION_CONFIG=$1 &&
64+
REPO_ADOPTION_RATE=$2 &&
65+
ENV_VAR_VERSION=$3
66+
EXPECTED_OUTPUT_VERSION=$4 &&
6367
(
6468
rm -f .git/index &&
65-
GIT_INDEX_VERSION=4 &&
66-
export GIT_INDEX_VERSION &&
67-
git config --add index.version 2 &&
69+
rm -f .git/config &&
70+
if test "$INDEX_VERSION_CONFIG" -ne 0
71+
then
72+
git config --add index.version $INDEX_VERSION_CONFIG
73+
fi &&
74+
if test "$REPO_ADOPTION_RATE" -ne 0
75+
then
76+
git config --add core.featureAdoptionRate $REPO_ADOPTION_RATE
77+
fi &&
78+
if test "$ENV_VAR_VERSION" -ne 0
79+
then
80+
GIT_INDEX_VERSION=$ENV_VAR_VERSION &&
81+
export GIT_INDEX_VERSION
82+
else
83+
unset GIT_INDEX_VERSION
84+
fi &&
6885
git add a 2>&1 &&
69-
echo 4 >expect &&
86+
echo $EXPECTED_OUTPUT_VERSION >expect &&
7087
test-tool index-version <.git/index >actual &&
7188
test_cmp expect actual
7289
)
90+
}
91+
92+
test_expect_success 'index version config precedence' '
93+
test_index_version 2 0 4 4 &&
94+
test_index_version 2 3 0 2 &&
95+
test_index_version 0 3 0 4 &&
96+
test_index_version 0 3 2 2
7397
'
7498

7599
test_done

0 commit comments

Comments
 (0)