]> git.ipfire.org Git - thirdparty/git.git/blame - advice.c
The twelfth batch
[thirdparty/git.git] / advice.c
CommitLineData
fc7bd51b
EN
1#include "git-compat-util.h"
2#include "advice.h"
b2141fc1 3#include "config.h"
960786e7 4#include "color.h"
fc7bd51b 5#include "gettext.h"
3ac68a93 6#include "help.h"
a20f7047 7#include "string-list.h"
75194438 8
960786e7
RD
9static int advice_use_color = -1;
10static char advice_colors[][COLOR_MAXLEN] = {
11 GIT_COLOR_RESET,
12 GIT_COLOR_YELLOW, /* HINT */
13};
14
15enum color_advice {
16 ADVICE_COLOR_RESET = 0,
17 ADVICE_COLOR_HINT = 1,
18};
19
20static int parse_advise_color_slot(const char *slot)
21{
22 if (!strcasecmp(slot, "reset"))
23 return ADVICE_COLOR_RESET;
24 if (!strcasecmp(slot, "hint"))
25 return ADVICE_COLOR_HINT;
26 return -1;
27}
28
29static const char *advise_get_color(enum color_advice ix)
30{
31 if (want_color_stderr(advice_use_color))
32 return advice_colors[ix];
33 return "";
34}
35
d919965a
RJ
36enum advice_level {
37 ADVICE_LEVEL_NONE = 0,
38 ADVICE_LEVEL_DISABLED,
39 ADVICE_LEVEL_ENABLED,
40};
41
b3b18d16
HW
42static struct {
43 const char *key;
d919965a 44 enum advice_level level;
b3b18d16 45} advice_setting[] = {
d919965a
RJ
46 [ADVICE_ADD_EMBEDDED_REPO] = { "addEmbeddedRepo" },
47 [ADVICE_ADD_EMPTY_PATHSPEC] = { "addEmptyPathspec" },
48 [ADVICE_ADD_IGNORED_FILE] = { "addIgnoredFile" },
49 [ADVICE_AMBIGUOUS_FETCH_REFSPEC] = { "ambiguousFetchRefspec" },
50 [ADVICE_AM_WORK_DIR] = { "amWorkDir" },
51 [ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName" },
52 [ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge" },
53 [ADVICE_DETACHED_HEAD] = { "detachedHead" },
54 [ADVICE_DIVERGING] = { "diverging" },
55 [ADVICE_FETCH_SHOW_FORCED_UPDATES] = { "fetchShowForcedUpdates" },
56 [ADVICE_FORCE_DELETE_BRANCH] = { "forceDeleteBranch" },
57 [ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated" },
58 [ADVICE_IGNORED_HOOK] = { "ignoredHook" },
59 [ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity" },
60 [ADVICE_NESTED_TAG] = { "nestedTag" },
61 [ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning" },
62 [ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists" },
63 [ADVICE_PUSH_FETCH_FIRST] = { "pushFetchFirst" },
64 [ADVICE_PUSH_NEEDS_FORCE] = { "pushNeedsForce" },
65 [ADVICE_PUSH_NON_FF_CURRENT] = { "pushNonFFCurrent" },
66 [ADVICE_PUSH_NON_FF_MATCHING] = { "pushNonFFMatching" },
67 [ADVICE_PUSH_REF_NEEDS_UPDATE] = { "pushRefNeedsUpdate" },
68 [ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName" },
69 [ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected" },
70 [ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward" }, /* backwards compatibility */
8fbd903e 71 [ADVICE_REF_SYNTAX] = { "refSyntax" },
d919965a
RJ
72 [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" },
73 [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" },
74 [ADVICE_RM_HINTS] = { "rmHints" },
75 [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" },
76 [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" },
77 [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
78 [ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning" },
79 [ADVICE_STATUS_HINTS] = { "statusHints" },
80 [ADVICE_STATUS_U_OPTION] = { "statusUoption" },
81 [ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated" },
82 [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie" },
b9e55be7 83 [ADVICE_SUBMODULE_MERGE_CONFLICT] = { "submoduleMergeConflict" },
d919965a
RJ
84 [ADVICE_SUGGEST_DETACHING_HEAD] = { "suggestDetachingHead" },
85 [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath" },
86 [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor" },
87 [ADVICE_WORKTREE_ADD_ORPHAN] = { "worktreeAddOrphan" },
b3b18d16
HW
88};
89
90static const char turn_off_instructions[] =
91N_("\n"
92 "Disable this message with \"git config advice.%s false\"");
93
94static void vadvise(const char *advice, int display_instructions,
95 const char *key, va_list params)
38ef61cf 96{
23cb5bf3 97 struct strbuf buf = STRBUF_INIT;
23cb5bf3 98 const char *cp, *np;
38ef61cf 99
447b99c8 100 strbuf_vaddf(&buf, advice, params);
23cb5bf3 101
b3b18d16
HW
102 if (display_instructions)
103 strbuf_addf(&buf, turn_off_instructions, key);
23cb5bf3
JH
104
105 for (cp = buf.buf; *cp; cp = np) {
106 np = strchrnul(cp, '\n');
960786e7
RD
107 fprintf(stderr, _("%shint: %.*s%s\n"),
108 advise_get_color(ADVICE_COLOR_HINT),
109 (int)(np - cp), cp,
110 advise_get_color(ADVICE_COLOR_RESET));
23cb5bf3
JH
111 if (*np)
112 np++;
113 }
114 strbuf_release(&buf);
38ef61cf
RR
115}
116
06ac2b3b
HW
117void advise(const char *advice, ...)
118{
119 va_list params;
120 va_start(params, advice);
b3b18d16
HW
121 vadvise(advice, 0, "", params);
122 va_end(params);
123}
124
125int advice_enabled(enum advice_type type)
126{
d919965a
RJ
127 int enabled = advice_setting[type].level != ADVICE_LEVEL_DISABLED;
128
129 if (type == ADVICE_PUSH_UPDATE_REJECTED)
130 return enabled &&
131 advice_enabled(ADVICE_PUSH_UPDATE_REJECTED_ALIAS);
132
133 return enabled;
b3b18d16
HW
134}
135
136void advise_if_enabled(enum advice_type type, const char *advice, ...)
137{
138 va_list params;
139
140 if (!advice_enabled(type))
141 return;
142
143 va_start(params, advice);
d919965a
RJ
144 vadvise(advice, !advice_setting[type].level, advice_setting[type].key,
145 params);
06ac2b3b
HW
146 va_end(params);
147}
148
75194438
JK
149int git_default_advice_config(const char *var, const char *value)
150{
960786e7 151 const char *k, *slot_name;
75194438
JK
152 int i;
153
960786e7
RD
154 if (!strcmp(var, "color.advice")) {
155 advice_use_color = git_config_colorbool(var, value);
156 return 0;
157 }
158
159 if (skip_prefix(var, "color.advice.", &slot_name)) {
160 int slot = parse_advise_color_slot(slot_name);
161 if (slot < 0)
162 return 0;
163 if (!value)
164 return config_error_nonbool(var);
165 return color_parse(value, advice_colors[slot]);
166 }
167
cf4fff57
JK
168 if (!skip_prefix(var, "advice.", &k))
169 return 0;
170
b3b18d16
HW
171 for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
172 if (strcasecmp(k, advice_setting[i].key))
173 continue;
d919965a
RJ
174 advice_setting[i].level = git_config_bool(var, value)
175 ? ADVICE_LEVEL_ENABLED
176 : ADVICE_LEVEL_DISABLED;
75194438
JK
177 return 0;
178 }
179
180 return 0;
181}
d38a30df 182
3ac68a93
NTND
183void list_config_advices(struct string_list *list, const char *prefix)
184{
185 int i;
186
b3b18d16
HW
187 for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
188 list_config_item(list, prefix, advice_setting[i].key);
3ac68a93
NTND
189}
190
38ef61cf 191int error_resolve_conflict(const char *me)
d38a30df 192{
8785c425
VA
193 if (!strcmp(me, "cherry-pick"))
194 error(_("Cherry-picking is not possible because you have unmerged files."));
195 else if (!strcmp(me, "commit"))
196 error(_("Committing is not possible because you have unmerged files."));
197 else if (!strcmp(me, "merge"))
198 error(_("Merging is not possible because you have unmerged files."));
199 else if (!strcmp(me, "pull"))
200 error(_("Pulling is not possible because you have unmerged files."));
201 else if (!strcmp(me, "revert"))
202 error(_("Reverting is not possible because you have unmerged files."));
ff29a61c
OB
203 else if (!strcmp(me, "rebase"))
204 error(_("Rebasing is not possible because you have unmerged files."));
8785c425 205 else
ff29a61c 206 BUG("Unhandled conflict reason '%s'", me);
8785c425 207
ed9bff08 208 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
d38a30df
MM
209 /*
210 * Message used both when 'git commit' fails and when
211 * other commands doing a merge do.
212 */
c057b242 213 advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
91e70e00 214 "as appropriate to mark resolution and make a commit."));
38ef61cf
RR
215 return -1;
216}
217
218void NORETURN die_resolve_conflict(const char *me)
219{
220 error_resolve_conflict(me);
8785c425 221 die(_("Exiting because of an unresolved conflict."));
d38a30df 222}
2857093b 223
4a4cf9e8
PT
224void NORETURN die_conclude_merge(void)
225{
226 error(_("You have not concluded your merge (MERGE_HEAD exists)."));
ed9bff08 227 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
b7447679 228 advise(_("Please, commit your changes before merging."));
4a4cf9e8
PT
229 die(_("Exiting because of unfinished merge."));
230}
231
3d5fc24d
AH
232void NORETURN die_ff_impossible(void)
233{
765071a8
FC
234 advise_if_enabled(ADVICE_DIVERGING,
235 _("Diverging branches can't be fast-forwarded, you need to either:\n"
236 "\n"
237 "\tgit merge --no-ff\n"
238 "\n"
239 "or:\n"
240 "\n"
241 "\tgit rebase\n"));
3d5fc24d
AH
242 die(_("Not possible to fast-forward, aborting."));
243}
244
a20f7047
MT
245void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
246{
247 struct string_list_item *item;
248
249 if (!pathspec_list->nr)
250 return;
251
6579e788
DS
252 fprintf(stderr, _("The following paths and/or pathspecs matched paths that exist\n"
253 "outside of your sparse-checkout definition, so will not be\n"
254 "updated in the index:\n"));
a20f7047
MT
255 for_each_string_list_item(item, pathspec_list)
256 fprintf(stderr, "%s\n", item->string);
257
258 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
6579e788
DS
259 _("If you intend to update such entries, try one of the following:\n"
260 "* Use the --sparse option.\n"
261 "* Disable or modify the sparsity rules."));
a20f7047
MT
262}
263
2857093b
NTND
264void detach_advice(const char *new_name)
265{
e9f3cec4 266 const char *fmt =
328c6cb8 267 _("Note: switching to '%s'.\n"
af9ded5b 268 "\n"
2857093b
NTND
269 "You are in 'detached HEAD' state. You can look around, make experimental\n"
270 "changes and commit them, and you can discard any commits you make in this\n"
328c6cb8 271 "state without impacting any branches by switching back to a branch.\n"
af9ded5b 272 "\n"
2857093b 273 "If you want to create a new branch to retain commits you create, you may\n"
328c6cb8 274 "do so (now or later) by using -c with the switch command. Example:\n"
af9ded5b 275 "\n"
328c6cb8 276 " git switch -c <new-branch-name>\n"
af9ded5b 277 "\n"
328c6cb8 278 "Or undo this operation with:\n"
af9ded5b 279 "\n"
328c6cb8 280 " git switch -\n"
af9ded5b
NTND
281 "\n"
282 "Turn off this advice by setting config variable advice.detachedHead to false\n\n");
2857093b
NTND
283
284 fprintf(stderr, fmt, new_name);
285}
5efd533e
SY
286
287void advise_on_moving_dirty_path(struct string_list *pathspec_list)
288{
289 struct string_list_item *item;
290
291 if (!pathspec_list->nr)
292 return;
293
294 fprintf(stderr, _("The following paths have been moved outside the\n"
295 "sparse-checkout definition but are not sparse due to local\n"
296 "modifications.\n"));
297 for_each_string_list_item(item, pathspec_list)
298 fprintf(stderr, "%s\n", item->string);
299
300 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
301 _("To correct the sparsity of these paths, do the following:\n"
302 "* Use \"git add --sparse <paths>\" to update the index\n"
303 "* Use \"git sparse-checkout reapply\" to apply the sparsity rules"));
304}