refs: add create_only option to refs_update_symref_extended
Allow the caller to specify that it only wants to update the symref if it does not already exist. Silently ignore the error from the transaction API if the symref already exists. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Bence Ferdinandy committed
Nov 22, 2024 at 13:28 UTC
9963746c841dc786529827b7b6755d0a3e208ad4
3 files changed
+26
-11
builtin/remote.c
+1
-1
@@ -1476,7 +1476,7 @@ static int set_head(int argc, const char **argv, const char *prefix)
1476
goto cleanup;
1477
}
1478
was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
1479
- "remote set-head", &b_local_head);
1479
+ "remote set-head", &b_local_head, 0);
1480
if (was_detached == -1) {
1481
result |= error(_("Could not set up %s"), b_head.buf);
1482
goto cleanup;
refs.c
+24
-9
@@ -2116,26 +2116,38 @@ int peel_iterated_oid(struct repository *r, const struct object_id *base, struct
2116
int refs_update_symref(struct ref_store *refs, const char *ref,
2117
const char *target, const char *logmsg)
2118
{
2119
- return refs_update_symref_extended(refs, ref, target, logmsg, NULL);
2119
+ return refs_update_symref_extended(refs, ref, target, logmsg, NULL, 0);
2120
}
2121
2122
int refs_update_symref_extended(struct ref_store *refs, const char *ref,
2123
const char *target, const char *logmsg,
2124
- struct strbuf *referent)
2124
+ struct strbuf *referent, int create_only)
2125
{
2126
struct ref_transaction *transaction;
2127
struct strbuf err = STRBUF_INIT;
2128
- int ret = 0;
2128
+ int ret = 0, prepret = 0;
2129
2130
transaction = ref_store_transaction_begin(refs, &err);
2131
- if (!transaction ||
2132
- ref_transaction_update(transaction, ref, NULL, NULL,
2133
- target, NULL, REF_NO_DEREF,
2134
- logmsg, &err) ||
2135
- ref_transaction_prepare(transaction, &err)) {
2131
+ if (!transaction) {
2132
+ error_return:
2133
ret = error("%s", err.buf);
2134
goto cleanup;
2135
}
2136
+ if (create_only) {
2137
+ if (ref_transaction_create(transaction, ref, NULL, target,
2138
+ REF_NO_DEREF, logmsg, &err))
2139
+ goto error_return;
2140
+ prepret = ref_transaction_prepare(transaction, &err);
2141
+ if (prepret && prepret != TRANSACTION_CREATE_EXISTS)
2142
+ goto error_return;
2143
+ } else {
2144
+ if (ref_transaction_update(transaction, ref, NULL, NULL,
2145
+ target, NULL, REF_NO_DEREF,
2146
+ logmsg, &err) ||
2147
+ ref_transaction_prepare(transaction, &err))
2148
+ goto error_return;
2149
+ }
2150
+
2151
if (referent && refs_read_symbolic_ref(refs, ref, referent) == NOT_A_SYMREF) {
2152
struct object_id oid;
2153
if (!refs_read_ref(refs, ref, &oid)) {
@@ -2144,8 +2156,11 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref,
2156
}
2157
}
2158
2159
+ if (prepret == TRANSACTION_CREATE_EXISTS)
2160
+ goto cleanup;
2161
+
2162
if (ref_transaction_commit(transaction, &err))
2148
- ret = error("%s", err.buf);
2163
+ goto error_return;
2164
2165
cleanup:
2166
strbuf_release(&err);
refs.h
+1
-1
@@ -586,7 +586,7 @@ int refs_update_symref(struct ref_store *refs, const char *refname,
586
587
int refs_update_symref_extended(struct ref_store *refs, const char *refname,
588
const char *target, const char *logmsg,
589
- struct strbuf *referent);
589
+ struct strbuf *referent, int create_only);
590
591
enum action_on_err {
592
UPDATE_REFS_MSG_ON_ERR,