Merge branch 'pw/3.0-commentchar-auto-deprecation'
"core.commentChar=auto" that attempts to dynamically pick a suitable comment character is non-workable, as it is too much trouble to support for little benefit, and is marked as deprecated. * pw/3.0-commentchar-auto-deprecation: commit: print advice when core.commentString=auto config: warn on core.commentString=auto breaking-changes: deprecate support for core.commentString=automain
						commit
						1fbfabfa71
					
				|  | @ -239,6 +239,11 @@ These features will be removed. | |||
| + | ||||
| The command will be removed. | ||||
|  | ||||
| * Support for `core.commentString=auto` has been deprecated and will | ||||
|   be removed in Git 3.0. | ||||
| + | ||||
| cf. <xmqqa59i45wc.fsf@gitster.g> | ||||
|  | ||||
| == Superseded features that will not be deprecated | ||||
|  | ||||
| Some features have gained newer replacements that aim to improve the design in | ||||
|  |  | |||
|  | @ -531,9 +531,25 @@ core.commentString:: | |||
| 	commented, and removes them after the editor returns | ||||
| 	(default '#'). | ||||
| + | ||||
| If set to "auto", `git-commit` would select a character that is not | ||||
| ifndef::with-breaking-changes[] | ||||
| If set to "auto", `git-commit` will select a character that is not | ||||
| the beginning character of any line in existing commit messages. | ||||
| Support for this value is deprecated and will be removed in Git 3.0 | ||||
| due to the following limitations: | ||||
| + | ||||
| -- | ||||
| * It is incompatible with adding comments in a commit message | ||||
|   template. This includes the conflicts comments added to | ||||
|   the commit message by `cherry-pick`, `merge`, `rebase` and | ||||
|   `revert`. | ||||
| * It is incompatible with adding comments to the commit message | ||||
|   in the `prepare-commit-msg` hook. | ||||
| * It is incompatible with the `fixup` and `squash` commands when | ||||
|   rebasing, | ||||
| * It is not respected by `git notes` | ||||
| -- | ||||
| + | ||||
| endif::with-breaking-changes[] | ||||
| Note that these two variables are aliases of each other, and in modern | ||||
| versions of Git you are free to use a string (e.g., `//` or `⁑⁕⁑`) with | ||||
| `commentChar`. Versions of Git prior to v2.45.0 will ignore | ||||
|  |  | |||
|  | @ -695,6 +695,7 @@ static int author_date_is_interesting(void) | |||
| 	return author_message || force_date; | ||||
| } | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| static void adjust_comment_line_char(const struct strbuf *sb) | ||||
| { | ||||
| 	char candidates[] = "#;@!$%^&|:"; | ||||
|  | @ -732,6 +733,7 @@ static void adjust_comment_line_char(const struct strbuf *sb) | |||
| 	free(comment_line_str_to_free); | ||||
| 	comment_line_str = comment_line_str_to_free = xstrfmt("%c", *p); | ||||
| } | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
|  | ||||
| static void prepare_amend_commit(struct commit *commit, struct strbuf *sb, | ||||
| 				struct pretty_print_context *ctx) | ||||
|  | @ -928,8 +930,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix, | |||
| 	if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len) | ||||
| 		die_errno(_("could not write commit template")); | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	if (auto_comment_line_char) | ||||
| 		adjust_comment_line_char(&sb); | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	strbuf_release(&sb); | ||||
|  | ||||
| 	/* This checks if committer ident is explicitly given */ | ||||
|  | @ -1793,6 +1797,9 @@ int cmd_commit(int argc, | |||
| 	show_usage_with_options_if_asked(argc, argv, | ||||
| 					 builtin_commit_usage, builtin_commit_options); | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	warn_on_auto_comment_char = true; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	prepare_repo_settings(the_repository); | ||||
| 	the_repository->settings.command_requires_full_index = 0; | ||||
|  | ||||
|  |  | |||
|  | @ -1379,6 +1379,9 @@ int cmd_merge(int argc, | |||
| 	show_usage_with_options_if_asked(argc, argv, | ||||
| 					 builtin_merge_usage, builtin_merge_options); | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	warn_on_auto_comment_char = true; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	prepare_repo_settings(the_repository); | ||||
| 	the_repository->settings.command_requires_full_index = 0; | ||||
|  | ||||
|  |  | |||
|  | @ -1242,6 +1242,9 @@ int cmd_rebase(int argc, | |||
| 					 builtin_rebase_usage, | ||||
| 					 builtin_rebase_options); | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	warn_on_auto_comment_char = true; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	prepare_repo_settings(the_repository); | ||||
| 	the_repository->settings.command_requires_full_index = 0; | ||||
|  | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| #include "builtin.h" | ||||
| #include "parse-options.h" | ||||
| #include "diff.h" | ||||
| #include "environment.h" | ||||
| #include "gettext.h" | ||||
| #include "revision.h" | ||||
| #include "rerere.h" | ||||
|  | @ -285,6 +286,9 @@ int cmd_revert(int argc, | |||
| 	struct replay_opts opts = REPLAY_OPTS_INIT; | ||||
| 	int res; | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	warn_on_auto_comment_char = true; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	opts.action = REPLAY_REVERT; | ||||
| 	sequencer_init_config(&opts); | ||||
| 	res = run_sequencer(argc, argv, prefix, &opts); | ||||
|  | @ -302,6 +306,9 @@ struct repository *repo UNUSED) | |||
| 	struct replay_opts opts = REPLAY_OPTS_INIT; | ||||
| 	int res; | ||||
|  | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 	warn_on_auto_comment_char = true; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 	opts.action = REPLAY_PICK; | ||||
| 	sequencer_init_config(&opts); | ||||
| 	res = run_sequencer(argc, argv, prefix, &opts); | ||||
|  |  | |||
							
								
								
									
										297
									
								
								config.c
								
								
								
								
							
							
						
						
									
										297
									
								
								config.c
								
								
								
								
							|  | @ -8,9 +8,11 @@ | |||
|  | ||||
| #include "git-compat-util.h" | ||||
| #include "abspath.h" | ||||
| #include "advice.h" | ||||
| #include "date.h" | ||||
| #include "branch.h" | ||||
| #include "config.h" | ||||
| #include "dir.h" | ||||
| #include "parse.h" | ||||
| #include "convert.h" | ||||
| #include "environment.h" | ||||
|  | @ -1948,10 +1950,290 @@ 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; | ||||
| 	bool auto_set_in_file; | ||||
| 	struct strintmap key_flags; | ||||
| 	size_t alloc, nr; | ||||
| 	struct comment_char_config_item { | ||||
| 		unsigned key_id; | ||||
| 		char *path; | ||||
| 		enum config_scope scope; | ||||
| 	} *item; | ||||
| }; | ||||
|  | ||||
| #define COMMENT_CHAR_CFG_INIT {			\ | ||||
| 		.key_flags = STRINTMAP_INIT,	\ | ||||
| 	} | ||||
|  | ||||
| static void comment_char_config_release(struct comment_char_config *config) | ||||
| { | ||||
| 	strintmap_clear(&config->key_flags); | ||||
| 	for (size_t i = 0; i < config->nr; i++) | ||||
| 		free(config->item[i].path); | ||||
| 	free(config->item); | ||||
| } | ||||
|  | ||||
| /* Used to track whether the key occurs more than once in a given file */ | ||||
| #define KEY_SEEN_ONCE 1u | ||||
| #define KEY_SEEN_TWICE 2u | ||||
| #define COMMENT_KEY_SHIFT(id) (2 * (id)) | ||||
| #define COMMENT_KEY_MASK(id) (3u << COMMENT_KEY_SHIFT(id)) | ||||
|  | ||||
| static void set_comment_key_flags(struct comment_char_config *config, | ||||
| 				  const char *path, unsigned id, unsigned value) | ||||
| { | ||||
| 	unsigned old = strintmap_get(&config->key_flags, path); | ||||
| 	unsigned new = (old & ~COMMENT_KEY_MASK(id)) | | ||||
| 				value << COMMENT_KEY_SHIFT(id); | ||||
|  | ||||
| 	strintmap_set(&config->key_flags, path, new); | ||||
| } | ||||
|  | ||||
| static unsigned get_comment_key_flags(struct comment_char_config *config, | ||||
| 				      const char *path, unsigned id) | ||||
| { | ||||
| 	unsigned value = strintmap_get(&config->key_flags, path); | ||||
|  | ||||
| 	return (value & COMMENT_KEY_MASK(id)) >> COMMENT_KEY_SHIFT(id); | ||||
| } | ||||
|  | ||||
| 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, void *data) | ||||
| { | ||||
| 	struct comment_char_config *config = data; | ||||
| 	const struct key_value_info *kvi = ctx->kvi; | ||||
| 	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"); | ||||
| 	if (kvi->origin_type != CONFIG_ORIGIN_FILE) { | ||||
| 		return; | ||||
| 	} else if (get_comment_key_flags(config, kvi->filename, key_id)) { | ||||
| 		set_comment_key_flags(config, kvi->filename, key_id, | ||||
| 				      KEY_SEEN_TWICE); | ||||
| 	} else { | ||||
| 		struct comment_char_config_item *item; | ||||
|  | ||||
| 		ALLOC_GROW_BY(config->item, config->nr, 1, config->alloc); | ||||
| 		item = &config->item[config->nr - 1]; | ||||
| 		item->key_id = key_id; | ||||
| 		item->scope = kvi->scope; | ||||
| 		item->path = xstrdup(kvi->filename); | ||||
| 		set_comment_key_flags(config, kvi->filename, key_id, | ||||
| 				      KEY_SEEN_ONCE); | ||||
| 	} | ||||
| 	config->auto_set_in_file = config->auto_set; | ||||
| } | ||||
|  | ||||
| static void add_config_scope_arg(struct repository *repo, struct strbuf *buf, | ||||
| 				 struct comment_char_config_item *item) | ||||
| { | ||||
| 	char *global_config = git_global_config(); | ||||
| 	char *system_config = git_system_config(); | ||||
|  | ||||
| 	if (item->scope == CONFIG_SCOPE_SYSTEM && access(item->path, W_OK)) { | ||||
| 		/* | ||||
| 		 * If the user cannot write to the system config recommend | ||||
| 		 * setting the global config instead. | ||||
| 		 */ | ||||
| 		strbuf_addstr(buf, "--global "); | ||||
| 	} else if (fspatheq(item->path, system_config)) { | ||||
| 		strbuf_addstr(buf, "--system "); | ||||
| 	} else if (fspatheq(item->path, global_config)) { | ||||
| 		strbuf_addstr(buf, "--global "); | ||||
| 	} else if (fspatheq(item->path, | ||||
| 			    mkpath("%s/config", | ||||
| 				   repo_get_git_dir(repo)))) { | ||||
| 		; /* --local is the default */ | ||||
| 	} else if (fspatheq(item->path, | ||||
| 			    mkpath("%s/config.worktree", | ||||
| 				   repo_get_common_dir(repo)))) { | ||||
| 		strbuf_addstr(buf, "--worktree "); | ||||
| 	} else { | ||||
| 		const char *path = item->path; | ||||
| 		const char *home = getenv("HOME"); | ||||
|  | ||||
| 		strbuf_addstr(buf, "--file "); | ||||
| 		if (home && !fspathncmp(path, home, strlen(home))) { | ||||
| 			path += strlen(home); | ||||
| 			if (!fspathncmp(path, "/", 1)) | ||||
| 				path++; | ||||
| 			strbuf_addstr(buf, "~/"); | ||||
| 		} | ||||
| 		sq_quote_buf_pretty(buf, path); | ||||
| 		strbuf_addch(buf, ' '); | ||||
| 	} | ||||
|  | ||||
| 	free(global_config); | ||||
| 	free(system_config); | ||||
| } | ||||
|  | ||||
| static bool can_unset_comment_char_config(struct comment_char_config *config) | ||||
| { | ||||
| 	for (size_t i = 0; i < config->nr; i++) { | ||||
| 		struct comment_char_config_item *item = &config->item[i]; | ||||
|  | ||||
| 		if (item->scope == CONFIG_SCOPE_SYSTEM && | ||||
| 		    access(item->path, W_OK)) | ||||
| 			return false; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static void add_unset_auto_comment_char_advice(struct repository *repo, | ||||
| 					       struct comment_char_config *config) | ||||
| { | ||||
| 	struct strbuf buf = STRBUF_INIT; | ||||
|  | ||||
| 	if (!can_unset_comment_char_config(config)) | ||||
| 		return; | ||||
|  | ||||
| 	for (size_t i = 0; i < config->nr; i++) { | ||||
| 		struct comment_char_config_item *item = &config->item[i]; | ||||
|  | ||||
| 		strbuf_addstr(&buf, "    git config unset "); | ||||
| 		add_config_scope_arg(repo, &buf, item); | ||||
| 		if (get_comment_key_flags(config, item->path, item->key_id) == KEY_SEEN_TWICE) | ||||
| 			strbuf_addstr(&buf, "--all "); | ||||
| 		strbuf_addf(&buf, "%s\n", comment_key_name(item->key_id)); | ||||
| 	} | ||||
| 	advise(_("\nTo use the default comment string (#) please run\n\n%s"), | ||||
| 	       buf.buf); | ||||
| 	strbuf_release(&buf); | ||||
| } | ||||
|  | ||||
| static void add_comment_char_advice(struct repository *repo, | ||||
| 				    struct comment_char_config *config) | ||||
| { | ||||
| 	struct strbuf buf = STRBUF_INIT; | ||||
| 	struct comment_char_config_item *item; | ||||
| 	/* TRANSLATORS this is a place holder for the value of core.commentString */ | ||||
| 	const char *placeholder = _("<comment string>"); | ||||
|  | ||||
| 	/* | ||||
| 	 * If auto is set in the last file that we saw advise the user how to | ||||
| 	 * update their config. | ||||
| 	 */ | ||||
| 	if (!config->auto_set_in_file) | ||||
| 		return; | ||||
|  | ||||
| 	add_unset_auto_comment_char_advice(repo, config); | ||||
| 	item = &config->item[config->nr - 1]; | ||||
| 	strbuf_reset(&buf); | ||||
| 	strbuf_addstr(&buf, "    git config set "); | ||||
| 	add_config_scope_arg(repo, &buf, item); | ||||
| 	strbuf_addf(&buf, "%s %s\n", comment_key_name(item->key_id), | ||||
| 		    placeholder); | ||||
| 	advise(_("\nTo set a custom comment string please run\n\n" | ||||
| 		 "%s\nwhere '%s' is the string you wish to use.\n"), | ||||
| 	       buf.buf, placeholder); | ||||
| 	strbuf_release(&buf); | ||||
| } | ||||
|  | ||||
| #undef KEY_SEEN_ONCE | ||||
| #undef KEY_SEEN_TWICE | ||||
| #undef COMMENT_KEY_SHIFT | ||||
| #undef COMMENT_KEY_MASK | ||||
|  | ||||
| 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_,					\ | ||||
| 	}; | ||||
|  | ||||
| static void repo_config_release(struct repo_config *config) | ||||
| { | ||||
| 	comment_char_config_release(&config->comment_char_config); | ||||
| } | ||||
|  | ||||
| #ifdef WITH_BREAKING_CHANGES | ||||
| static void check_auto_comment_char_config(struct repository *repo, | ||||
| 					   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)); | ||||
| 	add_comment_char_advice(repo, config); | ||||
| 	die(NULL); | ||||
| } | ||||
| #else | ||||
| static void check_auto_comment_char_config(struct repository *repo, | ||||
| 					   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)); | ||||
| 	add_comment_char_advice(repo, config); | ||||
| } | ||||
| #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->repo, | ||||
| 				       &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; | ||||
|  | @ -1963,8 +2245,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 | ||||
|  | @ -1977,6 +2259,8 @@ static void repo_read_config(struct repository *repo) | |||
| 		 * immediately. | ||||
| 		 */ | ||||
| 		die(_("unknown error occurred while reading the configuration files")); | ||||
| 	check_deprecated_config(&config); | ||||
| 	repo_config_release(&config); | ||||
| } | ||||
|  | ||||
| static void git_config_check_init(struct repository *repo) | ||||
|  | @ -2664,6 +2948,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); | ||||
|  | ||||
|  | @ -2895,6 +3187,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: | ||||
|  |  | |||
|  | @ -121,7 +121,10 @@ int protect_ntfs = PROTECT_NTFS_DEFAULT; | |||
|  */ | ||||
| const char *comment_line_str = "#"; | ||||
| char *comment_line_str_to_free; | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| int auto_comment_line_char; | ||||
| bool warn_on_auto_comment_char; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
|  | ||||
| /* This is set by setup_git_directory_gently() and/or git_default_config() */ | ||||
| char *git_work_tree_cfg; | ||||
|  | @ -463,16 +466,22 @@ static int git_default_core_config(const char *var, const char *value, | |||
|  | ||||
| 	if (!strcmp(var, "core.commentchar") || | ||||
| 	    !strcmp(var, "core.commentstring")) { | ||||
| 		if (!value) | ||||
| 		if (!value) { | ||||
| 			return config_error_nonbool(var); | ||||
| 		else if (!strcasecmp(value, "auto")) | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 		} else if (!strcasecmp(value, "auto")) { | ||||
| 			auto_comment_line_char = 1; | ||||
| 		else if (value[0]) { | ||||
| 			FREE_AND_NULL(comment_line_str_to_free); | ||||
| 			comment_line_str = "#"; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 		} else if (value[0]) { | ||||
| 			if (strchr(value, '\n')) | ||||
| 				return error(_("%s cannot contain newline"), var); | ||||
| 			comment_line_str = value; | ||||
| 			FREE_AND_NULL(comment_line_str_to_free); | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| 			auto_comment_line_char = 0; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
| 		} else | ||||
| 			return error(_("%s must have at least one character"), var); | ||||
| 		return 0; | ||||
|  |  | |||
|  | @ -208,7 +208,10 @@ extern char *excludes_file; | |||
|  */ | ||||
| extern const char *comment_line_str; | ||||
| extern char *comment_line_str_to_free; | ||||
| #ifndef WITH_BREAKING_CHANGES | ||||
| extern int auto_comment_line_char; | ||||
| extern bool warn_on_auto_comment_char; | ||||
| #endif /* !WITH_BREAKING_CHANGES */ | ||||
|  | ||||
| # endif /* USE_THE_REPOSITORY_VARIABLE */ | ||||
| #endif /* ENVIRONMENT_H */ | ||||
|  |  | |||
|  | @ -57,6 +57,7 @@ void initialize_repository(struct repository *repo) | |||
| 	repo->parsed_objects = parsed_object_pool_new(repo); | ||||
| 	ALLOC_ARRAY(repo->index, 1); | ||||
| 	index_state_init(repo->index, repo); | ||||
| 	repo->check_deprecated_config = true; | ||||
|  | ||||
| 	/* | ||||
| 	 * When a command runs inside a repository, it learns what | ||||
|  |  | |||
|  | @ -161,6 +161,9 @@ struct repository { | |||
|  | ||||
| 	/* Indicate if a repository has a different 'commondir' from 'gitdir' */ | ||||
| 	unsigned different_commondir:1; | ||||
|  | ||||
| 	/* Should repo_config() check for deprecated settings */ | ||||
| 	bool check_deprecated_config; | ||||
| }; | ||||
|  | ||||
| #ifdef USE_THE_REPOSITORY_VARIABLE | ||||
|  |  | |||
|  | @ -1176,7 +1176,7 @@ test_expect_success 'rebase -i respects core.commentchar' ' | |||
| 	test B = $(git cat-file commit HEAD^ | sed -ne \$p) | ||||
| ' | ||||
|  | ||||
| test_expect_success 'rebase -i respects core.commentchar=auto' ' | ||||
| test_expect_success !WITH_BREAKING_CHANGES 'rebase -i respects core.commentchar=auto' ' | ||||
| 	test_config core.commentchar auto && | ||||
| 	write_script copy-edit-script.sh <<-\EOF && | ||||
| 	cp "$1" edit-script | ||||
|  | @ -1184,8 +1184,23 @@ test_expect_success 'rebase -i respects core.commentchar=auto' ' | |||
| 	test_when_finished "git rebase --abort || :" && | ||||
| 	( | ||||
| 		test_set_editor "$(pwd)/copy-edit-script.sh" && | ||||
| 		git rebase -i HEAD^ | ||||
| 		git rebase -i HEAD^ 2>err | ||||
| 	) && | ||||
| 	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual && | ||||
| 	cat >expect <<-EOF && | ||||
| 	Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 | ||||
|  | ||||
| 	To use the default comment string (#) please run | ||||
|  | ||||
| 	    git config unset core.commentChar | ||||
|  | ||||
| 	To set a custom comment string please run | ||||
|  | ||||
| 	    git config set core.commentChar <comment string> | ||||
|  | ||||
| 	where ${SQ}<comment string>${SQ} is the string you wish to use. | ||||
| 	EOF | ||||
| 	test_cmp expect actual && | ||||
| 	test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" | ||||
| ' | ||||
|  | ||||
|  |  | |||
|  | @ -328,7 +328,7 @@ test_expect_success 'there is no --no-reschedule-failed-exec in an ongoing rebas | |||
| 	test_expect_code 129 git rebase --edit-todo --no-reschedule-failed-exec | ||||
| ' | ||||
|  | ||||
| test_expect_success 'no change in comment character due to conflicts markers with core.commentChar=auto' ' | ||||
| test_expect_success !WITH_BREAKING_CHANGES 'no change in comment character due to conflicts markers with core.commentChar=auto' ' | ||||
| 	git checkout -b branch-a && | ||||
| 	test_commit A F1 && | ||||
| 	git checkout -b branch-b HEAD^ && | ||||
|  |  | |||
|  | @ -956,13 +956,39 @@ test_expect_success 'commit --status with custom comment character' ' | |||
| 	test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG | ||||
| ' | ||||
|  | ||||
| test_expect_success 'switch core.commentchar' ' | ||||
| test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar' ' | ||||
| 	test_commit "#foo" foo && | ||||
| 	GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend && | ||||
| 	cat >config-include <<-\EOF && | ||||
| 	[core] | ||||
| 	    commentString=: | ||||
| 	    commentString=% | ||||
| 	    commentChar=auto | ||||
| 	EOF | ||||
| 	test_when_finished "rm config-include" && | ||||
| 	test_config include.path "$(pwd)/config-include" && | ||||
| 	test_config core.commentChar ! && | ||||
| 	GIT_EDITOR=.git/FAKE_EDITOR git commit --amend 2>err && | ||||
| 	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^warning: //p" err >actual && | ||||
| 	cat >expect <<-EOF && | ||||
| 	Support for ${SQ}core.commentChar=auto${SQ} is deprecated and will be removed in Git 3.0 | ||||
|  | ||||
| 	To use the default comment string (#) please run | ||||
|  | ||||
| 	    git config unset core.commentChar | ||||
| 	    git config unset --file ~/config-include --all core.commentString | ||||
| 	    git config unset --file ~/config-include core.commentChar | ||||
|  | ||||
| 	To set a custom comment string please run | ||||
|  | ||||
| 	    git config set --file ~/config-include core.commentChar <comment string> | ||||
|  | ||||
| 	where ${SQ}<comment string>${SQ} is the string you wish to use. | ||||
| 	EOF | ||||
| 	test_cmp expect actual && | ||||
| 	test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG | ||||
| ' | ||||
|  | ||||
| test_expect_success 'switch core.commentchar but out of options' ' | ||||
| test_expect_success !WITH_BREAKING_CHANGES 'switch core.commentchar but out of options' ' | ||||
| 	cat >text <<\EOF && | ||||
| # 1 | ||||
| ; 2 | ||||
|  | @ -982,4 +1008,24 @@ EOF | |||
| 	) | ||||
| ' | ||||
|  | ||||
| test_expect_success WITH_BREAKING_CHANGES 'core.commentChar=auto is rejected' ' | ||||
| 	test_config core.commentChar auto && | ||||
| 	test_must_fail git rev-parse --git-dir 2>err && | ||||
| 	sed -n "s/^hint: *\$//p; s/^hint: //p; s/^fatal: //p" err >actual && | ||||
| 	cat >expect <<-EOF && | ||||
| 	Support for ${SQ}core.commentChar=auto${SQ} has been removed in Git 3.0 | ||||
|  | ||||
| 	To use the default comment string (#) please run | ||||
|  | ||||
| 	    git config unset core.commentChar | ||||
|  | ||||
| 	To set a custom comment string please run | ||||
|  | ||||
| 	    git config set core.commentChar <comment string> | ||||
|  | ||||
| 	where ${SQ}<comment string>${SQ} is the string you wish to use. | ||||
| 	EOF | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
| test_done | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano