2009-09-09 15:38:58 +04:00
|
|
|
#include "cache.h"
|
2017-06-14 21:07:36 +03:00
|
|
|
#include "config.h"
|
2018-04-21 13:10:00 +03:00
|
|
|
#include "color.h"
|
2018-05-26 16:55:24 +03:00
|
|
|
#include "help.h"
|
2009-09-09 15:38:58 +04:00
|
|
|
|
2019-06-18 23:25:27 +03:00
|
|
|
int advice_fetch_show_forced_updates = 1;
|
2012-12-03 07:27:50 +04:00
|
|
|
int advice_push_update_rejected = 1;
|
push: Provide situational hints for non-fast-forward errors
Pushing a non-fast-forward update to a remote repository will result in
an error, but the hint text doesn't provide the correct resolution in
every case. Give better resolution advice in three push scenarios:
1) If you push your current branch and it triggers a non-fast-forward
error, you should merge remote changes with 'git pull' before pushing
again.
2) If you push to a shared repository others push to, and your local
tracking branches are not kept up to date, the 'matching refs' default
will generate non-fast-forward errors on outdated branches. If this is
your workflow, the 'matching refs' default is not for you. Consider
setting the 'push.default' configuration variable to 'current' or
'upstream' to ensure only your current branch is pushed.
3) If you explicitly specify a ref that is not your current branch or
push matching branches with ':', you will generate a non-fast-forward
error if any pushed branch tip is out of date. You should checkout the
offending branch and merge remote changes before pushing again.
Teach transport.c to recognize these scenarios and configure push.c
to hint for them. If 'git push's default behavior changes or we
discover more scenarios, extension is easy. Standardize on the
advice API and add three new advice variables, 'pushNonFFCurrent',
'pushNonFFDefault', and 'pushNonFFMatching'. Setting any of these
to 'false' will disable their affiliated advice. Setting
'pushNonFastForward' to false will disable all three, thus preserving the
config option for users who already set it, but guaranteeing new
users won't disable push advice accidentally.
Based-on-patch-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Christopher Tiwald <christiwald@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-03-20 08:31:33 +04:00
|
|
|
int advice_push_non_ff_current = 1;
|
|
|
|
int advice_push_non_ff_matching = 1;
|
2012-12-03 07:27:51 +04:00
|
|
|
int advice_push_already_exists = 1;
|
push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE
When we push to update an existing ref, if:
* the object at the tip of the remote is not a commit; or
* the object we are pushing is not a commit,
it won't be correct to suggest to fetch, integrate and push again,
as the old and new objects will not "merge". We should explain that
the push must be forced when there is a non-committish object is
involved in such a case.
If we do not have the current object at the tip of the remote, we do
not even know that object, when fetched, is something that can be
merged. In such a case, suggesting to pull first just like
non-fast-forward case may not be technically correct, but in
practice, most such failures are seen when you try to push your work
to a branch without knowing that somebody else already pushed to
update the same branch since you forked, so "pull first" would work
as a suggestion most of the time. And if the object at the tip is
not a commit, "pull first" will fail, without making any permanent
damage. As a side effect, it also makes the error message the user
will get during the next "push" attempt easier to understand, now
the user is aware that a non-commit object is involved.
In these cases, the current code already rejects such a push on the
client end, but we used the same error and advice messages as the
ones used when rejecting a non-fast-forward push, i.e. pull from
there and integrate before pushing again.
Introduce new rejection reasons and reword the messages
appropriately.
[jc: with help by Peff on message details]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-01-24 01:55:30 +04:00
|
|
|
int advice_push_fetch_first = 1;
|
|
|
|
int advice_push_needs_force = 1;
|
push: add an advice on unqualified <dst> push
Add an advice to the recently improved error message added in
f8aae12034 ("push: allow unqualified dest refspecs to DWIM",
2008-04-23).
Now with advice.pushUnqualifiedRefName=true (on by default) we show a
hint about how to proceed:
$ ./git-push avar v2.19.0^{commit}:newbranch -n
error: The destination you provided is not a full refname (i.e.,
starting with "refs/"). We tried to guess what you meant by:
- Looking for a ref that matches 'newbranch' on the remote side.
- Checking if the <src> being pushed ('v2.19.0^{commit}')
is a ref in "refs/{heads,tags}/". If so we add a corresponding
refs/{heads,tags}/ prefix on the remote side.
Neither worked, so we gave up. You must fully qualify the ref.
hint: The <src> part of the refspec is a commit object.
hint: Did you mean to create a new branch by pushing to
hint: 'v2.19.0^{commit}:refs/heads/newbranch'?
error: failed to push some refs to 'git@github.com:avar/git.git'
When trying to push a tag, tree or a blob we suggest that perhaps the
user meant to push them to refs/tags/ instead.
The if/else duplication for all of OBJ_{COMMIT,TAG,TREE,BLOB} is
unfortunate, but is required to correctly mark the messages for
translation. See the discussion in
<87r2gxebsi.fsf@evledraar.gmail.com> about that.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-13 22:52:43 +03:00
|
|
|
int advice_push_unqualified_ref_name = 1;
|
2020-10-03 15:10:45 +03:00
|
|
|
int advice_push_ref_needs_update = 1;
|
2009-09-09 15:43:03 +04:00
|
|
|
int advice_status_hints = 1;
|
2013-03-13 16:59:16 +04:00
|
|
|
int advice_status_u_option = 1;
|
2019-06-18 23:21:27 +03:00
|
|
|
int advice_status_ahead_behind_warning = 1;
|
2009-11-23 01:26:17 +03:00
|
|
|
int advice_commit_before_merge = 1;
|
2018-10-23 22:04:23 +03:00
|
|
|
int advice_reset_quiet_warning = 1;
|
Be more user-friendly when refusing to do something because of conflict.
Various commands refuse to run in the presence of conflicts (commit,
merge, pull, cherry-pick/revert). They all used to provide rough, and
inconsistant error messages.
A new variable advice.resolveconflict is introduced, and allows more
verbose messages, pointing the user to the appropriate solution.
For commit, the error message used to look like this:
$ git commit
foo.txt: needs merge
foo.txt: unmerged (c34a92682e0394bc0d6f4d4a67a8e2d32395c169)
foo.txt: unmerged (3afcd75de8de0bb5076942fcb17446be50451030)
foo.txt: unmerged (c9785d77b76dfe4fb038bf927ee518f6ae45ede4)
error: Error building trees
The "need merge" line is given by refresh_cache. We add the IN_PORCELAIN
option to make the output more consistant with the other porcelain
commands, and catch the error in return, to stop with a clean error
message. The next lines were displayed by a call to cache_tree_update(),
which is not reached anymore if we noticed the conflict.
The new output looks like:
U foo.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.
Pull is slightly modified to abort immediately if $GIT_DIR/MERGE_HEAD
exists instead of waiting for merge to complain.
The behavior of merge and the test-case are slightly modified to reflect
the usual flow: start with conflicts, fix them, and afterwards get rid of
MERGE_HEAD, with different error messages at each stage.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-12 12:54:44 +03:00
|
|
|
int advice_resolve_conflict = 1;
|
2019-07-02 12:11:25 +03:00
|
|
|
int advice_sequencer_in_use = 1;
|
2010-01-13 23:17:08 +03:00
|
|
|
int advice_implicit_identity = 1;
|
2010-01-30 09:03:24 +03:00
|
|
|
int advice_detached_head = 1;
|
2013-04-02 23:05:12 +04:00
|
|
|
int advice_set_upstream_failure = 1;
|
2013-05-29 16:12:42 +04:00
|
|
|
int advice_object_name_warning = 1;
|
2018-05-26 16:55:27 +03:00
|
|
|
int advice_amworkdir = 1;
|
2013-06-12 12:06:44 +04:00
|
|
|
int advice_rm_hints = 1;
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 13:58:22 +03:00
|
|
|
int advice_add_embedded_repo = 1;
|
2017-10-06 11:07:55 +03:00
|
|
|
int advice_ignored_hook = 1;
|
2017-12-07 18:16:41 +03:00
|
|
|
int advice_waiting_for_editor = 1;
|
Deprecate support for .git/info/grafts
The grafts feature was a convenient way to "stitch together" ancient
history to the fresh start of linux.git.
Its implementation is, however, not up to Git's standards, as there are
too many ways where it can lead to surprising and unwelcome behavior.
For example, when pushing from a repository with active grafts, it is
possible to miss commits that have been "grafted out", resulting in a
broken state on the other side.
Also, the grafts feature is limited to "rewriting" commits' list of
parents, it cannot replace anything else.
The much younger feature implemented as `git replace` set out to remedy
those limitations and dangerous bugs.
Seeing as `git replace` is pretty mature by now (since 4228e8bc98
(replace: add --graft option, 2014-07-19) it can perform the graft
file's duties), it is time to deprecate support for the graft file, and
to retire it eventually.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Reviewed-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-29 01:44:44 +03:00
|
|
|
int advice_graft_file_deprecated = 1;
|
checkout: add advice for ambiguous "checkout <branch>"
As the "checkout" documentation describes:
If <branch> is not found but there does exist a tracking branch in
exactly one remote (call it <remote>) with a matching name, treat
as equivalent to [...] <remote>/<branch.
This is a really useful feature. The problem is that when you add
another remote (e.g. a fork), git won't find a unique branch name
anymore, and will instead print this unhelpful message:
$ git checkout master
error: pathspec 'master' did not match any file(s) known to git
Now it will, on my git.git checkout, print:
$ ./git --exec-path=$PWD checkout master
error: pathspec 'master' did not match any file(s) known to git.
hint: 'master' matched more than one remote tracking branch.
hint: We found 26 remotes with a reference that matched. So we fell back
hint: on trying to resolve the argument as a path, but failed there too!
hint:
hint: If you meant to check out a remote tracking branch on, e.g. 'origin',
hint: you can do so by fully qualifying the name with the --track option:
hint:
hint: git checkout --track origin/<name>
Note that the "error: pathspec[...]" message is still printed. This is
because whatever else checkout may have tried earlier, its final
fallback is to try to resolve the argument as a path. E.g. in this
case:
$ ./git --exec-path=$PWD checkout master pu
error: pathspec 'master' did not match any file(s) known to git.
error: pathspec 'pu' did not match any file(s) known to git.
There we don't print the "hint:" implicitly due to earlier logic
around the DWIM fallback. That fallback is only used if it looks like
we have one argument that might be a branch.
I can't think of an intrinsic reason for why we couldn't in some
future change skip printing the "error: pathspec[...]" error. However,
to do so we'd need to pass something down to checkout_paths() to make
it suppress printing an error on its own, and for us to be confident
that we're not silencing cases where those errors are meaningful.
I don't think that's worth it since determining whether that's the
case could easily change due to future changes in the checkout logic.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-05 17:40:48 +03:00
|
|
|
int advice_checkout_ambiguous_remote_branch_name = 1;
|
2019-12-02 22:57:52 +03:00
|
|
|
int advice_submodule_alternate_error_strategy_die = 1;
|
2020-02-06 13:57:30 +03:00
|
|
|
int advice_add_ignored_file = 1;
|
|
|
|
int advice_add_empty_pathspec = 1;
|
2009-09-09 15:38:58 +04:00
|
|
|
|
2018-04-21 13:10:00 +03:00
|
|
|
static int advice_use_color = -1;
|
|
|
|
static char advice_colors[][COLOR_MAXLEN] = {
|
|
|
|
GIT_COLOR_RESET,
|
|
|
|
GIT_COLOR_YELLOW, /* HINT */
|
|
|
|
};
|
|
|
|
|
|
|
|
enum color_advice {
|
|
|
|
ADVICE_COLOR_RESET = 0,
|
|
|
|
ADVICE_COLOR_HINT = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int parse_advise_color_slot(const char *slot)
|
|
|
|
{
|
|
|
|
if (!strcasecmp(slot, "reset"))
|
|
|
|
return ADVICE_COLOR_RESET;
|
|
|
|
if (!strcasecmp(slot, "hint"))
|
|
|
|
return ADVICE_COLOR_HINT;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *advise_get_color(enum color_advice ix)
|
|
|
|
{
|
|
|
|
if (want_color_stderr(advice_use_color))
|
|
|
|
return advice_colors[ix];
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2009-09-09 15:38:58 +04:00
|
|
|
static struct {
|
|
|
|
const char *name;
|
|
|
|
int *preference;
|
|
|
|
} advice_config[] = {
|
2019-06-18 23:25:27 +03:00
|
|
|
{ "fetchShowForcedUpdates", &advice_fetch_show_forced_updates },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "pushUpdateRejected", &advice_push_update_rejected },
|
|
|
|
{ "pushNonFFCurrent", &advice_push_non_ff_current },
|
|
|
|
{ "pushNonFFMatching", &advice_push_non_ff_matching },
|
|
|
|
{ "pushAlreadyExists", &advice_push_already_exists },
|
|
|
|
{ "pushFetchFirst", &advice_push_fetch_first },
|
|
|
|
{ "pushNeedsForce", &advice_push_needs_force },
|
push: add an advice on unqualified <dst> push
Add an advice to the recently improved error message added in
f8aae12034 ("push: allow unqualified dest refspecs to DWIM",
2008-04-23).
Now with advice.pushUnqualifiedRefName=true (on by default) we show a
hint about how to proceed:
$ ./git-push avar v2.19.0^{commit}:newbranch -n
error: The destination you provided is not a full refname (i.e.,
starting with "refs/"). We tried to guess what you meant by:
- Looking for a ref that matches 'newbranch' on the remote side.
- Checking if the <src> being pushed ('v2.19.0^{commit}')
is a ref in "refs/{heads,tags}/". If so we add a corresponding
refs/{heads,tags}/ prefix on the remote side.
Neither worked, so we gave up. You must fully qualify the ref.
hint: The <src> part of the refspec is a commit object.
hint: Did you mean to create a new branch by pushing to
hint: 'v2.19.0^{commit}:refs/heads/newbranch'?
error: failed to push some refs to 'git@github.com:avar/git.git'
When trying to push a tag, tree or a blob we suggest that perhaps the
user meant to push them to refs/tags/ instead.
The if/else duplication for all of OBJ_{COMMIT,TAG,TREE,BLOB} is
unfortunate, but is required to correctly mark the messages for
translation. See the discussion in
<87r2gxebsi.fsf@evledraar.gmail.com> about that.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-13 22:52:43 +03:00
|
|
|
{ "pushUnqualifiedRefName", &advice_push_unqualified_ref_name },
|
2020-10-03 15:10:45 +03:00
|
|
|
{ "pushRefNeedsUpdate", &advice_push_ref_needs_update },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "statusHints", &advice_status_hints },
|
|
|
|
{ "statusUoption", &advice_status_u_option },
|
2019-06-18 23:21:27 +03:00
|
|
|
{ "statusAheadBehindWarning", &advice_status_ahead_behind_warning },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "commitBeforeMerge", &advice_commit_before_merge },
|
2018-10-23 22:04:23 +03:00
|
|
|
{ "resetQuiet", &advice_reset_quiet_warning },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "resolveConflict", &advice_resolve_conflict },
|
2019-07-02 12:11:25 +03:00
|
|
|
{ "sequencerInUse", &advice_sequencer_in_use },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "implicitIdentity", &advice_implicit_identity },
|
|
|
|
{ "detachedHead", &advice_detached_head },
|
2020-03-02 23:01:58 +03:00
|
|
|
{ "setUpstreamFailure", &advice_set_upstream_failure },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "objectNameWarning", &advice_object_name_warning },
|
2018-05-26 16:55:27 +03:00
|
|
|
{ "amWorkDir", &advice_amworkdir },
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "rmHints", &advice_rm_hints },
|
|
|
|
{ "addEmbeddedRepo", &advice_add_embedded_repo },
|
|
|
|
{ "ignoredHook", &advice_ignored_hook },
|
|
|
|
{ "waitingForEditor", &advice_waiting_for_editor },
|
|
|
|
{ "graftFileDeprecated", &advice_graft_file_deprecated },
|
2018-08-03 01:30:41 +03:00
|
|
|
{ "checkoutAmbiguousRemoteBranchName", &advice_checkout_ambiguous_remote_branch_name },
|
2019-12-02 22:57:52 +03:00
|
|
|
{ "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
|
2020-02-06 13:57:30 +03:00
|
|
|
{ "addIgnoredFile", &advice_add_ignored_file },
|
|
|
|
{ "addEmptyPathspec", &advice_add_empty_pathspec },
|
2012-12-03 07:27:50 +04:00
|
|
|
|
|
|
|
/* make this an alias for backward compatibility */
|
2018-05-26 16:55:26 +03:00
|
|
|
{ "pushNonFastForward", &advice_push_update_rejected }
|
2009-09-09 15:38:58 +04:00
|
|
|
};
|
|
|
|
|
2020-03-02 23:01:59 +03:00
|
|
|
static struct {
|
|
|
|
const char *key;
|
|
|
|
int enabled;
|
|
|
|
} advice_setting[] = {
|
|
|
|
[ADVICE_ADD_EMBEDDED_REPO] = { "addEmbeddedRepo", 1 },
|
|
|
|
[ADVICE_AM_WORK_DIR] = { "amWorkDir", 1 },
|
|
|
|
[ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName", 1 },
|
|
|
|
[ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge", 1 },
|
|
|
|
[ADVICE_DETACHED_HEAD] = { "detachedHead", 1 },
|
|
|
|
[ADVICE_FETCH_SHOW_FORCED_UPDATES] = { "fetchShowForcedUpdates", 1 },
|
|
|
|
[ADVICE_GRAFT_FILE_DEPRECATED] = { "graftFileDeprecated", 1 },
|
|
|
|
[ADVICE_IGNORED_HOOK] = { "ignoredHook", 1 },
|
|
|
|
[ADVICE_IMPLICIT_IDENTITY] = { "implicitIdentity", 1 },
|
|
|
|
[ADVICE_NESTED_TAG] = { "nestedTag", 1 },
|
|
|
|
[ADVICE_OBJECT_NAME_WARNING] = { "objectNameWarning", 1 },
|
|
|
|
[ADVICE_PUSH_ALREADY_EXISTS] = { "pushAlreadyExists", 1 },
|
|
|
|
[ADVICE_PUSH_FETCH_FIRST] = { "pushFetchFirst", 1 },
|
|
|
|
[ADVICE_PUSH_NEEDS_FORCE] = { "pushNeedsForce", 1 },
|
2020-10-03 15:10:45 +03:00
|
|
|
[ADVICE_PUSH_REF_NEEDS_UPDATE] = { "pushRefNeedsUpdate", 1 },
|
2020-03-02 23:01:59 +03:00
|
|
|
|
|
|
|
/* make this an alias for backward compatibility */
|
|
|
|
[ADVICE_PUSH_UPDATE_REJECTED_ALIAS] = { "pushNonFastForward", 1 },
|
|
|
|
|
|
|
|
[ADVICE_PUSH_NON_FF_CURRENT] = { "pushNonFFCurrent", 1 },
|
|
|
|
[ADVICE_PUSH_NON_FF_MATCHING] = { "pushNonFFMatching", 1 },
|
|
|
|
[ADVICE_PUSH_UNQUALIFIED_REF_NAME] = { "pushUnqualifiedRefName", 1 },
|
|
|
|
[ADVICE_PUSH_UPDATE_REJECTED] = { "pushUpdateRejected", 1 },
|
|
|
|
[ADVICE_RESET_QUIET_WARNING] = { "resetQuiet", 1 },
|
|
|
|
[ADVICE_RESOLVE_CONFLICT] = { "resolveConflict", 1 },
|
|
|
|
[ADVICE_RM_HINTS] = { "rmHints", 1 },
|
|
|
|
[ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse", 1 },
|
|
|
|
[ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure", 1 },
|
|
|
|
[ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning", 1 },
|
|
|
|
[ADVICE_STATUS_HINTS] = { "statusHints", 1 },
|
|
|
|
[ADVICE_STATUS_U_OPTION] = { "statusUoption", 1 },
|
|
|
|
[ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 },
|
|
|
|
[ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char turn_off_instructions[] =
|
|
|
|
N_("\n"
|
|
|
|
"Disable this message with \"git config advice.%s false\"");
|
|
|
|
|
|
|
|
static void vadvise(const char *advice, int display_instructions,
|
|
|
|
const char *key, va_list params)
|
2011-08-04 14:38:59 +04:00
|
|
|
{
|
i18n of multi-line advice messages
Advice messages are by definition meant for human end-users, and prime
candidates for i18n/l10n. They tend to also be more verbose to be helpful,
and need to be longer than just one line.
Although we do not have parameterized multi-line advice messages yet, once
we do, we cannot emit such a message like this:
advise(_("Please rename %s to something else"), gostak);
advise(_("so that we can avoid distimming %s unnecessarily."), doshes);
because some translations may need to have the replacement of 'gostak' on
the second line (or 'doshes' on the first line). Some languages may even
need to use three lines in order to fit the same message within a
reasonable width.
Instead, it has to be a single advise() construct, like this:
advise(_("Please rename %s to something else\n"
"so that we can avoid distimming %s unnecessarily."),
gostak, doshes);
Update the advise() function and its existing callers to
- take a format string that can be multi-line and translatable as a
whole;
- use the string and the parameters to form a localized message; and
- show each line in the result with the localization of the "hint: ".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-22 23:21:26 +04:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
const char *cp, *np;
|
2011-08-04 14:38:59 +04:00
|
|
|
|
2012-07-23 22:48:57 +04:00
|
|
|
strbuf_vaddf(&buf, advice, params);
|
i18n of multi-line advice messages
Advice messages are by definition meant for human end-users, and prime
candidates for i18n/l10n. They tend to also be more verbose to be helpful,
and need to be longer than just one line.
Although we do not have parameterized multi-line advice messages yet, once
we do, we cannot emit such a message like this:
advise(_("Please rename %s to something else"), gostak);
advise(_("so that we can avoid distimming %s unnecessarily."), doshes);
because some translations may need to have the replacement of 'gostak' on
the second line (or 'doshes' on the first line). Some languages may even
need to use three lines in order to fit the same message within a
reasonable width.
Instead, it has to be a single advise() construct, like this:
advise(_("Please rename %s to something else\n"
"so that we can avoid distimming %s unnecessarily."),
gostak, doshes);
Update the advise() function and its existing callers to
- take a format string that can be multi-line and translatable as a
whole;
- use the string and the parameters to form a localized message; and
- show each line in the result with the localization of the "hint: ".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-22 23:21:26 +04:00
|
|
|
|
2020-03-02 23:01:59 +03:00
|
|
|
if (display_instructions)
|
|
|
|
strbuf_addf(&buf, turn_off_instructions, key);
|
i18n of multi-line advice messages
Advice messages are by definition meant for human end-users, and prime
candidates for i18n/l10n. They tend to also be more verbose to be helpful,
and need to be longer than just one line.
Although we do not have parameterized multi-line advice messages yet, once
we do, we cannot emit such a message like this:
advise(_("Please rename %s to something else"), gostak);
advise(_("so that we can avoid distimming %s unnecessarily."), doshes);
because some translations may need to have the replacement of 'gostak' on
the second line (or 'doshes' on the first line). Some languages may even
need to use three lines in order to fit the same message within a
reasonable width.
Instead, it has to be a single advise() construct, like this:
advise(_("Please rename %s to something else\n"
"so that we can avoid distimming %s unnecessarily."),
gostak, doshes);
Update the advise() function and its existing callers to
- take a format string that can be multi-line and translatable as a
whole;
- use the string and the parameters to form a localized message; and
- show each line in the result with the localization of the "hint: ".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-22 23:21:26 +04:00
|
|
|
|
|
|
|
for (cp = buf.buf; *cp; cp = np) {
|
|
|
|
np = strchrnul(cp, '\n');
|
2018-04-21 13:10:00 +03:00
|
|
|
fprintf(stderr, _("%shint: %.*s%s\n"),
|
|
|
|
advise_get_color(ADVICE_COLOR_HINT),
|
|
|
|
(int)(np - cp), cp,
|
|
|
|
advise_get_color(ADVICE_COLOR_RESET));
|
i18n of multi-line advice messages
Advice messages are by definition meant for human end-users, and prime
candidates for i18n/l10n. They tend to also be more verbose to be helpful,
and need to be longer than just one line.
Although we do not have parameterized multi-line advice messages yet, once
we do, we cannot emit such a message like this:
advise(_("Please rename %s to something else"), gostak);
advise(_("so that we can avoid distimming %s unnecessarily."), doshes);
because some translations may need to have the replacement of 'gostak' on
the second line (or 'doshes' on the first line). Some languages may even
need to use three lines in order to fit the same message within a
reasonable width.
Instead, it has to be a single advise() construct, like this:
advise(_("Please rename %s to something else\n"
"so that we can avoid distimming %s unnecessarily."),
gostak, doshes);
Update the advise() function and its existing callers to
- take a format string that can be multi-line and translatable as a
whole;
- use the string and the parameters to form a localized message; and
- show each line in the result with the localization of the "hint: ".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-22 23:21:26 +04:00
|
|
|
if (*np)
|
|
|
|
np++;
|
|
|
|
}
|
|
|
|
strbuf_release(&buf);
|
2011-08-04 14:38:59 +04:00
|
|
|
}
|
|
|
|
|
2020-03-02 23:01:57 +03:00
|
|
|
void advise(const char *advice, ...)
|
|
|
|
{
|
|
|
|
va_list params;
|
|
|
|
va_start(params, advice);
|
2020-03-02 23:01:59 +03:00
|
|
|
vadvise(advice, 0, "", params);
|
|
|
|
va_end(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
int advice_enabled(enum advice_type type)
|
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
case ADVICE_PUSH_UPDATE_REJECTED:
|
|
|
|
return advice_setting[ADVICE_PUSH_UPDATE_REJECTED].enabled &&
|
|
|
|
advice_setting[ADVICE_PUSH_UPDATE_REJECTED_ALIAS].enabled;
|
|
|
|
default:
|
|
|
|
return advice_setting[type].enabled;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void advise_if_enabled(enum advice_type type, const char *advice, ...)
|
|
|
|
{
|
|
|
|
va_list params;
|
|
|
|
|
|
|
|
if (!advice_enabled(type))
|
|
|
|
return;
|
|
|
|
|
|
|
|
va_start(params, advice);
|
|
|
|
vadvise(advice, 1, advice_setting[type].key, params);
|
2020-03-02 23:01:57 +03:00
|
|
|
va_end(params);
|
|
|
|
}
|
|
|
|
|
2009-09-09 15:38:58 +04:00
|
|
|
int git_default_advice_config(const char *var, const char *value)
|
|
|
|
{
|
2018-04-21 13:10:00 +03:00
|
|
|
const char *k, *slot_name;
|
2009-09-09 15:38:58 +04:00
|
|
|
int i;
|
|
|
|
|
2018-04-21 13:10:00 +03:00
|
|
|
if (!strcmp(var, "color.advice")) {
|
|
|
|
advice_use_color = git_config_colorbool(var, value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skip_prefix(var, "color.advice.", &slot_name)) {
|
|
|
|
int slot = parse_advise_color_slot(slot_name);
|
|
|
|
if (slot < 0)
|
|
|
|
return 0;
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
|
|
|
return color_parse(value, advice_colors[slot]);
|
|
|
|
}
|
|
|
|
|
refactor skip_prefix to return a boolean
The skip_prefix() function returns a pointer to the content
past the prefix, or NULL if the prefix was not found. While
this is nice and simple, in practice it makes it hard to use
for two reasons:
1. When you want to conditionally skip or keep the string
as-is, you have to introduce a temporary variable.
For example:
tmp = skip_prefix(buf, "foo");
if (tmp)
buf = tmp;
2. It is verbose to check the outcome in a conditional, as
you need extra parentheses to silence compiler
warnings. For example:
if ((cp = skip_prefix(buf, "foo"))
/* do something with cp */
Both of these make it harder to use for long if-chains, and
we tend to use starts_with() instead. However, the first line
of "do something" is often to then skip forward in buf past
the prefix, either using a magic constant or with an extra
strlen(3) (which is generally computed at compile time, but
means we are repeating ourselves).
This patch refactors skip_prefix() to return a simple boolean,
and to provide the pointer value as an out-parameter. If the
prefix is not found, the out-parameter is untouched. This
lets you write:
if (skip_prefix(arg, "foo ", &arg))
do_foo(arg);
else if (skip_prefix(arg, "bar ", &arg))
do_bar(arg);
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-18 23:44:19 +04:00
|
|
|
if (!skip_prefix(var, "advice.", &k))
|
|
|
|
return 0;
|
|
|
|
|
2009-09-09 15:38:58 +04:00
|
|
|
for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
|
2018-05-26 16:55:26 +03:00
|
|
|
if (strcasecmp(k, advice_config[i].name))
|
2009-09-09 15:38:58 +04:00
|
|
|
continue;
|
|
|
|
*advice_config[i].preference = git_config_bool(var, value);
|
2020-03-02 23:01:59 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(advice_setting); i++) {
|
|
|
|
if (strcasecmp(k, advice_setting[i].key))
|
|
|
|
continue;
|
|
|
|
advice_setting[i].enabled = git_config_bool(var, value);
|
2009-09-09 15:38:58 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
Be more user-friendly when refusing to do something because of conflict.
Various commands refuse to run in the presence of conflicts (commit,
merge, pull, cherry-pick/revert). They all used to provide rough, and
inconsistant error messages.
A new variable advice.resolveconflict is introduced, and allows more
verbose messages, pointing the user to the appropriate solution.
For commit, the error message used to look like this:
$ git commit
foo.txt: needs merge
foo.txt: unmerged (c34a92682e0394bc0d6f4d4a67a8e2d32395c169)
foo.txt: unmerged (3afcd75de8de0bb5076942fcb17446be50451030)
foo.txt: unmerged (c9785d77b76dfe4fb038bf927ee518f6ae45ede4)
error: Error building trees
The "need merge" line is given by refresh_cache. We add the IN_PORCELAIN
option to make the output more consistant with the other porcelain
commands, and catch the error in return, to stop with a clean error
message. The next lines were displayed by a call to cache_tree_update(),
which is not reached anymore if we noticed the conflict.
The new output looks like:
U foo.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.
Pull is slightly modified to abort immediately if $GIT_DIR/MERGE_HEAD
exists instead of waiting for merge to complain.
The behavior of merge and the test-case are slightly modified to reflect
the usual flow: start with conflicts, fix them, and afterwards get rid of
MERGE_HEAD, with different error messages at each stage.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-12 12:54:44 +03:00
|
|
|
|
2018-05-26 16:55:24 +03:00
|
|
|
void list_config_advices(struct string_list *list, const char *prefix)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2020-03-02 23:01:59 +03:00
|
|
|
for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
|
|
|
|
list_config_item(list, prefix, advice_setting[i].key);
|
2018-05-26 16:55:24 +03:00
|
|
|
}
|
|
|
|
|
2011-08-04 14:38:59 +04:00
|
|
|
int error_resolve_conflict(const char *me)
|
Be more user-friendly when refusing to do something because of conflict.
Various commands refuse to run in the presence of conflicts (commit,
merge, pull, cherry-pick/revert). They all used to provide rough, and
inconsistant error messages.
A new variable advice.resolveconflict is introduced, and allows more
verbose messages, pointing the user to the appropriate solution.
For commit, the error message used to look like this:
$ git commit
foo.txt: needs merge
foo.txt: unmerged (c34a92682e0394bc0d6f4d4a67a8e2d32395c169)
foo.txt: unmerged (3afcd75de8de0bb5076942fcb17446be50451030)
foo.txt: unmerged (c9785d77b76dfe4fb038bf927ee518f6ae45ede4)
error: Error building trees
The "need merge" line is given by refresh_cache. We add the IN_PORCELAIN
option to make the output more consistant with the other porcelain
commands, and catch the error in return, to stop with a clean error
message. The next lines were displayed by a call to cache_tree_update(),
which is not reached anymore if we noticed the conflict.
The new output looks like:
U foo.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.
Pull is slightly modified to abort immediately if $GIT_DIR/MERGE_HEAD
exists instead of waiting for merge to complain.
The behavior of merge and the test-case are slightly modified to reflect
the usual flow: start with conflicts, fix them, and afterwards get rid of
MERGE_HEAD, with different error messages at each stage.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-12 12:54:44 +03:00
|
|
|
{
|
2016-06-17 23:20:52 +03:00
|
|
|
if (!strcmp(me, "cherry-pick"))
|
|
|
|
error(_("Cherry-picking is not possible because you have unmerged files."));
|
|
|
|
else if (!strcmp(me, "commit"))
|
|
|
|
error(_("Committing is not possible because you have unmerged files."));
|
|
|
|
else if (!strcmp(me, "merge"))
|
|
|
|
error(_("Merging is not possible because you have unmerged files."));
|
|
|
|
else if (!strcmp(me, "pull"))
|
|
|
|
error(_("Pulling is not possible because you have unmerged files."));
|
|
|
|
else if (!strcmp(me, "revert"))
|
|
|
|
error(_("Reverting is not possible because you have unmerged files."));
|
|
|
|
else
|
|
|
|
error(_("It is not possible to %s because you have unmerged files."),
|
|
|
|
me);
|
|
|
|
|
i18n of multi-line advice messages
Advice messages are by definition meant for human end-users, and prime
candidates for i18n/l10n. They tend to also be more verbose to be helpful,
and need to be longer than just one line.
Although we do not have parameterized multi-line advice messages yet, once
we do, we cannot emit such a message like this:
advise(_("Please rename %s to something else"), gostak);
advise(_("so that we can avoid distimming %s unnecessarily."), doshes);
because some translations may need to have the replacement of 'gostak' on
the second line (or 'doshes' on the first line). Some languages may even
need to use three lines in order to fit the same message within a
reasonable width.
Instead, it has to be a single advise() construct, like this:
advise(_("Please rename %s to something else\n"
"so that we can avoid distimming %s unnecessarily."),
gostak, doshes);
Update the advise() function and its existing callers to
- take a format string that can be multi-line and translatable as a
whole;
- use the string and the parameters to form a localized message; and
- show each line in the result with the localization of the "hint: ".
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-22 23:21:26 +04:00
|
|
|
if (advice_resolve_conflict)
|
Be more user-friendly when refusing to do something because of conflict.
Various commands refuse to run in the presence of conflicts (commit,
merge, pull, cherry-pick/revert). They all used to provide rough, and
inconsistant error messages.
A new variable advice.resolveconflict is introduced, and allows more
verbose messages, pointing the user to the appropriate solution.
For commit, the error message used to look like this:
$ git commit
foo.txt: needs merge
foo.txt: unmerged (c34a92682e0394bc0d6f4d4a67a8e2d32395c169)
foo.txt: unmerged (3afcd75de8de0bb5076942fcb17446be50451030)
foo.txt: unmerged (c9785d77b76dfe4fb038bf927ee518f6ae45ede4)
error: Error building trees
The "need merge" line is given by refresh_cache. We add the IN_PORCELAIN
option to make the output more consistant with the other porcelain
commands, and catch the error in return, to stop with a clean error
message. The next lines were displayed by a call to cache_tree_update(),
which is not reached anymore if we noticed the conflict.
The new output looks like:
U foo.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.
Pull is slightly modified to abort immediately if $GIT_DIR/MERGE_HEAD
exists instead of waiting for merge to complain.
The behavior of merge and the test-case are slightly modified to reflect
the usual flow: start with conflicts, fix them, and afterwards get rid of
MERGE_HEAD, with different error messages at each stage.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-12 12:54:44 +03:00
|
|
|
/*
|
|
|
|
* Message used both when 'git commit' fails and when
|
|
|
|
* other commands doing a merge do.
|
|
|
|
*/
|
2014-06-03 11:17:17 +04:00
|
|
|
advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
|
merge, pull: stop advising 'commit -a' in case of conflict
'git commit -a' is rarely a good way to mark conflicts as resolved:
the user anyway has to go manually through the list of conflicts to
do the actual resolution, and it is usually better to use "git add"
on each files after doing the resolution.
On the other hand, using 'git commit -a' is potentially dangerous,
as it makes it very easy to mistakenly commit conflict markers
without noticing, and even worse, the user may have started a merge
while having local changes that do not overlap with it in the
working tree.
While we're there, synchronize the 'git pull' and 'git merge'
messages: the first was ending with '... and make a commit.', but
not the latter.
Eventually, git should detect that conflicts have been resolved in
the working tree and tailor these messages further. Not only "use
git commit -a" could be resurected, but "Fix them up in the work
tree" should be dropped when it happens.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-28 13:46:58 +04:00
|
|
|
"as appropriate to mark resolution and make a commit."));
|
2011-08-04 14:38:59 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NORETURN die_resolve_conflict(const char *me)
|
|
|
|
{
|
|
|
|
error_resolve_conflict(me);
|
2016-06-17 23:20:52 +03:00
|
|
|
die(_("Exiting because of an unresolved conflict."));
|
Be more user-friendly when refusing to do something because of conflict.
Various commands refuse to run in the presence of conflicts (commit,
merge, pull, cherry-pick/revert). They all used to provide rough, and
inconsistant error messages.
A new variable advice.resolveconflict is introduced, and allows more
verbose messages, pointing the user to the appropriate solution.
For commit, the error message used to look like this:
$ git commit
foo.txt: needs merge
foo.txt: unmerged (c34a92682e0394bc0d6f4d4a67a8e2d32395c169)
foo.txt: unmerged (3afcd75de8de0bb5076942fcb17446be50451030)
foo.txt: unmerged (c9785d77b76dfe4fb038bf927ee518f6ae45ede4)
error: Error building trees
The "need merge" line is given by refresh_cache. We add the IN_PORCELAIN
option to make the output more consistant with the other porcelain
commands, and catch the error in return, to stop with a clean error
message. The next lines were displayed by a call to cache_tree_update(),
which is not reached anymore if we noticed the conflict.
The new output looks like:
U foo.txt
fatal: 'commit' is not possible because you have unmerged files.
Please, fix them up in the work tree, and then use 'git add/rm <file>' as
appropriate to mark resolution and make a commit, or use 'git commit -a'.
Pull is slightly modified to abort immediately if $GIT_DIR/MERGE_HEAD
exists instead of waiting for merge to complain.
The behavior of merge and the test-case are slightly modified to reflect
the usual flow: start with conflicts, fix them, and afterwards get rid of
MERGE_HEAD, with different error messages at each stage.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-12 12:54:44 +03:00
|
|
|
}
|
2012-01-16 13:46:16 +04:00
|
|
|
|
2015-06-18 13:54:04 +03:00
|
|
|
void NORETURN die_conclude_merge(void)
|
|
|
|
{
|
|
|
|
error(_("You have not concluded your merge (MERGE_HEAD exists)."));
|
|
|
|
if (advice_resolve_conflict)
|
2015-10-02 07:25:33 +03:00
|
|
|
advise(_("Please, commit your changes before merging."));
|
2015-06-18 13:54:04 +03:00
|
|
|
die(_("Exiting because of unfinished merge."));
|
|
|
|
}
|
|
|
|
|
2012-01-16 13:46:16 +04:00
|
|
|
void detach_advice(const char *new_name)
|
|
|
|
{
|
2016-06-17 23:20:51 +03:00
|
|
|
const char *fmt =
|
2019-03-29 13:39:19 +03:00
|
|
|
_("Note: switching to '%s'.\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
2012-01-16 13:46:16 +04:00
|
|
|
"You are in 'detached HEAD' state. You can look around, make experimental\n"
|
|
|
|
"changes and commit them, and you can discard any commits you make in this\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
"state without impacting any branches by switching back to a branch.\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
2012-01-16 13:46:16 +04:00
|
|
|
"If you want to create a new branch to retain commits you create, you may\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
"do so (now or later) by using -c with the switch command. Example:\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
" git switch -c <new-branch-name>\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
"Or undo this operation with:\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
2019-03-29 13:39:19 +03:00
|
|
|
" git switch -\n"
|
2019-03-29 13:38:58 +03:00
|
|
|
"\n"
|
|
|
|
"Turn off this advice by setting config variable advice.detachedHead to false\n\n");
|
2012-01-16 13:46:16 +04:00
|
|
|
|
|
|
|
fprintf(stderr, fmt, new_name);
|
|
|
|
}
|