Skip to content

Commit 5d8a465

Browse files
authored
Merge pull request libgit2#5195 from tiennou/fix/commitish-smart-push
smart: use push_glob instead of manual filtering
2 parents 7475dfa + 53f51c6 commit 5d8a465

File tree

8 files changed

+88
-73
lines changed

8 files changed

+88
-73
lines changed

src/revwalk.c

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ git_commit_list_node *git_revwalk__commit_lookup(
3838
return commit;
3939
}
4040

41-
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
41+
int git_revwalk__push_commit(git_revwalk *walk, const git_oid *oid, const git_revwalk__push_options *opts)
4242
{
4343
git_oid commit_id;
4444
int error;
@@ -54,7 +54,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
5454

5555
if (error == GIT_ENOTFOUND || error == GIT_EINVALIDSPEC || error == GIT_EPEEL) {
5656
/* If this comes from e.g. push_glob("tags"), ignore this */
57-
if (from_glob)
57+
if (opts->from_glob)
5858
return 0;
5959

6060
git_error_set(GIT_ERROR_INVALID, "object is not a committish");
@@ -74,16 +74,18 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
7474
if (commit->uninteresting)
7575
return 0;
7676

77-
if (uninteresting) {
77+
if (opts->uninteresting) {
7878
walk->limited = 1;
7979
walk->did_hide = 1;
8080
} else {
8181
walk->did_push = 1;
8282
}
8383

84-
commit->uninteresting = uninteresting;
84+
commit->uninteresting = opts->uninteresting;
8585
list = walk->user_input;
86-
if (git_commit_list_insert(commit, &list) == NULL) {
86+
if ((opts->insert_by_date &&
87+
git_commit_list_insert_by_date(commit, &list) == NULL) ||
88+
git_commit_list_insert(commit, &list) == NULL) {
8789
git_error_set_oom();
8890
return -1;
8991
}
@@ -95,29 +97,36 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
9597

9698
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
9799
{
100+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
101+
98102
assert(walk && oid);
99-
return push_commit(walk, oid, 0, false);
103+
104+
return git_revwalk__push_commit(walk, oid, &opts);
100105
}
101106

102107

103108
int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
104109
{
110+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
105111
assert(walk && oid);
106-
return push_commit(walk, oid, 1, false);
112+
113+
opts.uninteresting = 1;
114+
return git_revwalk__push_commit(walk, oid, &opts);
107115
}
108116

109-
static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob)
117+
int git_revwalk__push_ref(git_revwalk *walk, const char *refname, const git_revwalk__push_options *opts)
110118
{
111119
git_oid oid;
112120

113121
if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
114122
return -1;
115123

116-
return push_commit(walk, &oid, hide, from_glob);
124+
return git_revwalk__push_commit(walk, &oid, opts);
117125
}
118126

119-
static int push_glob(git_revwalk *walk, const char *glob, int hide)
127+
int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwalk__push_options *given_opts)
120128
{
129+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
121130
int error = 0;
122131
git_buf buf = GIT_BUF_INIT;
123132
git_reference *ref;
@@ -126,6 +135,9 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
126135

127136
assert(walk && glob);
128137

138+
if (given_opts)
139+
memcpy(&opts, given_opts, sizeof(opts));
140+
129141
/* refs/ is implied if not given in the glob */
130142
if (git__prefixcmp(glob, GIT_REFS_DIR) != 0)
131143
git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
@@ -141,8 +153,9 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
141153
if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
142154
goto out;
143155

156+
opts.from_glob = true;
144157
while ((error = git_reference_next(&ref, iter)) == 0) {
145-
error = push_ref(walk, git_reference_name(ref), hide, true);
158+
error = git_revwalk__push_ref(walk, git_reference_name(ref), &opts);
146159
git_reference_free(ref);
147160
if (error < 0)
148161
break;
@@ -158,36 +171,49 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
158171

159172
int git_revwalk_push_glob(git_revwalk *walk, const char *glob)
160173
{
174+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
161175
assert(walk && glob);
162-
return push_glob(walk, glob, 0);
176+
177+
return git_revwalk__push_glob(walk, glob, &opts);
163178
}
164179

165180
int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
166181
{
182+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
167183
assert(walk && glob);
168-
return push_glob(walk, glob, 1);
184+
185+
opts.uninteresting = 1;
186+
return git_revwalk__push_glob(walk, glob, &opts);
169187
}
170188

171189
int git_revwalk_push_head(git_revwalk *walk)
172190
{
191+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
173192
assert(walk);
174-
return push_ref(walk, GIT_HEAD_FILE, 0, false);
193+
194+
return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
175195
}
176196

177197
int git_revwalk_hide_head(git_revwalk *walk)
178198
{
199+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
179200
assert(walk);
180-
return push_ref(walk, GIT_HEAD_FILE, 1, false);
201+
202+
opts.uninteresting = 1;
203+
return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
181204
}
182205

183206
int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
184207
{
208+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
185209
assert(walk && refname);
186-
return push_ref(walk, refname, 0, false);
210+
211+
return git_revwalk__push_ref(walk, refname, &opts);
187212
}
188213

189214
int git_revwalk_push_range(git_revwalk *walk, const char *range)
190215
{
216+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
191217
git_revspec revspec;
192218
int error = 0;
193219

@@ -207,10 +233,12 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
207233
goto out;
208234
}
209235

210-
if ((error = push_commit(walk, git_object_id(revspec.from), 1, false)))
236+
opts.uninteresting = 1;
237+
if ((error = git_revwalk__push_commit(walk, git_object_id(revspec.from), &opts)))
211238
goto out;
212239

213-
error = push_commit(walk, git_object_id(revspec.to), 0, false);
240+
opts.uninteresting = 0;
241+
error = git_revwalk__push_commit(walk, git_object_id(revspec.to), &opts);
214242

215243
out:
216244
git_object_free(revspec.from);
@@ -220,8 +248,10 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
220248

221249
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
222250
{
251+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
223252
assert(walk && refname);
224-
return push_ref(walk, refname, 1, false);
253+
opts.uninteresting = 1;
254+
return git_revwalk__push_ref(walk, refname, &opts);
225255
}
226256

227257
static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)

src/revwalk.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,24 @@ struct git_revwalk {
5050

5151
git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid);
5252

53+
typedef struct {
54+
int uninteresting;
55+
int from_glob;
56+
int insert_by_date;
57+
} git_revwalk__push_options;
58+
59+
#define GIT_REVWALK__PUSH_OPTIONS_INIT { 0 }
60+
61+
int git_revwalk__push_commit(git_revwalk *walk,
62+
const git_oid *oid,
63+
const git_revwalk__push_options *opts);
64+
65+
int git_revwalk__push_ref(git_revwalk *walk,
66+
const char *refname,
67+
const git_revwalk__push_options *opts);
68+
69+
int git_revwalk__push_glob(git_revwalk *walk,
70+
const char *glob,
71+
const git_revwalk__push_options *given_opts);
72+
5373
#endif

src/transports/smart_protocol.c

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "pack-objects.h"
1818
#include "remote.h"
1919
#include "util.h"
20+
#include "revwalk.h"
2021

2122
#define NETWORK_XFER_THRESHOLD (100*1024)
2223
/* The minimal interval between progress updates (in seconds). */
@@ -270,50 +271,6 @@ static int store_common(transport_smart *t)
270271
return 0;
271272
}
272273

273-
static int fetch_setup_walk(git_revwalk **out, git_repository *repo)
274-
{
275-
git_revwalk *walk = NULL;
276-
git_strarray refs;
277-
unsigned int i;
278-
git_reference *ref = NULL;
279-
int error;
280-
281-
if ((error = git_reference_list(&refs, repo)) < 0)
282-
return error;
283-
284-
if ((error = git_revwalk_new(&walk, repo)) < 0)
285-
return error;
286-
287-
git_revwalk_sorting(walk, GIT_SORT_TIME);
288-
289-
for (i = 0; i < refs.count; ++i) {
290-
git_reference_free(ref);
291-
ref = NULL;
292-
293-
/* No tags */
294-
if (!git__prefixcmp(refs.strings[i], GIT_REFS_TAGS_DIR))
295-
continue;
296-
297-
if ((error = git_reference_lookup(&ref, repo, refs.strings[i])) < 0)
298-
goto on_error;
299-
300-
if (git_reference_type(ref) == GIT_REFERENCE_SYMBOLIC)
301-
continue;
302-
303-
if ((error = git_revwalk_push(walk, git_reference_target(ref))) < 0)
304-
goto on_error;
305-
}
306-
307-
*out = walk;
308-
309-
on_error:
310-
if (error)
311-
git_revwalk_free(walk);
312-
git_reference_free(ref);
313-
git_strarray_free(&refs);
314-
return error;
315-
}
316-
317274
static int wait_while_ack(gitno_buffer *buf)
318275
{
319276
int error;
@@ -347,6 +304,7 @@ static int wait_while_ack(gitno_buffer *buf)
347304
int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, const git_remote_head * const *wants, size_t count)
348305
{
349306
transport_smart *t = (transport_smart *)transport;
307+
git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
350308
gitno_buffer *buf = &t->buffer;
351309
git_buf data = GIT_BUF_INIT;
352310
git_revwalk *walk = NULL;
@@ -358,7 +316,11 @@ int git_smart__negotiate_fetch(git_transport *transport, git_repository *repo, c
358316
if ((error = git_pkt_buffer_wants(wants, count, &t->caps, &data)) < 0)
359317
return error;
360318

361-
if ((error = fetch_setup_walk(&walk, repo)) < 0)
319+
if ((error = git_revwalk_new(&walk, repo)) < 0)
320+
goto on_error;
321+
322+
opts.insert_by_date = 1;
323+
if ((error = git_revwalk__push_glob(walk, "refs/*", &opts)) < 0)
362324
goto on_error;
363325

364326
/*

tests/network/fetchlocal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,15 @@ void test_network_fetchlocal__multi_remotes(void)
419419
cl_git_pass(git_remote_fetch(test, NULL, &options, NULL));
420420

421421
cl_git_pass(git_reference_list(&refnames, repo));
422-
cl_assert_equal_i(32, (int)refnames.count);
422+
cl_assert_equal_i(33, (int)refnames.count);
423423
git_strarray_free(&refnames);
424424

425425
cl_git_pass(git_remote_set_url(repo, "test_with_pushurl", cl_git_fixture_url("testrepo.git")));
426426
cl_git_pass(git_remote_lookup(&test2, repo, "test_with_pushurl"));
427427
cl_git_pass(git_remote_fetch(test2, NULL, &options, NULL));
428428

429429
cl_git_pass(git_reference_list(&refnames, repo));
430-
cl_assert_equal_i(44, (int)refnames.count);
430+
cl_assert_equal_i(45, (int)refnames.count);
431431

432432
git_strarray_free(&refnames);
433433
git_remote_free(test);

tests/network/remote/local.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void test_network_remote_local__retrieve_advertised_references(void)
6262

6363
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
6464

65-
cl_assert_equal_i(refs_len, 28);
65+
cl_assert_equal_i(refs_len, 29);
6666
}
6767

6868
void test_network_remote_local__retrieve_advertised_before_connect(void)
@@ -86,7 +86,7 @@ void test_network_remote_local__retrieve_advertised_references_after_disconnect(
8686

8787
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
8888

89-
cl_assert_equal_i(refs_len, 28);
89+
cl_assert_equal_i(refs_len, 29);
9090
}
9191

9292
void test_network_remote_local__retrieve_advertised_references_from_spaced_repository(void)
@@ -101,7 +101,7 @@ void test_network_remote_local__retrieve_advertised_references_from_spaced_repos
101101

102102
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));
103103

104-
cl_assert_equal_i(refs_len, 28);
104+
cl_assert_equal_i(refs_len, 29);
105105

106106
git_remote_free(remote); /* Disconnect from the "spaced repo" before the cleanup */
107107
remote = NULL;

tests/refs/foreachglob.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ static void assert_retrieval(const char *glob, int expected_count)
4848

4949
void test_refs_foreachglob__retrieve_all_refs(void)
5050
{
51-
/* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags */
52-
assert_retrieval("*", 22);
51+
/* 12 heads (including one packed head) + 1 note + 2 remotes + 7 tags + 1 blob */
52+
assert_retrieval("*", 23);
5353
}
5454

5555
void test_refs_foreachglob__retrieve_remote_branches(void)

tests/refs/iterator.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ void test_refs_iterator__cleanup(void)
1515
}
1616

1717
static const char *refnames[] = {
18+
"refs/blobs/annotated_tag_to_blob",
1819
"refs/heads/br2",
1920
"refs/heads/cannot-fetch",
2021
"refs/heads/chomped",
@@ -40,6 +41,7 @@ static const char *refnames[] = {
4041
};
4142

4243
static const char *refnames_with_symlink[] = {
44+
"refs/blobs/annotated_tag_to_blob",
4345
"refs/heads/br2",
4446
"refs/heads/cannot-fetch",
4547
"refs/heads/chomped",
@@ -99,7 +101,7 @@ void test_refs_iterator__list(void)
99101
git_vector output;
100102
git_reference *ref;
101103

102-
cl_git_pass(git_vector_init(&output, 32, &refcmp_cb));
104+
cl_git_pass(git_vector_init(&output, 33, &refcmp_cb));
103105
cl_git_pass(git_reference_iterator_new(&iter, repo));
104106

105107
while (1) {
@@ -143,7 +145,7 @@ static int refs_foreach_cb(git_reference *reference, void *payload)
143145
void test_refs_iterator__foreach(void)
144146
{
145147
git_vector output;
146-
cl_git_pass(git_vector_init(&output, 32, &refcmp_cb));
148+
cl_git_pass(git_vector_init(&output, 33, &refcmp_cb));
147149
cl_git_pass(git_reference_foreach(repo, refs_foreach_cb, &output));
148150
assert_all_refnames_match(refnames, &output);
149151
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
521d87c1ec3aef9824daf6d96cc0ae3710766d91

0 commit comments

Comments
 (0)