Skip to content

Commit 8e3cad1

Browse files
committed
repository: wire ref extensions to ref backends
The previous change introduced the extensions.refFormat config option. It is a multi-valued config option that currently understands "files" and "packed", with both values assumed by default. If any value is provided explicitly, this default is ignored and the provided settings are used instead. The multi-valued nature of this extension presents a way to allow a user to specify that they never want a packed-refs file (only use "files") or that they never want loose reference files (only use "packed"). However, that functionality is not currently connected. Before actually modifying the files backend to understand these extension settings, do the basic wiring that connects the extensions.refFormat parsing to the creation of the ref backend. A future change will actually change the ref backend initialization based on these settings, but this communication of the extension is sufficiently complicated to be worth an isolated change. For now, also forbid the setting of only "packed". This is done by redirecting the choice of backend to the packed backend when that selection is made. A later change will make the "files"-only extension value ignore the packed backend. Signed-off-by: Derrick Stolee <derrickstolee@github.com>
1 parent b3e18dc commit 8e3cad1

File tree

8 files changed

+63
-4
lines changed

8 files changed

+63
-4
lines changed

cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,8 @@ struct repository_format {
11551155
int hash_algo;
11561156
int sparse_index;
11571157
char *work_tree;
1158+
int ref_format_count;
1159+
enum ref_format_flags ref_format;
11581160
struct string_list unknown_extensions;
11591161
struct string_list v1_only_extensions;
11601162
};

refs.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,15 @@ static struct ref_store *lookup_ref_store_map(struct hashmap *map,
19561956
return entry ? entry->refs : NULL;
19571957
}
19581958

1959+
static int add_ref_format_flags(enum ref_format_flags flags, int caps) {
1960+
if (flags & REF_FORMAT_FILES)
1961+
caps |= REF_STORE_FORMAT_FILES;
1962+
if (flags & REF_FORMAT_PACKED)
1963+
caps |= REF_STORE_FORMAT_PACKED;
1964+
1965+
return caps;
1966+
}
1967+
19591968
/*
19601969
* Create, record, and return a ref_store instance for the specified
19611970
* gitdir.
@@ -1965,9 +1974,17 @@ static struct ref_store *ref_store_init(struct repository *repo,
19651974
unsigned int flags)
19661975
{
19671976
const char *be_name = "files";
1968-
struct ref_storage_be *be = find_ref_storage_backend(be_name);
1977+
struct ref_storage_be *be;
19691978
struct ref_store *refs;
19701979

1980+
flags = add_ref_format_flags(repo->ref_format, flags);
1981+
1982+
if (!(flags & REF_STORE_FORMAT_FILES) &&
1983+
(flags & REF_STORE_FORMAT_PACKED))
1984+
be_name = "packed";
1985+
1986+
be = find_ref_storage_backend(be_name);
1987+
19711988
if (!be)
19721989
BUG("reference backend %s is unknown", be_name);
19731990

@@ -1983,7 +2000,8 @@ struct ref_store *get_main_ref_store(struct repository *r)
19832000
if (!r->gitdir)
19842001
BUG("attempting to get main_ref_store outside of repository");
19852002

1986-
r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS);
2003+
r->refs_private = ref_store_init(r, r->gitdir,
2004+
REF_STORE_ALL_CAPS);
19872005
r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private);
19882006
return r->refs_private;
19892007
}

refs/files-backend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3282,7 +3282,7 @@ static int files_init_db(struct ref_store *ref_store, struct strbuf *err UNUSED)
32823282
}
32833283

32843284
struct ref_storage_be refs_be_files = {
3285-
.next = NULL,
3285+
.next = &refs_be_packed,
32863286
.name = "files",
32873287
.init = files_ref_store_create,
32883288
.init_db = files_init_db,

refs/refs-internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,9 @@ struct ref_store;
521521
REF_STORE_ODB | \
522522
REF_STORE_MAIN)
523523

524+
#define REF_STORE_FORMAT_FILES (1 << 8) /* can use loose ref files */
525+
#define REF_STORE_FORMAT_PACKED (1 << 9) /* can use packed-refs file */
526+
524527
/*
525528
* Initialize the ref_store for the specified gitdir. These functions
526529
* should call base_ref_store_init() to initialize the shared part of

repository.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ int repo_init(struct repository *repo,
182182
repo->repository_format_partial_clone = format.partial_clone;
183183
format.partial_clone = NULL;
184184

185+
repo->ref_format = format.ref_format;
186+
185187
if (worktree)
186188
repo_set_worktree(repo, worktree);
187189

repository.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ struct repo_path_cache {
6161
char *shallow;
6262
};
6363

64+
enum ref_format_flags {
65+
REF_FORMAT_FILES = (1 << 0),
66+
REF_FORMAT_PACKED = (1 << 1),
67+
};
68+
6469
struct repository {
6570
/* Environment */
6671
/*
@@ -95,6 +100,7 @@ struct repository {
95100
* the ref object.
96101
*/
97102
struct ref_store *refs_private;
103+
enum ref_format_flags ref_format;
98104

