Skip to content

Commit

Permalink
repo-settings: create core.featureAdoptionRate setting
Browse files Browse the repository at this point in the history
Several advanced config settings are highly recommended for clients
using large repositories. Power users learn these one-by-one and
enable them as they see fit. This could be made simpler, to allow
more users to have access to these almost-always beneficial features
(and more beneficial in larger repos).

Create a 'core.featureAdoptionRate' config setting that allows integer
values. This is a rating from 0 to 10 for the user's willingness to
adopt new or experimental features that improve Git performance.
The default is 0, meaning "don't change anything!" A value of 10
would mean "I'm willing for some behavior to change to get the
best performance I can get, and can take experimental features
in their first release." As we integrate this with more config
settings, we will make this scale more clear.

This config setting only changes the default values of other config
settings. If the setting is given explicitly, then take the
explicit value.

This change adds these two defaults when core.featureAdoptionRate
is at least three:

 * core.commitGraph=true
 * gc.writeCommitGraph=true

The use of "three or higher" for these settings means that a value
of 3 means "I'm willing to add optional features that can augment
the data on disk in favor of improved performance, but those
features should be stable after being included in multiple major
releases."

To centralize these config options and properly set the defaults,
create a repo_settings that contains chars for each config variable.
Use -1 as "unset", with 0 for false and 1 for true.

The prepare_repo_settings() method ensures that this settings
struct has been initialized, and avoids double-scanning the config
settings.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
derrickstolee authored and gitster committed Jun 20, 2019
1 parent a6a95cd commit 0a01e97
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 9 deletions.
21 changes: 20 additions & 1 deletion Documentation/config/core.txt
Expand Up @@ -577,7 +577,8 @@ 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 false, unless
`core.featureAdoptionRate` is at least three. See
linkgit:git-commit-graph[1] for more information.

core.useReplaceRefs::
Expand All @@ -601,3 +602,21 @@ core.abbrev::
in your repository, which hopefully is enough for
abbreviated object names to stay unique for some time.
The minimum length is 4.

core.featureAdoptionRate::
Set an integer value on a scale from 0 to 10 describing your
desire to adopt new performance features. Defaults to 0. As
the value increases, features are enabled by changing the
default values of other config settings. If a config variable
is specified explicitly, the explicit value will override these
defaults:
+
If the value is at least 3, then the following defaults are modified.
These represent relatively new features that have existed for multiple
major releases, and present significant performance benefits. They do
not modify the user-facing output of porcelain commands.
+
* `core.commitGraph=true` enables reading commit-graph files.
+
* `gc.writeCommitGraph=true` eneables writing commit-graph files during
`git gc`.
4 changes: 2 additions & 2 deletions Documentation/config/gc.txt
Expand Up @@ -63,8 +63,8 @@ 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]
for details.
required. Default is false, unless `core.featureAdoptionRage`
is at least three. See linkgit:git-commit-graph[1] for details.

gc.logExpiry::
If the file gc.log exists, then `git gc --auto` will print
Expand Down
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -961,6 +961,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
Expand Down
6 changes: 3 additions & 3 deletions builtin/gc.c
Expand Up @@ -27,6 +27,7 @@
#include "pack-objects.h"
#include "blob.h"
#include "tree.h"
#include "repo-settings.h"

#define FAILED_RUN "failed to run %s"

Expand All @@ -41,7 +42,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";
Expand Down Expand Up @@ -148,7 +148,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);
Expand Down Expand Up @@ -685,7 +684,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
clean_pack_garbage();
}

if (gc_write_commit_graph)
prepare_repo_settings(the_repository);
if (the_repository->settings->gc_write_commit_graph == 1)
write_commit_graph_reachable(get_object_directory(), 0,
!quiet && !daemonized);

Expand Down
7 changes: 4 additions & 3 deletions commit-graph.c
Expand Up @@ -16,6 +16,7 @@
#include "hashmap.h"
#include "replace-object.h"
#include "progress.h"
#include "repo-settings.h"

#define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
#define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
Expand Down Expand Up @@ -311,7 +312,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!",
Expand All @@ -321,9 +321,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
Expand Down
44 changes: 44 additions & 0 deletions repo-settings.c
@@ -0,0 +1,44 @@
#include "cache.h"
#include "repository.h"
#include "config.h"
#include "repo-settings.h"

#define UPDATE_DEFAULT(s,v) do { if (s == -1) { s = v; } } while(0)

static int git_repo_config(const char *key, const char *value, void *cb)
{
struct repo_settings *rs = (struct repo_settings *)cb;

if (!strcmp(key, "core.featureadoptionrate")) {
int rate = git_config_int(key, value);
if (rate >= 3) {
UPDATE_DEFAULT(rs->core_commit_graph, 1);
UPDATE_DEFAULT(rs->gc_write_commit_graph, 1);
}
return 0;
}
if (!strcmp(key, "core.commitgraph")) {
rs->core_commit_graph = git_config_bool(key, value);
return 0;
}
if (!strcmp(key, "gc.writecommitgraph")) {
rs->gc_write_commit_graph = git_config_bool(key, value);
return 0;
}

return 1;
}

void prepare_repo_settings(struct repository *r)
{
if (r->settings)
return;

r->settings = xmalloc(sizeof(*r->settings));

/* Defaults */
r->settings->core_commit_graph = -1;
r->settings->gc_write_commit_graph = -1;

repo_config(r, git_repo_config, r->settings);
}
13 changes: 13 additions & 0 deletions repo-settings.h
@@ -0,0 +1,13 @@
#ifndef REPO_SETTINGS_H
#define REPO_SETTINGS_H

struct repo_settings {
char core_commit_graph;
char gc_write_commit_graph;
};

struct repository;

void prepare_repo_settings(struct repository *r);

#endif /* REPO_SETTINGS_H */
3 changes: 3 additions & 0 deletions repository.h
Expand Up @@ -4,6 +4,7 @@
#include "path.h"

struct config_set;
struct repo_settings;
struct git_hash_algo;
struct index_state;
struct lock_file;
Expand Down Expand Up @@ -72,6 +73,8 @@ struct repository {
*/
char *submodule_prefix;

struct repo_settings *settings;

/* Subsystems */
/*
* Repository's config which contains key-value pairs from the usual
Expand Down

0 comments on commit 0a01e97

Please sign in to comment.