Skip to content

Commit 2e0a304

Browse files
committed
oidmap: introduce high-level setter for key/value pairs
Currently, one would use either `git_oidmap_insert` to insert key/value pairs into a map or `git_oidmap_put` to insert a key only. These function have historically been macros, which is why their syntax is kind of weird: instead of returning an error code directly, they instead have to be passed a pointer to where the return value shall be stored. This does not match libgit2's common idiom of directly returning error codes.Furthermore, `git_oidmap_put` is tightly coupled with implementation details of the map as it exposes the index of inserted entries. Introduce a new function `git_oidmap_set`, which takes as parameters the map, key and value and directly returns an error code. Convert all trivial callers of `git_oidmap_insert` and `git_oidmap_put` to make use of it.
1 parent 9694ef2 commit 2e0a304

File tree

10 files changed

+120
-67
lines changed

10 files changed

+120
-67
lines changed

src/cache.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
192192

193193
/* not found */
194194
if ((stored_entry = git_oidmap_get(cache->map, &entry->oid)) == NULL) {
195-
int rval;
196-
197-
git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
198-
if (rval >= 0) {
195+
if (git_oidmap_set(cache->map, &entry->oid, entry) == 0) {
199196
git_cached_obj_incref(entry);
200197
cache->used_memory += entry->size;
201198
git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size);
@@ -209,12 +206,10 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
209206
entry = stored_entry;
210207
} else if (stored_entry->flags == GIT_CACHE_STORE_RAW &&
211208
entry->flags == GIT_CACHE_STORE_PARSED) {
212-
int rval;
213-
214209
git_cached_obj_decref(stored_entry);
215210
git_cached_obj_incref(entry);
216211

217-
git_oidmap_insert(cache->map, &entry->oid, entry, &rval);
212+
git_oidmap_set(cache->map, &entry->oid, entry);
218213
} else {
219214
/* NO OP */
220215
}

src/describe.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,8 @@ static int add_to_known_names(
119119
e->path = git__strdup(path);
120120
git_oid_cpy(&e->peeled, peeled);
121121

122-
if (!found) {
123-
int ret;
124-
125-
git_oidmap_insert(names, &e->peeled, e, &ret);
126-
if (ret < 0)
127-
return -1;
128-
}
122+
if (!found && git_oidmap_set(names, &e->peeled, e) < 0)
123+
return -1;
129124
}
130125
else
131126
git_tag_free(tag);

src/indexer.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,8 @@ static int crc_object(uint32_t *crc_out, git_mwindow_file *mwf, git_off_t start,
309309
return 0;
310310
}
311311

312-
static void add_expected_oid(git_indexer *idx, const git_oid *oid)
312+
static int add_expected_oid(git_indexer *idx, const git_oid *oid)
313313
{
314-
int ret;
315-
316314
/*
317315
* If we know about that object because it is stored in our ODB or
318316
* because we have already processed it as part of our pack file, we do
@@ -323,8 +321,10 @@ static void add_expected_oid(git_indexer *idx, const git_oid *oid)
323321
!git_oidmap_exists(idx->expected_oids, oid)) {
324322
git_oid *dup = git__malloc(sizeof(*oid));
325323
git_oid_cpy(dup, oid);
326-
git_oidmap_put(idx->expected_oids, dup, &ret);
324+
return git_oidmap_set(idx->expected_oids, dup, NULL);
327325
}
326+
327+
return 0;
328328
}
329329

330330
static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
@@ -364,7 +364,8 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
364364
size_t i;
365365

366366
git_array_foreach(tree->entries, i, entry)
367-
add_expected_oid(idx, entry->oid);
367+
if (add_expected_oid(idx, entry->oid) < 0)
368+
goto out;
368369

369370
break;
370371
}
@@ -375,17 +376,20 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
375376
size_t i;
376377

377378
git_array_foreach(commit->parent_ids, i, parent_oid)
378-
add_expected_oid(idx, parent_oid);
379+
if (add_expected_oid(idx, parent_oid) < 0)
380+
goto out;
379381

380-
add_expected_oid(idx, &commit->tree_id);
382+
if (add_expected_oid(idx, &commit->tree_id) < 0)
383+
goto out;
381384

382385
break;
383386
}
384387
case GIT_OBJECT_TAG:
385388
{
386389
git_tag *tag = (git_tag *) object;
387390

388-
add_expected_oid(idx, &tag->target);
391+
if (add_expected_oid(idx, &tag->target) < 0)
392+
goto out;
389393

390394
break;
391395
}
@@ -403,7 +407,6 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
403407
static int store_object(git_indexer *idx)
404408
{
405409
int i, error;
406-
size_t k;
407410
git_oid oid;
408411
struct entry *entry;
409412
git_off_t entry_size;
@@ -439,22 +442,18 @@ static int store_object(git_indexer *idx)
439442
git_oid_cpy(&pentry->sha1, &oid);
440443
pentry->offset = entry_start;
441444

442-
k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
443-
if (error == -1) {
445+
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->sha1)) {
446+
git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->sha1));
444447
git__free(pentry);
445-
git_error_set_oom();
446448
goto on_error;
447449
}
448450

449-
if (error == 0) {
450-
git_error_set(GIT_ERROR_INDEXER, "duplicate object %s found in pack", git_oid_tostr_s(&pentry->sha1));
451+
if ((error = git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry)) < 0) {
451452
git__free(pentry);
453+
git_error_set_oom();
452454
goto on_error;
453455
}
454456

455-
456-
git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
457-
458457
git_oid_cpy(&entry->oid, &oid);
459458

460459
if (crc_object(&entry->crc, &idx->pack->mwf, entry_start, entry_size) < 0)
@@ -483,8 +482,7 @@ GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id)
483482

484483
static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start)
485484
{
486-
int i, error;
487-
size_t k;
485+
int i;
488486

489487
if (entry_start > UINT31_MAX) {
490488
entry->offset = UINT32_MAX;
@@ -494,15 +492,13 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent
494492
}
495493

496494
pentry->offset = entry_start;
497-
k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error);
498495

499-
if (error <= 0) {
496+
if (git_oidmap_exists(idx->pack->idx_cache, &pentry->sha1) ||
497+
git_oidmap_set(idx->pack->idx_cache, &pentry->sha1, pentry) < 0) {
500498
git_error_set(GIT_ERROR_INDEXER, "cannot insert object into pack");
501499
return -1;
502500
}
503501

504-
git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry);
505-
506502
/* Add the object to the list */
507503
if (git_vector_insert(&idx->objects, entry) < 0)
508504
return -1;

src/merge.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,6 @@ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid
11081108
{
11091109
deletes_by_oid_queue *queue;
11101110
size_t *array_entry;
1111-
int error;
11121111

11131112
if ((queue = git_oidmap_get(map, id)) == NULL) {
11141113
queue = git_pool_malloc(pool, sizeof(deletes_by_oid_queue));
@@ -1118,8 +1117,7 @@ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid
11181117
queue->next_pos = 0;
11191118
queue->first_entry = idx;
11201119

1121-
git_oidmap_insert(map, id, queue, &error);
1122-
if (error < 0)
1120+
if (git_oidmap_set(map, id, queue) < 0)
11231121
return -1;
11241122
} else {
11251123
array_entry = git_array_alloc(queue->arr);

src/odb_mempack.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,9 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
3737
{
3838
struct memory_packer_db *db = (struct memory_packer_db *)_backend;
3939
struct memobject *obj = NULL;
40-
size_t pos;
4140
size_t alloc_len;
42-
int rval;
4341

44-
pos = git_oidmap_put(db->objects, oid, &rval);
45-
if (rval < 0)
46-
return -1;
47-
48-
if (rval == 0)
42+
if (git_oidmap_exists(db->objects, oid))
4943
return 0;
5044

5145
GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len);
@@ -57,8 +51,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void
5751
obj->len = len;
5852
obj->type = type;
5953

60-
git_oidmap_set_key_at(db->objects, pos, &obj->oid);
61-
git_oidmap_set_value_at(db->objects, pos, obj);
54+
if (git_oidmap_set(db->objects, &obj->oid, obj) < 0)
55+
return -1;
6256

6357
if (type == GIT_OBJECT_COMMIT) {
6458
struct memobject **store = git_array_alloc(db->commits);

src/oidmap.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ void *git_oidmap_get(git_oidmap *map, const git_oid *key)
5757
return kh_val(map, idx);
5858
}
5959

60+
int git_oidmap_set(git_oidmap *map, const git_oid *key, void *value)
61+
{
62+
size_t idx;
63+
int rval;
64+
65+
idx = kh_put(oid, map, key, &rval);
66+
if (rval < 0)
67+
return -1;
68+
69+
if (rval == 0)
70+
kh_key(map, idx) = key;
71+
72+
kh_val(map, idx) = value;
73+
74+
return 0;
75+
}
76+
6077
size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key)
6178
{
6279
return kh_get(oid, map, key);

src/oidmap.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,21 @@ size_t git_oidmap_size(git_oidmap *map);
6161
*/
6262
void *git_oidmap_get(git_oidmap *map, const git_oid *key);
6363

64+
/**
65+
* Set the entry for key to value.
66+
*
67+
* If the map has no corresponding entry for the given key, a new
68+
* entry will be created with the given value. If an entry exists
69+
* already, its value will be updated to match the given value.
70+
*
71+
* @param map map to create new entry in
72+
* @param key key to set
73+
* @param value value to associate the key with; may be NULL
74+
* @return zero if the key was successfully set, a negative error
75+
* code otherwise
76+
*/
77+
int git_oidmap_set(git_oidmap *map, const git_oid *key, void *value);
78+
6479
size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key);
6580
int git_oidmap_valid_index(git_oidmap *map, size_t idx);
6681

src/pack-objects.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,24 +192,26 @@ unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n)
192192
return pb->nr_threads;
193193
}
194194

195-
static void rehash(git_packbuilder *pb)
195+
static int rehash(git_packbuilder *pb)
196196
{
197197
git_pobject *po;
198-
size_t pos, i;
199-
int ret;
198+
size_t i;
200199

201200
git_oidmap_clear(pb->object_ix);
201+
202202
for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) {
203-
pos = git_oidmap_put(pb->object_ix, &po->id, &ret);
204-
git_oidmap_set_value_at(pb->object_ix, pos, po);
203+
if (git_oidmap_set(pb->object_ix, &po->id, po) < 0)
204+
return -1;
205205
}
206+
207+
return 0;
206208
}
207209

