From: Junio C Hamano Date: Mon, 2 May 2016 21:24:04 +0000 (-0700) Subject: Merge branch 'jk/check-repository-format' into maint X-Git-Tag: v2.8.3~44 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/85916549980c709ae14f8a935a5a6266a4a80b26?ds=inline;hp=-c 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() --- 85916549980c709ae14f8a935a5a6266a4a80b26 diff --combined builtin/init-db.c index da531f6b76,d9934f3592..b2d8d40a67 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@@ -95,6 -95,8 +95,8 @@@ static void copy_templates(const char * struct strbuf path = STRBUF_INIT; struct strbuf template_path = STRBUF_INIT; size_t template_len; + struct repository_format template_format; + struct strbuf err = STRBUF_INIT; DIR *dir; char *to_free = NULL; @@@ -121,17 -123,18 +123,18 @@@ /* Make sure that template is from the correct vintage */ strbuf_addstr(&template_path, "config"); - repository_format_version = 0; - git_config_from_file(check_repository_format_version, - template_path.buf, NULL); + read_repository_format(&template_format, template_path.buf); strbuf_setlen(&template_path, template_len); - if (repository_format_version && - repository_format_version != GIT_REPO_VERSION) { - warning(_("not copying templates of " - "a wrong format version %d from '%s'"), - repository_format_version, - template_dir); + /* + * No mention of version at all is OK, but anything else should be + * verified. + */ + if (template_format.version >= 0 && + verify_repository_format(&template_format, &err) < 0) { + warning(_("not copying templates from '%s': %s"), + template_dir, err.buf); + strbuf_release(&err); goto close_free_return; } @@@ -199,13 -202,13 +202,13 @@@ static int create_default_files(const c /* reading existing config may have overwrote it */ if (init_shared_repository != -1) - shared_repository = init_shared_repository; + set_shared_repository(init_shared_repository); /* * We would have created the above under user's umask -- under * shared-repository settings, we would need to fix them up. */ - if (shared_repository) { + if (get_shared_repository()) { adjust_shared_perm(get_git_dir()); adjust_shared_perm(git_path_buf(&buf, "refs")); adjust_shared_perm(git_path_buf(&buf, "refs/heads")); @@@ -322,7 -325,6 +325,7 @@@ int set_git_dir_init(const char *git_di set_git_dir(real_path(git_dir)); git_link = NULL; } + startup_info->have_repository = 1; return 0; } @@@ -370,7 -372,7 +373,7 @@@ int init_db(const char *template_dir, u create_object_directory(); - if (shared_repository) { + if (get_shared_repository()) { char buf[10]; /* We do not spell "group" and such, so that * the configuration can be read by older version @@@ -378,12 -380,12 +381,12 @@@ * and compatibility values for PERM_GROUP and * PERM_EVERYBODY. */ - if (shared_repository < 0) + if (get_shared_repository() < 0) /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -shared_repository); - else if (shared_repository == PERM_GROUP) + xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); + else if (get_shared_repository() == PERM_GROUP) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (shared_repository == PERM_EVERYBODY) + else if (get_shared_repository() == PERM_EVERYBODY) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); else die("BUG: invalid value for shared_repository"); @@@ -399,7 -401,7 +402,7 @@@ "", and the last '%s%s' is the verbatim directory name. */ printf(_("%s%s Git repository in %s%s\n"), reinit ? _("Reinitialized existing") : _("Initialized empty"), - shared_repository ? _(" shared") : "", + get_shared_repository() ? _(" shared") : "", git_dir, len && git_dir[len-1] != '/' ? "/" : ""); } @@@ -494,8 -496,8 +497,8 @@@ int cmd_init_db(int argc, const char ** * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = shared_repository; - shared_repository = 0; + saved = get_shared_repository(); + set_shared_repository(0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@@ -507,7 -509,7 +510,7 @@@ die_errno(_("cannot mkdir %s"), argv[0]); break; } - shared_repository = saved; + set_shared_repository(saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@@ -525,7 -527,7 +528,7 @@@ } if (init_shared_repository != -1) - shared_repository = init_shared_repository; + set_shared_repository(init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --combined cache.h index 9f09540bbc,bec6db5e2e..2711048cad --- a/cache.h +++ b/cache.h @@@ -651,7 -651,6 +651,6 @@@ extern int prefer_symlink_refs extern int log_all_ref_updates; extern int warn_ambiguous_refs; extern int warn_on_object_refname_ambiguity; - extern int shared_repository; extern const char *apply_default_whitespace; extern const char *apply_default_ignorewhitespace; extern const char *git_attributes_file; @@@ -664,6 -663,9 +663,9 @@@ extern size_t delta_base_cache_limit extern unsigned long big_file_threshold; extern unsigned long pack_size_limit_cfg; + void set_shared_repository(int value); + int get_shared_repository(void); + /* * Do replace refs need to be checked this run? This variable is * initialized to true unless --no-replace-object is used or @@@ -745,9 -747,39 +747,39 @@@ extern int grafts_replace_parents */ #define GIT_REPO_VERSION 0 #define GIT_REPO_VERSION_READ 1 - extern int repository_format_version; extern int repository_format_precious_objects; - extern int check_repository_format(void); + + struct repository_format { + int version; + int precious_objects; + int is_bare; + char *work_tree; + struct string_list unknown_extensions; + }; + + /* + * Read the repository format characteristics from the config file "path" into + * "format" struct. Returns the numeric version. On error, -1 is returned, + * format->version is set to -1, and all other fields in the struct are + * undefined. + */ + int read_repository_format(struct repository_format *format, const char *path); + + /* + * Verify that the repository described by repository_format is something we + * can read. If it is, return 0. Otherwise, return -1, and "err" will describe + * any errors encountered. + */ + int verify_repository_format(const struct repository_format *format, + struct strbuf *err); + + /* + * Check the repository format version in the path found in get_git_dir(), + * and die if it is a version we don't understand. Generally one would + * set_git_dir() before calling this, and use it only for "are we in a valid + * repo?". + */ + extern void check_repository_format(void); #define MTIME_CHANGED 0x0001 #define CTIME_CHANGED 0x0002 @@@ -1526,7 -1558,6 +1558,6 @@@ extern void git_config(config_fn_t fn, extern int git_config_with_options(config_fn_t fn, void *, struct git_config_source *config_source, int respect_includes); - extern int git_config_early(config_fn_t fn, void *, const char *repo_config); extern int git_parse_ulong(const char *, unsigned long *); extern int git_parse_maybe_bool(const char *); extern int git_config_int(const char *, const char *); @@@ -1550,7 -1581,6 +1581,6 @@@ extern void git_config_set_multivar_in_ extern int git_config_rename_section(const char *, const char *); extern int git_config_rename_section_in_file(const char *, const char *, const char *); extern const char *git_etc_gitconfig(void); - extern int check_repository_format_version(const char *var, const char *value, void *cb); extern int git_env_bool(const char *, int); extern unsigned long git_env_ulong(const char *, unsigned long); extern int git_config_system(void); @@@ -1771,7 -1801,7 +1801,7 @@@ int split_cmdline(char *cmdline, const /* Takes a negative value returned by split_cmdline */ const char *split_cmdline_strerror(int cmdline_errno); -/* git.c */ +/* setup.c */ struct startup_info { int have_repository; const char *prefix; diff --combined environment.c index 6cc0a7780f,d9e3861fe8..57acb2fe2a --- a/environment.c +++ b/environment.c @@@ -25,11 -25,9 +25,9 @@@ int log_all_ref_updates = -1; /* unspec int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int ref_paranoia = -1; - int repository_format_version; int repository_format_precious_objects; const char *git_commit_encoding; const char *git_log_output_encoding; - int shared_repository = PERM_UMASK; const char *apply_default_whitespace; const char *apply_default_ignorewhitespace; const char *git_attributes_file; @@@ -64,6 -62,7 +62,6 @@@ int grafts_replace_parents = 1 int core_apply_sparse_checkout; int merge_log_config = -1; int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */ -struct startup_info *startup_info; unsigned long pack_size_limit_cfg; #ifndef PROTECT_HFS_DEFAULT @@@ -324,3 -323,24 +322,24 @@@ const char *get_commit_output_encoding( { return git_commit_encoding ? git_commit_encoding : "UTF-8"; } + + static int the_shared_repository = PERM_UMASK; + static int need_shared_repository_from_config = 1; + + void set_shared_repository(int value) + { + the_shared_repository = value; + need_shared_repository_from_config = 0; + } + + int get_shared_repository(void) + { + if (need_shared_repository_from_config) { + const char *var = "core.sharedrepository"; + const char *value; + if (!git_config_get_value(var, &value)) + the_shared_repository = git_config_perm(var, value); + need_shared_repository_from_config = 0; + } + return the_shared_repository; + } diff --combined path.c index 969b494d72,a6f1cd69a0..bbaea5ab0b --- a/path.c +++ b/path.c @@@ -584,9 -584,6 +584,9 @@@ char *expand_user_path(const char *path if (!home) goto return_null; strbuf_addstr(&user_path, home); +#ifdef GIT_WINDOWS_NATIVE + convert_slashes(user_path.buf); +#endif } else { struct passwd *pw = getpw_str(username, username_len); if (!pw) @@@ -702,17 -699,17 +702,17 @@@ static int calc_shared_perm(int mode { int tweak; - if (shared_repository < 0) - tweak = -shared_repository; + if (get_shared_repository() < 0) + tweak = -get_shared_repository(); else - tweak = shared_repository; + tweak = get_shared_repository(); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (shared_repository < 0) + if (get_shared_repository() < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@@ -725,7 -722,7 +725,7 @@@ int adjust_shared_perm(const char *path { int old_mode, new_mode; - if (!shared_repository) + if (!get_shared_repository()) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; diff --combined setup.c index 3439ec6d81,09d37204f9..1563cd42df --- a/setup.c +++ b/setup.c @@@ -5,11 -5,7 +5,10 @@@ static int inside_git_dir = -1; static int inside_work_tree = -1; static int work_tree_config_is_bogus; - static struct string_list unknown_extensions = STRING_LIST_INIT_DUP; +static struct startup_info the_startup_info; +struct startup_info *startup_info = &the_startup_info; + /* * The input parameter must contain an absolute path, and it must already be * normalized. @@@ -373,14 -369,13 +372,13 @@@ void setup_work_tree(void initialized = 1; } - static int check_repo_format(const char *var, const char *value, void *cb) + static int check_repo_format(const char *var, const char *value, void *vdata) { + struct repository_format *data = vdata; const char *ext; if (strcmp(var, "core.repositoryformatversion") == 0) - repository_format_version = git_config_int(var, value); - else if (strcmp(var, "core.sharedrepository") == 0) - shared_repository = git_config_perm(var, value); + data->version = git_config_int(var, value); else if (skip_prefix(var, "extensions.", &ext)) { /* * record any known extensions here; otherwise, @@@ -390,9 -385,15 +388,15 @@@ if (!strcmp(ext, "noop")) ; else if (!strcmp(ext, "preciousobjects")) - repository_format_precious_objects = git_config_bool(var, value); + data->precious_objects = git_config_bool(var, value); else - string_list_append(&unknown_extensions, ext); + string_list_append(&data->unknown_extensions, ext); + } else if (strcmp(var, "core.bare") == 0) { + data->is_bare = git_config_bool(var, value); + } else if (strcmp(var, "core.worktree") == 0) { + if (!value) + return config_error_nonbool(var); + data->work_tree = xstrdup(value); } return 0; } @@@ -400,56 -401,84 +404,84 @@@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok) { struct strbuf sb = STRBUF_INIT; - const char *repo_config; - config_fn_t fn; - int ret = 0; - - string_list_clear(&unknown_extensions, 0); + struct strbuf err = STRBUF_INIT; + struct repository_format candidate; + int has_common; - if (get_common_dir(&sb, gitdir)) - fn = check_repo_format; - else - fn = check_repository_format_version; + has_common = get_common_dir(&sb, gitdir); strbuf_addstr(&sb, "/config"); - repo_config = sb.buf; + read_repository_format(&candidate, sb.buf); + strbuf_release(&sb); /* - * git_config() can't be used here because it calls git_pathdup() - * to get $GIT_CONFIG/config. That call will make setup_git_env() - * set git_dir to ".git". - * - * We are in gitdir setup, no git dir has been found useable yet. - * Use a gentler version of git_config() to check if this repo - * is a good one. + * For historical use of check_repository_format() in git-init, + * we treat a missing config as a silent "ok", even when nongit_ok + * is unset. */ - git_config_early(fn, NULL, repo_config); - if (GIT_REPO_VERSION_READ < repository_format_version) { - if (!nongit_ok) - die ("Expected git repo version <= %d, found %d", - GIT_REPO_VERSION_READ, repository_format_version); - warning("Expected git repo version <= %d, found %d", - GIT_REPO_VERSION_READ, repository_format_version); - warning("Please upgrade Git"); - *nongit_ok = -1; - ret = -1; - } - - if (repository_format_version >= 1 && unknown_extensions.nr) { + if (candidate.version < 0) + return 0; + + if (verify_repository_format(&candidate, &err) < 0) { + if (nongit_ok) { + warning("%s", err.buf); + strbuf_release(&err); + *nongit_ok = -1; + return -1; + } + die("%s", err.buf); + } + + repository_format_precious_objects = candidate.precious_objects; + string_list_clear(&candidate.unknown_extensions, 0); + if (!has_common) { + if (candidate.is_bare != -1) { + is_bare_repository_cfg = candidate.is_bare; + if (is_bare_repository_cfg == 1) + inside_work_tree = -1; + } + if (candidate.work_tree) { + free(git_work_tree_cfg); + git_work_tree_cfg = candidate.work_tree; + inside_work_tree = -1; + } + } else { + free(candidate.work_tree); + } + + return 0; + } + + int read_repository_format(struct repository_format *format, const char *path) + { + memset(format, 0, sizeof(*format)); + format->version = -1; + format->is_bare = -1; + string_list_init(&format->unknown_extensions, 1); + git_config_from_file(check_repo_format, path, format); + return format->version; + } + + int verify_repository_format(const struct repository_format *format, + struct strbuf *err) + { + if (GIT_REPO_VERSION_READ < format->version) { + strbuf_addf(err, _("Expected git repo version <= %d, found %d"), + GIT_REPO_VERSION_READ, format->version); + return -1; + } + + if (format->version >= 1 && format->unknown_extensions.nr) { int i; - if (!nongit_ok) - die("unknown repository extension: %s", - unknown_extensions.items[0].string); + strbuf_addstr(err, _("unknown repository extensions found:")); - for (i = 0; i < unknown_extensions.nr; i++) - warning("unknown repository extension: %s", - unknown_extensions.items[i].string); - *nongit_ok = -1; - ret = -1; + for (i = 0; i < format->unknown_extensions.nr; i++) + strbuf_addf(err, "\n\t%s", + format->unknown_extensions.items[i].string); + return -1; } - strbuf_release(&sb); - return ret; + return 0; } /* @@@ -908,9 -937,10 +940,9 @@@ const char *setup_git_directory_gently( else setenv(GIT_PREFIX_ENVIRONMENT, "", 1); - if (startup_info) { - startup_info->have_repository = !nongit_ok || !*nongit_ok; - startup_info->prefix = prefix; - } + startup_info->have_repository = !nongit_ok || !*nongit_ok; + startup_info->prefix = prefix; + return prefix; } @@@ -965,30 -995,9 +997,10 @@@ int git_config_perm(const char *var, co return -(i & 0666); } - int check_repository_format_version(const char *var, const char *value, void *cb) - { - int ret = check_repo_format(var, value, cb); - if (ret) - return ret; - if (strcmp(var, "core.bare") == 0) { - is_bare_repository_cfg = git_config_bool(var, value); - if (is_bare_repository_cfg == 1) - inside_work_tree = -1; - } else if (strcmp(var, "core.worktree") == 0) { - if (!value) - return config_error_nonbool(var); - free(git_work_tree_cfg); - git_work_tree_cfg = xstrdup(value); - inside_work_tree = -1; - } - return 0; - } - - int check_repository_format(void) + void check_repository_format(void) { check_repository_format_gently(get_git_dir(), NULL); + startup_info->have_repository = 1; - return 0; } /*