Merge branch 'dl/warn-tagging-a-tag'
authorJunio C Hamano <gitster@pobox.com>
Wed, 8 May 2019 15:37:22 +0000 (00:37 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 8 May 2019 15:37:22 +0000 (00:37 +0900)
"git tag" learned to give an advice suggesting it might be a
mistake when creating an annotated or signed tag that points at
another tag.

* dl/warn-tagging-a-tag:
tag: advise on nested tags
tag: fix formatting

Documentation/config/advice.txt
advice.c
advice.h
builtin/tag.c
t/t7004-tag.sh
index 88620429eacf857c7ba7941314c9b443b35b58ce..ec4f6ae6585bac4b107134e52f544d53c24cdf86 100644 (file)
@@ -90,4 +90,6 @@ advice.*::
        waitingForEditor::
                Print a message to the terminal whenever Git is waiting for
                editor input from the user.
+       nestedTag::
+               Advice shown if a user attempts to recursively tag a tag object.
 --
index 567209aa79afee0443dd0d7049343e1a004ae784..ce5f374ecd4917346145c8a380ac8c0e45e849a4 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -26,6 +26,7 @@ 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;
 
 static int advice_use_color = -1;
 static char advice_colors[][COLOR_MAXLEN] = {
@@ -81,6 +82,7 @@ static struct {
        { "waitingForEditor", &advice_waiting_for_editor },
        { "graftFileDeprecated", &advice_graft_file_deprecated },
        { "checkoutAmbiguousRemoteBranchName", &advice_checkout_ambiguous_remote_branch_name },
+       { "nestedTag", &advice_nested_tag },
 
        /* make this an alias for backward compatibility */
        { "pushNonFastForward", &advice_push_update_rejected }
index f875f8cd8da5fdb6e570770ecc7ab4461745f827..cb5d36161453dc4c3a8de8e6afd3b3ac28394eaa 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -26,6 +26,7 @@ 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;
 
 int git_default_advice_config(const char *var, const char *value);
 __attribute__((format (printf, 1, 2)))
index ad97595fbfaa25c8ec44efec8ce5f946cf7de184..8399a0ed5414321f9893f94d93dab6788f2175af 100644 (file)
 #include "ref-filter.h"
 
 static const char * const git_tag_usage[] = {
-       N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]"),
+       N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n"
+               "\t\t<tagname> [<head>]"),
        N_("git tag -d <tagname>..."),
-       N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]"
-               "\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
+       N_("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]\n"
+               "\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"),
        N_("git tag -v [--format=<format>] <tagname>..."),
        NULL
 };
@@ -205,7 +206,14 @@ struct create_tag_options {
        } cleanup_mode;
 };
 
-static void create_tag(const struct object_id *object, const char *tag,
+static const char message_advice_nested_tag[] =
+       N_("You have created a nested tag. The object referred to by your new is\n"
+          "already a tag. If you meant to tag the object that it points to, use:\n"
+          "\n"
+          "\tgit tag -f %s %s^{}");
+
+static void create_tag(const struct object_id *object, const char *object_ref,
+                      const char *tag,
                       struct strbuf *buf, struct create_tag_options *opt,
                       struct object_id *prev, struct object_id *result)
 {
@@ -215,7 +223,10 @@ static void create_tag(const struct object_id *object, const char *tag,
 
        type = oid_object_info(the_repository, object, NULL);
        if (type <= OBJ_NONE)
-           die(_("bad object type."));
+               die(_("bad object type."));
+
+       if (type == OBJ_TAG && advice_nested_tag)
+               advise(_(message_advice_nested_tag), tag, object_ref);
 
        strbuf_addf(&header,
                    "object %s\n"
@@ -549,7 +560,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        if (create_tag_object) {
                if (force_sign_annotate && !annotate)
                        opt.sign = 1;
-               create_tag(&object, tag, &buf, &opt, &prev, &object);
+               create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object);
        }
 
        transaction = ref_transaction_begin(&err);
index 0b01862c23aa182ee4ae7ce2944a40b4449d6049..e285686662df781c87d59c910aa9d596eb974c34 100755 (executable)
@@ -1700,6 +1700,17 @@ test_expect_success '--points-at finds annotated tags of tags' '
        test_cmp expect actual
 '
 
+test_expect_success 'recursive tagging should give advice' '
+       sed -e "s/|$//" <<-EOF >expect &&
+       hint: You have created a nested tag. The object referred to by your new is
+       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^{}
+       EOF
+       git tag -m nested nested annotated-v4.0 2>actual &&
+       test_i18ncmp expect actual
+'
+
 test_expect_success 'multiple --points-at are OR-ed together' '
        cat >expect <<-\EOF &&
        v2.0