]> git.ipfire.org Git - thirdparty/git.git/commitdiff
environment: move access to "core.bigFileThreshold" into repo settings
authorPatrick Steinhardt <ps@pks.im>
Mon, 10 Mar 2025 07:13:23 +0000 (08:13 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Mar 2025 20:16:18 +0000 (13:16 -0700)
The "core.bigFileThreshold" setting is stored in a global variable and
populated via `git_default_core_config()`. This may cause issues in
the case where one is handling multiple different repositories in a
single process with different values for that config key, as we may or
may not see the correct value in that case. Furthermore, global state
blocks our path towards libification.

Refactor the code so that we instead store the value in `struct
repo_settings`, where the value is computed as-needed and cached.

Note that this change requires us to adapt one test in t1050 that
verifies that we die when parsing an invalid "core.bigFileThreshold"
value. The exercised Git command doesn't use the value at all, and thus
it won't hit the new code path that parses the value. This is addressed
by using git-hash-object(1) instead, which does read the value.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
15 files changed:
archive.c
builtin/fast-import.c
builtin/index-pack.c
builtin/pack-objects.c
builtin/unpack-objects.c
config.c
diff.c
environment.c
environment.h
object-file.c
pack-check.c
repo-settings.c
repo-settings.h
streaming.c
t/t1050-large.sh

index 8be4e7ac8db50c7ae019ad12099362d9d392e194..f4331aeb49e7b3b011ae5624054e9ce4be30c654 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -216,7 +216,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
        /* Stream it? */
        if (S_ISREG(mode) && !args->convert &&
            oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
-           size > big_file_threshold)
+           size > repo_settings_get_big_file_threshold(the_repository))
                return write_entry(args, oid, path.buf, path.len, mode, NULL, size);
 
        buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
