Skip to content

Commit 8591654

Browse files
committed
Merge branch 'jk/check-repository-format' into maint
The repository set-up sequence has been streamlined (the biggest change is that there is no longer git_config_early()), so that we do not attempt to look into refs/* when we know we do not have a Git repository. * jk/check-repository-format: verify_repository_format: mark messages for translation setup: drop repository_format_version global setup: unify repository version callbacks init: use setup.c's repo version verification setup: refactor repo format reading and verification config: drop git_config_early check_repository_format_gently: stop using git_config_early lazily load core.sharedrepository wrap shared_repository global in get/set accessors setup: document check_repository_format()
2 parents ffaa7c5 + 274db84 commit 8591654

File tree

7 files changed

+167
-114
lines changed

7 files changed

+167
-114
lines changed

Documentation/technical/api-config.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,6 @@ parse for configuration, rather than looking in the usual files. Regular
6363
Specify whether include directives should be followed in parsed files.
6464
Regular `git_config` defaults to `1`.
6565

66-
There is a special version of `git_config` called `git_config_early`.
67-
This version takes an additional parameter to specify the repository
68-
config, instead of having it looked up via `git_path`. This is useful
69-
early in a Git program before the repository has been found. Unless
70-
you're working with early setup code, you probably don't want to use
71-
this.
72-
7366
Reading Specific Files
7467
----------------------
7568

builtin/init-db.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ static void copy_templates(const char *template_dir)
9595
struct strbuf path = STRBUF_INIT;
9696
struct strbuf template_path = STRBUF_INIT;
9797
size_t template_len;
98+
struct repository_format template_format;
99+
struct strbuf err = STRBUF_INIT;
98100
DIR *dir;
99101
char *to_free = NULL;
100102

@@ -121,17 +123,18 @@ static void copy_templates(const char *template_dir)
121123

122124
/* Make sure that template is from the correct vintage */
123125
strbuf_addstr(&template_path, "config");
124-
repository_format_version = 0;
125-
git_config_from_file(check_repository_format_version,
126-
template_path.buf, NULL);
126+
read_repository_format(&template_format, template_path.buf);
127127
strbuf_setlen(&template_path, template_len);
128128

