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