Skip to content

Commit 0a7e32b

Browse files
committed
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.
1 parent 04cddff commit 0a7e32b

File tree

18 files changed

+304
-176
lines changed

18 files changed

+304
-176
lines changed

include/git2/sys/transport.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@
2525

2626
GIT_BEGIN_DECL
2727

28-
typedef struct git_shallowarray git_shallowarray;
29-
3028
typedef struct {
3129
const git_remote_head * const *refs;
32-
size_t count;
33-
git_shallowarray *shallow_roots;
30+
size_t refs_len;
31+
git_oid *shallow_roots;
32+
size_t shallow_roots_len;
3433
int depth;
3534
} git_fetch_negotiation;
3635

@@ -107,6 +106,16 @@ struct git_transport {
107106
git_repository *repo,
108107
const git_fetch_negotiation *fetch_data);
109108

109+
/**
110+
* Return the shallow roots of the remote.
111+
*
112+
* This function may be called after a successful call to
113+
* `negotiate_fetch`.
114+
*/
115+
int GIT_CALLBACK(shallow_roots)(
116+
git_oidarray *out,
117+
git_transport *transport);
118+
110119
/**
111120
* Start downloading the packfile from the remote repository.
112121
*
@@ -450,11 +459,6 @@ GIT_EXTERN(int) git_smart_subtransport_ssh(
450459
git_transport *owner,
451460
void *param);
452461

453-
GIT_EXTERN(size_t) git_shallowarray_count(git_shallowarray *array);
454-
GIT_EXTERN(const git_oid *) git_shallowarray_get(git_shallowarray *array, size_t idx);
455-
GIT_EXTERN(int) git_shallowarray_add(git_shallowarray *array, git_oid *oid);
456-
GIT_EXTERN(int) git_shallowarray_remove(git_shallowarray *array, git_oid *oid);
457-
458462
/** @} */
459463
GIT_END_DECL
460464
#endif

src/libgit2/fetch.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static int mark_local(git_remote *remote)
6161

6262
git_vector_foreach(&remote->refs, i, head) {
6363
/* If we have the object, mark it so we don't ask for it.
64-
However if we are unshallowing, we need to ask for it
64+
However if we are unshallowing, we need to ask for it
6565
even though the head exists locally. */
6666
if (remote->nego.depth != INT_MAX && git_odb_exists(odb, &head->oid))
6767
head->local = 1;
@@ -169,6 +169,7 @@ static int filter_wants(git_remote *remote, const git_fetch_options *opts)
169169
int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
170170
{
171171
git_transport *t = remote->transport;
172+
int error;
172173

173174
remote->need_pack = 0;
174175

@@ -191,33 +192,39 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts)
191192
* server what we want and what we have.
192193
*/
193194
remote->nego.refs = (const git_remote_head * const *)remote->refs.contents;
194-
remote->nego.count = remote->refs.length;
195-
remote->nego.shallow_roots = git__malloc(sizeof(*remote->nego.shallow_roots));
196-
197-
git_array_init(remote->nego.shallow_roots->array);
195+
remote->nego.refs_len = remote->refs.length;
198196

199-
git_repository__shallow_roots(&remote->nego.shallow_roots->array, remote->repo);
197+
if (git_repository__shallow_roots(&remote->nego.shallow_roots,
198+
&remote->nego.shallow_roots_len,
199+
remote->repo) < 0)
200+
return -1;
200201

201-
return t->negotiate_fetch(t,
202+
error = t->negotiate_fetch(t,
202203
remote->repo,
203204
&remote->nego);
205+
206+
git__free(remote->nego.shallow_roots);
207+
208+
return error;
204209
}
205210

206211
int git_fetch_download_pack(git_remote *remote)
207212
{
213+
git_oidarray shallow_roots = { NULL };
208214
git_transport *t = remote->transport;
209215
int error;
210216

211217
if (!remote->need_pack)
212218
return 0;
213219

214-
if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0)
220+
if ((error = t->download_pack(t, remote->repo, &remote->stats)) != 0 ||
221+
(error = t->shallow_roots(&shallow_roots, t)) != 0)
215222
return error;
216223

217-
if ((error = git_repository__shallow_roots_write(remote->repo, remote->nego.shallow_roots->array)) != 0)
218-
return error;
224+
error = git_repository__shallow_roots_write(remote->repo, &shallow_roots);
219225

220-
return 0;
226+
git_oidarray_dispose(&shallow_roots);
227+
return error;
221228
}
222229

223230
int git_fetch_options_init(git_fetch_options *opts, unsigned int version)

src/libgit2/grafts.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,20 +243,26 @@ int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oi
243243
return 0;
244244
}
245245

246-
int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts)
246+
int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts)
247247
{
248+
git_array_oid_t array = GIT_ARRAY_INIT;
248249
const git_oid *oid;
249-
size_t i = 0;
250-
int error;
250+
size_t existing, i = 0;
251251

252252
GIT_ASSERT_ARG(out && grafts);
253253

254-
while ((error = git_oidmap_iterate(NULL, grafts->commits, &i, &oid)) == 0) {
255-
git_oid *cpy = git_array_alloc(*out);
254+
if ((existing = git_oidmap_size(grafts->commits)) > 0)
255+
git_array_init_to_size(array, existing);
256+
257+
while (git_oidmap_iterate(NULL, grafts->commits, &i, &oid) == 0) {
258+
git_oid *cpy = git_array_alloc(array);
256259
GIT_ERROR_CHECK_ALLOC(cpy);
257260
git_oid_cpy(cpy, oid);
258261
}
259262

263+
*out = array.ptr;
264+
*out_len = array.size;
265+
260266
return 0;
261267
}
262268

src/libgit2/grafts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int git_grafts_parse(git_grafts *grafts, const char *buf, size_t len);
3030
int git_grafts_add(git_grafts *grafts, const git_oid *oid, git_array_oid_t parents);
3131
int git_grafts_remove(git_grafts *grafts, const git_oid *oid);
3232
int git_grafts_get(git_commit_graft **out, git_grafts *grafts, const git_oid *oid);
33-
int git_grafts_get_oids(git_array_oid_t *out, git_grafts *grafts);
33+
int git_grafts_oids(git_oid **out, size_t *out_len, git_grafts *grafts);
3434
size_t git_grafts_size(git_grafts *grafts);
3535

3636
#endif

src/libgit2/oidarray.c

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ void git_oidarray_dispose(git_oidarray *arr)
1515
git__free(arr->ids);
1616
}
1717

18-
void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array)
18+
void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array)
1919
{
20-
arr->count = array->size;
21-
arr->ids = array->ptr;
20+
out->count = array->size;
21+
out->ids = array->ptr;
22+
}
23+
24+
void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array)
25+
{
26+
out->ptr = array->ids;
27+
out->size = array->count;
28+
out->asize = array->count;
2229
}
2330

2431
void git_oidarray__reverse(git_oidarray *arr)
@@ -33,6 +40,45 @@ void git_oidarray__reverse(git_oidarray *arr)
3340
}
3441
}
3542

43+
int git_oidarray__add(git_array_oid_t *arr, git_oid *id)
44+
{
45+
git_oid *add, *iter;
46+
size_t i;
47+
48+
git_array_foreach(*arr, i, iter) {
49+
if (git_oid_cmp(iter, id) == 0)
50+
return 0;
51+
}
52+
53+
if ((add = git_array_alloc(*arr)) == NULL)
54+
return -1;
55+
56+
git_oid_cpy(add, id);
57+
return 0;
58+
}
59+
60+
bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id)
61+
{
62+
bool found = false;
63+
size_t remain, i;
64+
git_oid *iter;
65+
66+
git_array_foreach(*arr, i, iter) {
67+
if (git_oid_cmp(iter, id) == 0) {
68+
arr->size--;
69+
remain = arr->size - i;
70+
71+
if (remain > 0)
72+
memmove(&arr->ptr[i], &arr->ptr[i+1], remain * sizeof(git_oid));
73+
74+
found = true;
75+
break;
76+
}
77+
}
78+
79+
return found;
80+
}
81+
3682
#ifndef GIT_DEPRECATE_HARD
3783

3884
void git_oidarray_free(git_oidarray *arr)

src/libgit2/oidarray.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
typedef git_array_t(git_oid) git_array_oid_t;
1616

1717
extern void git_oidarray__reverse(git_oidarray *arr);
18-
extern void git_oidarray__from_array(git_oidarray *arr, git_array_oid_t *array);
18+
extern void git_oidarray__from_array(git_oidarray *out, const git_array_oid_t *array);
19+
extern void git_oidarray__to_array(git_array_oid_t *out, const git_oidarray *array);
20+
21+
int git_oidarray__add(git_array_oid_t *arr, git_oid *id);
22+
bool git_oidarray__remove(git_array_oid_t *arr, git_oid *id);
1923

2024
#endif