index e1758aa95140ed2b43c8708f9882955ba00cfabf..ce52f78579d818df84dfe2be50030daa30ed87e9 100644 (file)
@@ -2021,7 +2021,7 @@ static void parse_and_store_blob(
        static struct strbuf buf = STRBUF_INIT;
        uintmax_t len;
 
-       if (parse_data(&buf, big_file_threshold, &len))
+       if (parse_data(&buf, repo_settings_get_big_file_threshold(the_repository), &len))
                store_object(OBJ_BLOB, &buf, last, oidout, mark);
        else {
                if (last) {
@@ -3402,7 +3402,7 @@ static int parse_one_option(const char *option)
                unsigned long v;
                if (!git_parse_ulong(option, &v))
                        return 0;
-               big_file_threshold = v;
+               repo_settings_set_big_file_threshold(the_repository, v);
        } else if (skip_prefix(option, "depth=", &option)) {
                option_depth(option);
        } else if (skip_prefix(option, "active-branches=", &option)) {
index 174e03afa612720115a89ab8060de56d9b7eabf0..09c0a8adf6379189d66c1a1f8f9c1d3a0812f28c 100644 (file)
@@ -485,7 +485,8 @@ static void *unpack_entry_data(off_t offset, unsigned long size,
                git_hash_update(&c, hdr, hdrlen);
        } else
                oid = NULL;
-       if (type == OBJ_BLOB && size > big_file_threshold)
+       if (type == OBJ_BLOB &&
+           size > repo_settings_get_big_file_threshold(the_repository))
                buf = fixed_buf;
        else
                buf = xmallocz(size);
@@ -799,7 +800,8 @@ static int check_collison(struct object_entry *entry)
        enum object_type type;
        unsigned long size;
 
-       if (entry->size <= big_file_threshold || entry->type != OBJ_BLOB)
+       if (entry->size <= repo_settings_get_big_file_threshold(the_repository) ||
+           entry->type != OBJ_BLOB)
                return -1;
 
        memset(&data, 0, sizeof(data));
index e05dfc4021e212eeb27a9b776cf0b5731776ee57..eefc6c7809607f75e173e8d05b2fea96ac206647 100644 (file)
@@ -499,7 +499,8 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
 
        if (!usable_delta) {
                if (oe_type(entry) == OBJ_BLOB &&
-                   oe_size_greater_than(&to_pack, entry, big_file_threshold) &&
+                   oe_size_greater_than(&to_pack, entry,
+                                        repo_settings_get_big_file_threshold(the_repository)) &&
                    (st = open_istream(the_repository, &entry->idx.oid, &type,
                                       &size, NULL)) != NULL)
                        buf = NULL;
@@ -2454,7 +2455,8 @@ static void get_object_details(void)
                struct object_entry *entry = sorted_by_offset[i];
                check_object(entry, i);
                if (entry->type_valid &&
-                   oe_size_greater_than(&to_pack, entry, big_file_threshold))
+                   oe_size_greater_than(&to_pack, entry,
+                                        repo_settings_get_big_file_threshold(the_repository)))
                        entry->no_try_delta = 1;
                display_progress(progress_state, i + 1);
        }
index 8383bcf404957d7e7641ffacc09b9679e6be2dbb..e20c120913e5e63d9336764898cf4b27aadea4f3 100644 (file)
@@ -553,7 +553,8 @@ static void unpack_one(unsigned nr)
 
        switch (type) {
        case OBJ_BLOB:
-               if (!dry_run && size > big_file_threshold) {
+               if (!dry_run &&
+                   size > repo_settings_get_big_file_threshold(the_repository)) {
                        stream_blob(size, nr);
                        return;
                }
index dfd03b9421cdf94733224c118b54ea2318df5abe..dc95608f749fb196cca8ac351c475ad3416cd768 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1490,11 +1490,6 @@ static int git_default_core_config(const char *var, const char *value,
                return 0;
        }
 
-       if (!strcmp(var, "core.bigfilethreshold")) {
-               big_file_threshold = git_config_ulong(var, value, ctx->kvi);
-               return 0;
-       }
-
        if (!strcmp(var, "core.autocrlf")) {
                if (value && !strcasecmp(value, "input")) {
                        auto_crlf = AUTO_CRLF_INPUT;
diff --git a/diff.c b/diff.c
index c89c15d98e0e29b3441e4a328d8450b71eb5fe28..4f802b4251c7125b1deb3dd0a3c5401c9fb1902a 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -4193,7 +4193,8 @@ int diff_populate_filespec(struct repository *r,
                 * is probably fine.
                 */
                if (check_binary &&
-                   s->size > big_file_threshold && s->is_binary == -1) {
+                   s->size > repo_settings_get_big_file_threshold(the_repository) &&
+                   s->is_binary == -1) {
                        s->is_binary = 1;
                        return 0;
                }
@@ -4243,7 +4244,8 @@ object_read:
                if (size_only || check_binary) {
                        if (size_only)
                                return 0;
-                       if (s->size > big_file_threshold && s->is_binary == -1) {
+                       if (s->size > repo_settings_get_big_file_threshold(the_repository) &&
+                           s->is_binary == -1) {
                                s->is_binary = 1;
                                return 0;
                        }
index 9e4c7781be049aea5186f527df9ab906c3c81fea..3c32367c28c30bf7252b6fd2c92f2e42421e8c41 100644 (file)
@@ -49,7 +49,6 @@ int fsync_object_files = -1;
 int use_fsync = -1;
 enum fsync_method fsync_method = FSYNC_METHOD_DEFAULT;
 enum fsync_component fsync_components = FSYNC_COMPONENTS_DEFAULT;
-unsigned long big_file_threshold = 512 * 1024 * 1024;
 char *editor_program;
 char *askpass_program;
 char *excludes_file;
index 45e690f203fd1dd24c80ffa6d1812d3327009952..91d854dcb087a8d239d4cc2cee403a285cecc2b7 100644 (file)
@@ -154,7 +154,6 @@ extern int zlib_compression_level;
 extern int pack_compression_level;
 extern size_t packed_git_window_size;
 extern size_t packed_git_limit;
-extern unsigned long big_file_threshold;
 extern unsigned long pack_size_limit_cfg;
 extern int max_allowed_tree_depth;
 
index 726e41a0475b432a45f8ca193c68e1740bb4ac69..b3e0276b2a45e1e1298ee640513e969188c55930 100644 (file)
@@ -2803,7 +2803,8 @@ int index_fd(struct index_state *istate, struct object_id *oid,
                ret = index_stream_convert_blob(istate, oid, fd, path, flags);
        else if (!S_ISREG(st->st_mode))
                ret = index_pipe(istate, oid, fd, type, path, flags);
-       else if (st->st_size <= big_file_threshold || type != OBJ_BLOB ||
+       else if (st->st_size <= repo_settings_get_big_file_threshold(the_repository) ||
+                type != OBJ_BLOB ||
                 (path && would_convert_to_git(istate, path)))
                ret = index_core(istate, oid, fd, xsize_t(st->st_size),
                                 type, path, flags);
@@ -3137,7 +3138,8 @@ int read_loose_object(const char *path,
                goto out;
        }
 
-       if (*oi->typep == OBJ_BLOB && *size > big_file_threshold) {
+       if (*oi->typep == OBJ_BLOB &&
+           *size > repo_settings_get_big_file_threshold(the_repository)) {
                if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
                        goto out;
        } else {
index 6bcadc1e679590d62432cc9ec93a12cf8aa8262e..017dc740f7b8cbef49db3c913b0f9de672f17986 100644 (file)
@@ -131,7 +131,8 @@ static int verify_packfile(struct repository *r,
                type = unpack_object_header(p, w_curs, &curpos, &size);
                unuse_pack(w_curs);
 
-               if (type == OBJ_BLOB && big_file_threshold <= size) {
+               if (type == OBJ_BLOB &&
+                   repo_settings_get_big_file_threshold(the_repository) <= size) {
                        /*
                         * Let stream_object_signature() check it with
                         * the streaming interface; no point slurping
index 67e9cfd2e63d9c7ccd0dd1cd84b1ba1cf4f2aeb3..4129f8fb2b43a33df5288772379437cfce2214ad 100644 (file)
@@ -20,6 +20,13 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,
                *dest = def;
 }
 
+static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest,
+                          unsigned long def)
+{
+       if (repo_config_get_ulong(r, key, dest))
+               *dest = def;
+}
+
 void prepare_repo_settings(struct repository *r)
 {
        int experimental;
@@ -151,6 +158,19 @@ void repo_settings_clear(struct repository *r)
        r->settings = empty;
 }
 
+unsigned long repo_settings_get_big_file_threshold(struct repository *repo)
+{
+       if (!repo->settings.big_file_threshold)
+               repo_cfg_ulong(repo, "core.bigfilethreshold",
+                              &repo->settings.big_file_threshold, 512 * 1024 * 1024);
+       return repo->settings.big_file_threshold;
+}
+
+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value)
+{
+       repo->settings.big_file_threshold = value;
+}
+
 enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)
 {
        const char *value;
index ddc11967e015df526ec94c58d8376e3bccc91f62..2bf24b259735c275331cea1b6a5d5e9ffc22e82a 100644 (file)
@@ -64,6 +64,7 @@ struct repo_settings {
        size_t delta_base_cache_limit;
        size_t packed_git_window_size;
        size_t packed_git_limit;
+       unsigned long big_file_threshold;
 
        char *hooks_path;
 };
@@ -88,6 +89,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo);
 /* Read the value for "core.hooksPath". */
 const char *repo_settings_get_hooks_path(struct repository *repo);
 
+/* Read and set the value for "core.bigFileThreshold". */
+unsigned long repo_settings_get_big_file_threshold(struct repository *repo);
+void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value);
+
 /* Read, set or reset the value for "core.sharedRepository". */
 int repo_settings_get_shared_repository(struct repository *repo);
 void repo_settings_set_shared_repository(struct repository *repo, int value);
index 38839511afc1924c8f85b017130e321b2f2f3ecd..018b794d252819b0620fc714ef677fe7b25a1dd0 100644 (file)
@@ -431,7 +431,8 @@ static int istream_source(struct git_istream *st,
                st->open = open_istream_loose;
                return 0;
        case OI_PACKED:
-               if (!oi.u.packed.is_delta && big_file_threshold < size) {
+               if (!oi.u.packed.is_delta &&
+                   repo_settings_get_big_file_threshold(the_repository) < size) {
                        st->u.in_pack.pack = oi.u.packed.pack;
                        st->u.in_pack.pos = oi.u.packed.offset;
                        st->open = open_istream_pack_non_delta;
index c71932b02423734908428a9b2be776fec229ce9e..5be273611ad850f62a24dfccd5aa89b0742c7e16 100755 (executable)
@@ -6,7 +6,8 @@ test_description='adding and checking out large blobs'
 . ./test-lib.sh
 
 test_expect_success 'core.bigFileThreshold must be non-negative' '
-       test_must_fail git -c core.bigFileThreshold=-1 rev-parse >out 2>err &&
+       : >input &&
+       test_must_fail git -c core.bigFileThreshold=-1 hash-object input >out 2>err &&
        grep "bad numeric config value" err &&
        test_must_be_empty out
 '