blob: 2e1fd483040bf399e3a689145d6c8dd3dfa277f5 [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
Ryan Dammrose960786e2018-04-21 12:10:00 +02007static int advice_use_color = -1;
8static char advice_colors[][COLOR_MAXLEN] = {
9 GIT_COLOR_RESET,
10 GIT_COLOR_YELLOW, /* HINT */
11};
12
13enum color_advice {
14 ADVICE_COLOR_RESET = 0,
15 ADVICE_COLOR_HINT = 1,
16};
17
18static int parse_advise_color_slot(const char *slot)
19{
20 if (!strcasecmp(slot, "reset"))
21 return ADVICE_COLOR_RESET;
22 if (!strcasecmp(slot, "hint"))
23 return ADVICE_COLOR_HINT;
24 return -1;
25}
26
27static const char *advise_get_color(enum color_advice ix)
28{
29 if (want_color_stderr(advice_use_color))
30 return advice_colors[ix];
31 return "";
32}
33
Jeff King75194432009-09-09 07:38:58 -040034static struct {
Heba Walyb3b18d12020-03-02 20:01:59 +000035 const char *key;
36 int enabled;
37} advice_setting[] = {
38 [ADVICE_ADD_EMBEDDED_REPO] = { "addEmbeddedRepo", 1 },
Ben Boeckel69290552021-08-23 12:43:59 +020039 [ADVICE_ADD_EMPTY_PATHSPEC] = { "addEmptyPathspec", 1 },
40 [ADVICE_ADD_IGNORED_FILE] = { "addIgnoredFile", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +000041 [ADVICE_AM_WORK_DIR] = { "amWorkDir", 1 },
42 [ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName", 1 },
43 [ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge", 1 },
44 [ADVICE_DETACHED_HEAD] = { "detachedHead", 1 },
Alex Henrie808213b2022-02-25 23:12:13 -070045 [ADVICE_SUGGEST_DETACHING_HEAD] = { "suggestDetachingHead", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +000046 [ADVICE_FETCH_SHOW_FORCED_UPDATES] = { "fetchShowForcedUpdates", 1 },
47 [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated", 1 },
48 [ADVICE_IGNORED_HOOK] = { "ignoredHook", 1 },
49 [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity", 1 },
50 [ADVICE_NESTED_TAG] = { "nestedTag", 1 },
51 [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning", 1 },
52 [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists", 1 },
53 [ADVICE_PUSH_FETCH_FIRST] = { "pushFetchFirst", 1 },
54 [ADVICE_PUSH_NEEDS_FORCE] = { "pushNeedsForce", 1 },
Srinidhi Kaushik3b990aa2020-10-03 17:40:45 +053055 [ADVICE_PUSH_REF_NEEDS_UPDATE] = { "pushRefNeedsUpdate", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +000056
57 /* make this an alias for backward compatibility */
58 [ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward", 1 },
59
60 [ADVICE_PUSH_NON_FF_CURRENT] = { "pushNonFFCurrent", 1 },
61 [ADVICE_PUSH_NON_FF_MATCHING] = { "pushNonFFMatching", 1 },
62 [ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName", 1 },
63 [ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected", 1 },
64 [ADVICE_RESET_QUIET_WARNING] = { "resetQuiet", 1 },
65 [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict", 1 },
66 [ADVICE_RM_HINTS] = { "rmHints", 1 },
67 [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
68 [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
Josh Steadmon767a4ca2021-08-30 14:46:02 -070069 [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +000070 [ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
71 [ADVICE_STATUS_HINTS] = { "statusHints", 1 },
72 [ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
73 [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
Glen Choo961b1302022-01-28 16:04:45 -080074 [ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated", 1 },
Matheus Tavaresa20f7042021-04-08 17:41:27 -030075 [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 },
Heba Walyb3b18d12020-03-02 20:01:59 +000076 [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
77};
78
79static const char turn_off_instructions[] =
80N_("\n"
81 "Disable this message with \"git config advice.%s false\"");
82
83static void vadvise(const char *advice, int display_instructions,
84 const char *key, va_list params)
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +053085{
Junio C Hamano23cb5bf2011-12-22 11:21:26 -080086 struct strbuf buf = STRBUF_INIT;
Junio C Hamano23cb5bf2011-12-22 11:21:26 -080087 const char *cp, *np;
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +053088
Jeff King447b99c2012-07-23 14:48:57 -040089 strbuf_vaddf(&buf, advice, params);
Junio C Hamano23cb5bf2011-12-22 11:21:26 -080090
Heba Walyb3b18d12020-03-02 20:01:59 +000091 if (display_instructions)
92 strbuf_addf(&buf, turn_off_instructions, key);
Junio C Hamano23cb5bf2011-12-22 11:21:26 -080093
94 for (cp = buf.buf; *cp; cp = np) {
95 np = strchrnul(cp, '\n');
Ryan Dammrose960786e2018-04-21 12:10:00 +020096 fprintf(stderr, _("%shint: %.*s%s\n"),
97 advise_get_color(ADVICE_COLOR_HINT),
98 (int)(np - cp), cp,
99 advise_get_color(ADVICE_COLOR_RESET));
Junio C Hamano23cb5bf2011-12-22 11:21:26 -0800100 if (*np)
101 np++;
102 }
103 strbuf_release(&buf);
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530104}
105
Heba Waly06ac2b32020-03-02 20:01:57 +0000106void advise(const char *advice, ...)
107{
108 va_list params;
109 va_start(params, advice);
Heba Walyb3b18d12020-03-02 20:01:59 +0000110 vadvise(advice, 0, "", params);
111 va_end(params);
112}
113
114int advice_enabled(enum advice_type type)
115{
116 switch(type) {
117 case ADVICE_PUSH_UPDATE_REJECTED:
118 return advice_setting[ADVICE_PUSH_UPDATE_REJECTED].enabled &&
119 advice_setting[ADVICE_PUSH_UPDATE_REJECTED_ALIAS].enabled;
120 default:
121 return advice_setting[type].enabled;
122 }
123}
124
125void advise_if_enabled(enum advice_type type, const char *advice, ...)
126{
127 va_list params;
128
129 if (!advice_enabled(type))
130 return;
131
132 va_start(params, advice);
133 vadvise(advice, 1, advice_setting[type].key, params);
Heba Waly06ac2b32020-03-02 20:01:57 +0000134 va_end(params);
135}
136
Jeff King75194432009-09-09 07:38:58 -0400137int git_default_advice_config(const char *var, const char *value)
138{
Ryan Dammrose960786e2018-04-21 12:10:00 +0200139 const char *k, *slot_name;
Jeff King75194432009-09-09 07:38:58 -0400140 int i;
141
Ryan Dammrose960786e2018-04-21 12:10:00 +0200142 if (!strcmp(var, "color.advice")) {
143 advice_use_color = git_config_colorbool(var, value);
144 return 0;
145 }
146
147 if (skip_prefix(var, "color.advice.", &slot_name)) {
148 int slot = parse_advise_color_slot(slot_name);
149 if (slot < 0)
150 return 0;
151 if (!value)
152 return config_error_nonbool(var);
153 return color_parse(value, advice_colors[slot]);
154 }
155
Jeff Kingcf4fff52014-06-18 15:44:19 -0400156 if (!skip_prefix(var, "advice.", &k))
157 return 0;
158
Heba Walyb3b18d12020-03-02 20:01:59 +0000159 for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
160 if (strcasecmp(k, advice_setting[i].key))
161 continue;
162 advice_setting[i].enabled = git_config_bool(var, value);
Jeff King75194432009-09-09 07:38:58 -0400163 return 0;
164 }
165
166 return 0;
167}
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100168
Nguyễn Thái Ngọc Duy3ac68a92018-05-26 15:55:24 +0200169void list_config_advices(struct string_list *list, const char *prefix)
170{
171 int i;
172
Heba Walyb3b18d12020-03-02 20:01:59 +0000173 for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
174 list_config_item(list, prefix, advice_setting[i].key);
Nguyễn Thái Ngọc Duy3ac68a92018-05-26 15:55:24 +0200175}
176
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530177int error_resolve_conflict(const char *me)
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100178{
Vasco Almeida8785c422016-06-17 20:20:52 +0000179 if (!strcmp(me, "cherry-pick"))
180 error(_("Cherry-picking is not possible because you have unmerged files."));
181 else if (!strcmp(me, "commit"))
182 error(_("Committing is not possible because you have unmerged files."));
183 else if (!strcmp(me, "merge"))
184 error(_("Merging is not possible because you have unmerged files."));
185 else if (!strcmp(me, "pull"))
186 error(_("Pulling is not possible because you have unmerged files."));
187 else if (!strcmp(me, "revert"))
188 error(_("Reverting is not possible because you have unmerged files."));
189 else
190 error(_("It is not possible to %s because you have unmerged files."),
191 me);
192
Ben Boeckeled9bff02021-08-23 12:44:00 +0200193 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100194 /*
195 * Message used both when 'git commit' fails and when
196 * other commands doing a merge do.
197 */
Jeff Kingc057b242014-06-03 03:17:17 -0400198 advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
Matthieu Moy91e70e02014-08-28 11:46:58 +0200199 "as appropriate to mark resolution and make a commit."));
Ramkumar Ramachandra38ef61c2011-08-04 16:08:59 +0530200 return -1;
201}
202
203void NORETURN die_resolve_conflict(const char *me)
204{
205 error_resolve_conflict(me);
Vasco Almeida8785c422016-06-17 20:20:52 +0000206 die(_("Exiting because of an unresolved conflict."));
Matthieu Moyd38a30d2010-01-12 10:54:44 +0100207}
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700208
Paul Tan4a4cf9e2015-06-18 18:54:04 +0800209void NORETURN die_conclude_merge(void)
210{
211 error(_("You have not concluded your merge (MERGE_HEAD exists)."));
Ben Boeckeled9bff02021-08-23 12:44:00 +0200212 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
Alex Henrieb7447672015-10-01 22:25:33 -0600213 advise(_("Please, commit your changes before merging."));
Paul Tan4a4cf9e2015-06-18 18:54:04 +0800214 die(_("Exiting because of unfinished merge."));
215}
216
Alex Henrie3d5fc242021-07-21 01:42:19 +0000217void NORETURN die_ff_impossible(void)
218{
219 die(_("Not possible to fast-forward, aborting."));
220}
221
Matheus Tavaresa20f7042021-04-08 17:41:27 -0300222void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
223{
224 struct string_list_item *item;
225
226 if (!pathspec_list->nr)
227 return;
228
Derrick Stolee6579e782021-09-24 15:39:14 +0000229 fprintf(stderr, _("The following paths and/or pathspecs matched paths that exist\n"
230 "outside of your sparse-checkout definition, so will not be\n"
231 "updated in the index:\n"));
Matheus Tavaresa20f7042021-04-08 17:41:27 -0300232 for_each_string_list_item(item, pathspec_list)
233 fprintf(stderr, "%s\n", item->string);
234
235 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
Derrick Stolee6579e782021-09-24 15:39:14 +0000236 _("If you intend to update such entries, try one of the following:\n"
237 "* Use the --sparse option.\n"
238 "* Disable or modify the sparsity rules."));
Matheus Tavaresa20f7042021-04-08 17:41:27 -0300239}
240
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700241void detach_advice(const char *new_name)
242{
Vasco Almeidae9f3cec2016-06-17 20:20:51 +0000243 const char *fmt =
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700244 _("Note: switching to '%s'.\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700245 "\n"
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700246 "You are in 'detached HEAD' state. You can look around, make experimental\n"
247 "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 +0700248 "state without impacting any branches by switching back to a branch.\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700249 "\n"
Nguyễn Thái Ngọc Duy28570932012-01-16 16:46:16 +0700250 "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 +0700251 "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 +0700252 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700253 " git switch -c <new-branch-name>\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700254 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700255 "Or undo this operation with:\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700256 "\n"
Nguyễn Thái Ngọc Duy328c6cb2019-03-29 17:39:19 +0700257 " git switch -\n"
Nguyễn Thái Ngọc Duyaf9ded52019-03-29 17:38:58 +0700258 "\n"
259 "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 +0700260
261 fprintf(stderr, fmt, new_name);
262}