99105
/*
100106
* Contains path to often used file names.

setup.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,14 @@ static enum extension_result handle_extension(const char *var,
578578
data->hash_algo = format;
579579
return EXTENSION_OK;
580580
} else if (!strcmp(ext, "refformat")) {
581-
if (strcmp(value, "files") && strcmp(value, "packed"))
581+
if (!strcmp(value, "files"))
582+
data->ref_format |= REF_FORMAT_FILES;
583+
else if (!strcmp(value, "packed"))
584+
data->ref_format |= REF_FORMAT_PACKED;
585+
else
582586
return error(_("invalid value for '%s': '%s'"),
583587
"extensions.refFormat", value);
588+
data->ref_format_count++;
584589
return EXTENSION_OK;
585590
}
586591
return EXTENSION_UNKNOWN;
@@ -723,6 +728,11 @@ int read_repository_format(struct repository_format *format, const char *path)
723728
git_config_from_file(check_repo_format, path, format);
724729
if (format->version == -1)
725730
clear_repository_format(format);
731+
732+
/* Set default ref_format if no extensions.refFormat exists. */
733+
if (!format->ref_format_count)
734+
format->ref_format = REF_FORMAT_FILES | REF_FORMAT_PACKED;
735+
726736
return format->version;
727737
}
728738

@@ -1425,6 +1435,9 @@ int discover_git_directory(struct strbuf *commondir,
14251435
candidate.partial_clone;
14261436
candidate.partial_clone = NULL;
14271437

1438+
/* take ownership of candidate.ref_format */
1439+
the_repository->ref_format = candidate.ref_format;
1440+
14281441
clear_repository_format(&candidate);
14291442
return 0;
14301443
}
@@ -1561,6 +1574,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
15611574
the_repository->repository_format_partial_clone =
15621575
repo_fmt.partial_clone;
15631576
repo_fmt.partial_clone = NULL;
1577+
1578+
the_repository->ref_format = repo_fmt.ref_format;
15641579
}
15651580
}
15661581
/*
@@ -1650,6 +1665,7 @@ void check_repository_format(struct repository_format *fmt)
16501665
repo_set_hash_algo(the_repository, fmt->hash_algo);
16511666
the_repository->repository_format_partial_clone =
16521667
xstrdup_or_null(fmt->partial_clone);
1668+
the_repository->ref_format = fmt->ref_format;
16531669
clear_repository_format(&repo_fmt);
16541670
}
16551671

t/t3212-ref-formats.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,16 @@ test_expect_success 'invalid extensions.refFormat' '
2424
grep "invalid value for '\''extensions.refFormat'\'': '\''bogus'\''" err
2525
'
2626

27+
test_expect_success 'extensions.refFormat=packed only' '
28+
git init only-packed &&
29+
(
30+
cd only-packed &&
31+
git config core.repositoryFormatVersion 1 &&
32+
git config extensions.refFormat packed &&
33+
test_commit A &&
34+
test_path_exists .git/packed-refs &&
35+
test_path_is_missing .git/refs/tags/A
36+
)
37+
'
38+
2739
test_done

0 commit comments

Comments
 (0)