Commit 0a7e32b2 by Edward Thomson

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.
parent 04cddffe
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
GIT_BEGIN_DECL GIT_BEGIN_DECL
typedef struct git_shallowarray git_shallowarray;
typedef struct { typedef struct {
const git_remote_head * const *refs; const git_remote_head * const *refs;
size_t count; size_t refs_len;
git_shallowarray *shallow_roots; git_oid *shallow_roots;
size_t shallow_roots_len;
int depth; int depth;
} git_fetch_negotiation; } git_fetch_negotiation;
...@@ -108,6 +107,16 @@ struct git_transport { ...@@ -108,6 +107,16 @@ struct git_transport {
const git_fetch_negotiation *fetch_data); 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. * Start downloading the packfile from the remote repository.
* *
* This function may be called after a successful call to * This function may be called after a successful call to
...@@ -450,11 +459,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh( ...@@ -450,11 +459,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh(
git_transport *owner, git_transport *owner,
void *param); 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 GIT_END_DECL
#endif #endif
...@@ -169,6 +169,7 @@ cleanup: ...@@ -169,6 +169,7 @@ cleanup:
int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
{ {
git_transport *t = remote->transport; git_transport *t = remote->transport;
int error;
remote->need_pack = 0; remote->need_pack = 0;
...@@ -191,33 +192,39 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) ...@@ -191,33 +192,39 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
* server what we want and what we have. * server what we want and what we have.
*/ */
remote->nego.refs = (const git_remote_head * const *)remote->refs.contents; remote->nego.refs = (const git_remote_head * const *)remote->refs.contents;
remote->nego.count = remote->refs.length; remote->nego.refs_len = remote->refs.length;
remote->nego.shallow_roots = git__malloc(sizeof(*remote->nego.shallow_roots));
git_array_init(remote->nego.shallow_roots->array);
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->repo,
&remote->nego); &remote->nego);
git__free(remote->nego.shallow_roots);
return error;
} }
int git_fetch_download_pack(git_remote *remote) int git_fetch_download_pack(git_remote *remote)
{ {
git_oidarray shallow_roots = { NULL };
git_transport *t = remote->transport; git_transport *t = remote->transport;
int error; int error;
if (!remote->need_pack) if (!remote->need_pack)
return 0; 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; return error;
if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) != 0) error = git_repository__shallow_roots_write(remote->repo, &shallow_roots);
return error;
return 0; git_oidarray_dispose(&shallow_roots);
return error;
} }
int git_fetch_options_init(git_fetch_options *opts, unsigned int version) int git_fetch_options_init(git_fetch_options *opts, unsigned int version)
......
...@@ -243,20 +243,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi ...@@ -243,20 +243,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi
return 0; 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; const git_oid *oid;
size_t i = 0; size_t existing, i = 0;
int error;
GIT_ASSERT_ARG(out && grafts); GIT_ASSERT_ARG(out && grafts);
while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) { if ((existing = git_oidmap_size(grafts->commits)) > 0)
git_oid *cpy = git_array_alloc(*out); 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_ERROR_CHECK_ALLOC(cpy);
git_oid_cpy(cpy, oid); git_oid_cpy(cpy, oid);
} }
*out = array.ptr;
*out_len = array.size;
return 0; return 0;
} }
......
...@@ -30,7 +30,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len); ...@@ -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_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_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(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); size_t git_grafts_size(git_grafts *grafts);
#endif #endif
...@@ -15,10 +15,17 @@ void git_oidarray_dispose(git_oidarray *arr) ...@@ -15,10 +15,17 @@ void git_oidarray_dispose(git_oidarray *arr)
git__free(arr->ids); 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; out->count = array->size;
arr->ids = array->ptr; 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) void git_oidarray__reverse(git_oidarray *arr)
...@@ -33,6 +40,45 @@ 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 #ifndef GIT_DEPRECATE_HARD
void git_oidarray_free(git_oidarray *arr) void git_oidarray_free(git_oidarray *arr)
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
typedef git_array_t(git_oid) git_array_oid_t; typedef git_array_t(git_oid) git_array_oid_t;
extern void git_oidarray__reverse(git_oidarray *arr); 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 #endif
...@@ -2167,11 +2167,6 @@ void git_remote_free(git_remote *remote) ...@@ -2167,11 +2167,6 @@ void git_remote_free(git_remote *remote)
remote->transport = NULL; 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); git_vector_free(&remote->refs);
free_refspecs(&remote->refspecs); free_refspecs(&remote->refspecs);
......
...@@ -3651,7 +3651,11 @@ int git_repository_state_cleanup(git_repository *repo) ...@@ -3651,7 +3651,11 @@ int git_repository_state_cleanup(git_repository *repo)
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); 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; int error = 0;
if (!repo->shallow_grafts && (error = load_grafts(repo)) < 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) { ...@@ -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) if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0)
return error; 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 error;
return 0; 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_filebuf file = GIT_FILEBUF_INIT;
git_str path = GIT_STR_INIT; git_str path = GIT_STR_INIT;
char oid_str[GIT_OID_MAX_HEXSIZE + 1]; char oid_str[GIT_OID_MAX_HEXSIZE + 1];
size_t idx; size_t i;
git_oid *oid;
int filebuf_hash, error = 0; int filebuf_hash, error = 0;
GIT_ASSERT_ARG(repo); GIT_ASSERT_ARG(repo);
...@@ -3686,8 +3689,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro ...@@ -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) if ((error = git_filebuf_open(&file, git_str_cstr(&path), filebuf_hash, 0666)) < 0)
goto on_error; goto on_error;
git_array_foreach(roots, idx, oid) { for (i = 0; i < roots->count; i++) {
git_oid_tostr(oid_str, sizeof(oid_str), oid); 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, oid_str, git_oid_hexsize(repo->oid_type));
git_filebuf_write(&file, "\n", 1); git_filebuf_write(&file, "\n", 1);
} }
...@@ -3699,7 +3702,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro ...@@ -3699,7 +3702,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro
goto on_error; goto on_error;
} }
if (git_array_size(roots) == 0) if (!roots->count)
remove(path.ptr); remove(path.ptr);
on_error: on_error:
...@@ -3727,6 +3730,7 @@ int git_repository_is_shallow(git_repository *repo) ...@@ -3727,6 +3730,7 @@ int git_repository_is_shallow(git_repository *repo)
if (error < 0) if (error < 0)
return error; return error;
return st.st_size == 0 ? 0 : 1; return st.st_size == 0 ? 0 : 1;
} }
......
...@@ -246,8 +246,8 @@ extern size_t git_repository__reserved_names_posix_len; ...@@ -246,8 +246,8 @@ extern size_t git_repository__reserved_names_posix_len;
bool git_repository__reserved_names( bool git_repository__reserved_names(
git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs); 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(git_oid **out, size_t *out_len, git_repository *repo);
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);
/* /*
* The default branch for the repository; the `init.defaultBranch` * The default branch for the repository; the `init.defaultBranch`
......
...@@ -320,6 +320,16 @@ static int local_negotiate_fetch( ...@@ -320,6 +320,16 @@ static int local_negotiate_fetch(
return 0; 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( static int local_push_update_remote_ref(
git_repository *remote_repo, git_repository *remote_repo,
const char *lref, const char *lref,
...@@ -745,6 +755,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param) ...@@ -745,6 +755,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
t->parent.oid_type = local_oid_type; t->parent.oid_type = local_oid_type;
#endif #endif
t->parent.negotiate_fetch = local_negotiate_fetch; t->parent.negotiate_fetch = local_negotiate_fetch;
t->parent.shallow_roots = local_shallow_roots;
t->parent.download_pack = local_download_pack; t->parent.download_pack = local_download_pack;
t->parent.push = local_push; t->parent.push = local_push;
t->parent.close = local_close; t->parent.close = local_close;
......
...@@ -416,6 +416,8 @@ static void git_smart__free(git_transport *transport) ...@@ -416,6 +416,8 @@ static void git_smart__free(git_transport *transport)
git_remote_connect_options_dispose(&t->connect_opts); git_remote_connect_options_dispose(&t->connect_opts);
git_array_dispose(t->shallow_roots);
git__free(t->caps.object_format); git__free(t->caps.object_format);
git__free(t->caps.agent); git__free(t->caps.agent);
git__free(t); git__free(t);
...@@ -490,6 +492,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) ...@@ -490,6 +492,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
t->parent.close = git_smart__close; t->parent.close = git_smart__close;
t->parent.free = git_smart__free; t->parent.free = git_smart__free;
t->parent.negotiate_fetch = git_smart__negotiate_fetch; 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.download_pack = git_smart__download_pack;
t->parent.push = git_smart__push; t->parent.push = git_smart__push;
t->parent.ls = git_smart__ls; t->parent.ls = git_smart__ls;
...@@ -517,49 +520,3 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param) ...@@ -517,49 +520,3 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
*out = (git_transport *) t; *out = (git_transport *) t;
return 0; 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;
}
...@@ -163,6 +163,7 @@ typedef struct { ...@@ -163,6 +163,7 @@ typedef struct {
git_vector refs; git_vector refs;
git_vector heads; git_vector heads;
git_vector common; git_vector common;
git_array_oid_t shallow_roots;
git_atomic32 cancelled; git_atomic32 cancelled;
packetsize_cb packetsize_cb; packetsize_cb packetsize_cb;
void *packetsize_payload; void *packetsize_payload;
...@@ -183,6 +184,8 @@ int git_smart__negotiate_fetch( ...@@ -183,6 +184,8 @@ int git_smart__negotiate_fetch(
git_repository *repo, git_repository *repo,
const git_fetch_negotiation *wants); const git_fetch_negotiation *wants);
int git_smart__shallow_roots(git_oidarray *out, git_transport *transport);
int git_smart__download_pack( int git_smart__download_pack(
git_transport *transport, git_transport *transport,
git_repository *repo, git_repository *repo,
...@@ -208,8 +211,4 @@ int git_pkt_buffer_wants(const git_fetch_negotiation *wants, transport_smart_cap ...@@ -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); int git_pkt_buffer_have(git_oid *oid, git_str *buf);
void git_pkt_free(git_pkt *pkt); void git_pkt_free(git_pkt *pkt);
struct git_shallowarray {
git_array_oid_t array;
};
#endif #endif
...@@ -770,7 +770,7 @@ int git_pkt_buffer_wants( ...@@ -770,7 +770,7 @@ int git_pkt_buffer_wants(
size_t oid_hexsize, want_len, i = 0; size_t oid_hexsize, want_len, i = 0;
#ifdef GIT_EXPERIMENTAL_SHA256 #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 #else
oid_type = GIT_OID_SHA1; oid_type = GIT_OID_SHA1;
#endif #endif
...@@ -781,7 +781,7 @@ int git_pkt_buffer_wants( ...@@ -781,7 +781,7 @@ int git_pkt_buffer_wants(
oid_hexsize + 1 /* LF */; oid_hexsize + 1 /* LF */;
if (caps->common) { if (caps->common) {
for (; i < wants->count; ++i) { for (; i < wants->refs_len; ++i) {
head = wants->refs[i]; head = wants->refs[i];
if (!head->local) if (!head->local)
break; break;
...@@ -793,7 +793,7 @@ int git_pkt_buffer_wants( ...@@ -793,7 +793,7 @@ int git_pkt_buffer_wants(
i++; i++;
} }
for (; i < wants->count; ++i) { for (; i < wants->refs_len; ++i) {
head = wants->refs[i]; head = wants->refs[i];
if (head->local) if (head->local)
...@@ -810,12 +810,11 @@ int git_pkt_buffer_wants( ...@@ -810,12 +810,11 @@ int git_pkt_buffer_wants(
} }
/* Tell the server about our shallow objects */ /* 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]; char oid[GIT_OID_MAX_HEXSIZE + 1];
git_str shallow_buf = GIT_STR_INIT; git_str shallow_buf = GIT_STR_INIT;
git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, git_oid_tostr(oid, GIT_OID_MAX_HEXSIZE + 1, &wants->shallow_roots[i]);
git_shallowarray_get(wants->shallow_roots, i));
git_str_puts(&shallow_buf, "shallow "); git_str_puts(&shallow_buf, "shallow ");
git_str_puts(&shallow_buf, oid); git_str_puts(&shallow_buf, oid);
git_str_putc(&shallow_buf, '\n'); git_str_putc(&shallow_buf, '\n');
......
...@@ -364,7 +364,9 @@ static int cap_not_sup_err(const char *cap_name) ...@@ -364,7 +364,9 @@ static int cap_not_sup_err(const char *cap_name)
} }
/* Disables server capabilities we're not interested in */ /* 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 (wants->depth > 0) {
if (!caps->shallow) if (!caps->shallow)
...@@ -376,7 +378,27 @@ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *w ...@@ -376,7 +378,27 @@ static int setup_caps(transport_smart_caps *caps, const git_fetch_negotiation *w
return 0; 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; transport_smart *t = (transport_smart *)transport;
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT; 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 ...@@ -388,7 +410,8 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
unsigned int i; unsigned int i;
git_oid oid; 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; return error;
if ((error = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) 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 ...@@ -411,9 +434,9 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
bool complete = false; bool complete = false;
if (pkt->type == GIT_PKT_SHALLOW) { 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) { } 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) { } else if (pkt->type == GIT_PKT_FLUSH) {
/* Server is done, stop processing shallow oids */ /* Server is done, stop processing shallow oids */
complete = true; complete = true;
...@@ -431,6 +454,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c ...@@ -431,6 +454,7 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
if (error < 0) if (error < 0)
goto on_error; goto on_error;
} }
/* /*
* Our support for ACK extensions is simply to parse them. On * Our support for ACK extensions is simply to parse them. On
* the first ACK we will accept that as enough common * 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 ...@@ -531,10 +555,11 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
goto on_error; goto on_error;
if (t->cancelled.val) { 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; error = GIT_EUSER;
goto on_error; goto on_error;
} }
if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0) if ((error = git_smart__negotiation_step(&t->parent, data.ptr, data.size)) < 0)
goto on_error; goto on_error;
...@@ -562,6 +587,25 @@ on_error: ...@@ -562,6 +587,25 @@ on_error:
return 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) static int no_sideband(transport_smart *t, struct git_odb_writepack *writepack, gitno_buffer *buf, git_indexer_progress *stats)
{ {
int recvd; int recvd;
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#define git_array_init_to_size(a, desired) \ #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) 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) \ #define git_array_clear(a) \
do { git__free((a).ptr); git_array_init(a); } while (0) do { git__free((a).ptr); git_array_init(a); } while (0)
......
#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);
}
...@@ -16,7 +16,8 @@ void test_online_shallow__clone_depth_zero(void) ...@@ -16,7 +16,8 @@ void test_online_shallow__clone_depth_zero(void)
git_str path = GIT_STR_INIT; git_str path = GIT_STR_INIT;
git_repository *repo; git_repository *repo;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; 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.fetch_opts.depth = 0;
clone_opts.remote_cb = remote_single_branch; clone_opts.remote_cb = remote_single_branch;
...@@ -29,10 +30,10 @@ void test_online_shallow__clone_depth_zero(void) ...@@ -29,10 +30,10 @@ void test_online_shallow__clone_depth_zero(void)
cl_assert_equal_b(false, git_repository_is_shallow(repo)); cl_assert_equal_b(false, git_repository_is_shallow(repo));
/* full clones do not have shallow roots. */ /* full clones do not have shallow roots. */
cl_git_pass(git_repository__shallow_roots(&roots, repo)); cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(0, roots.size); cl_assert_equal_i(0, roots_len);
git_array_clear(roots); git__free(roots);
git_str_dispose(&path); git_str_dispose(&path);
git_repository_free(repo); git_repository_free(repo);
} }
...@@ -44,7 +45,8 @@ void test_online_shallow__clone_depth_one(void) ...@@ -44,7 +45,8 @@ void test_online_shallow__clone_depth_one(void)
git_revwalk *walk; git_revwalk *walk;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_oid oid; git_oid oid;
git_array_oid_t roots = GIT_ARRAY_INIT; git_oid *roots;
size_t roots_len;
size_t num_commits = 0; size_t num_commits = 0;
int error = 0; int error = 0;
...@@ -57,9 +59,9 @@ void test_online_shallow__clone_depth_one(void) ...@@ -57,9 +59,9 @@ void test_online_shallow__clone_depth_one(void)
cl_assert_equal_b(true, git_repository_is_shallow(repo)); cl_assert_equal_b(true, git_repository_is_shallow(repo));
cl_git_pass(git_repository__shallow_roots(&roots, repo)); cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(1, roots.size); cl_assert_equal_i(1, roots_len);
cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots.ptr[0])); cl_assert_equal_s("49322bb17d3acc9146f98c97d078513228bbf3c0", git_oid_tostr_s(&roots[0]));
git_revwalk_new(&walk, repo); git_revwalk_new(&walk, repo);
...@@ -72,7 +74,7 @@ void test_online_shallow__clone_depth_one(void) ...@@ -72,7 +74,7 @@ void test_online_shallow__clone_depth_one(void)
cl_assert_equal_i(num_commits, 1); cl_assert_equal_i(num_commits, 1);
cl_assert_equal_i(error, GIT_ITEROVER); cl_assert_equal_i(error, GIT_ITEROVER);
git_array_clear(roots); git__free(roots);
git_str_dispose(&path); git_str_dispose(&path);
git_revwalk_free(walk); git_revwalk_free(walk);
git_repository_free(repo); git_repository_free(repo);
...@@ -85,7 +87,8 @@ void test_online_shallow__clone_depth_five(void) ...@@ -85,7 +87,8 @@ void test_online_shallow__clone_depth_five(void)
git_revwalk *walk; git_revwalk *walk;
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_oid oid; git_oid oid;
git_array_oid_t roots = GIT_ARRAY_INIT; git_oid *roots;
size_t roots_len;
size_t num_commits = 0; size_t num_commits = 0;
int error = 0; int error = 0;
...@@ -98,11 +101,11 @@ void test_online_shallow__clone_depth_five(void) ...@@ -98,11 +101,11 @@ void test_online_shallow__clone_depth_five(void)
cl_assert_equal_b(true, git_repository_is_shallow(repo)); cl_assert_equal_b(true, git_repository_is_shallow(repo));
cl_git_pass(git_repository__shallow_roots(&roots, repo)); cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
cl_assert_equal_i(3, roots.size); cl_assert_equal_i(3, roots_len);
cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots.ptr[0])); cl_assert_equal_s("c070ad8c08840c8116da865b2d65593a6bb9cd2a", git_oid_tostr_s(&roots[0]));
cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots.ptr[1])); cl_assert_equal_s("0966a434eb1a025db6b71485ab63a3bfbea520b6", git_oid_tostr_s(&roots[1]));
cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots.ptr[2])); cl_assert_equal_s("83834a7afdaa1a1260568567f6ad90020389f664", git_oid_tostr_s(&roots[2]));
git_revwalk_new(&walk, repo); git_revwalk_new(&walk, repo);
...@@ -115,7 +118,7 @@ void test_online_shallow__clone_depth_five(void) ...@@ -115,7 +118,7 @@ void test_online_shallow__clone_depth_five(void)
cl_assert_equal_i(num_commits, 13); cl_assert_equal_i(num_commits, 13);
cl_assert_equal_i(error, GIT_ITEROVER); cl_assert_equal_i(error, GIT_ITEROVER);
git_array_clear(roots); git__free(roots);
git_str_dispose(&path); git_str_dispose(&path);
git_revwalk_free(walk); git_revwalk_free(walk);
git_repository_free(repo); git_repository_free(repo);
......
#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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment