Git fork

config: warn on core.commentString=auto

As support for this setting was deprecated in the last commit print a
warning (or die when WITH_BREAKING_CHANGES is enabled) if it is set.
Avoid bombarding the user with warnings by only printing it (a) when
running commands that call "git commit" and (b) only once per command.

Some scaffolding is added to repo_read_config() to allow it to
detect deprecated config settings and warn about them. As both
"core.commentChar" and "core.commentString" set the comment
character we record which one of them is used and tailor the
warning message appropriately.

Note the odd combination of die_message() followed by die(NULL)
is to allow the next commit to insert a call to advise() in the middle.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Phillip Wood and committed by
Junio C Hamano
a0e6aaea fdae4114

+157 -4
+3
builtin/commit.c
··· 1783 1783 show_usage_with_options_if_asked(argc, argv, 1784 1784 builtin_commit_usage, builtin_commit_options); 1785 1785 1786 + #ifndef WITH_BREAKING_CHANGES 1787 + warn_on_auto_comment_char = true; 1788 + #endif /* !WITH_BREAKING_CHANGES */ 1786 1789 prepare_repo_settings(the_repository); 1787 1790 the_repository->settings.command_requires_full_index = 0; 1788 1791
+3
builtin/merge.c
··· 1378 1378 show_usage_with_options_if_asked(argc, argv, 1379 1379 builtin_merge_usage, builtin_merge_options); 1380 1380 1381 + #ifndef WITH_BREAKING_CHANGES 1382 + warn_on_auto_comment_char = true; 1383 + #endif /* !WITH_BREAKING_CHANGES */ 1381 1384 prepare_repo_settings(the_repository); 1382 1385 the_repository->settings.command_requires_full_index = 0; 1383 1386
+3
builtin/rebase.c
··· 1242 1242 builtin_rebase_usage, 1243 1243 builtin_rebase_options); 1244 1244 1245 + #ifndef WITH_BREAKING_CHANGES 1246 + warn_on_auto_comment_char = true; 1247 + #endif /* !WITH_BREAKING_CHANGES */ 1245 1248 prepare_repo_settings(the_repository); 1246 1249 the_repository->settings.command_requires_full_index = 0; 1247 1250
+7
builtin/revert.c
··· 4 4 #include "builtin.h" 5 5 #include "parse-options.h" 6 6 #include "diff.h" 7 + #include "environment.h" 7 8 #include "gettext.h" 8 9 #include "revision.h" 9 10 #include "rerere.h" ··· 285 286 struct replay_opts opts = REPLAY_OPTS_INIT; 286 287 int res; 287 288 289 + #ifndef WITH_BREAKING_CHANGES 290 + warn_on_auto_comment_char = true; 291 + #endif /* !WITH_BREAKING_CHANGES */ 288 292 opts.action = REPLAY_REVERT; 289 293 sequencer_init_config(&opts); 290 294 res = run_sequencer(argc, argv, prefix, &opts); ··· 302 306 struct replay_opts opts = REPLAY_OPTS_INIT; 303 307 int res; 304 308 309 + #ifndef WITH_BREAKING_CHANGES 310 + warn_on_auto_comment_char = true; 311 + #endif /* !WITH_BREAKING_CHANGES */ 305 312 opts.action = REPLAY_PICK; 306 313 sequencer_init_config(&opts); 307 314 res = run_sequencer(argc, argv, prefix, &opts);
+113 -2
config.c
··· 11 11 #include "date.h" 12 12 #include "branch.h" 13 13 #include "config.h" 14 + #include "dir.h" 14 15 #include "parse.h" 15 16 #include "convert.h" 16 17 #include "environment.h" ··· 1951 1952 return 1; 1952 1953 } 1953 1954 1955 + struct comment_char_config { 1956 + unsigned last_key_id; 1957 + bool auto_set; 1958 + }; 1959 + 1960 + #define COMMENT_CHAR_CFG_INIT { 0 } 1961 + 1962 + static const char *comment_key_name(unsigned id) 1963 + { 1964 + static const char *name[] = { 1965 + "core.commentChar", 1966 + "core.commentString", 1967 + }; 1968 + 1969 + if (id >= ARRAY_SIZE(name)) 1970 + BUG("invalid comment key id"); 1971 + 1972 + return name[id]; 1973 + } 1974 + 1975 + static void comment_char_callback(const char *key, const char *value, 1976 + const struct config_context *ctx UNUSED, 1977 + void *data) 1978 + { 1979 + struct comment_char_config *config = data; 1980 + unsigned key_id; 1981 + 1982 + if (!strcmp(key, "core.commentchar")) 1983 + key_id = 0; 1984 + else if (!strcmp(key, "core.commentstring")) 1985 + key_id = 1; 1986 + else 1987 + return; 1988 + 1989 + config->last_key_id = key_id; 1990 + config->auto_set = value && !strcmp(value, "auto"); 1991 + } 1992 + 1993 + struct repo_config { 1994 + struct repository *repo; 1995 + struct comment_char_config comment_char_config; 1996 + }; 1997 + 1998 + #define REPO_CONFIG_INIT(repo_) { \ 1999 + .comment_char_config = COMMENT_CHAR_CFG_INIT, \ 2000 + .repo = repo_, \ 2001 + }; 2002 + 2003 + #ifdef WITH_BREAKING_CHANGES 2004 + static void check_auto_comment_char_config(struct comment_char_config *config) 2005 + { 2006 + if (!config->auto_set) 2007 + return; 2008 + 2009 + die_message(_("Support for '%s=auto' has been removed in Git 3.0"), 2010 + comment_key_name(config->last_key_id)); 2011 + die(NULL); 2012 + } 2013 + #else 2014 + static void check_auto_comment_char_config(struct comment_char_config *config) 2015 + { 2016 + extern bool warn_on_auto_comment_char; 2017 + const char *DEPRECATED_CONFIG_ENV = 2018 + "GIT_AUTO_COMMENT_CHAR_CONFIG_WARNING_GIVEN"; 2019 + 2020 + if (!config->auto_set || !warn_on_auto_comment_char) 2021 + return; 2022 + 2023 + /* 2024 + * Use an environment variable to ensure that subprocesses do not repeat 2025 + * the warning. 2026 + */ 2027 + if (git_env_bool(DEPRECATED_CONFIG_ENV, false)) 2028 + return; 2029 + 2030 + setenv(DEPRECATED_CONFIG_ENV, "true", true); 2031 + 2032 + warning(_("Support for '%s=auto' is deprecated and will be removed in " 2033 + "Git 3.0"), comment_key_name(config->last_key_id)); 2034 + } 2035 + #endif /* WITH_BREAKING_CHANGES */ 2036 + 2037 + static void check_deprecated_config(struct repo_config *config) 2038 + { 2039 + if (!config->repo->check_deprecated_config) 2040 + return; 2041 + 2042 + check_auto_comment_char_config(&config->comment_char_config); 2043 + } 2044 + 2045 + static int repo_config_callback(const char *key, const char *value, 2046 + const struct config_context *ctx, void *data) 2047 + { 2048 + struct repo_config *config = data; 2049 + 2050 + comment_char_callback(key, value, ctx, &config->comment_char_config); 2051 + return config_set_callback(key, value, ctx, config->repo->config); 2052 + } 2053 + 1954 2054 /* Functions use to read configuration from a repository */ 1955 2055 static void repo_read_config(struct repository *repo) 1956 2056 { 1957 2057 struct config_options opts = { 0 }; 2058 + struct repo_config config = REPO_CONFIG_INIT(repo); 1958 2059 1959 2060 opts.respect_includes = 1; 1960 2061 opts.commondir = repo->commondir; ··· 1966 2067 git_configset_clear(repo->config); 1967 2068 1968 2069 git_configset_init(repo->config); 1969 - if (config_with_options(config_set_callback, repo->config, NULL, 1970 - repo, &opts) < 0) 2070 + if (config_with_options(repo_config_callback, &config, NULL, repo, 2071 + &opts) < 0) 1971 2072 /* 1972 2073 * config_with_options() normally returns only 1973 2074 * zero, as most errors are fatal, and ··· 1980 2081 * immediately. 1981 2082 */ 1982 2083 die(_("unknown error occurred while reading the configuration files")); 2084 + check_deprecated_config(&config); 1983 2085 } 1984 2086 1985 2087 static void git_config_check_init(struct repository *repo) ··· 2667 2769 char *contents = NULL; 2668 2770 size_t contents_sz; 2669 2771 struct config_store_data store = CONFIG_STORE_INIT; 2772 + bool saved_check_deprecated_config = r->check_deprecated_config; 2773 + 2774 + /* 2775 + * Do not warn or die if there are deprecated config settings as 2776 + * we want the user to be able to change those settings by running 2777 + * "git config". 2778 + */ 2779 + r->check_deprecated_config = false; 2670 2780 2671 2781 validate_comment_string(comment); 2672 2782 ··· 2898 3008 if (in_fd >= 0) 2899 3009 close(in_fd); 2900 3010 config_store_data_clear(&store); 3011 + r->check_deprecated_config = saved_check_deprecated_config; 2901 3012 return ret; 2902 3013 2903 3014 write_err_out:
+1
environment.c
··· 124 124 char *comment_line_str_to_free; 125 125 #ifndef WITH_BREAKING_CHANGES 126 126 int auto_comment_line_char; 127 + bool warn_on_auto_comment_char; 127 128 #endif /* !WITH_BREAKING_CHANGES */ 128 129 129 130 /* This is set by setup_git_directory_gently() and/or git_default_config() */
+1
environment.h
··· 210 210 extern char *comment_line_str_to_free; 211 211 #ifndef WITH_BREAKING_CHANGES 212 212 extern int auto_comment_line_char; 213 + extern bool warn_on_auto_comment_char; 213 214 #endif /* !WITH_BREAKING_CHANGES */ 214 215 215 216 # endif /* USE_THE_REPOSITORY_VARIABLE */
+1
repository.c
··· 57 57 repo->parsed_objects = parsed_object_pool_new(repo); 58 58 ALLOC_ARRAY(repo->index, 1); 59 59 index_state_init(repo->index, repo); 60 + repo->check_deprecated_config = true; 60 61 61 62 /* 62 63 * When a command runs inside a repository, it learns what
+3
repository.h
··· 161 161 162 162 /* Indicate if a repository has a different 'commondir' from 'gitdir' */ 163 163 unsigned different_commondir:1; 164 + 165 + /* Should repo_config() check for deprecated settings */ 166 + bool check_deprecated_config; 164 167 }; 165 168 166 169 #ifdef USE_THE_REPOSITORY_VARIABLE
+6 -1
t/t3404-rebase-interactive.sh
··· 1184 1184 test_when_finished "git rebase --abort || :" && 1185 1185 ( 1186 1186 test_set_editor "$(pwd)/copy-edit-script.sh" && 1187 - git rebase -i HEAD^ 1187 + git rebase -i HEAD^ 2>err 1188 1188 ) && 1189 + sed -n "s/^warning: //p" err >actual && 1190 + cat >expect <<-EOF && 1191 + Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 1192 + EOF 1193 + test_cmp expect actual && 1189 1194 test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" 1190 1195 ' 1191 1196
+16 -1
t/t7502-commit-porcelain.sh
··· 958 958 959 959 test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar' ' 960 960 test_commit "#foo" foo && 961 - GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend && 961 + GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend 2>err && 962 + sed -n "s/^warning: //p" err >actual && 963 + cat >expect <<-EOF && 964 + Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 965 + EOF 966 + test_cmp expect actual && 962 967 test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG 963 968 ' 964 969 ··· 980 985 test_set_editor .git/FAKE_EDITOR && 981 986 test_must_fail git -c core.commentChar=auto commit --amend 982 987 ) 988 + ' 989 + 990 + test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' ' 991 + test_config core.commentChar auto && 992 + test_must_fail git rev-parse --git-dir 2>err && 993 + sed -n "s/^fatal: //p" err >actual && 994 + cat >expect <<-EOF && 995 + Support for ${SQ}core.commentChar=auto${SQ} has been removed in Git 3.0 996 + EOF 997 + test_cmp expect actual 983 998 ' 984 999 985 1000 test_done