THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Browse Source

Merge branch 'ew/hashmap'

Code clean-up of the hashmap API, both users and implementation.

* ew/hashmap:
  hashmap_entry: remove first member requirement from docs
  hashmap: remove type arg from hashmap_{get,put,remove}_entry
  OFFSETOF_VAR macro to simplify hashmap iterators
  hashmap: introduce hashmap_free_entries
  hashmap: hashmap_{put,remove} return hashmap_entry *
  hashmap: use *_entry APIs for iteration
  hashmap_cmp_fn takes hashmap_entry params
  hashmap_get{,_from_hash} return "struct hashmap_entry *"
  hashmap: use *_entry APIs to wrap container_of
  hashmap_get_next returns "struct hashmap_entry *"
  introduce container_of macro
  hashmap_put takes "struct hashmap_entry *"
  hashmap_remove takes "const struct hashmap_entry *"
  hashmap_get takes "const struct hashmap_entry *"
  hashmap_add takes "struct hashmap_entry *"
  hashmap_get_next takes "const struct hashmap_entry *"
  hashmap_entry_init takes "struct hashmap_entry *"
  packfile: use hashmap_entry in delta_base_cache_entry
  coccicheck: detect hashmap_entry.hash assignment
  diff: use hashmap_entry_init on moved_entry.ent
tags/v2.24.0-rc0
Junio C Hamano 1 month ago
parent
commit
5efabc7ed9
31 changed files with 667 additions and 381 deletions
  1. +13
    -11
      attr.c
  2. +14
    -11
      blame.c
  3. +12
    -9
      builtin/describe.c
  4. +32
    -24
      builtin/difftool.c
  5. +10
    -5
      builtin/fast-export.c
  6. +18
    -14
      builtin/fetch.c
  7. +13
    -11
      config.c
  8. +16
    -0
      contrib/coccinelle/hashmap.cocci
  9. +18
    -13
      diff.c
  10. +7
    -8
      diffcore-rename.c
  11. +38
    -0
      git-compat-util.h
  12. +37
    -21
      hashmap.c
  13. +141
    -35
      hashmap.h
  14. +51
    -40
      merge-recursive.c
  15. +31
    -26
      name-hash.c
  16. +13
    -7
      oidmap.c
  17. +4
    -2
      oidmap.h
  18. +14
    -8
      packfile.c
  19. +10
    -8
      patch-ids.c
  20. +5
    -5
      range-diff.c
  21. +20
    -13
      ref-filter.c
  22. +18
    -7
      refs.c
  23. +12
    -9
      remote.c
  24. +1
    -1
      remote.h
  25. +16
    -12
      revision.c
  26. +29
    -15
      sequencer.c
  27. +11
    -9
      sub-process.c
  28. +3
    -3
      sub-process.h
  29. +29
    -23
      submodule-config.c
  30. +27
    -23
      t/helper/test-hashmap.c
  31. +4
    -8
      t/helper/test-lazy-init-name-hash.c

+ 13
- 11
attr.c View File

@@ -62,7 +62,7 @@ static struct attr_hashmap g_attr_hashmap;

