blob: 0b9c89c48ab996da0e7938ac0667a3ecad925efc [file] [log] [blame]
Jeff King75194432009-09-09 07:38:58 -04001#include "cache.h"
Brandon Williamsb2141fc2017-06-14 11:07:36 -07002#include "config.h"
Ryan Dammrose960786e2018-04-21 12:10:00 +02003#include "color.h"
Nguyễn Thái Ngọc Duy3ac68a92018-05-26 15:55:24 +02004#include "help.h"
Matheus Tavaresa20f7042021-04-08 17:41:27 -03005#include "string-list.h"
Jeff King75194432009-09-09 07:38:58 -04006
Derrick Stolee377444b2019-06-18 13:25:27 -07007int advice_fetch_show_forced_updates = 1;
Chris Rorvick11845642012-12-02 21:27:50 -06008int advice_push_update_rejected = 1;
Christopher Tiwaldf25950f2012-03-20 00:31:33 -04009int advice_push_non_ff_current = 1;
Christopher Tiwaldf25950f2012-03-20 00:31:33 -040010int advice_push_non_ff_matching = 1;
Chris Rorvickb4505682012-12-02 21:27:51 -060011int advice_push_already_exists = 1;
Junio C Hamano75e5c0d2013-01-23 13:55:30 -080012int advice_push_fetch_first = 1;
13int advice_push_needs_force = 1;
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +000014int advice_push_unqualified_ref_name = 1;
Srinidhi Kaushik3b990aa2020-10-03 17:40:45 +053015int advice_push_ref_needs_update = 1;
Jeff Kingedf563f2009-09-09 07:43:03 -040016int advice_status_hints = 1;
Nguyễn Thái Ngọc Duy6a38ef22013-03-13 19:59:16 +070017int advice_status_u_option = 1;
Jeff Hostetler0a535612019-06-18 13:21:27 -070018int advice_status_ahead_behind_warning = 1;
Matthieu Moy4c371f92009-11-22 23:26:17 +010019int advice_commit_before_merge = 1;
Ben Peart649bf3a2018-10-23 15:04:23 -040020int advice_reset_quiet_warning = 1;
Matthieu Moyd38a30d2010-01-12 10:54:44 +010021int advice_resolve_conflict = 1;
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +053022int advice_sequencer_in_use = 1;
Jeff Kingb706fcf2010-01-13 15:17:08 -050023int advice_implicit_identity = 1;
Junio C Hamano13be3e32010-01-29 22:03:24 -080024int advice_detached_head = 1;
Jeff Kingcaa20362013-04-02 15:05:12 -040025int advice_set_upstream_failure = 1;
Nguyễn Thái Ngọc Duy798c35f2013-05-29 19:12:42 +070026int advice_object_name_warning = 1;
Nguyễn Thái Ngọc Duy431bb232018-05-26 15:55:27 +020027int advice_amworkdir = 1;
Mathieu Lienard--Mayor7e309442013-06-12 10:06:44 +020028int advice_rm_hints = 1;
Jeff King53213992017-06-14 06:58:22 -040029int advice_add_embedded_repo = 1;
Damien Mariéf805a002017-10-06 08:07:55 +000030int advice_ignored_hook = 1;
Lars Schneiderabfb04d2017-12-07 16:16:41 +010031int advice_waiting_for_editor = 1;
Johannes Schindelinf9f99b32018-04-29 00:44:44 +020032int advice_graft_file_deprecated = 1;
Ævar Arnfjörð Bjarmasonad8d5102018-06-05 14:40:48 +000033int advice_checkout_ambiguous_remote_branch_name = 1;
Jonathan Tan4f3e57e2019-12-02 11:57:52 -080034int advice_submodule_alternate_error_strategy_die = 1;
Heba Waly887a0fd2020-02-06 23:57:30 +130035int advice_add_ignored_file = 1;
36int advice_add_empty_pathspec = 1;
Jeff King75194432009-09-09 07:38:58 -040037
Ryan Dammrose960786e2018-04-21 12:10:00 +020038static int advice_use_color = -1;
39static char advice_colors[][COLOR_MAXLEN] = {
40 GIT_COLOR_RESET,
41 GIT_COLOR_YELLOW, /* HINT */
42};
43
44enum color_advice {
45 ADVICE_COLOR_RESET = 0,
46 ADVICE_COLOR_HINT = 1,
47};
48
49static int parse_advise_color_slot(const char *slot)
50{
51 if (!strcasecmp(slot, "reset"))
52 return ADVICE_COLOR_RESET;
53 if (!strcasecmp(slot, "hint"))
54 return ADVICE_COLOR_HINT;
55 return -1;
56}
57
58static const char *advise_get_color(enum color_advice ix)
59{
60 if (want_color_stderr(advice_use_color))
61 return advice_colors[ix];
62 return "";
63}
64
Jeff King75194432009-09-09 07:38:58 -040065static struct {
66 const char *name;
67 int *preference;
68} advice_config[] = {
Derrick Stolee377444b2019-06-18 13:25:27 -070069 { "fetchShowForcedUpdates", &advice_fetch_show_forced_updates },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020070 { "pushUpdateRejected", &advice_push_update_rejected },
71 { "pushNonFFCurrent", &advice_push_non_ff_current },
72 { "pushNonFFMatching", &advice_push_non_ff_matching },
73 { "pushAlreadyExists", &advice_push_already_exists },
74 { "pushFetchFirst", &advice_push_fetch_first },
75 { "pushNeedsForce", &advice_push_needs_force },
Ævar Arnfjörð Bjarmasondd8dd302018-11-13 19:52:43 +000076 { "pushUnqualifiedRefName", &advice_push_unqualified_ref_name },
Srinidhi Kaushik3b990aa2020-10-03 17:40:45 +053077 { "pushRefNeedsUpdate", &advice_push_ref_needs_update },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020078 { "statusHints", &advice_status_hints },
79 { "statusUoption", &advice_status_u_option },
Jeff Hostetler0a535612019-06-18 13:21:27 -070080 { "statusAheadBehindWarning", &advice_status_ahead_behind_warning },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020081 { "commitBeforeMerge", &advice_commit_before_merge },
Ben Peart649bf3a2018-10-23 15:04:23 -040082 { "resetQuiet", &advice_reset_quiet_warning },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020083 { "resolveConflict", &advice_resolve_conflict },
Rohit Ashiwal6a1f9042019-07-02 14:41:25 +053084 { "sequencerInUse", &advice_sequencer_in_use },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020085 { "implicitIdentity", &advice_implicit_identity },
86 { "detachedHead", &advice_detached_head },
Heba Walyfef0c762020-03-02 20:01:58 +000087 { "setUpstreamFailure", &advice_set_upstream_failure },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020088 { "objectNameWarning", &advice_object_name_warning },
Nguyễn Thái Ngọc Duy431bb232018-05-26 15:55:27 +020089 { "amWorkDir", &advice_amworkdir },
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +020090 { "rmHints", &advice_rm_hints },
91 { "addEmbeddedRepo", &advice_add_embedded_repo },
92 { "ignoredHook", &advice_ignored_hook },
93 { "waitingForEditor", &advice_waiting_for_editor },
94 { "graftFileDeprecated", &advice_graft_file_deprecated },
Junio C Hamano50858ed2018-08-02 15:30:41 -070095 { "checkoutAmbiguousRemoteBranchName", &advice_checkout_ambiguous_remote_branch_name },
Jonathan Tan4f3e57e2019-12-02 11:57:52 -080096 { "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
Heba Waly887a0fd2020-02-06 23:57:30 +130097 { "addIgnoredFile", &advice_add_ignored_file },
98 { "addEmptyPathspec", &advice_add_empty_pathspec },
Chris Rorvick11845642012-12-02 21:27:50 -060099
100 /* make this an alias for backward compatibility */
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +0200101 { "pushNonFastForward", &advice_push_update_rejected }
Jeff King75194432009-09-09 07:38:58 -0400102};
103
Heba Walyb3b18d12020-03-02 20:01:59 +0000104static struct {
105 const char *key;
106 int enabled;
107} advice_setting[] = {
108 [ADVICE_ADD_EMBEDDED_REPO] = { "addEmbeddedRepo", 1 },
109 [ADVICE_AM_WORK_DIR] = { "amWorkDir", 1 },
110 [ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName", 1 },
111 [ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge", 1 },
112 [ADVICE_DETACHED_HEAD] = { "detachedHead", 1 },
113 [ADVICE_FETCH_SHOW_FORCED_UPDATES] = { "fetchShowForcedUpdates", 1 },
114 [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated", 1 },
115 [ADVICE_IGNORED_HOOK] = { "ignoredHook", 1 },
116 [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity", 1 },
117 [ADVICE_NESTED_TAG] = { "nestedTag", 1 },
118 [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning", 1 },
119 [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists", 1 },
120 [ADVICE_PUSH_FETCH_FIRST] = { "pushFetchFirst", 1 },
121 [ADVICE_PUSH_NEEDS_FORCE] = { "pushNeedsForce", 1 },
Srinidhi Kaushik3b990aa2020-10-03 17:40:45 +0530122 [ADVICE_PUSH_REF_NEEDS_UPDATE] = { "pushRefNeedsUpdate", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +0000123
124 /* make this an alias for backward compatibility */
125 [ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward", 1 },
126
127 [ADVICE_PUSH_NON_FF_CURRENT] = { "pushNonFFCurrent", 1 },
128 [ADVICE_PUSH_NON_FF_MATCHING] = { "pushNonFFMatching", 1 },
129 [ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName", 1 },
130 [ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected", 1 },
131 [ADVICE_RESET_QUIET_WARNING] = { "resetQuiet", 1 },
132 [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict", 1 },
133 [ADVICE_RM_HINTS] = { "rmHints", 1 },
134 [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
135 [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
136 [ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
137 [ADVICE_STATUS_HINTS] = { "statusHints", 1 },
138 [ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
139 [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
Matheus Tavaresa20f7042021-04-08 17:41:27 -0300140 [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +0000141 [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
142};
143
144static const char turn_off_instructions[] =
145N_("\n"
146 "Disable this message with \"git config advice.%s false\"");
147
148static void vadvise(const char *advice, int display_instructions,
149 const char *key, va_list params)
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530150{
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800151 struct strbuf buf = STRBUF_INIT;
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800152 const char *cp, *np;
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530153
Jeff King447b99c2012-07-23 14:48:57 -0400154 strbuf_vaddf(&buf, advice, params);
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800155
Heba Walyb3b18d12020-03-02 20:01:59 +0000156 if (display_instructions)
157 strbuf_addf(&buf, turn_off_instructions, key);
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800158
159 for (cp = buf.buf; *cp; cp = np) {
160 np = strchrnul(cp, '\n');
Ryan Dammrose960786e2018-04-21 12:10:00 +0200161 fprintf(stderr, _("%shint: %.*s%s\n"),
162 advise_get_color(ADVICE_COLOR_HINT),
163 (int)(np - cp), cp,
164 advise_get_color(ADVICE_COLOR_RESET));
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800165 if (*np)
166 np++;
167 }
168 strbuf_release(&buf);
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530169}
170
Heba Waly06ac2b32020-03-02 20:01:57 +0000171void advise(const char *advice, ...)
172{
173 va_list params;
174 va_start(params, advice);
Heba Walyb3b18d12020-03-02 20:01:59 +0000175 vadvise(advice, 0, "", params);
176 va_end(params);
177}
178
179int advice_enabled(enum advice_type type)
180{
181 switch(type) {
182 case ADVICE_PUSH_UPDATE_REJECTED:
183 return advice_setting[ADVICE_PUSH_UPDATE_REJECTED].enabled &&
184 advice_setting[ADVICE_PUSH_UPDATE_REJECTED_ALIAS].enabled;
185 default:
186 return advice_setting[type].enabled;
187 }
188}
189
190void advise_if_enabled(enum advice_type type, const char *advice, ...)
191{
192 va_list params;
193
194 if (!advice_enabled(type))
195 return;
196
197 va_start(params, advice);
198 vadvise(advice, 1, advice_setting[type].key, params);
Heba Waly06ac2b32020-03-02 20:01:57 +0000199 va_end(params);
200}
201
Jeff King75194432009-09-09 07:38:58 -0400202int git_default_advice_config(const char *var, const char *value)
203{
Ryan Dammrose960786e2018-04-21 12:10:00 +0200204 const char *k, *slot_name;
Jeff King75194432009-09-09 07:38:58 -0400205 int i;
206
Ryan Dammrose960786e2018-04-21 12:10:00 +0200207 if (!strcmp(var, "color.advice")) {
208 advice_use_color = git_config_colorbool(var, value);
209 return 0;
210 }
211
212 if (skip_prefix(var, "color.advice.", &slot_name)) {
213 int slot = parse_advise_color_slot(slot_name);
214 if (slot < 0)
215 return 0;
216 if (!value)
217 return config_error_nonbool(var);
218 return color_parse(value, advice_colors[slot]);
219 }
220
Jeff Kingcf4fff52014-06-18 15:44:19 -0400221 if (!skip_prefix(var, "advice.", &k))
222 return 0;
223
Jeff King75194432009-09-09 07:38:58 -0400224 for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
Nguyễn Thái Ngọc Duyfb6fbff2018-05-26 15:55:26 +0200225 if (strcasecmp(k, advice_config[i].name))
Jeff King75194432009-09-09 07:38:58 -0400226 continue;
227 *advice_config[i].preference = git_config_bool(var, value);
Heba Walyb3b18d12020-03-02 20:01:59 +0000228 break;
229 }
230
231 for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
232 if (strcasecmp(k, advice_setting[i].key))
233 continue;
234 advice_setting[i].enabled = git_config_bool(var, value);
Jeff King75194432009-09-09 07:38:58 -0400235 return 0;
236 }
237
238 return 0;
239}
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100240
Nguyễn Thái Ngọc Duy3ac68a92018-05-26 15:55:24 +0200241void list_config_advices(struct string_list *list, const char *prefix)
242{
243 int i;
244
Heba Walyb3b18d12020-03-02 20:01:59 +0000245 for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
246 list_config_item(list, prefix, advice_setting[i].key);
Nguyễn Thái Ngọc Duy3ac68a92018-05-26 15:55:24 +0200247}
248
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530249int error_resolve_conflict(const char *me)
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100250{
Vasco Almeida8785c422016-06-17 20:20:52 +0000251 if (!strcmp(me, "cherry-pick"))
252 error(_("Cherry-picking is not possible because you have unmerged files."));
253 else if (!strcmp(me, "commit"))
254 error(_("Committing is not possible because you have unmerged files."));
255 else if (!strcmp(me, "merge"))
256 error(_("Merging is not possible because you have unmerged files."));
257 else if (!strcmp(me, "pull"))
258 error(_("Pulling is not possible because you have unmerged files."));
259 else if (!strcmp(me, "revert"))
260 error(_("Reverting is not possible because you have unmerged files."));
261 else
262 error(_("It is not possible to %s because you have unmerged files."),
263 me);
264
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800265 if (advice_resolve_conflict)
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100266 /*
267 * Message used both when 'git commit' fails and when
268 * other commands doing a merge do.
269 */
Jeff Kingc057b242014-06-03 03:17:17 -0400270 advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
Matthieu Moy91e70e02014-08-28 11:46:58 +0200271 "as appropriate to mark resolution and make a commit."));
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530272 return -1;
273}
274
275void NORETURN die_resolve_conflict(const char *me)
276{
277 error_resolve_conflict(me);
Vasco Almeida8785c422016-06-17 20:20:52 +0000278 die(_("Exiting because of an unresolved conflict."));
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100279}
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700280
Paul Tan4a4cf9e2015-06-18 18:54:04 +0800281void NORETURN die_conclude_merge(void)
282{
283 error(_("You have not concluded your merge (MERGE_HEAD exists)."));
284 if (advice_resolve_conflict)
Alex Henrieb7447672015-10-01 22:25:33 -0600285 advise(_("Please, commit your changes before merging."));
Paul Tan4a4cf9e2015-06-18 18:54:04 +0800286 die(_("Exiting because of unfinished merge."));
287}
288
Matheus Tavaresa20f7042021-04-08 17:41:27 -0300289void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
290{
291 struct string_list_item *item;
292
293 if (!pathspec_list->nr)
294 return;
295
296 fprintf(stderr, _("The following pathspecs didn't match any"
297 " eligible path, but they do match index\n"
298 "entries outside the current sparse checkout:\n"));
299 for_each_string_list_item(item, pathspec_list)
300 fprintf(stderr, "%s\n", item->string);
301
302 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
303 _("Disable or modify the sparsity rules if you intend"
304 " to update such entries."));
305}
306
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700307void detach_advice(const char *new_name)
308{
Vasco Almeidae9f3cec2016-06-17 20:20:51 +0000309 const char *fmt =
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700310 _("Note: switching to '%s'.\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700311 "\n"
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700312 "You are in 'detached HEAD' state. You can look around, make experimental\n"
313 "changes and commit them, and you can discard any commits you make in this\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700314 "state without impacting any branches by switching back to a branch.\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700315 "\n"
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700316 "If you want to create a new branch to retain commits you create, you may\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700317 "do so (now or later) by using -c with the switch command. Example:\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700318 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700319 " git switch -c <new-branch-name>\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700320 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700321 "Or undo this operation with:\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700322 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700323 " git switch -\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700324 "\n"
325 "Turn off this advice by setting config variable advice.detachedHead to false\n\n");
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700326
327 fprintf(stderr, fmt, new_name);
328}