return ret;
}
-int refs_verify_refname_available(struct ref_store *refs,
- const char *refname,
- const struct string_list *extras,
- const struct string_list *skip,
- unsigned int initial_transaction,
- struct strbuf *err)
+int refs_verify_refnames_available(struct ref_store *refs,
+ const struct string_list *refnames,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err)
{
- const char *slash;
- const char *extra_refname;
struct strbuf dirname = STRBUF_INIT;
struct strbuf referent = STRBUF_INIT;
- struct object_id oid;
- unsigned int type;
+ struct string_list_item *item;
int ret = -1;
/*
assert(err);
- strbuf_grow(&dirname, strlen(refname) + 1);
- for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
- /*
- * Just saying "Is a directory" when we e.g. can't
- * lock some multi-level ref isn't very informative,
- * the user won't be told *what* is a directory, so
- * let's not use strerror() below.
- */
- int ignore_errno;
- /* Expand dirname to the new prefix, not including the trailing slash: */
- strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
+ for_each_string_list_item(item, refnames) {
+ const char *refname = item->string;
+ const char *extra_refname;
+ struct object_id oid;
+ unsigned int type;
+ const char *slash;
+
+ strbuf_reset(&dirname);
+
+ for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
+ /*
+ * Just saying "Is a directory" when we e.g. can't
+ * lock some multi-level ref isn't very informative,
+ * the user won't be told *what* is a directory, so
+ * let's not use strerror() below.
+ */
+ int ignore_errno;
+
+ /* Expand dirname to the new prefix, not including the trailing slash: */
+ strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
+
+ /*
+ * We are still at a leading dir of the refname (e.g.,
+ * "refs/foo"; if there is a reference with that name,
+ * it is a conflict, *unless* it is in skip.
+ */
+ if (skip && string_list_has_string(skip, dirname.buf))
+ continue;
+
+ if (!initial_transaction &&
+ !refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
+ &type, &ignore_errno)) {
+ strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
+ dirname.buf, refname);
+ goto cleanup;
+ }
+
+ if (extras && string_list_has_string(extras, dirname.buf)) {
+ strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
+ refname, dirname.buf);
+ goto cleanup;
+ }
+ }
/*
- * We are still at a leading dir of the refname (e.g.,
- * "refs/foo"; if there is a reference with that name,
- * it is a conflict, *unless* it is in skip.
+ * We are at the leaf of our refname (e.g., "refs/foo/bar").
+ * There is no point in searching for a reference with that
+ * name, because a refname isn't considered to conflict with
+ * itself. But we still need to check for references whose
+ * names are in the "refs/foo/bar/" namespace, because they
+ * *do* conflict.
*/
- if (skip && string_list_has_string(skip, dirname.buf))
- continue;
+ strbuf_addstr(&dirname, refname + dirname.len);
+ strbuf_addch(&dirname, '/');
+
+ if (!initial_transaction) {
+ struct ref_iterator *iter;
+ int ok;
+
+ iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
+ DO_FOR_EACH_INCLUDE_BROKEN);
+ while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
+ if (skip &&
+ string_list_has_string(skip, iter->refname))
+ continue;
+
+ strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
+ iter->refname, refname);
+ ref_iterator_abort(iter);
+ goto cleanup;
+ }
- if (!initial_transaction &&
- !refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
- &type, &ignore_errno)) {
- strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
- dirname.buf, refname);
- goto cleanup;
+ if (ok != ITER_DONE)
+ BUG("error while iterating over references");
}
- if (extras && string_list_has_string(extras, dirname.buf)) {
+ extra_refname = find_descendant_ref(dirname.buf, extras, skip);
+ if (extra_refname) {
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
- refname, dirname.buf);
+ refname, extra_refname);
goto cleanup;
}
}
- /*
- * We are at the leaf of our refname (e.g., "refs/foo/bar").
- * There is no point in searching for a reference with that
- * name, because a refname isn't considered to conflict with
- * itself. But we still need to check for references whose
- * names are in the "refs/foo/bar/" namespace, because they
- * *do* conflict.
- */
- strbuf_addstr(&dirname, refname + dirname.len);
- strbuf_addch(&dirname, '/');
-
- if (!initial_transaction) {
- struct ref_iterator *iter;
- int ok;
-
- iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
- DO_FOR_EACH_INCLUDE_BROKEN);
- while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
- if (skip &&
- string_list_has_string(skip, iter->refname))
- continue;
-
- strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
- iter->refname, refname);
- ref_iterator_abort(iter);
- goto cleanup;
- }
-
- if (ok != ITER_DONE)
- BUG("error while iterating over references");
- }
-
- extra_refname = find_descendant_ref(dirname.buf, extras, skip);
- if (extra_refname)
- strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
- refname, extra_refname);
- else
- ret = 0;
+ ret = 0;
cleanup:
strbuf_release(&referent);
return ret;
}
+int refs_verify_refname_available(struct ref_store *refs,
+ const char *refname,
+ const struct string_list *extras,
+ const struct string_list *skip,
+ unsigned int initial_transaction,
+ struct strbuf *err)
+{
+ struct string_list_item item = { .string = (char *) refname };
+ struct string_list refnames = {
+ .items = &item,
+ .nr = 1,
+ };
+
+ return refs_verify_refnames_available(refs, &refnames, extras, skip,
+ initial_transaction, err);
+}
+
struct do_for_each_reflog_help {
each_reflog_fn *fn;
void *cb_data;