refs_verify_refname_available(): implement once for all backends

It turns out that we can now implement `refs_verify_refname_available()` based on the other virtual functions, so there is no need for it to be defined at the backend level. Instead, define it once in `refs.c` and remove the `files_backend` definition. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Apr 16, 2017 at 08:41 UTC b05855b5bcaf07fe8a636e621bd9d12d51963b5a
4 files changed +92 -41
refs.c
+83 -2
@@ -5,6 +5,7 @@
5 #include "cache.h"
6 #include "hashmap.h"
7 #include "lockfile.h"
8 +#include "iterator.h"
9 #include "refs.h"
10 #include "refs/refs-internal.h"
11 #include "object.h"
@@ -1658,11 +1659,91 @@ int ref_transaction_commit(struct ref_transaction *transaction,
1659
1660 int refs_verify_refname_available(struct ref_store *refs,
1661 const char *refname,
1661 - const struct string_list *extra,
1662 + const struct string_list *extras,
1663 const struct string_list *skip,
1664 struct strbuf *err)
1665 {
1665 - return refs->be->verify_refname_available(refs, refname, extra, skip, err);
1666 + const char *slash;
1667 + const char *extra_refname;
1668 + struct strbuf dirname = STRBUF_INIT;
1669 + struct strbuf referent = STRBUF_INIT;
1670 + struct object_id oid;
1671 + unsigned int type;
1672 + struct ref_iterator *iter;
1673 + int ok;
1674 + int ret = -1;
1675 +
1676 + /*
1677 + * For the sake of comments in this function, suppose that
1678 + * refname is "refs/foo/bar".
1679 + */
1680 +
1681 + assert(err);
1682 +
1683 + strbuf_grow(&dirname, strlen(refname) + 1);
1684 + for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
1685 + /* Expand dirname to the new prefix, not including the trailing slash: */
1686 + strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
1687 +
1688 + /*
1689 + * We are still at a leading dir of the refname (e.g.,
1690 + * "refs/foo"; if there is a reference with that name,
1691 + * it is a conflict, *unless* it is in skip.
1692 + */
1693 + if (skip && string_list_has_string(skip, dirname.buf))
1694 + continue;
1695 +
1696 + if (!refs_read_raw_ref(refs, dirname.buf, oid.hash, &referent, &type)) {
1697 + strbuf_addf(err, "'%s' exists; cannot create '%s'",
1698 + dirname.buf, refname);
1699 + goto cleanup;
1700 + }
1701 +
1702 + if (extras && string_list_has_string(extras, dirname.buf)) {
1703 + strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
1704 + refname, dirname.buf);
1705 + goto cleanup;
1706 + }
1707 + }
1708 +
1709 + /*
1710 + * We are at the leaf of our refname (e.g., "refs/foo/bar").
1711 + * There is no point in searching for a reference with that
1712 + * name, because a refname isn't considered to conflict with
1713 + * itself. But we still need to check for references whose
1714 + * names are in the "refs/foo/bar/" namespace, because they
1715 + * *do* conflict.
1716 + */
1717 + strbuf_addstr(&dirname, refname + dirname.len);
1718 + strbuf_addch(&dirname, '/');
1719 +
1720 + iter = refs_ref_iterator_begin(refs, dirname.buf, 0,
1721 + DO_FOR_EACH_INCLUDE_BROKEN);
1722 + while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
1723 + if (skip &&
1724 + string_list_has_string(skip, iter->refname))
1725 + continue;
1726 +
1727 + strbuf_addf(err, "'%s' exists; cannot create '%s'",
1728 + iter->refname, refname);
1729 + ref_iterator_abort(iter);
1730 + goto cleanup;
1731 + }
1732 +
1733 + if (ok != ITER_DONE)
1734 + die("BUG: error while iterating over references");
1735 +
1736 + extra_refname = find_descendant_ref(dirname.buf, extras, skip);
1737 + if (extra_refname)
1738 + strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
1739 + refname, extra_refname);
1740 + else
1741 + ret = 0;
1742 +
1743 +cleanup:
1744 + strbuf_release(&referent);
1745 + strbuf_release(&dirname);
1746 + return ret;
1747 }
1748
1749 int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
refs.h
+1 -1
@@ -97,7 +97,7 @@ int read_ref(const char *refname, unsigned char *sha1);
97
98 int refs_verify_refname_available(struct ref_store *refs,
99 const char *refname,
100 - const struct string_list *extra,
100 + const struct string_list *extras,
101 const struct string_list *skip,
102 struct strbuf *err);
103
refs/files-backend.c
+8 -31
@@ -1724,10 +1724,9 @@ retry:
1724 goto error_return;
1725 } else if (remove_dir_recursively(&ref_file,
1726 REMOVE_DIR_EMPTY_ONLY)) {
1727 - if (verify_refname_available_dir(
1728 - refname, extras, skip,
1729 - get_loose_refs(refs),
1730 - err)) {
1727 + if (refs_verify_refname_available(
1728 + &refs->base, refname,
1729 + extras, skip, err)) {
1730 /*
1731 * The error message set by
1732 * verify_refname_available() is OK.
@@ -2094,9 +2093,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2093 */
2094 if (remove_empty_directories(&ref_file)) {
2095 last_errno = errno;
2097 - if (!verify_refname_available_dir(
2098 - refname, extras, skip,
2099 - get_loose_refs(refs), err))
2096 + if (!refs_verify_refname_available(
2097 + &refs->base,
2098 + refname, extras, skip, err))
2099 strbuf_addf(err, "there are still refs under '%s'",
2100 refname);
2101 goto error_return;
@@ -2108,9 +2107,8 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
2107 if (!resolved) {
2108 last_errno = errno;
2109 if (last_errno != ENOTDIR ||
2111 - !verify_refname_available_dir(
2112 - refname, extras, skip,
2113 - get_loose_refs(refs), err))
2110 + !refs_verify_refname_available(&refs->base, refname,
2111 + extras, skip, err))
2112 strbuf_addf(err, "unable to resolve reference '%s': %s",
2113 refname, strerror(last_errno));
2114
@@ -2606,26 +2604,6 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
2604 return ret;
2605 }
2606
2609 -static int files_verify_refname_available(struct ref_store *ref_store,
2610 - const char *newname,
2611 - const struct string_list *extras,
2612 - const struct string_list *skip,
2613 - struct strbuf *err)
2614 -{
2615 - struct files_ref_store *refs =
2616 - files_downcast(ref_store, REF_STORE_READ, "verify_refname_available");
2617 - struct ref_dir *packed_refs = get_packed_refs(refs);
2618 - struct ref_dir *loose_refs = get_loose_refs(refs);
2619 -
2620 - if (verify_refname_available_dir(newname, extras, skip,
2621 - packed_refs, err) ||
2622 - verify_refname_available_dir(newname, extras, skip,
2623 - loose_refs, err))
2624 - return -1;
2625 -
2626 - return 0;
2627 -}
2628 -
2607 static int write_ref_to_lockfile(struct ref_lock *lock,
2608 const unsigned char *sha1, struct strbuf *err);
2609 static int commit_ref_update(struct files_ref_store *refs,
@@ -4288,7 +4266,6 @@ struct ref_storage_be refs_be_files = {
4266
4267 files_ref_iterator_begin,
4268 files_read_raw_ref,
4291 - files_verify_refname_available,
4269
4270 files_reflog_iterator_begin,
4271 files_for_each_reflog_ent,
refs/refs-internal.h
-7
@@ -590,12 +590,6 @@ typedef int read_raw_ref_fn(struct ref_store *ref_store,
590 const char *refname, unsigned char *sha1,
591 struct strbuf *referent, unsigned int *type);
592
593 -typedef int verify_refname_available_fn(struct ref_store *ref_store,
594 - const char *newname,
595 - const struct string_list *extras,
596 - const struct string_list *skip,
597 - struct strbuf *err);
598 -
593 struct ref_storage_be {
594 struct ref_storage_be *next;
595 const char *name;
@@ -612,7 +606,6 @@ struct ref_storage_be {
606
607 ref_iterator_begin_fn *iterator_begin;
608 read_raw_ref_fn *read_raw_ref;
615 - verify_refname_available_fn *verify_refname_available;
609
610 reflog_iterator_begin_fn *reflog_iterator_begin;
611 for_each_reflog_ent_fn *for_each_reflog_ent;