src/libgit2/remote.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,11 +2167,6 @@ void git_remote_free(git_remote *remote)
21672167
remote->transport = NULL;
21682168
}
21692169

2170-
if (remote->nego.shallow_roots) {
2171-
git_array_clear(remote->nego.shallow_roots->array);
2172-
git__free(remote->nego.shallow_roots);
2173-
}
2174-
21752170
git_vector_free(&remote->refs);
21762171

21772172
free_refspecs(&remote->refspecs);

src/libgit2/repository.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,7 +3651,11 @@ int git_repository_state_cleanup(git_repository *repo)
36513651
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
36523652
}
36533653

3654-
int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo) {
3654+
int git_repository__shallow_roots(
3655+
git_oid **out,
3656+
size_t *out_len,
3657+
git_repository *repo)
3658+
{
36553659
int error = 0;
36563660

36573661
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) {
36603664
if ((error = git_grafts_refresh(repo->shallow_grafts)) < 0)
36613665
return error;
36623666

3663-
if ((error = git_grafts_get_oids(out, repo->shallow_grafts)) < 0)
3667+
if ((error = git_grafts_oids(out, out_len, repo->shallow_grafts)) < 0)
36643668
return error;
36653669

36663670
return 0;
36673671
}
36683672

3669-
int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots)
3673+
int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots)
36703674
{
36713675
git_filebuf file = GIT_FILEBUF_INIT;
36723676
git_str path = GIT_STR_INIT;
36733677
char oid_str[GIT_OID_MAX_HEXSIZE + 1];
3674-
size_t idx;
3675-
git_oid *oid;
3678+
size_t i;
36763679
int filebuf_hash, error = 0;
36773680

36783681
GIT_ASSERT_ARG(repo);
@@ -3686,8 +3689,8 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro
36863689
if ((error = git_filebuf_open(&file, git_str_cstr(&path), filebuf_hash, 0666)) < 0)
36873690
goto on_error;
36883691

3689-
git_array_foreach(roots, idx, oid) {
3690-
git_oid_tostr(oid_str, sizeof(oid_str), oid);
3692+
for (i = 0; i < roots->count; i++) {
3693+
git_oid_tostr(oid_str, sizeof(oid_str), &roots->ids[i]);
36913694
git_filebuf_write(&file, oid_str, git_oid_hexsize(repo->oid_type));
36923695
git_filebuf_write(&file, "\n", 1);
36933696
}
@@ -3699,7 +3702,7 @@ int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t ro
36993702
goto on_error;
37003703
}
37013704

3702-
if (git_array_size(roots) == 0)
3705+
if (!roots->count)
37033706
remove(path.ptr);
37043707

37053708
on_error:
@@ -3727,6 +3730,7 @@ int git_repository_is_shallow(git_repository *repo)
37273730

37283731
if (error < 0)
37293732
return error;
3733+
37303734
return st.st_size == 0 ? 0 : 1;
37313735
}
37323736

src/libgit2/repository.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ extern size_t git_repository__reserved_names_posix_len;
246246
bool git_repository__reserved_names(
247247
git_str **out, size_t *outlen, git_repository *repo, bool include_ntfs);
248248

249-
int git_repository__shallow_roots(git_array_oid_t *out, git_repository *repo);
250-
int git_repository__shallow_roots_write(git_repository *repo, git_array_oid_t roots);
249+
int git_repository__shallow_roots(git_oid **out, size_t *out_len, git_repository *repo);
250+
int git_repository__shallow_roots_write(git_repository *repo, git_oidarray *roots);
251251

252252
/*
253253
* The default branch for the repository; the `init.defaultBranch`

src/libgit2/transports/local.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,16 @@ static int local_negotiate_fetch(
320320
return 0;
321321
}
322322

323+
static int local_shallow_roots(
324+
git_oidarray *out,
325+
git_transport *transport)
326+
{
327+
GIT_UNUSED(out);
328+
GIT_UNUSED(transport);
329+
330+
return 0;
331+
}
332+
323333
static int local_push_update_remote_ref(
324334
git_repository *remote_repo,
325335
const char *lref,
@@ -745,6 +755,7 @@ int git_transport_local(git_transport **out, git_remote *owner, void *param)
745755
t->parent.oid_type = local_oid_type;
746756
#endif
747757
t->parent.negotiate_fetch = local_negotiate_fetch;
758+
t->parent.shallow_roots = local_shallow_roots;
748759
t->parent.download_pack = local_download_pack;
749760
t->parent.push = local_push;
750761
t->parent.close = local_close;

0 commit comments

Comments
 (0)