aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--builtin/remote.c2
-rw-r--r--refs.c33
-rw-r--r--refs.h2
3 files changed, 26 insertions, 11 deletions
diff --git a/builtin/remote.c b/builtin/remote.c
index 6d659d63ca..3dc1135b5c 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1476,7 +1476,7 @@ static int set_head(int argc, const char **argv, const char *prefix)
goto cleanup;
}
was_detached = refs_update_symref_extended(refs, b_head.buf, b_remote_head.buf,
- "remote set-head", &b_local_head);
+ "remote set-head", &b_local_head, 0);
if (was_detached == -1) {
result |= error(_("Could not set up %s"), b_head.buf);
goto cleanup;
diff --git a/refs.c b/refs.c
index d80efd58f0..2efa6bcc5c 100644
--- a/refs.c
+++ b/refs.c
@@ -2116,26 +2116,38 @@ int peel_iterated_oid(struct repository *r, const struct object_id *base, struct
int refs_update_symref(struct ref_store *refs, const char *ref,
const char *target, const char *logmsg)
{
- return refs_update_symref_extended(refs, ref, target, logmsg, NULL);
+ return refs_update_symref_extended(refs, ref, target, logmsg, NULL, 0);
}
int refs_update_symref_extended(struct ref_store *refs, const char *ref,
const char *target, const char *logmsg,
- struct strbuf *referent)
+ struct strbuf *referent, int create_only)
{
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
- int ret = 0;
+ int ret = 0, prepret = 0;
transaction = ref_store_transaction_begin(refs, &err);
- if (!transaction ||
- ref_transaction_update(transaction, ref, NULL, NULL,
- target, NULL, REF_NO_DEREF,
- logmsg, &err) ||
- ref_transaction_prepare(transaction, &err)) {
+ if (!transaction) {
+ error_return:
ret = error("%s", err.buf);
goto cleanup;
}
+ if (create_only) {
+ if (ref_transaction_create(transaction, ref, NULL, target,
+ REF_NO_DEREF, logmsg, &err))
+ goto error_return;
+ prepret = ref_transaction_prepare(transaction, &err);
+ if (prepret && prepret != TRANSACTION_CREATE_EXISTS)
+ goto error_return;
+ } else {
+ if (ref_transaction_update(transaction, ref, NULL, NULL,
+ target, NULL, REF_NO_DEREF,
+ logmsg, &err) ||
+ ref_transaction_prepare(transaction, &err))
+ goto error_return;
+ }
+
if (referent && refs_read_symbolic_ref(refs, ref, referent) == NOT_A_SYMREF) {
struct object_id oid;
if (!refs_read_ref(refs, ref, &oid)) {
@@ -2144,8 +2156,11 @@ int refs_update_symref_extended(struct ref_store *refs, const char *ref,
}
}
+ if (prepret == TRANSACTION_CREATE_EXISTS)
+ goto cleanup;
+
if (ref_transaction_commit(transaction, &err))
- ret = error("%s", err.buf);
+ goto error_return;
cleanup:
strbuf_release(&err);
diff --git a/refs.h b/refs.h
index b243739e4b..be38377b1f 100644
--- a/refs.h
+++ b/refs.h
@@ -586,7 +586,7 @@ int refs_update_symref(struct ref_store *refs, const char *refname,
int refs_update_symref_extended(struct ref_store *refs, const char *refname,
const char *target, const char *logmsg,
- struct strbuf *referent);
+ struct strbuf *referent, int create_only);
enum action_on_err {
UPDATE_REFS_MSG_ON_ERR,