summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2023-05-08 10:07:11 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2023-05-09 17:14:08 +0100
commit0a7e32b2326c02a91f9560dfd209e56ea9fb9d49 (patch)
tree1040ae92dd88cdacce82395200ecf4f966883310
parent04cddffea9d00d5788b4f41a7dce3356089228ab (diff)
downloadlibgit2-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.h22
-rw-r--r--src/libgit2/fetch.c29
-rw-r--r--src/libgit2/grafts.c16
-rw-r--r--src/libgit2/grafts.h2
-rw-r--r--src/libgit2/oidarray.c52
-rw-r--r--src/libgit2/oidarray.h6
-rw-r--r--src/libgit2/remote.c5
-rw-r--r--src/libgit2/repository.c20
-rw-r--r--src/libgit2/repository.h4
-rw-r--r--src/libgit2/transports/local.c11
-rw-r--r--src/libgit2/transports/smart.c49
-rw-r--r--src/libgit2/transports/smart.h7
-rw-r--r--src/libgit2/transports/smart_pkt.c13
-rw-r--r--src/libgit2/transports/smart_protocol.c56
-rw-r--r--src/util/array.h3
-rw-r--r--tests/libgit2/core/oidarray.c98
-rw-r--r--tests/libgit2/online/shallow.c35
-rw-r--r--tests/libgit2/transports/smart/shallowarray.c52
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);
-}