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;