Skip to content

Commit b05855b

Browse files
mhaggergitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e121b9c commit b05855b

File tree

4 files changed

+92
-41
lines changed

4 files changed

+92
-41
lines changed

refs.c

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "cache.h"
66
#include "hashmap.h"
77
#include "lockfile.h"
8+
#include "iterator.h"
89
#include "refs.h"
910
#include "refs/refs-internal.h"
1011
#include "object.h"
@@ -1658,11 +1659,91 @@ int ref_transaction_commit(struct ref_transaction *transaction,
16581659

16591660
int refs_verify_refname_available(struct ref_store *refs,
16601661
const char *refname,
1661-
const struct string_list *extra,
1662+
const struct string_list *extras,
16621663
const struct string_list *skip,
16631664
struct strbuf *err)
16641665
{
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;
16661747
}
16671748

16681749
int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)

refs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ int read_ref(const char *refname, unsigned char *sha1);
9797

9898
int refs_verify_refname_available(struct ref_store *refs,
9999
const char *refname,
100-
const struct string_list *extra,
100+
const struct string_list *extras,
101101
const struct string_list *skip,
102102
struct strbuf *err);
103103

refs/files-backend.c

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,10 +1724,9 @@ static int lock_raw_ref(struct files_ref_store *refs,
17241724
goto error_return;
17251725
} else if (remove_dir_recursively(&ref_file,
17261726
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)) {
17311730
/*
17321731
* The error message set by
17331732
* verify_refname_available() is OK.
@@ -2094,9 +2093,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
20942093
*/
20952094
if (remove_empty_directories(&ref_file)) {
20962095
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))
21002099
strbuf_addf(err, "there are still refs under '%s'",
21012100
refname);
21022101
goto error_return;
@@ -2108,9 +2107,8 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
21082107
if (!resolved) {
21092108
last_errno = errno;
21102109
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))
21142112
strbuf_addf(err, "unable to resolve reference '%s': %s",
21152113
refname, strerror(last_errno));
21162114

@@ -2606,26 +2604,6 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname)
26062604
return ret;
26072605
}
26082606

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-
26292607
static int write_ref_to_lockfile(struct ref_lock *lock,
26302608
const unsigned char *sha1, struct strbuf *err);
26312609
static int commit_ref_update(struct files_ref_store *refs,
@@ -4288,7 +4266,6 @@ struct ref_storage_be refs_be_files = {
42884266

42894267
files_ref_iterator_begin,
42904268
files_read_raw_ref,
4291-
files_verify_refname_available,
42924269

42934270
files_reflog_iterator_begin,
42944271
files_for_each_reflog_ent,

refs/refs-internal.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -590,12 +590,6 @@ typedef int read_raw_ref_fn(struct ref_store *ref_store,
590590
const char *refname, unsigned char *sha1,
591591
struct strbuf *referent, unsigned int *type);
592592

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-
599593
struct ref_storage_be {
600594
struct ref_storage_be *next;
601595
const char *name;
@@ -612,7 +606,6 @@ struct ref_storage_be {
612606

613607
ref_iterator_begin_fn *iterator_begin;
614608
read_raw_ref_fn *read_raw_ref;
615-
verify_refname_available_fn *verify_refname_available;
616609

617610
reflog_iterator_begin_fn *reflog_iterator_begin;
618611
for_each_reflog_ent_fn *for_each_reflog_ent;

0 commit comments

Comments
 (0)