Merge branch 'kh/keep-tag-editmsg-upon-failure'
"git tag" learned to leave the "$GIT_DIR/TAG_EDITMSG" file when the command failed, so that the user can salvage what they typed. * kh/keep-tag-editmsg-upon-failure: tag: keep the message file in case ref transaction fails t/t7004-tag: add regression test for successful tag creation doc: tag: document `TAG_EDITMSG`
This commit is contained in:
@ -381,6 +381,16 @@ $ GIT_COMMITTER_DATE="2006-10-02 10:31" git tag -s v1.0.1
|
|||||||
|
|
||||||
include::date-formats.txt[]
|
include::date-formats.txt[]
|
||||||
|
|
||||||
|
FILES
|
||||||
|
-----
|
||||||
|
|
||||||
|
`$GIT_DIR/TAG_EDITMSG`::
|
||||||
|
This file contains the message of an in-progress annotated
|
||||||
|
tag. If `git tag` exits due to an error before creating an
|
||||||
|
annotated tag then the tag message that has been provided by the
|
||||||
|
user in an editor session will be available in this file, but
|
||||||
|
may be overwritten by the next invocation of `git tag`.
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -271,11 +271,10 @@ static const char message_advice_nested_tag[] =
|
|||||||
static void create_tag(const struct object_id *object, const char *object_ref,
|
static void create_tag(const struct object_id *object, const char *object_ref,
|
||||||
const char *tag,
|
const char *tag,
|
||||||
struct strbuf *buf, struct create_tag_options *opt,
|
struct strbuf *buf, struct create_tag_options *opt,
|
||||||
struct object_id *prev, struct object_id *result)
|
struct object_id *prev, struct object_id *result, char *path)
|
||||||
{
|
{
|
||||||
enum object_type type;
|
enum object_type type;
|
||||||
struct strbuf header = STRBUF_INIT;
|
struct strbuf header = STRBUF_INIT;
|
||||||
char *path = NULL;
|
|
||||||
|
|
||||||
type = oid_object_info(the_repository, object, NULL);
|
type = oid_object_info(the_repository, object, NULL);
|
||||||
if (type <= OBJ_NONE)
|
if (type <= OBJ_NONE)
|
||||||
@ -299,7 +298,6 @@ static void create_tag(const struct object_id *object, const char *object_ref,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
/* write the template message before editing: */
|
/* write the template message before editing: */
|
||||||
path = git_pathdup("TAG_EDITMSG");
|
|
||||||
fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||||
|
|
||||||
if (opt->message_given) {
|
if (opt->message_given) {
|
||||||
@ -341,10 +339,6 @@ static void create_tag(const struct object_id *object, const char *object_ref,
|
|||||||
path);
|
path);
|
||||||
exit(128);
|
exit(128);
|
||||||
}
|
}
|
||||||
if (path) {
|
|
||||||
unlink_or_warn(path);
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
|
static void create_reflog_msg(const struct object_id *oid, struct strbuf *sb)
|
||||||
@ -495,6 +489,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
|||||||
};
|
};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const char *only_in_list = NULL;
|
const char *only_in_list = NULL;
|
||||||
|
char *path = NULL;
|
||||||
|
|
||||||
setup_ref_filter_porcelain_msg();
|
setup_ref_filter_porcelain_msg();
|
||||||
|
|
||||||
@ -629,7 +624,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
|||||||
if (create_tag_object) {
|
if (create_tag_object) {
|
||||||
if (force_sign_annotate && !annotate)
|
if (force_sign_annotate && !annotate)
|
||||||
opt.sign = 1;
|
opt.sign = 1;
|
||||||
create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object);
|
path = git_pathdup("TAG_EDITMSG");
|
||||||
|
create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object,
|
||||||
|
path);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction = ref_transaction_begin(&err);
|
transaction = ref_transaction_begin(&err);
|
||||||
@ -637,8 +634,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
|||||||
ref_transaction_update(transaction, ref.buf, &object, &prev,
|
ref_transaction_update(transaction, ref.buf, &object, &prev,
|
||||||
create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
|
create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
|
||||||
reflog_msg.buf, &err) ||
|
reflog_msg.buf, &err) ||
|
||||||
ref_transaction_commit(transaction, &err))
|
ref_transaction_commit(transaction, &err)) {
|
||||||
|
if (path)
|
||||||
|
fprintf(stderr,
|
||||||
|
_("The tag message has been left in %s\n"),
|
||||||
|
path);
|
||||||
die("%s", err.buf);
|
die("%s", err.buf);
|
||||||
|
}
|
||||||
|
if (path) {
|
||||||
|
unlink_or_warn(path);
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
ref_transaction_free(transaction);
|
ref_transaction_free(transaction);
|
||||||
if (force && !is_null_oid(&prev) && !oideq(&prev, &object))
|
if (force && !is_null_oid(&prev) && !oideq(&prev, &object))
|
||||||
printf(_("Updated tag '%s' (was %s)\n"), tag,
|
printf(_("Updated tag '%s' (was %s)\n"), tag,
|
||||||
|
@ -2188,4 +2188,23 @@ test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
|
|||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'If tag is created then tag message file is unlinked' '
|
||||||
|
test_when_finished "git tag -d foo" &&
|
||||||
|
write_script fakeeditor <<-\EOF &&
|
||||||
|
echo Message >.git/TAG_EDITMSG
|
||||||
|
EOF
|
||||||
|
GIT_EDITOR=./fakeeditor git tag -a foo &&
|
||||||
|
test_path_is_missing .git/TAG_EDITMSG
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'If tag cannot be created then tag message file is not unlinked' '
|
||||||
|
test_when_finished "git tag -d foo/bar && rm .git/TAG_EDITMSG" &&
|
||||||
|
write_script fakeeditor <<-\EOF &&
|
||||||
|
echo Message >.git/TAG_EDITMSG
|
||||||
|
EOF
|
||||||
|
git tag foo/bar &&
|
||||||
|
test_must_fail env GIT_EDITOR=./fakeeditor git tag -a foo &&
|
||||||
|
test_path_exists .git/TAG_EDITMSG
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user