fix tag signing when the key file does not exist This should fail without creating any tag. Before, ssh-keygen(1) would print an error to stderr, but got would create an unsigned tag. ok op@
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
diff --git a/got/got.c b/got/got.c
index 78d2132..ce9c1f6 100644
--- a/got/got.c
+++ b/got/got.c
@@ -7214,7 +7214,7 @@ done:
static const struct got_error *
add_tag(struct got_repository *repo, const char *tagger,
const char *tag_name, const char *commit_arg, const char *tagmsg_arg,
- const char *key_file, int verbosity)
+ const char *signer_id, int verbosity)
{
const struct got_error *err = NULL;
struct got_object_id *commit_id = NULL, *tag_id = NULL;
@@ -7280,7 +7280,7 @@ add_tag(struct got_repository *repo, const char *tagger,
}
err = got_object_tag_create(&tag_id, tag_name, commit_id,
- tagger, time(NULL), tagmsg ? tagmsg : tagmsg_arg, key_file, repo,
+ tagger, time(NULL), tagmsg ? tagmsg : tagmsg_arg, signer_id, repo,
verbosity);
if (err) {
if (tagmsg_path)
diff --git a/include/got_error.h b/include/got_error.h
index 4bfaed5..9dcd5b8 100644
--- a/include/got_error.h
+++ b/include/got_error.h
@@ -171,6 +171,7 @@
#define GOT_ERR_PIN_PACK 153
#define GOT_ERR_BAD_TAG_SIGNATURE 154
#define GOT_ERR_VERIFY_TAG_SIGNATURE 155
+#define GOT_ERR_SIGNING_TAG 156
struct got_error {
int code;
diff --git a/lib/error.c b/lib/error.c
index 3c092e6..bde78fa 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -219,6 +219,7 @@ static const struct got_error got_errors[] = {
{ GOT_ERR_PIN_PACK, "could not pin pack file" },
{ GOT_ERR_BAD_TAG_SIGNATURE, "invalid tag signature" },
{ GOT_ERR_VERIFY_TAG_SIGNATURE, "cannot verify signature" },
+ { GOT_ERR_SIGNING_TAG, "unable to sign tag" },
};
static struct got_custom_error {
diff --git a/lib/object_create.c b/lib/object_create.c
index 8f33d6b..2e773fd 100644
--- a/lib/object_create.c
+++ b/lib/object_create.c
@@ -612,7 +612,7 @@ done:
const struct got_error *
got_object_tag_create(struct got_object_id **id,
const char *tag_name, struct got_object_id *object_id, const char *tagger,
- time_t tagger_time, const char *tagmsg, const char *key_file,
+ time_t tagger_time, const char *tagmsg, const char *signer_id,
struct got_repository *repo, int verbosity)
{
const struct got_error *err = NULL;
@@ -687,7 +687,7 @@ got_object_tag_create(struct got_object_id **id,
while (isspace((unsigned char)msg[0]))
msg++;
- if (key_file) {
+ if (signer_id) {
FILE *out;
pid_t pid;
size_t len;
@@ -721,7 +721,7 @@ got_object_tag_create(struct got_object_id **id,
if (err)
goto done;
- err = got_sigs_sign_tag_ssh(&pid, &in_fd, &out_fd, key_file,
+ err = got_sigs_sign_tag_ssh(&pid, &in_fd, &out_fd, signer_id,
verbosity);
if (err)
goto done;
@@ -738,6 +738,10 @@ got_object_tag_create(struct got_object_id **id,
err = got_error_from_errno("waitpid");
goto done;
}
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ err = got_error(GOT_ERR_SIGNING_TAG);
+ goto done;
+ }
out = fdopen(out_fd, "r");
if (out == NULL) {
@@ -840,7 +844,7 @@ got_object_tag_create(struct got_object_id **id,
}
tagsize += n;
- if (key_file && buf_len(buf) > 0) {
+ if (signer_id && buf_len(buf) > 0) {
len = buf_len(buf);
SHA1Update(&sha1_ctx, buf_get(buf), len);
n = fwrite(buf_get(buf), 1, len, tagfile);
diff --git a/regress/cmdline/tag.sh b/regress/cmdline/tag.sh
index b39af2b..07c00cb 100755
--- a/regress/cmdline/tag.sh
+++ b/regress/cmdline/tag.sh
@@ -417,6 +417,43 @@ test_tag_create_ssh_signed() {
test_done "$testroot" "$ret"
}
+test_tag_create_ssh_signed_missing_key() {
+ local testroot=`test_init tag_create`
+ local commit_id=`git_show_head $testroot/repo`
+ local tag=1.0.0
+
+ # Fail to create a signed tag due to a missing SSH key
+ got tag -s $testroot/bogus -m 'test' -r $testroot/repo \
+ -c HEAD $tag > $testroot/stdout 2> $testroot/stderr
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "got tag command succeeded unexpectedly"
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ got ref -r $testroot/repo -l > $testroot/stdout
+ echo "HEAD: refs/heads/master" > $testroot/stdout.expected
+ echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout $testroot/stdout.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ printf "Couldn't load public key $testroot/bogus: " \
+ echo "got: unable to sign tag" >> $testroot/stderr.expected
+ printf "No such file or directory\r\n" >> $testroot/stderr.expected
+ cmp -s $testroot/stderr $testroot/stderr.expected
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ fi
+ test_done "$testroot" "$ret"
+}
+
+test_parseargs "$@"
test_parseargs "$@"
run_test test_tag_create
run_test test_tag_list