Message ID | 718a8bf5d7a0ed92c3004991a42419279ff38253.1610107599.git.ps@pks.im (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | fetch: implement support for atomic reference updates | expand |
Patrick Steinhardt <ps@pks.im> writes: > @@ -598,30 +598,33 @@ static int s_update_ref(const char *action, > msg = xstrfmt("%s: %s", rla, action); > > transaction = ref_transaction_begin(&err); > - if (!transaction || > - ref_transaction_update(transaction, ref->name, > - &ref->new_oid, > - check_old ? &ref->old_oid : NULL, > - 0, msg, &err)) > - goto fail; > + if (!transaction) { > + ret = STORE_REF_ERROR_OTHER; > + goto out; > + } > + > + ret = ref_transaction_update(transaction, ref->name, &ref->new_oid, > + check_old ? &ref->old_oid : NULL, > + 0, msg, &err); > + if (ret) { > + ret = STORE_REF_ERROR_OTHER; > + goto out; > + } The above certainly got cleaner thanks to Christian's suggestion, but I wonder why transaction = ref_transaction_begin(&err); if (!transaction || ref_transaction_update(transaction, ref->name, &ref->new_oid, check_old ? &ref->old_oid : NULL, 0, msg, &err)) { ret = STORE_REF_ERROR_OTHER; goto out; } shouldn't be sufficient. > ret = ref_transaction_commit(transaction, &err); > if (ret) { > - df_conflict = (ret == TRANSACTION_NAME_CONFLICT); > - goto fail; > + ret = (ret == TRANSACTION_NAME_CONFLICT) ? STORE_REF_ERROR_DF_CONFLICT > + : STORE_REF_ERROR_OTHER; > + goto out; > } > > +out: > ref_transaction_free(transaction); It is a bit funny to see a goto that jumps to the label without having anything else in between, but we know we will be adding more code just before the "out:" label, so it is a good preliminary preparation. I think a variant that is much easier to follow would be to write like this instead: switch (ref_transaction_commit(transaction, &err)) { case 0: /* happy */ break; case TRANSACTION_NAME_CONFLICT: ret = STORE_REF_ERROR_DF_CONFLICT; goto out; default: ret = STORE_REF_ERROR_OTHER; goto out; } > + if (ret) > + error("%s", err.buf); OK. > strbuf_release(&err); > free(msg); > - return 0; > -fail: > - ref_transaction_free(transaction); > - error("%s", err.buf); > - strbuf_release(&err); > - free(msg); > - return df_conflict ? STORE_REF_ERROR_DF_CONFLICT > - : STORE_REF_ERROR_OTHER; > + return ret; > } > > static int refcol_width = 10; THanks.
On Fri, Jan 08, 2021 at 03:50:00PM -0800, Junio C Hamano wrote: > Patrick Steinhardt <ps@pks.im> writes: [snip] > > ret = ref_transaction_commit(transaction, &err); > > if (ret) { > > - df_conflict = (ret == TRANSACTION_NAME_CONFLICT); > > - goto fail; > > + ret = (ret == TRANSACTION_NAME_CONFLICT) ? STORE_REF_ERROR_DF_CONFLICT > > + : STORE_REF_ERROR_OTHER; > > + goto out; > > } > > > > +out: > > ref_transaction_free(transaction); > > It is a bit funny to see a goto that jumps to the label without > having anything else in between, but we know we will be adding more > code just before the "out:" label, so it is a good preliminary > preparation. > > I think a variant that is much easier to follow would be to write > like this instead: > > switch (ref_transaction_commit(transaction, &err)) { > case 0: /* happy */ > break; > case TRANSACTION_NAME_CONFLICT: > ret = STORE_REF_ERROR_DF_CONFLICT; > goto out; > default: > ret = STORE_REF_ERROR_OTHER; > goto out; > } Agreed, that is easier to read. Thanks! Patrick
diff --git a/builtin/fetch.c b/builtin/fetch.c index 557ec130db..5221a9dbed 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -589,7 +589,7 @@ static int s_update_ref(const char *action, char *rla = getenv("GIT_REFLOG_ACTION"); struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; - int ret, df_conflict = 0; + int ret; if (dry_run) return 0; @@ -598,30 +598,33 @@ static int s_update_ref(const char *action, msg = xstrfmt("%s: %s", rla, action); transaction = ref_transaction_begin(&err); - if (!transaction || - ref_transaction_update(transaction, ref->name, - &ref->new_oid, - check_old ? &ref->old_oid : NULL, - 0, msg, &err)) - goto fail; + if (!transaction) { + ret = STORE_REF_ERROR_OTHER; + goto out; + } + + ret = ref_transaction_update(transaction, ref->name, &ref->new_oid, + check_old ? &ref->old_oid : NULL, + 0, msg, &err); + if (ret) { + ret = STORE_REF_ERROR_OTHER; + goto out; + } ret = ref_transaction_commit(transaction, &err); if (ret) { - df_conflict = (ret == TRANSACTION_NAME_CONFLICT); - goto fail; + ret = (ret == TRANSACTION_NAME_CONFLICT) ? STORE_REF_ERROR_DF_CONFLICT + : STORE_REF_ERROR_OTHER; + goto out; } +out: ref_transaction_free(transaction); + if (ret) + error("%s", err.buf); strbuf_release(&err); free(msg); - return 0; -fail: - ref_transaction_free(transaction); - error("%s", err.buf); - strbuf_release(&err); - free(msg); - return df_conflict ? STORE_REF_ERROR_DF_CONFLICT - : STORE_REF_ERROR_OTHER; + return ret; } static int refcol_width = 10;
The cleanup code in `s_update_ref()` is currently duplicated for both succesful and erroneous exit paths. This commit refactors the function to have a shared exit path for both cases to remove the duplication. Suggested-by: Christian Couder <christian.couder@gmail.com> Signed-off-by: Patrick Steinhardt <ps@pks.im> --- builtin/fetch.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-)