advice.con commit t2024: mark test using "checkout -p" with PERL prerequisite (3338e99)
   1#include "cache.h"
   2#include "config.h"
   3#include "color.h"
   4
   5int advice_push_update_rejected = 1;
   6int advice_push_non_ff_current = 1;
   7int advice_push_non_ff_matching = 1;
   8int advice_push_already_exists = 1;
   9int advice_push_fetch_first = 1;
  10int advice_push_needs_force = 1;
  11int advice_status_hints = 1;
  12int advice_status_u_option = 1;
  13int advice_commit_before_merge = 1;
  14int advice_resolve_conflict = 1;
  15int advice_implicit_identity = 1;
  16int advice_detached_head = 1;
  17int advice_set_upstream_failure = 1;
  18int advice_object_name_warning = 1;
  19int advice_rm_hints = 1;
  20int advice_add_embedded_repo = 1;
  21int advice_ignored_hook = 1;
  22int advice_waiting_for_editor = 1;
  23int advice_graft_file_deprecated = 1;
  24int advice_checkout_ambiguous_remote_branch_name = 1;
  25
  26static int advice_use_color = -1;
  27static char advice_colors[][COLOR_MAXLEN] = {
  28        GIT_COLOR_RESET,
  29        GIT_COLOR_YELLOW,       /* HINT */
  30};
  31
  32enum color_advice {
  33        ADVICE_COLOR_RESET = 0,
  34        ADVICE_COLOR_HINT = 1,
  35};
  36
  37static int parse_advise_color_slot(const char *slot)
  38{
  39        if (!strcasecmp(slot, "reset"))
  40                return ADVICE_COLOR_RESET;
  41        if (!strcasecmp(slot, "hint"))
  42                return ADVICE_COLOR_HINT;
  43        return -1;
  44}
  45
  46static const char *advise_get_color(enum color_advice ix)
  47{
  48        if (want_color_stderr(advice_use_color))
  49                return advice_colors[ix];
  50        return "";
  51}
  52
  53static struct {
  54        const char *name;
  55        int *preference;
  56} advice_config[] = {
  57        { "pushupdaterejected", &advice_push_update_rejected },
  58        { "pushnonffcurrent", &advice_push_non_ff_current },
  59        { "pushnonffmatching", &advice_push_non_ff_matching },
  60        { "pushalreadyexists", &advice_push_already_exists },
  61        { "pushfetchfirst", &advice_push_fetch_first },
  62        { "pushneedsforce", &advice_push_needs_force },
  63        { "statushints", &advice_status_hints },
  64        { "statusuoption", &advice_status_u_option },
  65        { "commitbeforemerge", &advice_commit_before_merge },
  66        { "resolveconflict", &advice_resolve_conflict },
  67        { "implicitidentity", &advice_implicit_identity },
  68        { "detachedhead", &advice_detached_head },
  69        { "setupstreamfailure", &advice_set_upstream_failure },
  70        { "objectnamewarning", &advice_object_name_warning },
  71        { "rmhints", &advice_rm_hints },
  72        { "addembeddedrepo", &advice_add_embedded_repo },
  73        { "ignoredhook", &advice_ignored_hook },
  74        { "waitingforeditor", &advice_waiting_for_editor },
  75        { "graftfiledeprecated", &advice_graft_file_deprecated },
  76        { "checkoutambiguousremotebranchname", &advice_checkout_ambiguous_remote_branch_name },
  77
  78        /* make this an alias for backward compatibility */
  79        { "pushnonfastforward", &advice_push_update_rejected }
  80};
  81
  82void advise(const char *advice, ...)
  83{
  84        struct strbuf buf = STRBUF_INIT;
  85        va_list params;
  86        const char *cp, *np;
  87
  88        va_start(params, advice);
  89        strbuf_vaddf(&buf, advice, params);
  90        va_end(params);
  91
  92        for (cp = buf.buf; *cp; cp = np) {
  93                np = strchrnul(cp, '\n');
  94                fprintf(stderr, _("%shint: %.*s%s\n"),
  95                        advise_get_color(ADVICE_COLOR_HINT),
  96                        (int)(np - cp), cp,
  97                        advise_get_color(ADVICE_COLOR_RESET));
  98                if (*np)
  99                        np++;
 100        }
 101        strbuf_release(&buf);
 102}
 103
 104int git_default_advice_config(const char *var, const char *value)
 105{
 106        const char *k, *slot_name;
 107        int i;
 108
 109        if (!strcmp(var, "color.advice")) {
 110                advice_use_color = git_config_colorbool(var, value);
 111                return 0;
 112        }
 113
 114        if (skip_prefix(var, "color.advice.", &slot_name)) {
 115                int slot = parse_advise_color_slot(slot_name);
 116                if (slot < 0)
 117                        return 0;
 118                if (!value)
 119                        return config_error_nonbool(var);
 120                return color_parse(value, advice_colors[slot]);
 121        }
 122
 123        if (!skip_prefix(var, "advice.", &k))
 124                return 0;
 125
 126        for (i = 0; i < ARRAY_SIZE(advice_config); i++) {
 127                if (strcmp(k, advice_config[i].name))
 128                        continue;
 129                *advice_config[i].preference = git_config_bool(var, value);
 130                return 0;
 131        }
 132
 133        return 0;
 134}
 135
 136int error_resolve_conflict(const char *me)
 137{
 138        if (!strcmp(me, "cherry-pick"))
 139                error(_("Cherry-picking is not possible because you have unmerged files."));
 140        else if (!strcmp(me, "commit"))
 141                error(_("Committing is not possible because you have unmerged files."));
 142        else if (!strcmp(me, "merge"))
 143                error(_("Merging is not possible because you have unmerged files."));
 144        else if (!strcmp(me, "pull"))
 145                error(_("Pulling is not possible because you have unmerged files."));
 146        else if (!strcmp(me, "revert"))
 147                error(_("Reverting is not possible because you have unmerged files."));
 148        else
 149                error(_("It is not possible to %s because you have unmerged files."),
 150                        me);
 151
 152        if (advice_resolve_conflict)
 153                /*
 154                 * Message used both when 'git commit' fails and when
 155                 * other commands doing a merge do.
 156                 */
 157                advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
 158                         "as appropriate to mark resolution and make a commit."));
 159        return -1;
 160}
 161
 162void NORETURN die_resolve_conflict(const char *me)
 163{
 164        error_resolve_conflict(me);
 165        die(_("Exiting because of an unresolved conflict."));
 166}
 167
 168void NORETURN die_conclude_merge(void)
 169{
 170        error(_("You have not concluded your merge (MERGE_HEAD exists)."));
 171        if (advice_resolve_conflict)
 172                advise(_("Please, commit your changes before merging."));
 173        die(_("Exiting because of unfinished merge."));
 174}
 175
 176void detach_advice(const char *new_name)
 177{
 178        const char *fmt =
 179        _("Note: checking out '%s'.\n\n"
 180        "You are in 'detached HEAD' state. You can look around, make experimental\n"
 181        "changes and commit them, and you can discard any commits you make in this\n"
 182        "state without impacting any branches by performing another checkout.\n\n"
 183        "If you want to create a new branch to retain commits you create, you may\n"
 184        "do so (now or later) by using -b with the checkout command again. Example:\n\n"
 185        "  git checkout -b <new-branch-name>\n\n");
 186
 187        fprintf(stderr, fmt, new_name);
 188}