diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-09-13 11:49:53 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-09-14 09:24:56 +0300 |
commit | edfc2daf3452a059d7baa94e9debe5c393286a19 (patch) | |
tree | 5cd866151fc7b6bf607753131f007a634181e4b6 /_support | |
parent | 07a81867515f925c6108033d2bb05aebfcf14bd0 (diff) |
Makefile: Fix git-update-ref(1) not flushing status updates
When executing git-update-ref(1) with the `--stdin` flag, then the user
can queue updates and, since e48cf33b61 (update-ref: implement
interactive transaction handling, 2020-04-02), interactively drive the
transaction's state via a set of transactional verbs. This interactivity
is somewhat broken though: while the caller can use these verbs to drive
the transaction's state, the status messages which confirm that a verb
has been processed is not flushed. The caller may thus be left hanging
waiting for the acknowledgement.
This bug keeps us from using those status updates in the updateref
package, which effectively means that we cannot be sure whether the
state transition was successful until we try to commit changes. Add the
baseline for fixing this bug by applying the patch to our Git version.
Diffstat (limited to '_support')
-rw-r--r-- | _support/git-patches/0015-update-ref-fix-streaming-of-status-updates.patch | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/_support/git-patches/0015-update-ref-fix-streaming-of-status-updates.patch b/_support/git-patches/0015-update-ref-fix-streaming-of-status-updates.patch new file mode 100644 index 000000000..ecdca4675 --- /dev/null +++ b/_support/git-patches/0015-update-ref-fix-streaming-of-status-updates.patch @@ -0,0 +1,124 @@ +From efa3d64ce86a600563c8bf909c46dd0985ee6c11 Mon Sep 17 00:00:00 2001 +Message-Id: <efa3d64ce86a600563c8bf909c46dd0985ee6c11.1631522930.git.ps@pks.im> +From: Patrick Steinhardt <ps@pks.im> +Date: Fri, 3 Sep 2021 11:06:37 +0200 +Subject: [PATCH] update-ref: fix streaming of status updates + +When executing git-update-ref(1) with the `--stdin` flag, then the user +can queue updates and, since e48cf33b61 (update-ref: implement +interactive transaction handling, 2020-04-02), interactively drive the +transaction's state via a set of transactional verbs. This interactivity +is somewhat broken though: while the caller can use these verbs to drive +the transaction's state, the status messages which confirm that a verb +has been processed is not flushed. The caller may thus be left hanging +waiting for the acknowledgement. + +Fix the bug by flushing stdout after writing the status update. Add a +test which catches this bug. + +Signed-off-by: Patrick Steinhardt <ps@pks.im> +Signed-off-by: Junio C Hamano <gitster@pobox.com> +--- + builtin/update-ref.c | 14 ++++++++++---- + t/t1400-update-ref.sh | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/builtin/update-ref.c b/builtin/update-ref.c +index 6029a80544..a84e7b47a2 100644 +--- a/builtin/update-ref.c ++++ b/builtin/update-ref.c +@@ -302,6 +302,12 @@ static void parse_cmd_verify(struct ref_transaction *transaction, + strbuf_release(&err); + } + ++static void report_ok(const char *command) ++{ ++ fprintf(stdout, "%s: ok\n", command); ++ fflush(stdout); ++} ++ + static void parse_cmd_option(struct ref_transaction *transaction, + const char *next, const char *end) + { +@@ -317,7 +323,7 @@ static void parse_cmd_start(struct ref_transaction *transaction, + { + if (*next != line_termination) + die("start: extra input: %s", next); +- puts("start: ok"); ++ report_ok("start"); + } + + static void parse_cmd_prepare(struct ref_transaction *transaction, +@@ -328,7 +334,7 @@ static void parse_cmd_prepare(struct ref_transaction *transaction, + die("prepare: extra input: %s", next); + if (ref_transaction_prepare(transaction, &error)) + die("prepare: %s", error.buf); +- puts("prepare: ok"); ++ report_ok("prepare"); + } + + static void parse_cmd_abort(struct ref_transaction *transaction, +@@ -339,7 +345,7 @@ static void parse_cmd_abort(struct ref_transaction *transaction, + die("abort: extra input: %s", next); + if (ref_transaction_abort(transaction, &error)) + die("abort: %s", error.buf); +- puts("abort: ok"); ++ report_ok("abort"); + } + + static void parse_cmd_commit(struct ref_transaction *transaction, +@@ -350,7 +356,7 @@ static void parse_cmd_commit(struct ref_transaction *transaction, + die("commit: extra input: %s", next); + if (ref_transaction_commit(transaction, &error)) + die("commit: %s", error.buf); +- puts("commit: ok"); ++ report_ok("commit"); + ref_transaction_free(transaction); + } + +diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh +index 4506cd435b..1e754e258f 100755 +--- a/t/t1400-update-ref.sh ++++ b/t/t1400-update-ref.sh +@@ -1598,6 +1598,38 @@ test_expect_success 'transaction cannot restart ongoing transaction' ' + test_must_fail git show-ref --verify refs/heads/restart + ' + ++test_expect_success PIPE 'transaction flushes status updates' ' ++ mkfifo in out && ++ (git update-ref --stdin <in >out &) && ++ ++ exec 9>in && ++ test_when_finished "exec 9>&-" && ++ ++ echo "start" >&9 && ++ echo "start: ok" >expected && ++ read line <out && ++ echo "$line" >actual && ++ test_cmp expected actual && ++ ++ echo "create refs/heads/flush $A" >&9 && ++ ++ echo prepare >&9 && ++ echo "prepare: ok" >expected && ++ read line <out && ++ echo "$line" >actual && ++ test_cmp expected actual && ++ ++ # This must now fail given that we have locked the ref. ++ test_must_fail git update-ref refs/heads/flush $B 2>stderr && ++ grep "fatal: update_ref failed for ref ${SQ}refs/heads/flush${SQ}: cannot lock ref" stderr && ++ ++ echo commit >&9 && ++ echo "commit: ok" >expected && ++ read line <out && ++ echo "$line" >actual && ++ test_cmp expected actual ++' ++ + test_expect_success 'directory not created deleting packed ref' ' + git branch d1/d2/r1 HEAD && + git pack-refs --all && +-- +2.33.0 + |