208210
int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
209211
const char *name)
210212
{
211213
git_pobject *po;
212-
size_t newsize, pos;
214+
size_t newsize;
213215
int ret;
214216

215217
assert(pb && oid);
@@ -233,7 +235,9 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
233235
pb->object_list = git__reallocarray(pb->object_list,
234236
pb->nr_alloc, sizeof(*po));
235237
GIT_ERROR_CHECK_ALLOC(pb->object_list);
236-
rehash(pb);
238+
239+
if (rehash(pb) < 0)
240+
return -1;
237241
}
238242

239243
po = pb->object_list + pb->nr_objects;
@@ -246,13 +250,10 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
246250
git_oid_cpy(&po->id, oid);
247251
po->hash = name_hash(name);
248252

249-
pos = git_oidmap_put(pb->object_ix, &po->id, &ret);
250-
if (ret < 0) {
253+
if (git_oidmap_set(pb->object_ix, &po->id, po) < 0) {
251254
git_error_set_oom();
252-
return ret;
255+
return -1;
253256
}
254-
assert(ret != 0);
255-
git_oidmap_set_value_at(pb->object_ix, pos, po);
256257

257258
pb->done = false;
258259

@@ -1541,7 +1542,8 @@ static int retrieve_object(struct walk_object **out, git_packbuilder *pb, const
15411542
if ((error = lookup_walk_object(&obj, pb, id)) < 0)
15421543
return error;
15431544

1544-
git_oidmap_insert(pb->walk_objects, &obj->id, obj, &error);
1545+
if ((error = git_oidmap_set(pb->walk_objects, &obj->id, obj)) < 0)
1546+
return error;
15451547
}
15461548

15471549
*out = obj;

src/revwalk.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ git_commit_list_node *git_revwalk__commit_lookup(
2121
git_revwalk *walk, const git_oid *oid)
2222
{
2323
git_commit_list_node *commit;
24-
size_t pos;
25-
int ret;
2624

2725
/* lookup and reserve space if not already present */
2826
if ((commit = git_oidmap_get(walk->commits, oid)) != NULL)
@@ -34,9 +32,8 @@ git_commit_list_node *git_revwalk__commit_lookup(
3432

3533
git_oid_cpy(&commit->oid, oid);
3634

37-
pos = git_oidmap_put(walk->commits, &commit->oid, &ret);
38-
assert(ret != 0);
39-
git_oidmap_set_value_at(walk->commits, pos, commit);
35+
if ((git_oidmap_set(walk->commits, &commit->oid, commit)) < 0)
36+
return NULL;
4037

4138
return commit;
4239
}

tests/core/oidmap.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,47 @@ void test_core_oidmap__get_fails_with_nonexisting_key(void)
182182

183183
git_oidmap_free(map);
184184
}
185+
186+
void test_core_oidmap__setting_oid_persists(void)
187+
{
188+
git_oid oids[] = {
189+
{{ 0x01 }},
190+
{{ 0x02 }},
191+
{{ 0x03 }}
192+
};
193+
git_oidmap *map;
194+
195+
cl_git_pass(git_oidmap_new(&map));
196+
cl_git_pass(git_oidmap_set(map, &oids[0], "one"));
197+
cl_git_pass(git_oidmap_set(map, &oids[1], "two"));
198+
cl_git_pass(git_oidmap_set(map, &oids[2], "three"));
199+
200+
cl_assert_equal_s(git_oidmap_get(map, &oids[0]), "one");
201+
cl_assert_equal_s(git_oidmap_get(map, &oids[1]), "two");
202+
cl_assert_equal_s(git_oidmap_get(map, &oids[2]), "three");
203+
204+
git_oidmap_free(map);
205+
}
206+
207+
void test_core_oidmap__setting_existing_key_updates(void)
208+
{
209+
git_oid oids[] = {
210+
{{ 0x01 }},
211+
{{ 0x02 }},
212+
{{ 0x03 }}
213+
};
214+
git_oidmap *map;
215+
216+
cl_git_pass(git_oidmap_new(&map));
217+
cl_git_pass(git_oidmap_set(map, &oids[0], "one"));
218+
cl_git_pass(git_oidmap_set(map, &oids[1], "two"));
219+
cl_git_pass(git_oidmap_set(map, &oids[2], "three"));
220+
cl_assert_equal_i(git_oidmap_size(map), 3);
221+
222+
cl_git_pass(git_oidmap_set(map, &oids[1], "other"));
223+
cl_assert_equal_i(git_oidmap_size(map), 3);
224+
225+
cl_assert_equal_s(git_oidmap_get(map, &oids[1]), "other");
226+
227+
git_oidmap_free(map);
228+
}

0 commit comments

Comments
 (0)