/* The container for objects stored in "struct attr_hashmap" */
struct attr_hash_entry {
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;
const char *key; /* the key; memory should be owned by value */
size_t keylen; /* length of the key */
void *value; /* the stored value */
@@ -70,12 +70,14 @@ struct attr_hash_entry {

/* attr_hashmap comparison function */
static int attr_hash_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct attr_hash_entry *a = entry;
const struct attr_hash_entry *b = entry_or_key;
const struct attr_hash_entry *a, *b;

a = container_of(eptr, const struct attr_hash_entry, ent);
b = container_of(entry_or_key, const struct attr_hash_entry, ent);
return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
}

@@ -98,10 +100,10 @@ static void *attr_hashmap_get(struct attr_hashmap *map,
if (!map->map.tablesize)
attr_hashmap_init(map);

hashmap_entry_init(&k, memhash(key, keylen));
hashmap_entry_init(&k.ent, memhash(key, keylen));
k.key = key;
k.keylen = keylen;
e = hashmap_get(&map->map, &k, NULL);
e = hashmap_get_entry(&map->map, &k, ent, NULL);

return e ? e->value : NULL;
}
@@ -117,12 +119,12 @@ static void attr_hashmap_add(struct attr_hashmap *map,
attr_hashmap_init(map);

e = xmalloc(sizeof(struct attr_hash_entry));
hashmap_entry_init(e, memhash(key, keylen));
hashmap_entry_init(&e->ent, memhash(key, keylen));
e->key = key;
e->keylen = keylen;
e->value = value;

hashmap_add(&map->map, e);
hashmap_add(&map->map, &e->ent);
}

struct all_attrs_item {
@@ -161,12 +163,12 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
if (size != check->all_attrs_nr) {
struct attr_hash_entry *e;
struct hashmap_iter iter;
hashmap_iter_init(&map->map, &iter);

REALLOC_ARRAY(check->all_attrs, size);
check->all_attrs_nr = size;

while ((e = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&map->map, &iter, e,
ent /* member name */) {
const struct git_attr *a = e->value;
check->all_attrs[a->attr_nr].attr = a;
}


+ 14
- 11
blame.c View File

@@ -417,14 +417,15 @@ static void get_fingerprint(struct fingerprint *result,
/* Ignore whitespace pairs */
if (hash == 0)
continue;
hashmap_entry_init(entry, hash);
hashmap_entry_init(&entry->entry, hash);

found_entry = hashmap_get(&result->map, entry, NULL);
found_entry = hashmap_get_entry(&result->map, entry,
/* member name */ entry, NULL);
if (found_entry) {
found_entry->count += 1;
} else {
entry->count = 1;
hashmap_add(&result->map, entry);
hashmap_add(&result->map, &entry->entry);
++entry;
}
}
@@ -432,7 +433,7 @@ static void get_fingerprint(struct fingerprint *result,

static void free_fingerprint(struct fingerprint *f)
{
hashmap_free(&f->map, 0);
hashmap_free(&f->map);
free(f->entries);
}

@@ -449,10 +450,10 @@ static int fingerprint_similarity(struct fingerprint *a, struct fingerprint *b)
struct hashmap_iter iter;
const struct fingerprint_entry *entry_a, *entry_b;

hashmap_iter_init(&b->map, &iter);
while ((entry_b = hashmap_iter_next(&iter))) {
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
hashmap_for_each_entry(&b->map, &iter, entry_b,
entry /* member name */) {
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
if (entry_a) {
intersection += entry_a->count < entry_b->count ?
entry_a->count : entry_b->count;
}
@@ -470,10 +471,12 @@ static void fingerprint_subtract(struct fingerprint *a, struct fingerprint *b)

hashmap_iter_init(&b->map, &iter);

while ((entry_b = hashmap_iter_next(&iter))) {
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
hashmap_for_each_entry(&b->map, &iter, entry_b,
entry /* member name */) {
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
if (entry_a) {
if (entry_a->count <= entry_b->count)
hashmap_remove(&a->map, entry_b, NULL);
hashmap_remove(&a->map, &entry_b->entry, NULL);
else
entry_a->count -= entry_b->count;
}


+ 12
- 9
builtin/describe.c View File

@@ -63,19 +63,22 @@ static const char *prio_names[] = {
};

static int commit_name_neq(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *peeled)
{
const struct commit_name *cn1 = entry;
const struct commit_name *cn2 = entry_or_key;
const struct commit_name *cn1, *cn2;

cn1 = container_of(eptr, const struct commit_name, entry);
cn2 = container_of(entry_or_key, const struct commit_name, entry);

return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled);
}

static inline struct commit_name *find_commit_name(const struct object_id *peeled)
{
return hashmap_get_from_hash(&names, oidhash(peeled), peeled);
return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled,
struct commit_name, entry);
}

static int replace_name(struct commit_name *e,
@@ -122,8 +125,8 @@ static void add_to_known_names(const char *path,
if (!e) {
e = xmalloc(sizeof(struct commit_name));
oidcpy(&e->peeled, peeled);
hashmap_entry_init(e, oidhash(peeled));
hashmap_add(&names, e);
hashmap_entry_init(&e->entry, oidhash(peeled));
hashmap_add(&names, &e->entry);
e->path = NULL;
}
e->tag = tag;
@@ -329,8 +332,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
struct commit_name *n;

init_commit_names(&commit_names);
n = hashmap_iter_first(&names, &iter);
for (; n; n = hashmap_iter_next(&iter)) {
hashmap_for_each_entry(&names, &iter, n,
entry /* member name */) {
c = lookup_commit_reference_gently(the_repository,
&n->peeled, 1);
if (c)


+ 32
- 24
builtin/difftool.c View File

@@ -125,12 +125,15 @@ struct working_tree_entry {
};

static int working_tree_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct working_tree_entry *a = entry;
const struct working_tree_entry *b = entry_or_key;
const struct working_tree_entry *a, *b;

a = container_of(eptr, const struct working_tree_entry, entry);
b = container_of(entry_or_key, const struct working_tree_entry, entry);

return strcmp(a->path, b->path);
}

@@ -145,12 +148,14 @@ struct pair_entry {
};

static int pair_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct pair_entry *a = entry;
const struct pair_entry *b = entry_or_key;
const struct pair_entry *a, *b;

a = container_of(eptr, const struct pair_entry, entry);
b = container_of(entry_or_key, const struct pair_entry, entry);

return strcmp(a->path, b->path);
}
@@ -161,14 +166,14 @@ static void add_left_or_right(struct hashmap *map, const char *path,
struct pair_entry *e, *existing;

FLEX_ALLOC_STR(e, path, path);
hashmap_entry_init(e, strhash(path));
existing = hashmap_get(map, e, NULL);
hashmap_entry_init(&e->entry, strhash(path));
existing = hashmap_get_entry(map, e, entry, NULL);
if (existing) {
free(e);
e = existing;
} else {
e->left[0] = e->right[0] = '\0';
hashmap_add(map, e);
hashmap_add(map, &e->entry);
}
strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
}
@@ -179,12 +184,14 @@ struct path_entry {
};

static int path_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *key)
{
const struct path_entry *a = entry;
const struct path_entry *b = entry_or_key;
const struct path_entry *a, *b;

a = container_of(eptr, const struct path_entry, entry);
b = container_of(entry_or_key, const struct path_entry, entry);

return strcmp(a->path, key ? key : b->path);
}
@@ -234,8 +241,8 @@ static void changed_files(struct hashmap *result, const char *index_path,
while (!strbuf_getline_nul(&buf, fp)) {
struct path_entry *entry;
FLEX_ALLOC_STR(entry, path, buf.buf);
hashmap_entry_init(entry, strhash(buf.buf));
hashmap_add(result, entry);
hashmap_entry_init(&entry->entry, strhash(buf.buf));
hashmap_add(result, &entry->entry);
}
fclose(fp);
if (finish_command(&diff_files))
@@ -461,12 +468,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,

/* Avoid duplicate working_tree entries */
FLEX_ALLOC_STR(entry, path, dst_path);
hashmap_entry_init(entry, strhash(dst_path));
if (hashmap_get(&working_tree_dups, entry, NULL)) {
hashmap_entry_init(&entry->entry, strhash(dst_path));
if (hashmap_get(&working_tree_dups, &entry->entry,
NULL)) {
free(entry);
continue;
}
hashmap_add(&working_tree_dups, entry);
hashmap_add(&working_tree_dups, &entry->entry);

if (!use_wt_file(workdir, dst_path, &roid)) {
if (checkout_path(rmode, &roid, dst_path,
@@ -530,8 +538,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
* temporary file to both the left and right directories to show the
* change in the recorded SHA1 for the submodule.
*/
hashmap_iter_init(&submodules, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&submodules, &iter, entry,
entry /* member name */) {
if (*entry->left) {
add_path(&ldir, ldir_len, entry->path);
ensure_leading_directories(ldir.buf);
@@ -549,8 +557,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
* shows only the link itself, not the contents of the link target.
* This loop replicates that behavior.
*/
hashmap_iter_init(&symlinks2, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&symlinks2, &iter, entry,
entry /* member name */) {
if (*entry->left) {
add_path(&ldir, ldir_len, entry->path);
ensure_leading_directories(ldir.buf);


+ 10
- 5
builtin/fast-export.c View File

@@ -127,10 +127,15 @@ struct anonymized_entry {
};

static int anonymized_entry_cmp(const void *unused_cmp_data,
const void *va, const void *vb,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct anonymized_entry *a = va, *b = vb;
const struct anonymized_entry *a, *b;

a = container_of(eptr, const struct anonymized_entry, hash);
b = container_of(entry_or_key, const struct anonymized_entry, hash);

return a->orig_len != b->orig_len ||
memcmp(a->orig, b->orig, a->orig_len);
}
@@ -149,10 +154,10 @@ static const void *anonymize_mem(struct hashmap *map,
if (!map->cmpfn)
hashmap_init(map, anonymized_entry_cmp, NULL, 0);

hashmap_entry_init(&key, memhash(orig, *len));
hashmap_entry_init(&key.hash, memhash(orig, *len));
key.orig = orig;
key.orig_len = *len;
ret = hashmap_get(map, &key, NULL);
ret = hashmap_get_entry(map, &key, hash, NULL);

if (!ret) {
ret = xmalloc(sizeof(*ret));
@@ -161,7 +166,7 @@ static const void *anonymize_mem(struct hashmap *map,
ret->orig_len = *len;
ret->anon = generate(orig, len);
ret->anon_len = *len;
hashmap_put(map, ret);
hashmap_put(map, &ret->hash);
}

*len = ret->anon_len;


+ 18
- 14
builtin/fetch.c View File

@@ -264,20 +264,21 @@ static void create_fetch_oidset(struct ref **head, struct oidset *out)
}

struct refname_hash_entry {
struct hashmap_entry ent; /* must be the first member */
struct hashmap_entry ent;
struct object_id oid;
int ignore;
char refname[FLEX_ARRAY];
};

static int refname_hash_entry_cmp(const void *hashmap_cmp_fn_data,
const void *e1_,
const void *e2_,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct refname_hash_entry *e1 = e1_;
const struct refname_hash_entry *e2 = e2_;
const struct refname_hash_entry *e1, *e2;

e1 = container_of(eptr, const struct refname_hash_entry, ent);
e2 = container_of(entry_or_key, const struct refname_hash_entry, ent);
return strcmp(e1->refname, keydata ? keydata : e2->refname);
}

@@ -289,9 +290,9 @@ static struct refname_hash_entry *refname_hash_add(struct hashmap *map,
size_t len = strlen(refname);

FLEX_ALLOC_MEM(ent, refname, refname, len);
hashmap_entry_init(ent, strhash(refname));
hashmap_entry_init(&ent->ent, strhash(refname));
oidcpy(&ent->oid, oid);
hashmap_add(map, ent);
hashmap_add(map, &ent->ent);
return ent;
}

@@ -380,7 +381,7 @@ static void find_non_local_tags(const struct ref *refs,
item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
string_list_insert(&remote_refs_list, ref->name);
}
hashmap_free(&existing_refs, 1);
hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);

/*
* We may have a final lightweight tag that needs to be
@@ -398,8 +399,10 @@ static void find_non_local_tags(const struct ref *refs,
for_each_string_list_item(remote_ref_item, &remote_refs_list) {
const char *refname = remote_ref_item->string;
struct ref *rm;
unsigned int hash = strhash(refname);

item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname);
item = hashmap_get_entry_from_hash(&remote_refs, hash, refname,
struct refname_hash_entry, ent);
if (!item)
BUG("unseen remote ref?");

@@ -413,7 +416,7 @@ static void find_non_local_tags(const struct ref *refs,
**tail = rm;
*tail = &rm->next;
}
hashmap_free(&remote_refs, 1);
hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
string_list_clear(&remote_refs_list, 0);
oidset_clear(&fetch_oids);
}
@@ -532,17 +535,18 @@ static struct ref *get_ref_map(struct remote *remote,
if (rm->peer_ref) {
const char *refname = rm->peer_ref->name;
struct refname_hash_entry *peer_item;
unsigned int hash = strhash(refname);

peer_item = hashmap_get_from_hash(&existing_refs,
strhash(refname),
refname);
peer_item = hashmap_get_entry_from_hash(&existing_refs,
hash, refname,
struct refname_hash_entry, ent);
if (peer_item) {
struct object_id *old_oid = &peer_item->oid;
oidcpy(&rm->peer_ref->old_oid, old_oid);
}
}
}
hashmap_free(&existing_refs, 1);
hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);

return ref_map;
}


+ 13
- 11
config.c View File

@@ -1856,9 +1856,9 @@ static struct config_set_element *configset_find_element(struct config_set *cs,
if (git_config_parse_key(key, &normalized_key, NULL))
return NULL;

hashmap_entry_init(&k, strhash(normalized_key));
hashmap_entry_init(&k.ent, strhash(normalized_key));
k.key = normalized_key;
found_entry = hashmap_get(&cs->config_hash, &k, NULL);
found_entry = hashmap_get_entry(&cs->config_hash, &k, ent, NULL);
free(normalized_key);
return found_entry;
}
@@ -1877,10 +1877,10 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
*/
if (!e) {
e = xmalloc(sizeof(*e));
hashmap_entry_init(e, strhash(key));
hashmap_entry_init(&e->ent, strhash(key));
e->key = xstrdup(key);
string_list_init(&e->value_list, 1);
hashmap_add(&cs->config_hash, e);
hashmap_add(&cs->config_hash, &e->ent);
}
si = string_list_append_nodup(&e->value_list, xstrdup_or_null(value));

@@ -1908,12 +1908,14 @@ static int configset_add_value(struct config_set *cs, const char *key, const cha
}

static int config_set_element_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct config_set_element *e1 = entry;
const struct config_set_element *e2 = entry_or_key;
const struct config_set_element *e1, *e2;

e1 = container_of(eptr, const struct config_set_element, ent);
e2 = container_of(entry_or_key, const struct config_set_element, ent);

return strcmp(e1->key, e2->key);
}
@@ -1934,12 +1936,12 @@ void git_configset_clear(struct config_set *cs)
if (!cs->hash_initialized)
return;

hashmap_iter_init(&cs->config_hash, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&cs->config_hash, &iter, entry,
ent /* member name */) {
free(entry->key);
string_list_clear(&entry->value_list, 1);
}
hashmap_free(&cs->config_hash, 1);
hashmap_free_entries(&cs->config_hash, struct config_set_element, ent);
cs->hash_initialized = 0;
free(cs->list.items);
cs->list.nr = 0;


+ 16
- 0
contrib/coccinelle/hashmap.cocci View File

@@ -0,0 +1,16 @@
@ hashmap_entry_init_usage @
expression E;
struct hashmap_entry HME;
@@
- HME.hash = E;
+ hashmap_entry_init(&HME, E);

@@
identifier f !~ "^hashmap_entry_init$";
expression E;
struct hashmap_entry *HMEP;
@@
f(...) {<...
- HMEP->hash = E;
+ hashmap_entry_init(HMEP, E);
...>}

+ 18
- 13
diff.c View File

@@ -933,16 +933,18 @@ static int cmp_in_block_with_wsd(const struct diff_options *o,
}

static int moved_entry_cmp(const void *hashmap_cmp_fn_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct diff_options *diffopt = hashmap_cmp_fn_data;
const struct moved_entry *a = entry;
const struct moved_entry *b = entry_or_key;
const struct moved_entry *a, *b;
unsigned flags = diffopt->color_moved_ws_handling
& XDF_WHITESPACE_FLAGS;

a = container_of(eptr, const struct moved_entry, ent);
b = container_of(entry_or_key, const struct moved_entry, ent);

if (diffopt->color_moved_ws_handling &
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE)
/*
@@ -964,8 +966,9 @@ static struct moved_entry *prepare_entry(struct diff_options *o,
struct moved_entry *ret = xmalloc(sizeof(*ret));
struct emitted_diff_symbol *l = &o->emitted_symbols->buf[line_no];
unsigned flags = o->color_moved_ws_handling & XDF_WHITESPACE_FLAGS;
unsigned int hash = xdiff_hash_string(l->line, l->len, flags);

ret->ent.hash = xdiff_hash_string(l->line, l->len, flags);
hashmap_entry_init(&ret->ent, hash);
ret->es = l;
ret->next_line = NULL;

@@ -1002,7 +1005,7 @@ static void add_lines_to_move_detection(struct diff_options *o,
if (prev_line && prev_line->es->s == o->emitted_symbols->buf[n].s)
prev_line->next_line = key;

hashmap_add(hm, key);
hashmap_add(hm, &key->ent);
prev_line = key;
}
}
@@ -1018,7 +1021,7 @@ static void pmb_advance_or_null(struct diff_options *o,
struct moved_entry *prev = pmb[i].match;
struct moved_entry *cur = (prev && prev->next_line) ?
prev->next_line : NULL;
if (cur && !hm->cmpfn(o, cur, match, NULL)) {
if (cur && !hm->cmpfn(o, &cur->ent, &match->ent, NULL)) {
pmb[i].match = cur;
} else {
pmb[i].match = NULL;
@@ -1035,7 +1038,7 @@ static void pmb_advance_or_null_multi_match(struct diff_options *o,
int i;
char *got_match = xcalloc(1, pmb_nr);

for (; match; match = hashmap_get_next(hm, match)) {
hashmap_for_each_entry_from(hm, match, ent) {
for (i = 0; i < pmb_nr; i++) {
struct moved_entry *prev = pmb[i].match;
struct moved_entry *cur = (prev && prev->next_line) ?
@@ -1143,13 +1146,13 @@ static void mark_color_as_moved(struct diff_options *o,
case DIFF_SYMBOL_PLUS:
hm = del_lines;
key = prepare_entry(o, n);
match = hashmap_get(hm, key, NULL);
match = hashmap_get_entry(hm, key, ent, NULL);
free(key);
break;
case DIFF_SYMBOL_MINUS:
hm = add_lines;
key = prepare_entry(o, n);
match = hashmap_get(hm, key, NULL);
match = hashmap_get_entry(hm, key, ent, NULL);
free(key);
break;
default:
@@ -1188,7 +1191,7 @@ static void mark_color_as_moved(struct diff_options *o,
* The current line is the start of a new block.
* Setup the set of potential blocks.
*/
for (; match; match = hashmap_get_next(hm, match)) {
hashmap_for_each_entry_from(hm, match, ent) {
ALLOC_GROW(pmb, pmb_nr + 1, pmb_alloc);
if (o->color_moved_ws_handling &
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE) {
@@ -6230,8 +6233,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
dim_moved_lines(o);

hashmap_free(&add_lines, 1);
hashmap_free(&del_lines, 1);
hashmap_free_entries(&add_lines, struct moved_entry,
ent);
hashmap_free_entries(&del_lines, struct moved_entry,
ent);
}

for (i = 0; i < esm.nr; i++)


+ 7
- 8
diffcore-rename.c View File

@@ -274,18 +274,17 @@ static int find_identical_files(struct hashmap *srcs,
struct diff_options *options)
{
int renames = 0;

struct diff_filespec *target = rename_dst[dst_index].two;
struct file_similarity *p, *best = NULL;
int i = 100, best_score = -1;
unsigned int hash = hash_filespec(options->repo, target);

/*
* Find the best source match for specified destination.
*/
p = hashmap_get_from_hash(srcs,
hash_filespec(options->repo, target),
NULL);
for (; p; p = hashmap_get_next(srcs, p)) {
p = hashmap_get_entry_from_hash(srcs, hash, NULL,
struct file_similarity, entry);
hashmap_for_each_entry_from(srcs, p, entry) {
int score;
struct diff_filespec *source = p->filespec;

@@ -329,8 +328,8 @@ static void insert_file_table(struct repository *r,
entry->index = index;
entry->filespec = filespec;

hashmap_entry_init(entry, hash_filespec(r, filespec));
hashmap_add(table, entry);
hashmap_entry_init(&entry->entry, hash_filespec(r, filespec));
hashmap_add(table, &entry->entry);
}

/*
@@ -359,7 +358,7 @@ static int find_exact_renames(struct diff_options *options)
renames += find_identical_files(&file_table, i, options);

/* Free the hash data structure and entries */
hashmap_free(&file_table, 1);
hashmap_free_entries(&file_table, struct file_similarity, entry);

return renames;
}


+ 38
- 0
git-compat-util.h View File

@@ -1313,4 +1313,42 @@ void unleak_memory(const void *ptr, size_t len);
*/
#include "banned.h"

/*
* container_of - Get the address of an object containing a field.
*
* @ptr: pointer to the field.
* @type: type of the object.
* @member: name of the field within the object.
*/
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) - offsetof(type, member)))

/*
* helper function for `container_of_or_null' to avoid multiple
* evaluation of @ptr
*/
static inline void *container_of_or_null_offset(void *ptr, size_t offset)
{
return ptr ? (char *)ptr - offset : NULL;
}

/*
* like `container_of', but allows returned value to be NULL
*/
#define container_of_or_null(ptr, type, member) \
(type *)container_of_or_null_offset(ptr, offsetof(type, member))

/*
* like offsetof(), but takes a pointer to a a variable of type which
* contains @member, instead of a specified type.
* @ptr is subject to multiple evaluation since we can't rely on __typeof__
* everywhere.
*/
#if defined(__GNUC__) /* clang sets this, too */
#define OFFSETOF_VAR(ptr, member) offsetof(__typeof__(*ptr), member)
#else /* !__GNUC__ */
#define OFFSETOF_VAR(ptr, member) \
((uintptr_t)&(ptr)->member - (uintptr_t)(ptr))
#endif /* !__GNUC__ */

#endif

+ 37
- 21
hashmap.c View File

@@ -140,8 +140,8 @@ static inline struct hashmap_entry **find_entry_ptr(const struct hashmap *map,
}

static int always_equal(const void *unused_cmp_data,
const void *unused1,
const void *unused2,
const struct hashmap_entry *unused1,
const struct hashmap_entry *unused2,
const void *unused_keydata)
{
return 0;
@@ -171,41 +171,49 @@ void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
map->do_count_items = 1;
}

void hashmap_free(struct hashmap *map, int free_entries)
void hashmap_free_(struct hashmap *map, ssize_t entry_offset)
{
if (!map || !map->table)
return;
if (free_entries) {
if (entry_offset >= 0) { /* called by hashmap_free_entries */
struct hashmap_iter iter;
struct hashmap_entry *e;

hashmap_iter_init(map, &iter);
while ((e = hashmap_iter_next(&iter)))
free(e);
/*
* like container_of, but using caller-calculated
* offset (caller being hashmap_free_entries)
*/
free((char *)e - entry_offset);
}
free(map->table);
memset(map, 0, sizeof(*map));
}

void *hashmap_get(const struct hashmap *map, const void *key, const void *keydata)
struct hashmap_entry *hashmap_get(const struct hashmap *map,
const struct hashmap_entry *key,
const void *keydata)
{
return *find_entry_ptr(map, key, keydata);
}

void *hashmap_get_next(const struct hashmap *map, const void *entry)
struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
const struct hashmap_entry *entry)
{
struct hashmap_entry *e = ((struct hashmap_entry *) entry)->next;
struct hashmap_entry *e = entry->next;
for (; e; e = e->next)
if (entry_equals(map, entry, e, NULL))
return e;
return NULL;
}

void hashmap_add(struct hashmap *map, void *entry)
void hashmap_add(struct hashmap *map, struct hashmap_entry *entry)
{
unsigned int b = bucket(map, entry);

/* add entry */
((struct hashmap_entry *) entry)->next = map->table[b];
entry->next = map->table[b];
map->table[b] = entry;

/* fix size and rehash if appropriate */
@@ -216,7 +224,9 @@ void hashmap_add(struct hashmap *map, void *entry)
}
}

void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)
struct hashmap_entry *hashmap_remove(struct hashmap *map,
const struct hashmap_entry *key,
const void *keydata)
{
struct hashmap_entry *old;
struct hashmap_entry **e = find_entry_ptr(map, key, keydata);
@@ -238,7 +248,8 @@ void *hashmap_remove(struct hashmap *map, const void *key, const void *keydata)
return old;
}

void *hashmap_put(struct hashmap *map, void *entry)
struct hashmap_entry *hashmap_put(struct hashmap *map,
struct hashmap_entry *entry)
{
struct hashmap_entry *old = hashmap_remove(map, entry, NULL);
hashmap_add(map, entry);
@@ -252,7 +263,7 @@ void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter)
iter->next = NULL;
}

void *hashmap_iter_next(struct hashmap_iter *iter)
struct hashmap_entry *hashmap_iter_next(struct hashmap_iter *iter)
{
struct hashmap_entry *current = iter->next;
for (;;) {
@@ -275,10 +286,15 @@ struct pool_entry {
};

static int pool_entry_cmp(const void *unused_cmp_data,
const struct pool_entry *e1,
const struct pool_entry *e2,
const unsigned char *keydata)
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct pool_entry *e1, *e2;

e1 = container_of(eptr, const struct pool_entry, ent);
e2 = container_of(entry_or_key, const struct pool_entry, ent);

return e1->data != keydata &&
(e1->len != e2->len || memcmp(e1->data, keydata, e1->len));
}
@@ -290,18 +306,18 @@ const void *memintern(const void *data, size_t len)

/* initialize string pool hashmap */
if (!map.tablesize)
hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, NULL, 0);
hashmap_init(&map, pool_entry_cmp, NULL, 0);

/* lookup interned string in pool */
hashmap_entry_init(&key, memhash(data, len));
hashmap_entry_init(&key.ent, memhash(data, len));
key.len = len;
e = hashmap_get(&map, &key, data);
e = hashmap_get_entry(&map, &key, ent, data);
if (!e) {
/* not found: create it */
FLEX_ALLOC_MEM(e, data, data, len);
hashmap_entry_init(e, key.ent.hash);
hashmap_entry_init(&e->ent, key.ent.hash);
e->len = len;
hashmap_add(&map, e);
hashmap_add(&map, &e->ent);
}
return e->data;
}

+ 141
- 35
hashmap.h View File

@@ -13,7 +13,7 @@
*
* struct hashmap map;
* struct long2string {
* struct hashmap_entry ent; // must be the first member!
* struct hashmap_entry ent;
* long key;
* char value[FLEX_ARRAY]; // be careful with allocating on stack!
* };
@@ -21,12 +21,16 @@
* #define COMPARE_VALUE 1
*
* static int long2string_cmp(const void *hashmap_cmp_fn_data,
* const struct long2string *e1,
* const struct long2string *e2,
* const struct hashmap_entry *eptr,
* const struct hashmap_entry *entry_or_key,
* const void *keydata)
* {
* const char *string = keydata;
* unsigned flags = *(unsigned *)hashmap_cmp_fn_data;
* const struct long2string *e1, *e2;
*
* e1 = container_of(eptr, const struct long2string, ent);
* e2 = container_of(entry_or_key, const struct long2string, ent);
*
* if (flags & COMPARE_VALUE)
* return e1->key != e2->key ||
@@ -41,54 +45,58 @@
* char value[255], action[32];
* unsigned flags = 0;
*
* hashmap_init(&map, (hashmap_cmp_fn) long2string_cmp, &flags, 0);
* hashmap_init(&map, long2string_cmp, &flags, 0);
*
* while (scanf("%s %ld %s", action, &key, value)) {
*
* if (!strcmp("add", action)) {
* struct long2string *e;
* FLEX_ALLOC_STR(e, value, value);
* hashmap_entry_init(e, memhash(&key, sizeof(long)));
* hashmap_entry_init(&e->ent, memhash(&key, sizeof(long)));
* e->key = key;
* hashmap_add(&map, e);
* hashmap_add(&map, &e->ent);
* }
*
* if (!strcmp("print_all_by_key", action)) {
* struct long2string k, *e;
* hashmap_entry_init(&k, memhash(&key, sizeof(long)));
* hashmap_entry_init(&k->ent, memhash(&key, sizeof(long)));
* k.key = key;
*
* flags &= ~COMPARE_VALUE;
* e = hashmap_get(&map, &k, NULL);
* e = hashmap_get_entry(&map, &k, ent, NULL);
* if (e) {
* printf("first: %ld %s\n", e->key, e->value);
* while ((e = hashmap_get_next(&map, e)))
* while ((e = hashmap_get_next_entry(&map, e,
* struct long2string, ent))) {
* printf("found more: %ld %s\n", e->key, e->value);
* }
* }
* }
*
* if (!strcmp("has_exact_match", action)) {
* struct long2string *e;
* FLEX_ALLOC_STR(e, value, value);
* hashmap_entry_init(e, memhash(&key, sizeof(long)));
* hashmap_entry_init(&e->ent, memhash(&key, sizeof(long)));
* e->key = key;
*
* flags |= COMPARE_VALUE;
* printf("%sfound\n", hashmap_get(&map, e, NULL) ? "" : "not ");
* printf("%sfound\n",
* hashmap_get(&map, &e->ent, NULL) ? "" : "not ");
* free(e);
* }
*
* if (!strcmp("has_exact_match_no_heap_alloc", action)) {
* struct long2string k;
* hashmap_entry_init(&k, memhash(&key, sizeof(long)));
* hashmap_entry_init(&k->ent, memhash(&key, sizeof(long)));
* k.key = key;
*
* flags |= COMPARE_VALUE;
* printf("%sfound\n", hashmap_get(&map, &k, value) ? "" : "not ");
* printf("%sfound\n",
* hashmap_get(&map, &k->ent, value) ? "" : "not ");
* }
*
* if (!strcmp("end", action)) {
* hashmap_free(&map, 1);
* hashmap_free_entries(&map, struct long2string, ent);
* break;
* }
* }
@@ -133,7 +141,7 @@ static inline unsigned int oidhash(const struct object_id *oid)

/*
* struct hashmap_entry is an opaque structure representing an entry in the
* hash table, which must be used as first member of user data structures.
* hash table.
* Ideally it should be followed by an int-sized member to prevent unused
* memory on 64-bit systems due to alignment.
*/
@@ -168,7 +176,8 @@ struct hashmap_entry {
* The `hashmap_cmp_fn_data` entry is the pointer given in the init function.
*/
typedef int (*hashmap_cmp_fn)(const void *hashmap_cmp_fn_data,
const void *entry, const void *entry_or_key,
const struct hashmap_entry *entry,
const struct hashmap_entry *entry_or_key,
const void *keydata);

/*
@@ -223,13 +232,20 @@ void hashmap_init(struct hashmap *map,
const void *equals_function_data,
size_t initial_size);

/* internal function for freeing hashmap */
void hashmap_free_(struct hashmap *map, ssize_t offset);

/*
* Frees a hashmap structure and allocated memory.
*
* If `free_entries` is true, each hashmap_entry in the map is freed as well
* using stdlibs free().
* Frees a hashmap structure and allocated memory, leaves entries undisturbed
*/
void hashmap_free(struct hashmap *map, int free_entries);
#define hashmap_free(map) hashmap_free_(map, -1)

/*
* Frees @map and all entries. @type is the struct type of the entry
* where @member is the hashmap_entry struct used to associate with @map
*/
#define hashmap_free_entries(map, type, member) \
hashmap_free_(map, offsetof(type, member));

/* hashmap_entry functions */

@@ -244,9 +260,9 @@ void hashmap_free(struct hashmap *map, int free_entries);
* your structure was allocated with xmalloc(), you can just free(3) it,
* and if it is on stack, you can just let it go out of scope).
*/
static inline void hashmap_entry_init(void *entry, unsigned int hash)
static inline void hashmap_entry_init(struct hashmap_entry *e,
unsigned int hash)
{
struct hashmap_entry *e = entry;
e->hash = hash;
e->next = NULL;
}
@@ -286,8 +302,9 @@ static inline unsigned int hashmap_get_size(struct hashmap *map)
* If an entry with matching hash code is found, `key` and `keydata` are passed
* to `hashmap_cmp_fn` to decide whether the entry matches the key.
*/
void *hashmap_get(const struct hashmap *map, const void *key,
const void *keydata);
struct hashmap_entry *hashmap_get(const struct hashmap *map,
const struct hashmap_entry *key,
const void *keydata);

/*
* Returns the hashmap entry for the specified hash code and key data,
@@ -301,9 +318,10 @@ void *hashmap_get(const struct hashmap *map, const void *key,
* `entry_or_key` parameter of `hashmap_cmp_fn` points to a hashmap_entry
* structure that should not be used in the comparison.
*/
static inline void *hashmap_get_from_hash(const struct hashmap *map,
unsigned int hash,
const void *keydata)
static inline struct hashmap_entry *hashmap_get_from_hash(
const struct hashmap *map,
unsigned int hash,
const void *keydata)
{
struct hashmap_entry key;
hashmap_entry_init(&key, hash);
@@ -318,7 +336,8 @@ static inline void *hashmap_get_from_hash(const struct hashmap *map,
* `entry` is the hashmap_entry to start the search from, obtained via a previous
* call to `hashmap_get` or `hashmap_get_next`.
*/
void *hashmap_get_next(const struct hashmap *map, const void *entry);
struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
const struct hashmap_entry *entry);

/*
* Adds a hashmap entry. This allows to add duplicate entries (i.e.
@@ -327,7 +346,7 @@ void *hashmap_get_next(const struct hashmap *map, const void *entry);
* `map` is the hashmap structure.
* `entry` is the entry to add.
*/
void hashmap_add(struct hashmap *map, void *entry);
void hashmap_add(struct hashmap *map, struct hashmap_entry *entry);

/*
* Adds or replaces a hashmap entry. If the hashmap contains duplicate
@@ -337,7 +356,20 @@ void hashmap_add(struct hashmap *map, void *entry);
* `entry` is the entry to add or replace.
* Returns the replaced entry, or NULL if not found (i.e. the entry was added).
*/
void *hashmap_put(struct hashmap *map, void *entry);
struct hashmap_entry *hashmap_put(struct hashmap *map,
struct hashmap_entry *entry);

/*
* Adds or replaces a hashmap entry contained within @keyvar,
* where @keyvar is a pointer to a struct containing a
* "struct hashmap_entry" @member.
*
* Returns the replaced pointer which is of the same type as @keyvar,
* or NULL if not found.
*/
#define hashmap_put_entry(map, keyvar, member) \
container_of_or_null_offset(hashmap_put(map, &(keyvar)->member), \
OFFSETOF_VAR(keyvar, member))

/*
* Removes a hashmap entry matching the specified key. If the hashmap contains
@@ -346,8 +378,24 @@ void *hashmap_put(struct hashmap *map, void *entry);
*
* Argument explanation is the same as in `hashmap_get`.
*/
void *hashmap_remove(struct hashmap *map, const void *key,
const void *keydata);
struct hashmap_entry *hashmap_remove(struct hashmap *map,
const struct hashmap_entry *key,
const void *keydata);

/*
* Removes a hashmap entry contained within @keyvar,
* where @keyvar is a pointer to a struct containing a
* "struct hashmap_entry" @member.
*
* See `hashmap_get` for an explanation of @keydata
*
* Returns the replaced pointer which is of the same type as @keyvar,
* or NULL if not found.
*/
#define hashmap_remove_entry(map, keyvar, member, keydata) \
container_of_or_null_offset( \
hashmap_remove(map, &(keyvar)->member, keydata), \
OFFSETOF_VAR(keyvar, member))

/*
* Returns the `bucket` an entry is stored in.
@@ -370,16 +418,74 @@ struct hashmap_iter {
void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);

/* Returns the next hashmap_entry, or NULL if there are no more entries. */
void *hashmap_iter_next(struct hashmap_iter *iter);
struct hashmap_entry *hashmap_iter_next(struct hashmap_iter *iter);

/* Initializes the iterator and returns the first entry, if any. */
static inline void *hashmap_iter_first(struct hashmap *map,
static inline struct hashmap_entry *hashmap_iter_first(struct hashmap *map,
struct hashmap_iter *iter)
{
hashmap_iter_init(map, iter);
return hashmap_iter_next(iter);
}

/*
* returns the first entry in @map using @iter, where the entry is of
* @type (e.g. "struct foo") and @member is the name of the
* "struct hashmap_entry" in @type
*/
#define hashmap_iter_first_entry(map, iter, type, member) \
container_of_or_null(hashmap_iter_first(map, iter), type, member)

/* internal macro for hashmap_for_each_entry */
#define hashmap_iter_next_entry_offset(iter, offset) \
container_of_or_null_offset(hashmap_iter_next(iter), offset)

/* internal macro for hashmap_for_each_entry */
#define hashmap_iter_first_entry_offset(map, iter, offset) \
container_of_or_null_offset(hashmap_iter_first(map, iter), offset)

/*
* iterate through @map using @iter, @var is a pointer to a type
* containing a @member which is a "struct hashmap_entry"
*/
#define hashmap_for_each_entry(map, iter, var, member) \
for (var = hashmap_iter_first_entry_offset(map, iter, \
OFFSETOF_VAR(var, member)); \
var; \
var = hashmap_iter_next_entry_offset(iter, \
OFFSETOF_VAR(var, member)))

/*
* returns a pointer of type matching @keyvar, or NULL if nothing found.
* @keyvar is a pointer to a struct containing a
* "struct hashmap_entry" @member.
*/
#define hashmap_get_entry(map, keyvar, member, keydata) \
container_of_or_null_offset( \
hashmap_get(map, &(keyvar)->member, keydata), \
OFFSETOF_VAR(keyvar, member))

#define hashmap_get_entry_from_hash(map, hash, keydata, type, member) \
container_of_or_null(hashmap_get_from_hash(map, hash, keydata), \
type, member)
/*
* returns the next equal pointer to @var, or NULL if not found.
* @var is a pointer of any type containing "struct hashmap_entry"
* @member is the name of the "struct hashmap_entry" field
*/
#define hashmap_get_next_entry(map, var, member) \
container_of_or_null_offset(hashmap_get_next(map, &(var)->member), \
OFFSETOF_VAR(var, member))

/*
* iterate @map starting from @var, where @var is a pointer of @type
* and @member is the name of the "struct hashmap_entry" field in @type
*/
#define hashmap_for_each_entry_from(map, var, member) \
for (; \
var; \
var = hashmap_get_next_entry(map, var, member))

/*
* Disable item counting and automatic rehashing when adding/removing items.
*


+ 51
- 40
merge-recursive.c View File

@@ -45,14 +45,16 @@ struct path_hashmap_entry {
};

static int path_hashmap_cmp(const void *cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct path_hashmap_entry *a = entry;
const struct path_hashmap_entry *b = entry_or_key;
const struct path_hashmap_entry *a, *b;
const char *key = keydata;

a = container_of(eptr, const struct path_hashmap_entry, e);
b = container_of(entry_or_key, const struct path_hashmap_entry, e);

if (ignore_case)
return strcasecmp(a->path, key ? key : b->path);
else
@@ -75,7 +77,7 @@ static unsigned int path_hash(const char *path)
* in get_directory_renames() for details
*/
struct dir_rename_entry {
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;
char *dir;
unsigned non_unique_new_dir:1;
struct strbuf new_dir;
@@ -89,18 +91,20 @@ static struct dir_rename_entry *dir_rename_find_entry(struct hashmap *hashmap,

if (dir == NULL)
return NULL;
hashmap_entry_init(&key, strhash(dir));
hashmap_entry_init(&key.ent, strhash(dir));
key.dir = dir;
return hashmap_get(hashmap, &key, NULL);
return hashmap_get_entry(hashmap, &key, ent, NULL);
}

static int dir_rename_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct dir_rename_entry *e1 = entry;
const struct dir_rename_entry *e2 = entry_or_key;
const struct dir_rename_entry *e1, *e2;

e1 = container_of(eptr, const struct dir_rename_entry, ent);
e2 = container_of(entry_or_key, const struct dir_rename_entry, ent);

return strcmp(e1->dir, e2->dir);
}
@@ -113,7 +117,7 @@ static void dir_rename_init(struct hashmap *map)
static void dir_rename_entry_init(struct dir_rename_entry *entry,
char *directory)
{
hashmap_entry_init(entry, strhash(directory));
hashmap_entry_init(&entry->ent, strhash(directory));
entry->dir = directory;
entry->non_unique_new_dir = 0;
strbuf_init(&entry->new_dir, 0);
@@ -121,7 +125,7 @@ static void dir_rename_entry_init(struct dir_rename_entry *entry,
}

struct collision_entry {
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;
char *target_file;
struct string_list source_files;
unsigned reported_already:1;
@@ -132,22 +136,27 @@ static struct collision_entry *collision_find_entry(struct hashmap *hashmap,
{
struct collision_entry key;

hashmap_entry_init(&key, strhash(target_file));
hashmap_entry_init(&key.ent, strhash(target_file));
key.target_file = target_file;
return hashmap_get(hashmap, &key, NULL);
return hashmap_get_entry(hashmap, &key, ent, NULL);
}

static int collision_cmp(void *unused_cmp_data,
const struct collision_entry *e1,
const struct collision_entry *e2,
static int collision_cmp(const void *unused_cmp_data,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct collision_entry *e1, *e2;

e1 = container_of(eptr, const struct collision_entry, ent);
e2 = container_of(entry_or_key, const struct collision_entry, ent);

return strcmp(e1->target_file, e2->target_file);
}

static void collision_init(struct hashmap *map)
{
hashmap_init(map, (hashmap_cmp_fn) collision_cmp, NULL, 0);
hashmap_init(map, collision_cmp, NULL, 0);
}

static void flush_output(struct merge_options *opt)
@@ -464,8 +473,8 @@ static int save_files_dirs(const struct object_id *oid,
strbuf_addstr(base, path);

FLEX_ALLOC_MEM(entry, path, base->buf, base->len);
hashmap_entry_init(entry, path_hash(entry->path));
hashmap_add(&opt->priv->current_file_dir_set, entry);
hashmap_entry_init(&entry->e, path_hash(entry->path));
hashmap_add(&opt->priv->current_file_dir_set, &entry->e);

strbuf_setlen(base, baselen);
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
@@ -743,8 +752,8 @@ static char *unique_path(struct merge_options *opt,
}

FLEX_ALLOC_MEM(entry, path, newpath.buf, newpath.len);
hashmap_entry_init(entry, path_hash(entry->path));
hashmap_add(&opt->priv->current_file_dir_set, entry);
hashmap_entry_init(&entry->e, path_hash(entry->path));
hashmap_add(&opt->priv->current_file_dir_set, &entry->e);
return strbuf_detach(&newpath, NULL);
}

@@ -2013,7 +2022,7 @@ static void remove_hashmap_entries(struct hashmap *dir_renames,

for (i = 0; i < items_to_remove->nr; i++) {
entry = items_to_remove->items[i].util;
hashmap_remove(dir_renames, entry, NULL);
hashmap_remove(dir_renames, &entry->ent, NULL);
}
string_list_clear(items_to_remove, 0);
}
@@ -2136,8 +2145,8 @@ static void handle_directory_level_conflicts(struct merge_options *opt,
struct string_list remove_from_head = STRING_LIST_INIT_NODUP;
struct string_list remove_from_merge = STRING_LIST_INIT_NODUP;

hashmap_iter_init(dir_re_head, &iter);
while ((head_ent = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(dir_re_head, &iter, head_ent,
ent /* member name */) {
merge_ent = dir_rename_find_entry(dir_re_merge, head_ent->dir);
if (merge_ent &&
!head_ent->non_unique_new_dir &&
@@ -2161,8 +2170,8 @@ static void handle_directory_level_conflicts(struct merge_options *opt,
remove_hashmap_entries(dir_re_head, &remove_from_head);
remove_hashmap_entries(dir_re_merge, &remove_from_merge);

hashmap_iter_init(dir_re_merge, &iter);
while ((merge_ent = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(dir_re_merge, &iter, merge_ent,
ent /* member name */) {
head_ent = dir_rename_find_entry(dir_re_head, merge_ent->dir);
if (tree_has_path(opt->repo, merge, merge_ent->dir)) {
/* 2. This wasn't a directory rename after all */
@@ -2241,7 +2250,7 @@ static struct hashmap *get_directory_renames(struct diff_queue_struct *pairs)
if (!entry) {
entry = xmalloc(sizeof(*entry));
dir_rename_entry_init(entry, old_dir);
hashmap_put(dir_renames, entry);
hashmap_put(dir_renames, &entry->ent);
} else {
free(old_dir);
}
@@ -2266,8 +2275,8 @@ static struct hashmap *get_directory_renames(struct diff_queue_struct *pairs)
* we set non_unique_new_dir. Once we've determined the winner (or
* that there is no winner), we no longer need possible_new_dirs.
*/
hashmap_iter_init(dir_renames, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(dir_renames, &iter, entry,
ent /* member name */) {
int max = 0;
int bad_max = 0;
char *best = NULL;
@@ -2370,8 +2379,9 @@ static void compute_collisions(struct hashmap *collisions,
if (!collision_ent) {
collision_ent = xcalloc(1,
sizeof(struct collision_entry));
hashmap_entry_init(collision_ent, strhash(new_path));
hashmap_put(collisions, collision_ent);
hashmap_entry_init(&collision_ent->ent,
strhash(new_path));
hashmap_put(collisions, &collision_ent->ent);
collision_ent->target_file = new_path;
} else {
free(new_path);
@@ -2624,12 +2634,12 @@ static struct string_list *get_renames(struct merge_options *opt,
entries);
}

hashmap_iter_init(&collisions, &iter);
while ((e = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&collisions, &iter, e,
ent /* member name */) {
free(e->target_file);
string_list_clear(&e->source_files, 0);
}
hashmap_free(&collisions, 1);
hashmap_free_entries(&collisions, struct collision_entry, ent);
return renames;
}

@@ -2842,13 +2852,13 @@ static void initial_cleanup_rename(struct diff_queue_struct *pairs,
struct hashmap_iter iter;
struct dir_rename_entry *e;

hashmap_iter_init(dir_renames, &iter);
while ((e = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(dir_renames, &iter, e,
ent /* member name */) {
free(e->dir);
strbuf_release(&e->new_dir);
/* possible_new_dirs already cleared in get_directory_renames */
}
hashmap_free(dir_renames, 1);
hashmap_free_entries(dir_renames, struct dir_rename_entry, ent);
free(dir_renames);

free(pairs->queue);
@@ -3475,7 +3485,8 @@ static int merge_trees_internal(struct merge_options *opt,
string_list_clear(entries, 1);
free(entries);

hashmap_free(&opt->priv->current_file_dir_set, 1);
hashmap_free_entries(&opt->priv->current_file_dir_set,
struct path_hashmap_entry, e);

if (clean < 0) {
unpack_trees_finish(opt);


+ 31
- 26
name-hash.c View File

@@ -17,14 +17,16 @@ struct dir_entry {
};

static int dir_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct dir_entry *e1 = entry;
const struct dir_entry *e2 = entry_or_key;
const struct dir_entry *e1, *e2;
const char *name = keydata;

e1 = container_of(eptr, const struct dir_entry, ent);
e2 = container_of(entry_or_key, const struct dir_entry, ent);

return e1->namelen != e2->namelen || strncasecmp(e1->name,
name ? name : e2->name, e1->namelen);
}
@@ -33,9 +35,9 @@ static struct dir_entry *find_dir_entry__hash(struct index_state *istate,
const char *name, unsigned int namelen, unsigned int hash)
{
struct dir_entry key;
hashmap_entry_init(&key, hash);
hashmap_entry_init(&key.ent, hash);
key.namelen = namelen;
return hashmap_get(&istate->dir_hash, &key, name);
return hashmap_get_entry(&istate->dir_hash, &key, ent, name);
}

static struct dir_entry *find_dir_entry(struct index_state *istate,
@@ -68,9 +70,9 @@ static struct dir_entry *hash_dir_entry(struct index_state *istate,
if (!dir) {
/* not found, create it and add to hash table */
FLEX_ALLOC_MEM(dir, name, ce->name, namelen);
hashmap_entry_init(dir, memihash(ce->name, namelen));
hashmap_entry_init(&dir->ent, memihash(ce->name, namelen));
dir->namelen = namelen;
hashmap_add(&istate->dir_hash, dir);
hashmap_add(&istate->dir_hash, &dir->ent);

/* recursively add missing parent directories */
dir->parent = hash_dir_entry(istate, ce, namelen);
@@ -95,7 +97,7 @@ static void remove_dir_entry(struct index_state *istate, struct cache_entry *ce)
struct dir_entry *dir = hash_dir_entry(istate, ce, ce_namelen(ce));
while (dir && !(--dir->nr)) {
struct dir_entry *parent = dir->parent;
hashmap_remove(&istate->dir_hash, dir, NULL);
hashmap_remove(&istate->dir_hash, &dir->ent, NULL);
free(dir);
dir = parent;
}
@@ -106,20 +108,23 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
if (ce->ce_flags & CE_HASHED)
return;
ce->ce_flags |= CE_HASHED;
hashmap_entry_init(ce, memihash(ce->name, ce_namelen(ce)));
hashmap_add(&istate->name_hash, ce);
hashmap_entry_init(&ce->ent, memihash(ce->name, ce_namelen(ce)));
hashmap_add(&istate->name_hash, &ce->ent);

if (ignore_case)
add_dir_entry(istate, ce);
}

static int cache_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *remove)
{
const struct cache_entry *ce1 = entry;
const struct cache_entry *ce2 = entry_or_key;
const struct cache_entry *ce1, *ce2;

ce1 = container_of(eptr, const struct cache_entry, ent);
ce2 = container_of(entry_or_key, const struct cache_entry, ent);

/*
* For remove_name_hash, find the exact entry (pointer equality); for
* index_file_exists, find all entries with matching hash code and
@@ -280,10 +285,10 @@ static struct dir_entry *hash_dir_entry_with_parent_and_prefix(
dir = find_dir_entry__hash(istate, prefix->buf, prefix->len, hash);
if (!dir) {
FLEX_ALLOC_MEM(dir, name, prefix->buf, prefix->len);
hashmap_entry_init(dir, hash);
hashmap_entry_init(&dir->ent, hash);
dir->namelen = prefix->len;
dir->parent = parent;
hashmap_add(&istate->dir_hash, dir);
hashmap_add(&istate->dir_hash, &dir->ent);

if (parent) {
unlock_dir_mutex(lock_nr);
@@ -472,8 +477,8 @@ static void *lazy_name_thread_proc(void *_data)
for (k = 0; k < d->istate->cache_nr; k++) {
struct cache_entry *ce_k = d->istate->cache[k];
ce_k->ce_flags |= CE_HASHED;
hashmap_entry_init(ce_k, d->lazy_entries[k].hash_name);
hashmap_add(&d->istate->name_hash, ce_k);
hashmap_entry_init(&ce_k->ent, d->lazy_entries[k].hash_name);
hashmap_add(&d->istate->name_hash, &ce_k->ent);
}

return NULL;
@@ -625,7 +630,7 @@ void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
if (!istate->name_hash_initialized || !(ce->ce_flags & CE_HASHED))
return;
ce->ce_flags &= ~CE_HASHED;
hashmap_remove(&istate->name_hash, ce, ce);
hashmap_remove(&istate->name_hash, &ce->ent, ce);

if (ignore_case)
remove_dir_entry(istate, ce);
@@ -702,15 +707,15 @@ void adjust_dirname_case(struct index_state *istate, char *name)
struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int icase)
{
struct cache_entry *ce;
unsigned int hash = memihash(name, namelen);

lazy_init_name_hash(istate);

ce = hashmap_get_from_hash(&istate->name_hash,
memihash(name, namelen), NULL);
while (ce) {
ce = hashmap_get_entry_from_hash(&istate->name_hash, hash, NULL,
struct cache_entry, ent);
hashmap_for_each_entry_from(&istate->name_hash, ce, ent) {
if (same_name(ce, name, namelen, icase))
return ce;
ce = hashmap_get_next(&istate->name_hash, ce);
}
return NULL;
}
@@ -721,6 +726,6 @@ void free_name_hash(struct index_state *istate)
return;
istate->name_hash_initialized = 0;

hashmap_free(&istate->name_hash, 0);
hashmap_free(&istate->dir_hash, 1);
hashmap_free(&istate->name_hash);
hashmap_free_entries(&istate->dir_hash, struct dir_entry, ent);
}

+ 13
- 7
oidmap.c View File

@@ -2,14 +2,18 @@
#include "oidmap.h"

static int oidmap_neq(const void *hashmap_cmp_fn_data,
const void *entry, const void *entry_or_key,
const struct hashmap_entry *e1,
const struct hashmap_entry *e2,
const void *keydata)
{
const struct oidmap_entry *entry_ = entry;
const struct oidmap_entry *a, *b;

a = container_of(e1, const struct oidmap_entry, internal_entry);
b = container_of(e2, const struct oidmap_entry, internal_entry);

if (keydata)
return !oideq(&entry_->oid, (const struct object_id *) keydata);
return !oideq(&entry_->oid,
&((const struct oidmap_entry *) entry_or_key)->oid);
return !oideq(&a->oid, (const struct object_id *) keydata);
return !oideq(&a->oid, &b->oid);
}

void oidmap_init(struct oidmap *map, size_t initial_size)
@@ -21,7 +25,9 @@ void oidmap_free(struct oidmap *map, int free_entries)
{
if (!map)
return;
hashmap_free(&map->map, free_entries);

/* TODO: make oidmap itself not depend on struct layouts */
hashmap_free_(&map->map, free_entries ? 0 : -1);
}

void *oidmap_get(const struct oidmap *map, const struct object_id *key)
@@ -51,5 +57,5 @@ void *oidmap_put(struct oidmap *map, void *entry)
oidmap_init(map, 0);

hashmap_entry_init(&to_put->internal_entry, oidhash(&to_put->oid));
return hashmap_put(&map->map, to_put);
return hashmap_put(&map->map, &to_put->internal_entry);
}

+ 4
- 2
oidmap.h View File

@@ -78,14 +78,16 @@ static inline void oidmap_iter_init(struct oidmap *map, struct oidmap_iter *iter

static inline void *oidmap_iter_next(struct oidmap_iter *iter)
{
return hashmap_iter_next(&iter->h_iter);
/* TODO: this API could be reworked to do compile-time type checks */
return (void *)hashmap_iter_next(&iter->h_iter);
}

static inline void *oidmap_iter_first(struct oidmap *map,
struct oidmap_iter *iter)
{
oidmap_iter_init(map, iter);
return oidmap_iter_next(iter);
/* TODO: this API could be reworked to do compile-time type checks */
return (void *)oidmap_iter_next(iter);
}

#endif

+ 14
- 8
packfile.c View File

@@ -1343,7 +1343,7 @@ struct delta_base_cache_key {
};

struct delta_base_cache_entry {
struct hashmap hash;
struct hashmap_entry ent;
struct delta_base_cache_key key;
struct list_head lru;
void *data;
@@ -1363,7 +1363,7 @@ static unsigned int pack_entry_hash(struct packed_git *p, off_t base_offset)
static struct delta_base_cache_entry *
get_delta_base_cache_entry(struct packed_git *p, off_t base_offset)
{
struct hashmap_entry entry;
struct hashmap_entry entry, *e;
struct delta_base_cache_key key;

if (!delta_base_cache.cmpfn)
@@ -1372,7 +1372,8 @@ get_delta_base_cache_entry(struct packed_git *p, off_t base_offset)
hashmap_entry_init(&entry, pack_entry_hash(p, base_offset));
key.p = p;
key.base_offset = base_offset;
return hashmap_get(&delta_base_cache, &entry, &key);
e = hashmap_get(&delta_base_cache, &entry, &key);
return e ? container_of(e, struct delta_base_cache_entry, ent) : NULL;
}

static int delta_base_cache_key_eq(const struct delta_base_cache_key *a,
@@ -1382,11 +1383,16 @@ static int delta_base_cache_key_eq(const struct delta_base_cache_key *a,
}

static int delta_base_cache_hash_cmp(const void *unused_cmp_data,
const void *va, const void *vb,
const struct hashmap_entry *va,
const struct hashmap_entry *vb,
const void *vkey)
{
const struct delta_base_cache_entry *a = va, *b = vb;
const struct delta_base_cache_entry *a, *b;
const struct delta_base_cache_key *key = vkey;

a = container_of(va, const struct delta_base_cache_entry, ent);
b = container_of(vb, const struct delta_base_cache_entry, ent);

if (key)
return !delta_base_cache_key_eq(&a->key, key);
else
@@ -1405,7 +1411,7 @@ static int in_delta_base_cache(struct packed_git *p, off_t base_offset)
*/
static void detach_delta_base_cache_entry(struct delta_base_cache_entry *ent)
{
hashmap_remove(&delta_base_cache, ent, &ent->key);
hashmap_remove(&delta_base_cache, &ent->ent, &ent->key);
list_del(&ent->lru);
delta_base_cached -= ent->size;
free(ent);
@@ -1469,8 +1475,8 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,

if (!delta_base_cache.cmpfn)
hashmap_init(&delta_base_cache, delta_base_cache_hash_cmp, NULL, 0);
hashmap_entry_init(ent, pack_entry_hash(p, base_offset));
hashmap_add(&delta_base_cache, ent);
hashmap_entry_init(&ent->ent, pack_entry_hash(p, base_offset));
hashmap_add(&delta_base_cache, &ent->ent);
}

int packed_object_info(struct repository *r, struct packed_git *p,


+ 10
- 8
patch-ids.c View File

@@ -36,14 +36,16 @@ int commit_patch_id(struct commit *commit, struct diff_options *options,
* any significance; only that it is non-zero matters.
*/
static int patch_id_neq(const void *cmpfn_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
/* NEEDSWORK: const correctness? */
struct diff_options *opt = (void *)cmpfn_data;
struct patch_id *a = (void *)entry;
struct patch_id *b = (void *)entry_or_key;
struct patch_id *a, *b;

a = container_of(eptr, struct patch_id, ent);
b = container_of(entry_or_key, struct patch_id, ent);

if (is_null_oid(&a->patch_id) &&
commit_patch_id(a->commit, opt, &a->patch_id, 0, 0))
@@ -69,7 +71,7 @@ int init_patch_ids(struct repository *r, struct patch_ids *ids)

int free_patch_ids(struct patch_ids *ids)
{
hashmap_free(&ids->patches, 1);
hashmap_free_entries(&ids->patches, struct patch_id, ent);
return 0;
}

@@ -83,7 +85,7 @@ static int init_patch_id_entry(struct patch_id *patch,
if (commit_patch_id(commit, &ids->diffopts, &header_only_patch_id, 1, 0))
return -1;

hashmap_entry_init(patch, oidhash(&header_only_patch_id));
hashmap_entry_init(&patch->ent, oidhash(&header_only_patch_id));
return 0;
}

@@ -99,7 +101,7 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
if (init_patch_id_entry(&patch, commit, ids))
return NULL;

return hashmap_get(&ids->patches, &patch, NULL);
return hashmap_get_entry(&ids->patches, &patch, ent, NULL);
}

struct patch_id *add_commit_patch_id(struct commit *commit,
@@ -116,6 +118,6 @@ struct patch_id *add_commit_patch_id(struct commit *commit,
return NULL;
}

hashmap_add(&ids->patches, key);
hashmap_add(&ids->patches, &key->ent);
return key;
}

+ 5
- 5
range-diff.c View File

@@ -218,8 +218,8 @@ static void find_exact_matches(struct string_list *a, struct string_list *b)
util->i = i;
util->patch = a->items[i].string;
util->diff = util->patch + util->diff_offset;
hashmap_entry_init(util, strhash(util->diff));
hashmap_add(&map, util);
hashmap_entry_init(&util->e, strhash(util->diff));
hashmap_add(&map, &util->e);
}

/* Now try to find exact matches in b */
@@ -229,8 +229,8 @@ static void find_exact_matches(struct string_list *a, struct string_list *b)
util->i = i;
util->patch = b->items[i].string;
util->diff = util->patch + util->diff_offset;
hashmap_entry_init(util, strhash(util->diff));
other = hashmap_remove(&map, util, NULL);
hashmap_entry_init(&util->e, strhash(util->diff));
other = hashmap_remove_entry(&map, util, e, NULL);
if (other) {
if (other->matching >= 0)
BUG("already assigned!");
@@ -240,7 +240,7 @@ static void find_exact_matches(struct string_list *a, struct string_list *b)
}
}

hashmap_free(&map, 0);
hashmap_free(&map);
}

static void diffsize_consume(void *data, char *line, unsigned long len)


+ 20
- 13
ref-filter.c View File

@@ -79,17 +79,20 @@ static struct expand_data {
} oi, oi_deref;

struct ref_to_worktree_entry {
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;
struct worktree *wt; /* key is wt->head_ref */
};

static int ref_to_worktree_map_cmpfnc(const void *unused_lookupdata,
const void *existing_hashmap_entry_to_test,
const void *key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *kptr,
const void *keydata_aka_refname)
{
const struct ref_to_worktree_entry *e = existing_hashmap_entry_to_test;
const struct ref_to_worktree_entry *k = key;
const struct ref_to_worktree_entry *e, *k;

e = container_of(eptr, const struct ref_to_worktree_entry, ent);
k = container_of(kptr, const struct ref_to_worktree_entry, ent);

return strcmp(e->wt->head_ref,
keydata_aka_refname ? keydata_aka_refname : k->wt->head_ref);
}
@@ -1565,9 +1568,10 @@ static void populate_worktree_map(struct hashmap *map, struct worktree **worktre
struct ref_to_worktree_entry *entry;
entry = xmalloc(sizeof(*entry));
entry->wt = worktrees[i];
hashmap_entry_init(entry, strhash(worktrees[i]->head_ref));
hashmap_entry_init(&entry->ent,
strhash(worktrees[i]->head_ref));

hashmap_add(map, entry);
hashmap_add(map, &entry->ent);
}
}
}
@@ -1584,18 +1588,20 @@ static void lazy_init_worktree_map(void)

static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref)
{
struct hashmap_entry entry;
struct hashmap_entry entry, *e;
struct ref_to_worktree_entry *lookup_result;

lazy_init_worktree_map();

hashmap_entry_init(&entry, strhash(ref->refname));
lookup_result = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname);
e = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname);

if (lookup_result)
return xstrdup(lookup_result->wt->path);
else
if (!e)
return xstrdup("");

lookup_result = container_of(e, struct ref_to_worktree_entry, ent);

return xstrdup(lookup_result->wt->path);
}

/*
@@ -2166,7 +2172,8 @@ void ref_array_clear(struct ref_array *array)
used_atom_cnt = 0;

if (ref_to_worktree_map.worktrees) {
hashmap_free(&(ref_to_worktree_map.map), 1);
hashmap_free_entries(&(ref_to_worktree_map.map),
struct ref_to_worktree_entry, ent);
free_worktrees(ref_to_worktree_map.worktrees);
ref_to_worktree_map.worktrees = NULL;
}


+ 18
- 7
refs.c View File

@@ -1772,7 +1772,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,

struct ref_store_hash_entry
{
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;

struct ref_store *refs;

@@ -1781,11 +1781,16 @@ struct ref_store_hash_entry
};

static int ref_store_hash_cmp(const void *unused_cmp_data,
const void *entry, const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *keydata)
{
const struct ref_store_hash_entry *e1 = entry, *e2 = entry_or_key;
const char *name = keydata ? keydata : e2->name;
const struct ref_store_hash_entry *e1, *e2;
const char *name;

e1 = container_of(eptr, const struct ref_store_hash_entry, ent);
e2 = container_of(entry_or_key, const struct ref_store_hash_entry, ent);
name = keydata ? keydata : e2->name;

return strcmp(e1->name, name);
}
@@ -1796,7 +1801,7 @@ static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
struct ref_store_hash_entry *entry;

FLEX_ALLOC_STR(entry, name, name);