129-
if (repository_format_version &&
130-
repository_format_version != GIT_REPO_VERSION) {
131-
warning(_("not copying templates of "
132-
"a wrong format version %d from '%s'"),
133-
repository_format_version,
134-
template_dir);
129+
/*
130+
* No mention of version at all is OK, but anything else should be
131+
* verified.
132+
*/
133+
if (template_format.version >= 0 &&
134+
verify_repository_format(&template_format, &err) < 0) {
135+
warning(_("not copying templates from '%s': %s"),
136+
template_dir, err.buf);
137+
strbuf_release(&err);
135138
goto close_free_return;
136139
}
137140

@@ -199,13 +202,13 @@ static int create_default_files(const char *template_path)
199202

200203
/* reading existing config may have overwrote it */
201204
if (init_shared_repository != -1)
202-
shared_repository = init_shared_repository;
205+
set_shared_repository(init_shared_repository);
203206

204207
/*
205208
* We would have created the above under user's umask -- under
206209
* shared-repository settings, we would need to fix them up.
207210
*/
208-
if (shared_repository) {
211+
if (get_shared_repository()) {
209212
adjust_shared_perm(get_git_dir());
210213
adjust_shared_perm(git_path_buf(&buf, "refs"));
211214
adjust_shared_perm(git_path_buf(&buf, "refs/heads"));
@@ -370,20 +373,20 @@ int init_db(const char *template_dir, unsigned int flags)
370373

371374
create_object_directory();
372375

373-
if (shared_repository) {
376+
if (get_shared_repository()) {
374377
char buf[10];
375378
/* We do not spell "group" and such, so that
376379
* the configuration can be read by older version
377380
* of git. Note, we use octal numbers for new share modes,
378381
* and compatibility values for PERM_GROUP and
379382
* PERM_EVERYBODY.
380383
*/
381-
if (shared_repository < 0)
384+
if (get_shared_repository() < 0)
382385
/* force to the mode value */
383-
xsnprintf(buf, sizeof(buf), "0%o", -shared_repository);
384-
else if (shared_repository == PERM_GROUP)
386+
xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository());
387+
else if (get_shared_repository() == PERM_GROUP)
385388
xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
386-
else if (shared_repository == PERM_EVERYBODY)
389+
else if (get_shared_repository() == PERM_EVERYBODY)
387390
xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
388391
else
389392
die("BUG: invalid value for shared_repository");
@@ -399,7 +402,7 @@ int init_db(const char *template_dir, unsigned int flags)
399402
"", and the last '%s%s' is the verbatim directory name. */
400403
printf(_("%s%s Git repository in %s%s\n"),
401404
reinit ? _("Reinitialized existing") : _("Initialized empty"),
402-
shared_repository ? _(" shared") : "",
405+
get_shared_repository() ? _(" shared") : "",
403406
git_dir, len && git_dir[len-1] != '/' ? "/" : "");
404407
}
405408

@@ -494,8 +497,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
494497
* and we know shared_repository should always be 0;
495498
* but just in case we play safe.
496499
*/
497-
saved = shared_repository;
498-
shared_repository = 0;
500+
saved = get_shared_repository();
501+
set_shared_repository(0);
499502
switch (safe_create_leading_directories_const(argv[0])) {
500503
case SCLD_OK:
501504
case SCLD_PERMS:
@@ -507,7 +510,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
507510
die_errno(_("cannot mkdir %s"), argv[0]);
508511
break;
509512
}
510-
shared_repository = saved;
513+
set_shared_repository(saved);
511514
if (mkdir(argv[0], 0777) < 0)
512515
die_errno(_("cannot mkdir %s"), argv[0]);
513516
mkdir_tried = 1;
@@ -525,7 +528,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
525528
}
526529

527530
if (init_shared_repository != -1)
528-
shared_repository = init_shared_repository;
531+
set_shared_repository(init_shared_repository);
529532

530533
/*
531534
* GIT_WORK_TREE makes sense only in conjunction with GIT_DIR

cache.h

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,6 @@ extern int prefer_symlink_refs;
651651
extern int log_all_ref_updates;
652652
extern int warn_ambiguous_refs;
653653
extern int warn_on_object_refname_ambiguity;
654-
extern int shared_repository;
655654
extern const char *apply_default_whitespace;
656655
extern const char *apply_default_ignorewhitespace;
657656
extern const char *git_attributes_file;
@@ -664,6 +663,9 @@ extern size_t delta_base_cache_limit;
664663
extern unsigned long big_file_threshold;
665664
extern unsigned long pack_size_limit_cfg;
666665

666+
void set_shared_repository(int value);
667+
int get_shared_repository(void);
668+
667669
/*
668670
* Do replace refs need to be checked this run? This variable is
669671
* initialized to true unless --no-replace-object is used or
@@ -745,9 +747,39 @@ extern int grafts_replace_parents;
745747
*/
746748
#define GIT_REPO_VERSION 0
747749
#define GIT_REPO_VERSION_READ 1
748-
extern int repository_format_version;
749750
extern int repository_format_precious_objects;
750-
extern int check_repository_format(void);
751+
752+
struct repository_format {
753+
int version;
754+
int precious_objects;
755+
int is_bare;
756+
char *work_tree;
757+
struct string_list unknown_extensions;
758+
};
759+
760+
/*
761+
* Read the repository format characteristics from the config file "path" into
762+
* "format" struct. Returns the numeric version. On error, -1 is returned,
763+
* format->version is set to -1, and all other fields in the struct are
764+
* undefined.
765+
*/
766+
int read_repository_format(struct repository_format *format, const char *path);
767+
768+
/*
769+
* Verify that the repository described by repository_format is something we
770+
* can read. If it is, return 0. Otherwise, return -1, and "err" will describe
771+
* any errors encountered.
772+
*/
773+
int verify_repository_format(const struct repository_format *format,
774+
struct strbuf *err);
775+
776+
/*
777+
* Check the repository format version in the path found in get_git_dir(),
778+
* and die if it is a version we don't understand. Generally one would
779+
* set_git_dir() before calling this, and use it only for "are we in a valid
780+
* repo?".
781+
*/
782+
extern void check_repository_format(void);
751783

752784
#define MTIME_CHANGED 0x0001
753785
#define CTIME_CHANGED 0x0002
@@ -1526,7 +1558,6 @@ extern void git_config(config_fn_t fn, void *);
15261558
extern int git_config_with_options(config_fn_t fn, void *,
15271559
struct git_config_source *config_source,
15281560
int respect_includes);
1529-
extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
15301561
extern int git_parse_ulong(const char *, unsigned long *);
15311562
extern int git_parse_maybe_bool(const char *);
15321563
extern int git_config_int(const char *, const char *);
@@ -1550,7 +1581,6 @@ extern void git_config_set_multivar_in_file(const char *, const char *, const ch
15501581
extern int git_config_rename_section(const char *, const char *);
15511582
extern int git_config_rename_section_in_file(const char *, const char *, const char *);
15521583
extern const char *git_etc_gitconfig(void);
1553-
extern int check_repository_format_version(const char *var, const char *value, void *cb);
15541584
extern int git_env_bool(const char *, int);
15551585
extern unsigned long git_env_ulong(const char *, unsigned long);
15561586
extern int git_config_system(void);

config.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,11 +1188,12 @@ int git_config_system(void)
11881188
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
11891189
}
11901190

1191-
int git_config_early(config_fn_t fn, void *data, const char *repo_config)
1191+
static int do_git_config_sequence(config_fn_t fn, void *data)
11921192
{
11931193
int ret = 0, found = 0;
11941194
char *xdg_config = xdg_config_home("config");
11951195
char *user_config = expand_user_path("~/.gitconfig");
1196+
char *repo_config = git_pathdup("config");
11961197

11971198
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
11981199
ret += git_config_from_file(fn, git_etc_gitconfig(),
@@ -1228,15 +1229,14 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
12281229

12291230
free(xdg_config);
12301231
free(user_config);
1232+
free(repo_config);
12311233
return ret == 0 ? found : ret;
12321234
}
12331235

12341236
int git_config_with_options(config_fn_t fn, void *data,
12351237
struct git_config_source *config_source,
12361238
int respect_includes)
12371239
{
1238-
char *repo_config = NULL;
1239-
int ret;
12401240
struct config_include_data inc = CONFIG_INCLUDE_INIT;
12411241

12421242
if (respect_includes) {
@@ -1257,11 +1257,7 @@ int git_config_with_options(config_fn_t fn, void *data,
12571257
else if (config_source && config_source->blob)
12581258
return git_config_from_blob_ref(fn, config_source->blob, data);
12591259

1260-
repo_config = git_pathdup("config");
1261-
ret = git_config_early(fn, data, repo_config);
1262-
if (repo_config)
1263-
free(repo_config);
1264-
return ret;
1260+
return do_git_config_sequence(fn, data);
12651261
}
12661262

12671263
static void git_config_raw(config_fn_t fn, void *data)

environment.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,9 @@ int log_all_ref_updates = -1; /* unspecified */
2525
int warn_ambiguous_refs = 1;
2626
int warn_on_object_refname_ambiguity = 1;
2727
int ref_paranoia = -1;
28-
int repository_format_version;
2928
int repository_format_precious_objects;
3029
const char *git_commit_encoding;
3130
const char *git_log_output_encoding;
32-
int shared_repository = PERM_UMASK;
3331
const char *apply_default_whitespace;
3432
const char *apply_default_ignorewhitespace;
3533
const char *git_attributes_file;
@@ -324,3 +322,24 @@ const char *get_commit_output_encoding(void)
324322
{
325323
return git_commit_encoding ? git_commit_encoding : "UTF-8";
326324
}
325+
326+
static int the_shared_repository = PERM_UMASK;
327+
static int need_shared_repository_from_config = 1;
328+
329+
void set_shared_repository(int value)
330+
{
331+
the_shared_repository = value;
332+
need_shared_repository_from_config = 0;
333+
}
334+
335+
int get_shared_repository(void)
336+
{
337+
if (need_shared_repository_from_config) {
338+
const char *var = "core.sharedrepository";
339+
const char *value;
340+
if (!git_config_get_value(var, &value))
341+
the_shared_repository = git_config_perm(var, value);
342+
need_shared_repository_from_config = 0;
343+
}
344+
return the_shared_repository;
345+
}

path.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -702,17 +702,17 @@ static int calc_shared_perm(int mode)
702702
{
703703
int tweak;
704704

705-
if (shared_repository < 0)
706-
tweak = -shared_repository;
705+
if (get_shared_repository() < 0)
706+
tweak = -get_shared_repository();
707707
else
708-
tweak = shared_repository;
708+
tweak = get_shared_repository();
709709

710710
if (!(mode & S_IWUSR))
711711
tweak &= ~0222;
712712
if (mode & S_IXUSR)
713713
/* Copy read bits to execute bits */
714714
tweak |= (tweak & 0444) >> 2;
715-
if (shared_repository < 0)
715+
if (get_shared_repository() < 0)
716716
mode = (mode & ~0777) | tweak;
717717
else
718718
mode |= tweak;
@@ -725,7 +725,7 @@ int adjust_shared_perm(const char *path)
725725
{
726726
int old_mode, new_mode;
727727

728-
if (!shared_repository)
728+
if (!get_shared_repository())
729729
return 0;
730730
if (get_st_mode_bits(path, &old_mode) < 0)
731731
return -1;

0 commit comments

Comments
 (0)