diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2023-05-08 10:07:11 +0100 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2023-05-09 17:14:08 +0100 |
commit | 0a7e32b2326c02a91f9560dfd209e56ea9fb9d49 (patch) | |
tree | 1040ae92dd88cdacce82395200ecf4f966883310 | |
parent | 04cddffea9d00d5788b4f41a7dce3356089228ab (diff) | |
download | libgit2-0a7e32b2326c02a91f9560dfd209e56ea9fb9d49.tar.gz |
oid: use an oid array instead of shallowarray
Users should provide us an array of object ids; we don't need a separate
type. And especially, we should not be mutating user-providing values.
Instead, use `git_oid *` in the shallow code.
-rw-r--r-- | include/git2/sys/transport.h | 22 | ||||
-rw-r--r-- | src/libgit2/fetch.c | 29 | ||||
-rw-r--r-- | src/libgit2/grafts.c | 16 | ||||
-rw-r--r-- | src/libgit2/grafts.h | 2 | ||||
-rw-r--r-- | src/libgit2/oidarray.c | 52 | ||||
-rw-r--r-- | src/libgit2/oidarray.h | 6 | ||||
-rw-r--r-- | src/libgit2/remote.c | 5 | ||||
-rw-r--r-- | src/libgit2/repository.c | 20 | ||||
-rw-r--r-- | src/libgit2/repository.h | 4 | ||||
-rw-r--r-- | src/libgit2/transports/local.c | 11 | ||||
-rw-r--r-- | src/libgit2/transports/smart.c | 49 | ||||
-rw-r--r-- | src/libgit2/transports/smart.h | 7 | ||||
-rw-r--r-- | src/libgit2/transports/smart_pkt.c | 13 | ||||
-rw-r--r-- | src/libgit2/transports/smart_protocol.c | 56 | ||||
-rw-r--r-- | src/util/array.h | 3 | ||||
-rw-r--r-- | tests/libgit2/core/oidarray.c | 98 | ||||
-rw-r--r-- | tests/libgit2/online/shallow.c | 35 | ||||
-rw-r--r-- | tests/libgit2/transports/smart/shallowarray.c | 52 |
18 files changed, 304 insertions, 176 deletions
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h index 062bcd0ed..96a35d08c 100644 --- a/include/git2/sys/transport.h +++ b/include/git2/sys/transport.h @@ -25,12 +25,11 @@ GIT_BEGIN_DECL -typedef struct git_shallowarray git_shallowarray; - typedef struct { const git_remote_head * const *refs; - size_t count; - git_shallowarray *shallow_roots; + size_t refs_len; + git_oid *shallow_roots; + size_t shallow_roots_len; int depth; } git_fetch_negotiation; @@ -108,6 +107,16 @@ struct git_transport { const git_fetch_negotiation *fetch_data); /** + * Return the shallow roots of the remote. + * + * This function may be called after a successful call to + * `negotiate_fetch`. + */ + int GIT_CALLBACK(shallow_roots)( + git_oidarray *out, + git_transport *transport); + + /** * Start downloading the packfile from the remote repository. * * This function may be called after a successful call to @@ -450,11 +459,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh( git_transport *owner, void *param); -GIT_EXTERN(size_t) git_shallowarray_count(git_shallowarray *array); -GIT_EXTERN(const git_oid *) git_shallowarray_get(git_shallowarray *array, size_t idx); -GIT_EXTERN(int) git_shallowarray_add(git_shallowarray *array, git_oid *oid); -GIT_EXTERN(int) git_shallowarray_remove(git_shallowarray *array, git_oid *oid); - /** @} */ GIT_END_DECL #endif diff --git a/src/libgit2/fetch.c b/src/libgit2/fetch.c index 86b650a60..b43425215 100644 --- a/src/libgit2/fetch.c +++ b/src/libgit2/fetch.c @@ -61,7 +61,7 @@ static int mark_local(git_remote *remote) git_vector_foreach(&remote->refs, i, head) { /* If we have the object, mark it so we don't ask for it. - However if we are unshallowing, we need to ask for it + However if we are unshallowing, we need to ask for it even though the head exists locally. */ if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid)) head->local = 1; @@ -169,6 +169,7 @@ cleanup: int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) { git_transport *t = remote->transport; + int error; remote->need_pack = 0; @@ -191,33 +192,39 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) * server what we want and what we have. */ remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; - remote->nego.count = remote->refs.length; - remote->nego.shallow_roots = git__malloc(sizeof(*remote->nego.shallow_roots)); - - git_array_init(remote->nego.shallow_roots->array); + remote->nego.refs_len = remote->refs.length; - git_repository__shallow_roots(&remote->nego.shallow_roots->array, remote->repo); + if (git_repository__shallow_roots(&remote->nego.shallow_roots, + &remote->nego.shallow_roots_len, + remote->repo) < 0) + return -1; - return t->negotiate_fetch(t, + error = t->negotiate_fetch(t, remote->repo, &remote->nego); + + git__free(remote->nego.shallow_roots); + + return error; } int git_fetch_download_pack(git_remote *remote) { + git_oidarray shallow_roots = { NULL }; git_transport *t = remote->transport; int error; if (!remote->need_pack) return 0; - if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0) + if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0 || + (error = t->shallow_roots(&shallow_roots, t)) != 0) return error; - if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) != 0) - return error; + error = git_repository__shallow_roots_write(remote->repo, &shallow_roots); - return 0; + git_oidarray_dispose(&shallow_roots); + return error; } int git_fetch_options_init(git_fetch_options *opts, unsigned int version) diff --git a/src/libgit2/grafts.c b/src/libgit2/grafts.c index 83f5b2ab4..1d9373a56 100644 --- a/src/libgit2/grafts.c +++ b/src/libgit2/grafts.c @@ -243,20 +243,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi return 0; } -int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts) +int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts) { + git_array_oid_t array = GIT_ARRAY_INIT; const git_oid *oid; - size_t i = 0; - int error; + size_t existing, i = 0; GIT_ASSERT_ARG(out && grafts); - while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { - git_oid *cpy = git_array_alloc(*out); + if ((existing = git_oidmap_size(grafts->commits)) > 0) + git_array_init_to_size(array, existing); + + while (git_oidmap_iterate(NULL, grafts->commits, &i, &oid) == 0) { + git_oid *cpy = git_array_alloc(array); GIT_ERROR_CHECK_ALLOC(cpy); git_oid_cpy(cpy, oid); } + *out = array.ptr; + *out_len = array.size; + return 0; } diff --git a/src/libgit2/grafts.h b/src/libgit2/grafts.h index 0d561fc25..394867fd6 100644 --- a/src/libgit2/grafts.h +++ b/src/libgit2/grafts.h @@ -30,7 +30,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len); int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents); int git_grafts_remove(git_grafts *grafts, const git_oid *oid); int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid); -int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts); +int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts); size_t git_grafts_size(git_grafts *grafts); #endif diff --git a/src/libgit2/oidarray.c b/src/libgit2/oidarray.c index 583017c4e..37f67756a 100644 --- a/src/libgit2/oidarray.c +++ b/src/libgit2/oidarray.c @@ -15,10 +15,17 @@ void git_oidarray_dispose(git_oidarray *arr) git__free(arr->ids); } -void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array) +void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array) { - arr->count = array->size; - arr->ids = array->ptr; + out->count = array->size; + out->ids = array->ptr; +} + +void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array) +{ + out->ptr = array->ids; + out->size = array->count; + out->asize = array->count; } void git_oidarray__reverse(git_oidarray *arr) @@ -33,6 +40,45 @@ void git_oidarray__reverse(git_oidarray *arr) } } +int git_oidarray__add(git_array_oid_t *arr, git_oid *id) +{ + git_oid *add, *iter; + size_t i; + + git_array_foreach(*arr, i, iter) { + if (git_oid_cmp(iter, id) == 0) + return 0; + } + + if ((add = git_array_alloc(*arr)) == NULL) + return -1; + + git_oid_cpy(add, id); + return 0; +} + +bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id) +{ + bool found = false; + size_t remain, i; + git_oid *iter; + + git_array_foreach(*arr, i, iter) { + if (git_oid_cmp(iter, id) == 0) { + arr->size--; + remain = arr->size - i; + + if (remain > 0) + memmove(&arr->ptr[i], &arr->ptr[i+1], remain * sizeof(git_oid)); + + found = true; + break; + } + } + + return found; +} + #ifndef GIT_DEPRECATE_HARD void git_oidarray_free(git_oidarray *arr) diff --git a/src/libgit2/oidarray.h b/src/libgit2/oidarray.h index eed3a1091..8f1543a32 100644 --- a/src/libgit2/oidarray.h +++ b/src/libgit2/oidarray.h @@ -15,6 +15,10 @@ typedef git_array_t(git_oid) git_array_oid_t; extern void git_oidarray__reverse(git_oidarray *arr); -extern void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array); +extern void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array); +extern void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array); + +int git_oidarray__add(git_array_oid_t *arr, git_oid *id); +bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id); #endif diff --git a/src/libgit2/remote.c b/src/libgit2/remote.c index ef414209f..fee2a7f39 100644 --- a/src/libgit2/remote.c +++ b/src/libgit2/remote.c @@ -2167,11 +2167,6 @@ void git_remote_free(git_remote *remote) remote->transport = NULL; } - if (remote->nego.shallow_roots) { - git_array_clear(remote->nego.shallow_roots->array); - git__free(remote->nego.shallow_roots); - } - git_vector_free(&remote->refs); free_refspecs(&remote->refspecs); diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index 763b62375..8fcc4e2ba 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -3651,7 +3651,11 @@ int git_repository_state_cleanup(git_repository *repo) return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); } -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { +int git_repository__shallow_roots( + git_oid **out, + size_t *out_len, + git_repository *repo) +{ int error = 0; if (!repo->shallow_grafts && (error = load_grafts(repo)) < 0) @@ -3660,19 +3664,18 @@ int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) { if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0) return error; - if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0) + if ((error = git_grafts_oids(out, out_len, repo->shallow_grafts)) < 0) return error; return 0; } -int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots) +int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots) { git_filebuf file = GIT_FILEBUF_INIT; git_str path = GIT_STR_INIT; char oid_str[GIT_OID_MAX_HEXSIZE + 1]; - size_t idx; - git_oid *oid; + size_t i; int filebuf_hash, error = 0; GIT_ASSERT_ARG(repo); @@ -3686,8 +3689,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro if ((error = git_filebuf_open(&file, git_str_cstr(&path), filebuf_hash, 0666)) < 0) goto on_error; - git_array_foreach(roots, idx, oid) { - git_oid_tostr(oid_str, sizeof(oid_str), oid); + for (i = 0; i < roots->count; i++) { + git_oid_tostr(oid_str, sizeof(oid_str), &roots->ids[i]); git_filebuf_write(&file, oid_str, git_oid_hexsize(repo->oid_type)); git_filebuf_write(&file, "\n", 1); } @@ -3699,7 +3702,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro goto on_error; } - if (git_array_size(roots) == 0) + if (!roots->count) remove(path.ptr); on_error: @@ -3727,6 +3730,7 @@ int git_repository_is_shallow(git_repository *repo) if (error < 0) return error; + return st.st_size == 0 ? 0 : 1; } diff --git a/src/libgit2/repository.h b/src/libgit2/repository.h index d86b36271..8dc20324d 100644 --- a/src/libgit2/repository.h +++ b/src/libgit2/repository.h @@ -246,8 +246,8 @@ extern size_t git_repository__reserved_names_posix_len; bool git_repository__reserved_names( git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs); -int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo); -int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots); +int git_repository__shallow_roots(git_oid **out, size_t *out_len, git_repository *repo); +int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots); /* * The default branch for the repository; the `init.defaultBranch` diff --git a/src/libgit2/transports/local.c b/src/libgit2/transports/local.c index f576682a7..64c21afbd 100644 --- a/src/libgit2/transports/local.c +++ b/src/libgit2/transports/local.c @@ -320,6 +320,16 @@ static int local_negotiate_fetch( return 0; } +static int local_shallow_roots( + git_oidarray *out, + git_transport *transport) +{ + GIT_UNUSED(out); + GIT_UNUSED(transport); + + return 0; +} + static int local_push_update_remote_ref( git_repository *remote_repo, const char *lref, @@ -745,6 +755,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param) t->parent.oid_type = local_oid_type; #endif t->parent.negotiate_fetch = local_negotiate_fetch; + t->parent.shallow_roots = local_shallow_roots; t->parent.download_pack = local_download_pack; t->parent.push = local_push; t->parent.close = local_close; diff --git a/src/libgit2/transports/smart.c b/src/libgit2/transports/smart.c index da6dca039..a56524bff 100644 --- a/src/libgit2/transports/smart.c +++ b/src/libgit2/transports/smart.c @@ -416,6 +416,8 @@ static void git_smart__free(git_transport *transport) git_remote_connect_options_dispose(&t->connect_opts); + git_array_dispose(t->shallow_roots); + git__free(t->caps.object_format); git__free(t->caps.agent); git__free(t); @@ -490,6 +492,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) t->parent.close = git_smart__close; t->parent.free = git_smart__free; t->parent.negotiate_fetch = git_smart__negotiate_fetch; + t->parent.shallow_roots = git_smart__shallow_roots; t->parent.download_pack = git_smart__download_pack; t->parent.push = git_smart__push; t->parent.ls = git_smart__ls; @@ -517,49 +520,3 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) *out = (git_transport *) t; return 0; } - -size_t git_shallowarray_count(git_shallowarray *array) -{ - return git_array_size(array->array); -} - -const git_oid * git_shallowarray_get(git_shallowarray *array, size_t idx) -{ - return git_array_get(array->array, idx); -} - -int git_shallowarray_add(git_shallowarray *array, git_oid *oid) -{ - size_t oid_index; - - if (git_array_search(&oid_index, array->array, (git_array_compare_cb)git_oid_cmp, oid) < 0) { - git_oid *tmp = git_array_alloc(array->array); - GIT_ERROR_CHECK_ALLOC(tmp); - - git_oid_cpy(tmp, oid); - } - - return 0; -} - -int git_shallowarray_remove(git_shallowarray *array, git_oid *oid) -{ - git_array_oid_t new_array = GIT_ARRAY_INIT; - git_oid *element; - git_oid *tmp; - size_t i; - - git_array_foreach(array->array, i, element) { - if (git_oid_cmp(oid, element)) { - tmp = git_array_alloc(new_array); - GIT_ERROR_CHECK_ALLOC(tmp); - - git_oid_cpy(tmp, element); - } - } - - git_array_clear(array->array); - array->array = new_array; - - return 0; -} diff --git a/src/libgit2/transports/smart.h b/src/libgit2/transports/smart.h index 8e06d03ef..34e27ea8e 100644 --- a/src/libgit2/transports/smart.h +++ b/src/libgit2/transports/smart.h @@ -163,6 +163,7 @@ typedef struct { git_vector refs; git_vector heads; git_vector common; + git_array_oid_t shallow_roots; git_atomic32 cancelled; packetsize_cb packetsize_cb; void *packetsize_payload; @@ -183,6 +184,8 @@ int git_smart__negotiate_fetch( git_repository *repo, const git_fetch_negotiation *wants); +int git_smart__shallow_roots(git_oidarray *out, git_transport *transport); + int git_smart__download_pack( git_transport *transport, git_repository *repo, @@ -208,8 +211,4 @@ int git_pkt_buffer_wants(const git_fetch_negotiation *wants, transport_smart_cap int git_pkt_buffer_have(git_oid *oid, git_str *buf); void git_pkt_free(git_pkt *pkt); -struct git_shallowarray { - git_array_oid_t array; -}; - #endif diff --git a/src/libgit2/transports/smart_pkt.c b/src/libgit2/transports/smart_pkt.c index f2c9eea8e..9127ad5fe 100644 --- a/src/libgit2/transports/smart_pkt.c +++ b/src/libgit2/transports/smart_pkt.c @@ -770,7 +770,7 @@ int git_pkt_buffer_wants( size_t oid_hexsize, want_len, i = 0; #ifdef GIT_EXPERIMENTAL_SHA256 - oid_type = wants->count > 0 ? wants->refs[0]->oid.type : GIT_OID_SHA1; + oid_type = wants->refs_len > 0 ? wants->refs[0]->oid.type : GIT_OID_SHA1; #else oid_type = GIT_OID_SHA1; #endif @@ -781,7 +781,7 @@ int git_pkt_buffer_wants( oid_hexsize + 1 /* LF */; if (caps->common) { - for (; i < wants->count; ++i) { + for (; i < wants->refs_len; ++i) { head = wants->refs[i]; if (!head->local) break; @@ -793,7 +793,7 @@ int git_pkt_buffer_wants( i++; } - for (; i < wants->count; ++i) { + for (; i < wants->refs_len; ++i) { head = wants->refs[i]; if (head->local) @@ -810,12 +810,11 @@ int git_pkt_buffer_wants( } /* Tell the server about our shallow objects */ - for (i = 0; i < git_shallowarray_count(wants->shallow_roots); i++) { + for (i = 0; i < wants->shallow_roots_len; i++) { char oid[GIT_OID_MAX_HEXSIZE + 1]; git_str shallow_buf = GIT_STR_INIT; - git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, - git_shallowarray_get(wants->shallow_roots, i)); + git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, &wants->shallow_roots[i]); git_str_puts(&shallow_buf, "shallow "); git_str_puts(&shallow_buf, oid); git_str_putc(&shallow_buf, '\n'); @@ -835,7 +834,7 @@ int git_pkt_buffer_wants( git_str_printf(buf,"%04x%s", (unsigned int)git_str_len(&deepen_buf) + 4, git_str_cstr(&deepen_buf)); git_str_dispose(&deepen_buf); - + if (git_str_oom(buf)) return -1; } diff --git a/src/libgit2/transports/smart_protocol.c b/src/libgit2/transports/smart_protocol.c index 6167a8074..488ef07c0 100644 --- a/src/libgit2/transports/smart_protocol.c +++ b/src/libgit2/transports/smart_protocol.c @@ -364,7 +364,9 @@ static int cap_not_sup_err(const char *cap_name) } /* Disables server capabilities we're not interested in */ -static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *wants) +static int setup_caps( + transport_smart_caps *caps, + const git_fetch_negotiation *wants) { if (wants->depth > 0) { if (!caps->shallow) @@ -376,7 +378,27 @@ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *w return 0; } -int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_fetch_negotiation *wants) +static int setup_shallow_roots( + git_array_oid_t *out, + const git_fetch_negotiation *wants) +{ + git_array_clear(*out); + + if (wants->shallow_roots_len > 0) { + git_array_init_to_size(*out, wants->shallow_roots_len); + GIT_ERROR_CHECK_ALLOC(out->ptr); + + memcpy(out->ptr, wants->shallow_roots, + sizeof(git_oid) * wants->shallow_roots_len); + } + + return 0; +} + +int git_smart__negotiate_fetch( + git_transport *transport, + git_repository *repo, + const git_fetch_negotiation *wants) { transport_smart *t = (transport_smart *)transport; git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; @@ -388,7 +410,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c unsigned int i; git_oid oid; - if ((error = setup_caps(&t->caps, wants)) < 0) + if ((error = setup_caps(&t->caps, wants)) < 0 || + (error = setup_shallow_roots(&t->shallow_roots, wants)) < 0) return error; if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) @@ -411,9 +434,9 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c bool complete = false; if (pkt->type == GIT_PKT_SHALLOW) { - git_shallowarray_add(wants->shallow_roots, &pkt->oid); + error = git_oidarray__add(&t->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_UNSHALLOW) { - git_shallowarray_remove(wants->shallow_roots, &pkt->oid); + git_oidarray__remove(&t->shallow_roots, &pkt->oid); } else if (pkt->type == GIT_PKT_FLUSH) { /* Server is done, stop processing shallow oids */ complete = true; @@ -431,6 +454,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c if (error < 0) goto on_error; } + /* * Our support for ACK extensions is simply to parse them. On * the first ACK we will accept that as enough common @@ -531,10 +555,11 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c goto on_error; if (t->cancelled.val) { - git_error_set(GIT_ERROR_NET, "The fetch was cancelled by the user"); + git_error_set(GIT_ERROR_NET, "the fetch was cancelled"); error = GIT_EUSER; goto on_error; } + if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0) goto on_error; @@ -562,6 +587,25 @@ on_error: return error; } +int git_smart__shallow_roots(git_oidarray *out, git_transport *transport) +{ + transport_smart *t = (transport_smart *)transport; + size_t len; + + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&len, t->shallow_roots.size, sizeof(git_oid)); + + out->count = t->shallow_roots.size; + + if (len) { + out->ids = git__malloc(len); + memcpy(out->ids, t->shallow_roots.ptr, len); + } else { + out->ids = NULL; + } + + return 0; +} + static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_indexer_progress *stats) { int recvd; diff --git a/src/util/array.h b/src/util/array.h index bf66e1c5a..633d598ee 100644 --- a/src/util/array.h +++ b/src/util/array.h @@ -33,6 +33,9 @@ #define git_array_init_to_size(a, desired) \ do { (a).size = 0; (a).asize = desired; (a).ptr = git__calloc(desired, sizeof(*(a).ptr)); } while (0) +#define git_array_dispose(a) \ + do { git__free((a).ptr); } while (0) + #define git_array_clear(a) \ do { git__free((a).ptr); git_array_init(a); } while (0) diff --git a/tests/libgit2/core/oidarray.c b/tests/libgit2/core/oidarray.c new file mode 100644 index 000000000..4a9e47c70 --- /dev/null +++ b/tests/libgit2/core/oidarray.c @@ -0,0 +1,98 @@ +#include "clar_libgit2.h" + +#include "git2/oid.h" +#include "git2/transport.h" + +#include "common.h" +#include "transports/smart.h" +#include "oid.h" +#include "oidarray.h" + +#include <assert.h> + +#define oid_0 "c070ad8c08840c8116da865b2d65593a6bb9cd2a" +#define oid_1 "0966a434eb1a025db6b71485ab63a3bfbea520b6" +#define oid_2 "83834a7afdaa1a1260568567f6ad90020389f664" +#define oid_3 "746fb4c91a7b6190bc4761adf7410afc4b59812c" + +void test_core_oidarray__add_and_remove_oid_from_shallowarray(void) +{ + git_oid oid_0_obj, oid_1_obj, oid_2_obj, oid_3_obj; + git_array_oid_t array = GIT_ARRAY_INIT; + + git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); + git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); + git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); + git_oid__fromstr(&oid_3_obj, oid_3, GIT_OID_SHA1); + + /* add some initial ids */ + git_oidarray__add(&array, &oid_0_obj); + git_oidarray__add(&array, &oid_1_obj); + git_oidarray__add(&array, &oid_2_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&array.ptr[2])); + + /* don't duplicate existing ids */ + git_oidarray__add(&array, &oid_1_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&array.ptr[2])); + + /* remove the last id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_2_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + + /* add another id */ + git_oidarray__add(&array, &oid_3_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[2])); + + /* remove the first id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_0_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[1])); + + /* removing a nonexistent oid does nothing */ + cl_assert_equal_i(0, git_oidarray__remove(&array, &oid_2_obj)); + + /* add another id */ + git_oidarray__add(&array, &oid_0_obj); + + cl_assert_equal_i(3, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("746fb4c91a7b6190bc4761adf7410afc4b59812c", git_oid_tostr_s(&array.ptr[1])); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[2])); + + /* remove another id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_3_obj)); + + cl_assert_equal_i(2, array.size); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&array.ptr[0])); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[1])); + + /* remove another id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_1_obj)); + + cl_assert_equal_i(1, array.size); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&array.ptr[0])); + + /* remove the final id */ + cl_assert_equal_i(1, git_oidarray__remove(&array, &oid_0_obj)); + + cl_assert_equal_i(0, array.size); + + git_array_clear(array); +} diff --git a/tests/libgit2/online/shallow.c b/tests/libgit2/online/shallow.c index a889a68cd..12ef7748b 100644 --- a/tests/libgit2/online/shallow.c +++ b/tests/libgit2/online/shallow.c @@ -16,7 +16,8 @@ void test_online_shallow__clone_depth_zero(void) git_str path = GIT_STR_INIT; git_repository *repo; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; clone_opts.fetch_opts.depth = 0; clone_opts.remote_cb = remote_single_branch; @@ -29,10 +30,10 @@ void test_online_shallow__clone_depth_zero(void) cl_assert_equal_b(false, git_repository_is_shallow(repo)); /* full clones do not have shallow roots. */ - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(0, roots.size); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(0, roots_len); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_repository_free(repo); } @@ -44,7 +45,8 @@ void test_online_shallow__clone_depth_one(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; size_t num_commits = 0; int error = 0; @@ -57,9 +59,9 @@ void test_online_shallow__clone_depth_one(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(1, roots.size); - cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(1, roots_len); + cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots[0])); git_revwalk_new(&walk, repo); @@ -72,7 +74,7 @@ void test_online_shallow__clone_depth_one(void) cl_assert_equal_i(num_commits, 1); cl_assert_equal_i(error, GIT_ITEROVER); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); @@ -85,7 +87,8 @@ void test_online_shallow__clone_depth_five(void) git_revwalk *walk; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_oid oid; - git_array_oid_t roots = GIT_ARRAY_INIT; + git_oid *roots; + size_t roots_len; size_t num_commits = 0; int error = 0; @@ -98,11 +101,11 @@ void test_online_shallow__clone_depth_five(void) cl_assert_equal_b(true, git_repository_is_shallow(repo)); - cl_git_pass(git_repository__shallow_roots(&roots, repo)); - cl_assert_equal_i(3, roots.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); + cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo)); + cl_assert_equal_i(3, roots_len); + cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0])); + cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots[1])); + cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots[2])); git_revwalk_new(&walk, repo); @@ -115,7 +118,7 @@ void test_online_shallow__clone_depth_five(void) cl_assert_equal_i(num_commits, 13); cl_assert_equal_i(error, GIT_ITEROVER); - git_array_clear(roots); + git__free(roots); git_str_dispose(&path); git_revwalk_free(walk); git_repository_free(repo); diff --git a/tests/libgit2/transports/smart/shallowarray.c b/tests/libgit2/transports/smart/shallowarray.c deleted file mode 100644 index 34511c5f6..000000000 --- a/tests/libgit2/transports/smart/shallowarray.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "clar_libgit2.h" - -#include "git2/oid.h" -#include "git2/transport.h" - -#include "common.h" -#include "transports/smart.h" -#include "oid.h" - -#include <assert.h> - -#define oid_0 "c070ad8c08840c8116da865b2d65593a6bb9cd2a" -#define oid_1 "0966a434eb1a025db6b71485ab63a3bfbea520b6" -#define oid_2 "83834a7afdaa1a1260568567f6ad90020389f664" - -void test_transports_smart_shallowarray__add_and_remove_oid_from_shallowarray(void) -{ - git_oid oid_0_obj, oid_1_obj, oid_2_obj; - git_shallowarray *shallow_roots = git__malloc(sizeof(git_shallowarray)); - git_array_init(shallow_roots->array); - - git_oid__fromstr(&oid_0_obj, oid_0, GIT_OID_SHA1); - git_oid__fromstr(&oid_1_obj, oid_1, GIT_OID_SHA1); - git_oid__fromstr(&oid_2_obj, oid_2, GIT_OID_SHA1); - - git_shallowarray_add(shallow_roots, &oid_0_obj); - git_shallowarray_add(shallow_roots, &oid_1_obj); - git_shallowarray_add(shallow_roots, &oid_2_obj); - - cl_assert_equal_i(3, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); - cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&shallow_roots->array.ptr[2])); - - git_shallowarray_remove(shallow_roots, &oid_2_obj); - - cl_assert_equal_i(2, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&shallow_roots->array.ptr[1])); - - git_shallowarray_remove(shallow_roots, &oid_1_obj); - - cl_assert_equal_i(1, shallow_roots->array.size); - cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&shallow_roots->array.ptr[0])); - - git_shallowarray_remove(shallow_roots, &oid_0_obj); - - cl_assert_equal_i(0, shallow_roots->array.size); - - git_array_clear(shallow_roots->array); - git__free(shallow_roots); -} |