summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config/advice.txt2
-rw-r--r--advice.c2
-rw-r--r--advice.h1
-rw-r--r--builtin/tag.c23
-rwxr-xr-xt/t7004-tag.sh11
5 files changed, 33 insertions, 6 deletions
diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index 88620429ea..ec4f6ae658 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -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.
--
diff --git a/advice.c b/advice.c
index 567209aa79..ce5f374ecd 100644
--- 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 }
diff --git a/advice.h b/advice.h
index f875f8cd8d..cb5d361614 100644
--- 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)))
diff --git a/builtin/tag.c b/builtin/tag.c
index ad97595fbf..8399a0ed54 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -22,10 +22,11 @@
#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);
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 0b01862c23..e285686662 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -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