]> git.ipfire.org Git - thirdparty/git.git/blame - advice.c
Merge branch 'js/check-null-from-read-object-file'
[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 */
71 [ADVICE_RESET_NO_REFRESH_WARNING] = { "resetNoRefresh" },
72 [ADVICE_RESOLVE_CONFLICT] = { "resolveConflict" },
73 [ADVICE_RM_HINTS] = { "rmHints" },
74 [ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" },
75 [ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" },
76 [ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
77 [ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning" },
78 [ADVICE_STATUS_HINTS] = { "statusHints" },
79 [ADVICE_STATUS_U_OPTION] = { "statusUoption" },
80 [ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated" },
81 [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie" },
82 [ADVICE_SUGGEST_DETACHING_HEAD] = { "suggestDetachingHead" },
83 [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath" },
84 [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor" },
85 [ADVICE_WORKTREE_ADD_ORPHAN] = { "worktreeAddOrphan" },
b3b18d16
HW
86};
87
88static const char turn_off_instructions[] =
89N_("\n"
90 "Disable this message with \"git config advice.%s false\"");
91
92static void vadvise(const char *advice, int display_instructions,
93 const char *key, va_list params)
38ef61cf 94{
23cb5bf3 95 struct strbuf buf = STRBUF_INIT;
23cb5bf3 96 const char *cp, *np;
38ef61cf 97
447b99c8 98 strbuf_vaddf(&buf, advice, params);
23cb5bf3 99
b3b18d16
HW
100 if (display_instructions)
101 strbuf_addf(&buf, turn_off_instructions, key);
23cb5bf3
JH
102
103 for (cp = buf.buf; *cp; cp = np) {
104 np = strchrnul(cp, '\n');
960786e7
RD
105 fprintf(stderr, _("%shint: %.*s%s\n"),
106 advise_get_color(ADVICE_COLOR_HINT),
107 (int)(np - cp), cp,
108 advise_get_color(ADVICE_COLOR_RESET));
23cb5bf3
JH
109 if (*np)
110 np++;
111 }
112 strbuf_release(&buf);
38ef61cf
RR
113}
114
06ac2b3b
HW
115void advise(const char *advice, ...)
116{
117 va_list params;
118 va_start(params, advice);
b3b18d16
HW
119 vadvise(advice, 0, "", params);
120 va_end(params);
121}
122
123int advice_enabled(enum advice_type type)
124{
d919965a
RJ
125 int enabled = advice_setting[type].level != ADVICE_LEVEL_DISABLED;
126
127 if (type == ADVICE_PUSH_UPDATE_REJECTED)
128 return enabled &&
129 advice_enabled(ADVICE_PUSH_UPDATE_REJECTED_ALIAS);
130
131 return enabled;
b3b18d16
HW
132}
133
134void advise_if_enabled(enum advice_type type, const char *advice, ...)
135{
136 va_list params;
137
138 if (!advice_enabled(type))
139 return;
140
141 va_start(params, advice);
d919965a
RJ
142 vadvise(advice, !advice_setting[type].level, advice_setting[type].key,
143 params);
06ac2b3b
HW
144 va_end(params);
145}
146
75194438
JK
147int git_default_advice_config(const char *var, const char *value)
148{
960786e7 149 const char *k, *slot_name;
75194438
JK
150 int i;
151
960786e7
RD
152 if (!strcmp(var, "color.advice")) {
153 advice_use_color = git_config_colorbool(var, value);
154 return 0;
155 }
156
157 if (skip_prefix(var, "color.advice.", &slot_name)) {
158 int slot = parse_advise_color_slot(slot_name);
159 if (slot < 0)
160 return 0;
161 if (!value)
162 return config_error_nonbool(var);
163 return color_parse(value, advice_colors[slot]);
164 }
165
cf4fff57
JK
166 if (!skip_prefix(var, "advice.", &k))
167 return 0;
168
b3b18d16
HW
169 for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
170 if (strcasecmp(k, advice_setting[i].key))
171 continue;
d919965a
RJ
172 advice_setting[i].level = git_config_bool(var, value)
173 ? ADVICE_LEVEL_ENABLED
174 : ADVICE_LEVEL_DISABLED;
75194438
JK
175 return 0;
176 }
177
178 return 0;
179}
d38a30df 180
3ac68a93
NTND
181void list_config_advices(struct string_list *list, const char *prefix)
182{
183 int i;
184
b3b18d16
HW
185 for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
186 list_config_item(list, prefix, advice_setting[i].key);
3ac68a93
NTND
187}
188
38ef61cf 189int error_resolve_conflict(const char *me)
d38a30df 190{
8785c425
VA
191 if (!strcmp(me, "cherry-pick"))
192 error(_("Cherry-picking is not possible because you have unmerged files."));
193 else if (!strcmp(me, "commit"))
194 error(_("Committing is not possible because you have unmerged files."));
195 else if (!strcmp(me, "merge"))
196 error(_("Merging is not possible because you have unmerged files."));
197 else if (!strcmp(me, "pull"))
198 error(_("Pulling is not possible because you have unmerged files."));
199 else if (!strcmp(me, "revert"))
200 error(_("Reverting is not possible because you have unmerged files."));
ff29a61c
OB
201 else if (!strcmp(me, "rebase"))
202 error(_("Rebasing is not possible because you have unmerged files."));
8785c425 203 else
ff29a61c 204 BUG("Unhandled conflict reason '%s'", me);
8785c425 205
ed9bff08 206 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
d38a30df
MM
207 /*
208 * Message used both when 'git commit' fails and when
209 * other commands doing a merge do.
210 */
c057b242 211 advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
91e70e00 212 "as appropriate to mark resolution and make a commit."));
38ef61cf
RR
213 return -1;
214}
215
216void NORETURN die_resolve_conflict(const char *me)
217{
218 error_resolve_conflict(me);
8785c425 219 die(_("Exiting because of an unresolved conflict."));
d38a30df 220}
2857093b 221
4a4cf9e8
PT
222void NORETURN die_conclude_merge(void)
223{
224 error(_("You have not concluded your merge (MERGE_HEAD exists)."));
ed9bff08 225 if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
b7447679 226 advise(_("Please, commit your changes before merging."));
4a4cf9e8
PT
227 die(_("Exiting because of unfinished merge."));
228}
229
3d5fc24d
AH
230void NORETURN die_ff_impossible(void)
231{
765071a8
FC
232 advise_if_enabled(ADVICE_DIVERGING,
233 _("Diverging branches can't be fast-forwarded, you need to either:\n"
234 "\n"
235 "\tgit merge --no-ff\n"
236 "\n"
237 "or:\n"
238 "\n"
239 "\tgit rebase\n"));
3d5fc24d
AH
240 die(_("Not possible to fast-forward, aborting."));
241}
242
a20f7047
MT
243void advise_on_updating_sparse_paths(struct string_list *pathspec_list)
244{
245 struct string_list_item *item;
246
247 if (!pathspec_list->nr)
248 return;
249
6579e788
DS
250 fprintf(stderr, _("The following paths and/or pathspecs matched paths that exist\n"
251 "outside of your sparse-checkout definition, so will not be\n"
252 "updated in the index:\n"));
a20f7047
MT
253 for_each_string_list_item(item, pathspec_list)
254 fprintf(stderr, "%s\n", item->string);
255
256 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
6579e788
DS
257 _("If you intend to update such entries, try one of the following:\n"
258 "* Use the --sparse option.\n"
259 "* Disable or modify the sparsity rules."));
a20f7047
MT
260}
261
2857093b
NTND
262void detach_advice(const char *new_name)
263{
e9f3cec4 264 const char *fmt =
328c6cb8 265 _("Note: switching to '%s'.\n"
af9ded5b 266 "\n"
2857093b
NTND
267 "You are in 'detached HEAD' state. You can look around, make experimental\n"
268 "changes and commit them, and you can discard any commits you make in this\n"
328c6cb8 269 "state without impacting any branches by switching back to a branch.\n"
af9ded5b 270 "\n"
2857093b 271 "If you want to create a new branch to retain commits you create, you may\n"
328c6cb8 272 "do so (now or later) by using -c with the switch command. Example:\n"
af9ded5b 273 "\n"
328c6cb8 274 " git switch -c <new-branch-name>\n"
af9ded5b 275 "\n"
328c6cb8 276 "Or undo this operation with:\n"
af9ded5b 277 "\n"
328c6cb8 278 " git switch -\n"
af9ded5b
NTND
279 "\n"
280 "Turn off this advice by setting config variable advice.detachedHead to false\n\n");
2857093b
NTND
281
282 fprintf(stderr, fmt, new_name);
283}
5efd533e
SY
284
285void advise_on_moving_dirty_path(struct string_list *pathspec_list)
286{
287 struct string_list_item *item;
288
289 if (!pathspec_list->nr)
290 return;
291
292 fprintf(stderr, _("The following paths have been moved outside the\n"
293 "sparse-checkout definition but are not sparse due to local\n"
294 "modifications.\n"));
295 for_each_string_list_item(item, pathspec_list)
296 fprintf(stderr, "%s\n", item->string);
297
298 advise_if_enabled(ADVICE_UPDATE_SPARSE_PATH,
299 _("To correct the sparsity of these paths, do the following:\n"
300 "* Use \"git add --sparse <paths>\" to update the index\n"
301 "* Use \"git sparse-checkout reapply\" to apply the sparsity rules"));
302}