summaryrefslogtreecommitdiff
path: root/config.c
diff options
context:
space:
mode:
authorPhillip Wood <phillip.wood@dunelm.org.uk>2025-08-26 14:35:27 +0100
committerJunio C Hamano <gitster@pobox.com>2025-08-26 08:52:44 -0700
commita0e6aaea7da5134bdc784c6d68d4cc2125865330 (patch)
treebeb4c0512ab49f0e84a619372b1bf425b8d8140d /config.c
parentfdae4114a696014b6bf28ad9b1bc076bd8d7eec8 (diff)
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>
Diffstat (limited to 'config.c')
-rw-r--r--config.c115
1 files changed, 113 insertions, 2 deletions
diff --git a/config.c b/config.c
index 97ffef4270..18b4219709 100644
--- a/config.c
+++ b/config.c
@@ -11,6 +11,7 @@
#include "date.h"
#include "branch.h"
#include "config.h"
+#include "dir.h"
#include "parse.h"
#include "convert.h"
#include "environment.h"
@@ -1951,10 +1952,110 @@ int git_configset_get_pathname(struct config_set *set, const char *key, char **d
return 1;
}
+struct comment_char_config {
+ unsigned last_key_id;
+ bool auto_set;
+};
+
+#define COMMENT_CHAR_CFG_INIT { 0 }
+
+static const char *comment_key_name(unsigned id)
+{
+ static const char *name[] = {
+ "core.commentChar",
+ "core.commentString",
+ };
+
+ if (id >= ARRAY_SIZE(name))
+ BUG("invalid comment key id");
+
+ return name[id];
+}
+
+static void comment_char_callback(const char *key, const char *value,
+ const struct config_context *ctx UNUSED,
+ void *data)
+{
+ struct comment_char_config *config = data;
+ unsigned key_id;
+
+ if (!strcmp(key, "core.commentchar"))
+ key_id = 0;
+ else if (!strcmp(key, "core.commentstring"))
+ key_id = 1;
+ else
+ return;
+
+ config->last_key_id = key_id;
+ config->auto_set = value && !strcmp(value, "auto");
+}
+
+struct repo_config {
+ struct repository *repo;
+ struct comment_char_config comment_char_config;
+};
+
+#define REPO_CONFIG_INIT(repo_) { \
+ .comment_char_config = COMMENT_CHAR_CFG_INIT, \
+ .repo = repo_, \
+ };
+
+#ifdef WITH_BREAKING_CHANGES
+static void check_auto_comment_char_config(struct comment_char_config *config)
+{
+ if (!config->auto_set)
+ return;
+
+ die_message(_("Support for '%s=auto' has been removed in Git 3.0"),
+ comment_key_name(config->last_key_id));
+ die(NULL);
+}
+#else
+static void check_auto_comment_char_config(struct comment_char_config *config)
+{
+ extern bool warn_on_auto_comment_char;
+ const char *DEPRECATED_CONFIG_ENV =
+ "GIT_AUTO_COMMENT_CHAR_CONFIG_WARNING_GIVEN";
+
+ if (!config->auto_set || !warn_on_auto_comment_char)
+ return;
+
+ /*
+ * Use an environment variable to ensure that subprocesses do not repeat
+ * the warning.
+ */
+ if (git_env_bool(DEPRECATED_CONFIG_ENV, false))
+ return;
+
+ setenv(DEPRECATED_CONFIG_ENV, "true", true);
+
+ warning(_("Support for '%s=auto' is deprecated and will be removed in "
+ "Git 3.0"), comment_key_name(config->last_key_id));
+}
+#endif /* WITH_BREAKING_CHANGES */
+
+static void check_deprecated_config(struct repo_config *config)
+{
+ if (!config->repo->check_deprecated_config)
+ return;
+
+ check_auto_comment_char_config(&config->comment_char_config);
+}
+
+static int repo_config_callback(const char *key, const char *value,
+ const struct config_context *ctx, void *data)
+{
+ struct repo_config *config = data;
+
+ comment_char_callback(key, value, ctx, &config->comment_char_config);
+ return config_set_callback(key, value, ctx, config->repo->config);
+}
+
/* Functions use to read configuration from a repository */
static void repo_read_config(struct repository *repo)
{
struct config_options opts = { 0 };
+ struct repo_config config = REPO_CONFIG_INIT(repo);
opts.respect_includes = 1;
opts.commondir = repo->commondir;
@@ -1966,8 +2067,8 @@ static void repo_read_config(struct repository *repo)
git_configset_clear(repo->config);
git_configset_init(repo->config);
- if (config_with_options(config_set_callback, repo->config, NULL,
- repo, &opts) < 0)
+ if (config_with_options(repo_config_callback, &config, NULL, repo,
+ &opts) < 0)
/*
* config_with_options() normally returns only
* zero, as most errors are fatal, and
@@ -1980,6 +2081,7 @@ static void repo_read_config(struct repository *repo)
* immediately.
*/
die(_("unknown error occurred while reading the configuration files"));
+ check_deprecated_config(&config);
}
static void git_config_check_init(struct repository *repo)
@@ -2667,6 +2769,14 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
char *contents = NULL;
size_t contents_sz;
struct config_store_data store = CONFIG_STORE_INIT;
+ bool saved_check_deprecated_config = r->check_deprecated_config;
+
+ /*
+ * Do not warn or die if there are deprecated config settings as
+ * we want the user to be able to change those settings by running
+ * "git config".
+ */
+ r->check_deprecated_config = false;
validate_comment_string(comment);
@@ -2898,6 +3008,7 @@ out_free:
if (in_fd >= 0)
close(in_fd);
config_store_data_clear(&store);
+ r->check_deprecated_config = saved_check_deprecated_config;
return ret;
write_err_out: