From: Junio C Hamano Date: Tue, 3 Jun 2014 19:06:40 +0000 (-0700) Subject: Merge branch 'mh/ref-transaction' X-Git-Tag: v2.1.0-rc0~200 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/2cc70cefdd4a249fab895943890d21071e03f8c7?hp=-c Merge branch 'mh/ref-transaction' Update "update-ref --stdin [-z]" and then introduce a transactional support for (multi-)reference updates. * mh/ref-transaction: (27 commits) ref_transaction_commit(): work with transaction->updates in place struct ref_update: add a type field struct ref_update: add a lock field ref_transaction_commit(): simplify code using temporary variables struct ref_update: store refname as a FLEX_ARRAY struct ref_update: rename field "ref_name" to "refname" refs: remove API function update_refs() update-ref --stdin: reimplement using reference transactions refs: add a concept of a reference transaction update-ref --stdin: harmonize error messages update-ref --stdin: improve the error message for unexpected EOF t1400: test one mistake at a time update-ref --stdin -z: deprecate interpreting the empty string as zeros update-ref.c: extract a new function, parse_next_sha1() t1400: test that stdin -z update treats empty as zeros update-ref --stdin: simplify error messages for missing oldvalues update-ref --stdin: make error messages more consistent update-ref --stdin: improve error messages for invalid values update-ref.c: extract a new function, parse_refname() parse_cmd_verify(): copy old_sha1 instead of evaluating twice ... --- 2cc70cefdd4a249fab895943890d21071e03f8c7 diff --combined builtin/checkout.c index 07cf555309,6bf23188c9..ff4492162d --- a/builtin/checkout.c +++ b/builtin/checkout.c @@@ -624,7 -624,7 +624,7 @@@ static void update_refs_for_switch(cons /* Nothing to do. */ } else if (opts->force_detach || !new->path) { /* No longer on any branch. */ update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL, - REF_NODEREF, DIE_ON_ERR); + REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); if (!opts->quiet) { if (old->path && advice_detached_head) detach_advice(new->name); @@@ -895,7 -895,7 +895,7 @@@ static int parse_branchname_arg(int arg * between A and B, A...B names that merge base. * * (b) If is _not_ a commit, either "--" is present - * or is not a path, no -t nor -b was given, and + * or is not a path, no -t or -b was given, and * and there is a tracking branch whose name is * in one and only one remote, then this is a short-hand to * fork local from that remote-tracking branch. @@@ -1095,7 -1095,7 +1095,7 @@@ int cmd_checkout(int argc, const char * OPT_BOOL(0, "detach", &opts.force_detach, N_("detach the HEAD at named commit")), OPT_SET_INT('t', "track", &opts.track, N_("set upstream info for new branch"), BRANCH_TRACK_EXPLICIT), - OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new branch"), N_("new unparented branch")), + OPT_STRING(0, "orphan", &opts.new_orphan_branch, N_("new-branch"), N_("new unparented branch")), OPT_SET_INT('2', "ours", &opts.writeout_stage, N_("checkout our version for unmerged files"), 2), OPT_SET_INT('3', "theirs", &opts.writeout_stage, N_("checkout their version for unmerged files"), diff --combined builtin/merge.c index 66d8843301,7d1d83e8a5..7c9d8f2432 --- a/builtin/merge.c +++ b/builtin/merge.c @@@ -220,7 -220,7 +220,7 @@@ static struct option builtin_merge_opti OPT_BOOL(0, "abort", &abort_current_merge, N_("abort the current in-progress merge")), OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1), - { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key id"), + { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"), N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")), OPT_END() @@@ -398,7 -398,7 +398,7 @@@ static void finish(struct commit *head_ const char *argv_gc_auto[] = { "gc", "--auto", NULL }; update_ref(reflog_message.buf, "HEAD", new_head, head, 0, - DIE_ON_ERR); + UPDATE_REFS_DIE_ON_ERR); /* * We ignore errors in 'gc --auto', since the * user should see them. @@@ -1222,7 -1222,7 +1222,7 @@@ int cmd_merge(int argc, const char **ar die(_("%s - not something we can merge"), argv[0]); read_empty(remote_head->object.sha1, 0); update_ref("initial pull", "HEAD", remote_head->object.sha1, - NULL, 0, DIE_ON_ERR); + NULL, 0, UPDATE_REFS_DIE_ON_ERR); goto done; } else { struct strbuf merge_names = STRBUF_INIT; @@@ -1339,7 -1339,7 +1339,7 @@@ } update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1, - NULL, 0, DIE_ON_ERR); + NULL, 0, UPDATE_REFS_DIE_ON_ERR); if (remoteheads && !common) ; /* No common ancestors found. We need a real merge. */ diff --combined builtin/notes.c index 39c8573cde,66147b6739..820c34135c --- a/builtin/notes.c +++ b/builtin/notes.c @@@ -717,7 -717,7 +717,7 @@@ static int merge_commit(struct notes_me strbuf_insert(&msg, 0, "notes: ", 7); update_ref(msg.buf, o->local_ref, sha1, is_null_sha1(parent_sha1) ? NULL : parent_sha1, - 0, DIE_ON_ERR); + 0, UPDATE_REFS_DIE_ON_ERR); free_notes(t); strbuf_release(&msg); @@@ -812,11 -812,11 +812,11 @@@ static int merge(int argc, const char * if (result >= 0) /* Merge resulted (trivially) in result_sha1 */ /* Update default notes ref with new commit */ update_ref(msg.buf, default_notes_ref(), result_sha1, NULL, - 0, DIE_ON_ERR); + 0, UPDATE_REFS_DIE_ON_ERR); else { /* Merge has unresolved conflicts */ /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL, - 0, DIE_ON_ERR); + 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL)) die("Failed to store link to current notes ref (%s)", @@@ -939,7 -939,7 +939,7 @@@ int cmd_notes(int argc, const char **ar int result; const char *override_notes_ref = NULL; struct option options[] = { - OPT_STRING(0, "ref", &override_notes_ref, N_("notes_ref"), + OPT_STRING(0, "ref", &override_notes_ref, N_("notes-ref"), N_("use notes from ")), OPT_END() }; diff --combined t/t1400-update-ref.sh index e130c528fe,48ccc4d635..4e2459afc5 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@@ -350,22 -350,28 +350,28 @@@ test_expect_success 'stdin fails on unk grep "fatal: unknown command: unknown $a" err ' - test_expect_success 'stdin fails on badly quoted input' ' + test_expect_success 'stdin fails on unbalanced quotes' ' echo "create $a \"master" >stdin && test_must_fail git update-ref --stdin err && grep "fatal: badly quoted argument: \\\"master" err ' - test_expect_success 'stdin fails on arguments not separated by space' ' + test_expect_success 'stdin fails on invalid escape' ' + echo "create $a \"ma\zter\"" >stdin && + test_must_fail git update-ref --stdin err && + grep "fatal: badly quoted argument: \\\"ma\\\\zter\\\"" err + ' + + test_expect_success 'stdin fails on junk after quoted argument' ' echo "create \"$a\"master" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: expected SP but got: master" err + grep "fatal: unexpected character after quoted argument: \\\"$a\\\"master" err ' test_expect_success 'stdin fails create with no ref' ' echo "create " >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: create line missing " err + grep "fatal: create: missing " err ' test_expect_success 'stdin fails create with bad ref name' ' @@@ -377,19 -383,19 +383,19 @@@ test_expect_success 'stdin fails create with no new value' ' echo "create $a" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: create $a missing " err + grep "fatal: create $a: missing " err ' test_expect_success 'stdin fails create with too many arguments' ' echo "create $a $m $m" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: create $a has extra input: $m" err + grep "fatal: create $a: extra input: $m" err ' test_expect_success 'stdin fails update with no ref' ' echo "update " >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: update line missing " err + grep "fatal: update: missing " err ' test_expect_success 'stdin fails update with bad ref name' ' @@@ -401,19 -407,19 +407,19 @@@ test_expect_success 'stdin fails update with no new value' ' echo "update $a" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: update $a missing " err + grep "fatal: update $a: missing " err ' test_expect_success 'stdin fails update with too many arguments' ' echo "update $a $m $m $m" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: update $a has extra input: $m" err + grep "fatal: update $a: extra input: $m" err ' test_expect_success 'stdin fails delete with no ref' ' echo "delete " >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: delete line missing " err + grep "fatal: delete: missing " err ' test_expect_success 'stdin fails delete with bad ref name' ' @@@ -425,13 -431,13 +431,13 @@@ test_expect_success 'stdin fails delete with too many arguments' ' echo "delete $a $m $m" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: delete $a has extra input: $m" err + grep "fatal: delete $a: extra input: $m" err ' test_expect_success 'stdin fails verify with too many arguments' ' echo "verify $a $m $m" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: verify $a has extra input: $m" err + grep "fatal: verify $a: extra input: $m" err ' test_expect_success 'stdin fails option with unknown name' ' @@@ -458,6 -464,24 +464,24 @@@ test_expect_success 'stdin create ref w test_cmp expect actual ' + test_expect_success 'stdin succeeds with quoted argument' ' + git update-ref -d $a && + echo "create $a \"$m\"" >stdin && + git update-ref --stdin expect && + git rev-parse $a >actual && + test_cmp expect actual + ' + + test_expect_success 'stdin succeeds with escaped character' ' + git update-ref -d $a && + echo "create $a \"ma\\163ter\"" >stdin && + git update-ref --stdin expect && + git rev-parse $a >actual && + test_cmp expect actual + ' + test_expect_success 'stdin update ref creates with zero old value' ' echo "update $b $m $Z" >stdin && git update-ref --stdin stdin && test_must_fail git update-ref --stdin err && - grep "fatal: invalid old value for ref $c: does-not-exist" err && + grep "fatal: update $c: invalid : does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' test_expect_success 'stdin create ref fails with bad new value' ' echo "create $c does-not-exist" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: invalid new value for ref $c: does-not-exist" err && + grep "fatal: create $c: invalid : does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' test_expect_success 'stdin create ref fails with zero new value' ' echo "create $c " >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: create $c given zero new value" err && + grep "fatal: create $c: zero " err && test_must_fail git rev-parse --verify -q $c ' @@@ -532,7 -556,7 +556,7 @@@ test_expect_success 'stdin delete ref f test_expect_success 'stdin delete ref fails with zero old value' ' echo "delete $a " >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: delete $a given zero old value" err && + grep "fatal: delete $a: zero " err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@@ -673,7 -697,7 +697,7 @@@ test_expect_success 'stdin -z fails on test_expect_success 'stdin -z fails create with no ref' ' printf $F "create " >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: create line missing " err + grep "fatal: create: missing " err ' test_expect_success 'stdin -z fails create with bad ref name' ' @@@ -685,7 -709,7 +709,7 @@@ test_expect_success 'stdin -z fails create with no new value' ' printf $F "create $a" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: create $a missing " err + grep "fatal: create $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails create with too many arguments' ' @@@ -697,25 -721,39 +721,39 @@@ test_expect_success 'stdin -z fails update with no ref' ' printf $F "update " >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: update line missing " err + grep "fatal: update: missing " err + ' + + test_expect_success 'stdin -z fails update with too few args' ' + printf $F "update $a" "$m" >stdin && + test_must_fail git update-ref -z --stdin err && + grep "fatal: update $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails update with bad ref name' ' - printf $F "update ~a" "$m" >stdin && + printf $F "update ~a" "$m" "" >stdin && test_must_fail git update-ref -z --stdin err && grep "fatal: invalid ref format: ~a" err ' + test_expect_success 'stdin -z emits warning with empty new value' ' + git update-ref $a $m && + printf $F "update $a" "" "" >stdin && + git update-ref -z --stdin err && + grep "warning: update $a: missing , treating as zero" err && + test_must_fail git rev-parse --verify -q $a + ' + test_expect_success 'stdin -z fails update with no new value' ' printf $F "update $a" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: update $a missing " err + grep "fatal: update $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails update with no old value' ' printf $F "update $a" "$m" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: update $a missing \\[\\] NUL" err + grep "fatal: update $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails update with too many arguments' ' @@@ -727,7 -765,7 +765,7 @@@ test_expect_success 'stdin -z fails delete with no ref' ' printf $F "delete " >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: delete line missing " err + grep "fatal: delete: missing " err ' test_expect_success 'stdin -z fails delete with bad ref name' ' @@@ -739,7 -777,7 +777,7 @@@ test_expect_success 'stdin -z fails delete with no old value' ' printf $F "delete $a" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: delete $a missing \\[\\] NUL" err + grep "fatal: delete $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails delete with too many arguments' ' @@@ -757,7 -795,7 +795,7 @@@ test_expect_success 'stdin -z fails ver test_expect_success 'stdin -z fails verify with no old value' ' printf $F "verify $a" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: verify $a missing \\[\\] NUL" err + grep "fatal: verify $a: unexpected end of input when reading " err ' test_expect_success 'stdin -z fails option with unknown name' ' @@@ -816,32 -854,21 +854,32 @@@ test_expect_success 'stdin -z update re test_expect_success 'stdin -z update ref fails with bad old value' ' printf $F "update $c" "$m" "does-not-exist" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: invalid old value for ref $c: does-not-exist" err && + grep "fatal: update $c: invalid : does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' +test_expect_success 'stdin -z create ref fails when ref exists' ' + git update-ref $c $m && + git rev-parse "$c" >expect && + printf $F "create $c" "$m~1" >stdin && + test_must_fail git update-ref -z --stdin err && + grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err && + git rev-parse "$c" >actual && + test_cmp expect actual +' + test_expect_success 'stdin -z create ref fails with bad new value' ' + git update-ref -d "$c" && printf $F "create $c" "does-not-exist" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: invalid new value for ref $c: does-not-exist" err && + grep "fatal: create $c: invalid : does-not-exist" err && test_must_fail git rev-parse --verify -q $c ' - test_expect_success 'stdin -z create ref fails with zero new value' ' + test_expect_success 'stdin -z create ref fails with empty new value' ' printf $F "create $c" "" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: create $c given zero new value" err && + grep "fatal: create $c: missing " err && test_must_fail git rev-parse --verify -q $c ' @@@ -865,7 -892,7 +903,7 @@@ test_expect_success 'stdin -z delete re test_expect_success 'stdin -z delete ref fails with zero old value' ' printf $F "delete $a" "$Z" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: delete $a given zero old value" err && + grep "fatal: delete $a: zero " err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@@ -923,7 -950,7 +961,7 @@@ test_expect_success 'stdin -z update re test_expect_success 'stdin -z update refs fails with wrong old value' ' git update-ref $c $m && - printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "" "$Z" >stdin && + printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$m" "$Z" >stdin && test_must_fail git update-ref -z --stdin err && grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err && git rev-parse $m >expect &&