mirror of
https://github.com/git/git.git
synced 2024-11-27 12:03:55 +08:00
Merge branch 'hw/advise-ng'
Revamping of the advise API to allow more systematic enumeration of advice knobs in the future. * hw/advise-ng: tag: use new advice API to check visibility advice: revamp advise API advice: change "setupStreamFailure" to "setUpstreamFailure" advice: extract vadvise() from advise()
This commit is contained in:
commit
c4a09cc9cc
1
Makefile
1
Makefile
@ -695,6 +695,7 @@ X =
|
||||
|
||||
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
|
||||
|
||||
TEST_BUILTINS_OBJS += test-advise.o
|
||||
TEST_BUILTINS_OBJS += test-chmtime.o
|
||||
TEST_BUILTINS_OBJS += test-config.o
|
||||
TEST_BUILTINS_OBJS += test-ctype.o
|
||||
|
97
advice.c
97
advice.c
@ -29,7 +29,6 @@ int advice_ignored_hook = 1;
|
||||
int advice_waiting_for_editor = 1;
|
||||
int advice_graft_file_deprecated = 1;
|
||||
int advice_checkout_ambiguous_remote_branch_name = 1;
|
||||
int advice_nested_tag = 1;
|
||||
int advice_submodule_alternate_error_strategy_die = 1;
|
||||
int advice_add_ignored_file = 1;
|
||||
int advice_add_empty_pathspec = 1;
|
||||
@ -82,7 +81,7 @@ static struct {
|
||||
{ "sequencerInUse", &advice_sequencer_in_use },
|
||||
{ "implicitIdentity", &advice_implicit_identity },
|
||||
{ "detachedHead", &advice_detached_head },
|
||||
{ "setupStreamFailure", &advice_set_upstream_failure },
|
||||
{ "setUpstreamFailure", &advice_set_upstream_failure },
|
||||
{ "objectNameWarning", &advice_object_name_warning },
|
||||
{ "amWorkDir", &advice_amworkdir },
|
||||
{ "rmHints", &advice_rm_hints },
|
||||
@ -91,7 +90,6 @@ static struct {
|
||||
{ "waitingForEditor", &advice_waiting_for_editor },
|
||||
{ "graftFileDeprecated", &advice_graft_file_deprecated },
|
||||
{ "checkoutAmbiguousRemoteBranchName", &advice_checkout_ambiguous_remote_branch_name },
|
||||
{ "nestedTag", &advice_nested_tag },
|
||||
{ "submoduleAlternateErrorStrategyDie", &advice_submodule_alternate_error_strategy_die },
|
||||
{ "addIgnoredFile", &advice_add_ignored_file },
|
||||
{ "addEmptyPathspec", &advice_add_empty_pathspec },
|
||||
@ -100,15 +98,58 @@ static struct {
|
||||
{ "pushNonFastForward", &advice_push_update_rejected }
|
||||
};
|
||||
|
||||
void advise(const char *advice, ...)
|
||||
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 },
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
va_list params;
|
||||
const char *cp, *np;
|
||||
|
||||
va_start(params, advice);
|
||||
strbuf_vaddf(&buf, advice, params);
|
||||
va_end(params);
|
||||
|
||||
if (display_instructions)
|
||||
strbuf_addf(&buf, turn_off_instructions, key);
|
||||
|
||||
for (cp = buf.buf; *cp; cp = np) {
|
||||
np = strchrnul(cp, '\n');
|
||||
@ -122,6 +163,37 @@ void advise(const char *advice, ...)
|
||||
strbuf_release(&buf);
|
||||
}
|
||||
|
||||
void advise(const char *advice, ...)
|
||||
{
|
||||
va_list params;
|
||||
va_start(params, advice);
|
||||
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);
|
||||
va_end(params);
|
||||
}
|
||||
|
||||
int git_default_advice_config(const char *var, const char *value)
|
||||
{
|
||||
const char *k, *slot_name;
|
||||
@ -148,6 +220,13 @@ int git_default_advice_config(const char *var, const char *value)
|
||||
if (strcasecmp(k, advice_config[i].name))
|
||||
continue;
|
||||
*advice_config[i].preference = git_config_bool(var, value);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -158,8 +237,8 @@ void list_config_advices(struct string_list *list, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(advice_config); i++)
|
||||
list_config_item(list, prefix, advice_config[i].name);
|
||||
for (i = 0; i < ARRAY_SIZE(advice_setting); i++)
|
||||
list_config_item(list, prefix, advice_setting[i].key);
|
||||
}
|
||||
|
||||
int error_resolve_conflict(const char *me)
|
||||
|
52
advice.h
52
advice.h
@ -29,14 +29,64 @@ extern int advice_ignored_hook;
|
||||
extern int advice_waiting_for_editor;
|
||||
extern int advice_graft_file_deprecated;
|
||||
extern int advice_checkout_ambiguous_remote_branch_name;
|
||||
extern int advice_nested_tag;
|
||||
extern int advice_submodule_alternate_error_strategy_die;
|
||||
extern int advice_add_ignored_file;
|
||||
extern int advice_add_empty_pathspec;
|
||||
|
||||
/*
|
||||
* To add a new advice, you need to:
|
||||
* Define a new advice_type.
|
||||
* Add a new entry to advice_setting array.
|
||||
* Add the new config variable to Documentation/config/advice.txt.
|
||||
* Call advise_if_enabled to print your advice.
|
||||
*/
|
||||
enum advice_type {
|
||||
ADVICE_ADD_EMBEDDED_REPO,
|
||||
ADVICE_AM_WORK_DIR,
|
||||
ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
|
||||
ADVICE_COMMIT_BEFORE_MERGE,
|
||||
ADVICE_DETACHED_HEAD,
|
||||
ADVICE_FETCH_SHOW_FORCED_UPDATES,
|
||||
ADVICE_GRAFT_FILE_DEPRECATED,
|
||||
ADVICE_IGNORED_HOOK,
|
||||
ADVICE_IMPLICIT_IDENTITY,
|
||||
ADVICE_NESTED_TAG,
|
||||
ADVICE_OBJECT_NAME_WARNING,
|
||||
ADVICE_PUSH_ALREADY_EXISTS,
|
||||
ADVICE_PUSH_FETCH_FIRST,
|
||||
ADVICE_PUSH_NEEDS_FORCE,
|
||||
ADVICE_PUSH_NON_FF_CURRENT,
|
||||
ADVICE_PUSH_NON_FF_MATCHING,
|
||||
ADVICE_PUSH_UNQUALIFIED_REF_NAME,
|
||||
ADVICE_PUSH_UPDATE_REJECTED_ALIAS,
|
||||
ADVICE_PUSH_UPDATE_REJECTED,
|
||||
ADVICE_RESET_QUIET_WARNING,
|
||||
ADVICE_RESOLVE_CONFLICT,
|
||||
ADVICE_RM_HINTS,
|
||||
ADVICE_SEQUENCER_IN_USE,
|
||||
ADVICE_SET_UPSTREAM_FAILURE,
|
||||
ADVICE_STATUS_AHEAD_BEHIND_WARNING,
|
||||
ADVICE_STATUS_HINTS,
|
||||
ADVICE_STATUS_U_OPTION,
|
||||
ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE,
|
||||
ADVICE_WAITING_FOR_EDITOR,
|
||||
};
|
||||
|
||||
int git_default_advice_config(const char *var, const char *value);
|
||||
__attribute__((format (printf, 1, 2)))
|
||||
void advise(const char *advice, ...);
|
||||
|
||||
/**
|
||||
* Checks if advice type is enabled (can be printed to the user).
|
||||
* Should be called before advise().
|
||||
*/
|
||||
int advice_enabled(enum advice_type type);
|
||||
|
||||
/**
|
||||
* Checks the visibility of the advice before printing.
|
||||
*/
|
||||
void advise_if_enabled(enum advice_type type, const char *advice, ...);
|
||||
|
||||
int error_resolve_conflict(const char *me);
|
||||
void NORETURN die_resolve_conflict(const char *me);
|
||||
void NORETURN die_conclude_merge(void);
|
||||
|
@ -231,8 +231,9 @@ static void create_tag(const struct object_id *object, const char *object_ref,
|
||||
if (type <= OBJ_NONE)
|
||||
die(_("bad object type."));
|
||||
|
||||
if (type == OBJ_TAG && advice_nested_tag)
|
||||
advise(_(message_advice_nested_tag), tag, object_ref);
|
||||
if (type == OBJ_TAG)
|
||||
advise_if_enabled(ADVICE_NESTED_TAG, _(message_advice_nested_tag),
|
||||
tag, object_ref);
|
||||
|
||||
strbuf_addf(&header,
|
||||
"object %s\n"
|
||||
|
22
t/helper/test-advise.c
Normal file
22
t/helper/test-advise.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "test-tool.h"
|
||||
#include "cache.h"
|
||||
#include "advice.h"
|
||||
#include "config.h"
|
||||
|
||||
int cmd__advise_if_enabled(int argc, const char **argv)
|
||||
{
|
||||
if (!argv[1])
|
||||
die("usage: %s <advice>", argv[0]);
|
||||
|
||||
setup_git_directory();
|
||||
git_config(git_default_config, NULL);
|
||||
|
||||
/*
|
||||
* Any advice type can be used for testing, but NESTED_TAG was
|
||||
* selected here and in t0018 where this command is being
|
||||
* executed.
|
||||
*/
|
||||
advise_if_enabled(ADVICE_NESTED_TAG, argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
@ -14,6 +14,7 @@ struct test_cmd {
|
||||
};
|
||||
|
||||
static struct test_cmd cmds[] = {
|
||||
{ "advise", cmd__advise_if_enabled },
|
||||
{ "chmtime", cmd__chmtime },
|
||||
{ "config", cmd__config },
|
||||
{ "ctype", cmd__ctype },
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define USE_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "git-compat-util.h"
|
||||
|
||||
int cmd__advise_if_enabled(int argc, const char **argv);
|
||||
int cmd__chmtime(int argc, const char **argv);
|
||||
int cmd__config(int argc, const char **argv);
|
||||
int cmd__ctype(int argc, const char **argv);
|
||||
|
32
t/t0018-advice.sh
Executable file
32
t/t0018-advice.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='Test advise_if_enabled functionality'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'advice should be printed when config variable is unset' '
|
||||
cat >expect <<-\EOF &&
|
||||
hint: This is a piece of advice
|
||||
hint: Disable this message with "git config advice.nestedTag false"
|
||||
EOF
|
||||
test-tool advise "This is a piece of advice" 2>actual &&
|
||||
test_i18ncmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'advice should be printed when config variable is set to true' '
|
||||
cat >expect <<-\EOF &&
|
||||
hint: This is a piece of advice
|
||||
hint: Disable this message with "git config advice.nestedTag false"
|
||||
EOF
|
||||
test_config advice.nestedTag true &&
|
||||
test-tool advise "This is a piece of advice" 2>actual &&
|
||||
test_i18ncmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'advice should not be printed when config variable is set to false' '
|
||||
test_config advice.nestedTag false &&
|
||||
test-tool advise "This is a piece of advice" 2>actual &&
|
||||
test_must_be_empty actual
|
||||
'
|
||||
|
||||
test_done
|
@ -1726,6 +1726,7 @@ test_expect_success 'recursive tagging should give advice' '
|
||||
hint: already a tag. If you meant to tag the object that it points to, use:
|
||||
hint: |
|
||||
hint: git tag -f nested annotated-v4.0^{}
|
||||
hint: Disable this message with "git config advice.nestedTag false"
|
||||
EOF
|
||||
git tag -m nested nested annotated-v4.0 2>actual &&
|
||||
test_i18ncmp expect actual
|
||||
|
Loading…
Reference in New Issue
Block a user