@@ -10,8 +10,11 @@ static char* repo2_path;
10
10
11
11
static const char * REPO1_REFNAME = "refs/heads/main" ;
12
12
static const char * REPO2_REFNAME = "refs/remotes/repo1/main" ;
13
+ static const char * REPO1_UNDERSCORE_REFNAME = "refs/heads/_branch" ;
14
+ static const char * REPO2_UNDERSCORE_REFNAME = "refs/remotes/repo1/_branch" ;
13
15
static char * FORCE_FETCHSPEC = "+refs/heads/main:refs/remotes/repo1/main" ;
14
16
static char * NON_FORCE_FETCHSPEC = "refs/heads/main:refs/remotes/repo1/main" ;
17
+ static char * NEGATIVE_SPEC = "^refs/heads/_*" ;
15
18
16
19
void test_remote_fetch__initialize (void ) {
17
20
git_config * c ;
@@ -170,3 +173,64 @@ void test_remote_fetch__do_update_refs_if_not_descendant_and_force(void) {
170
173
171
174
git_reference_free (ref );
172
175
}
176
+
177
+ /**
178
+ * This checks that negative refspecs are respected when fetching. We create a
179
+ * repository with a '_' prefixed reference. A second repository is configured
180
+ * with a negative refspec to ignore any refs prefixed with '_' and fetch the
181
+ * first repository into the second.
182
+ *
183
+ * @param commit1id A pointer to an OID which will be populated with the first
184
+ * commit.
185
+ */
186
+ static void do_fetch_repo_with_ref_matching_negative_refspec (git_oid * commit1id ) {
187
+ /* create a commit in repo 1 and a reference to it with '_' prefix */
188
+ {
189
+ git_oid empty_tree_id ;
190
+ git_tree * empty_tree ;
191
+ git_signature * sig ;
192
+ git_treebuilder * tb ;
193
+ cl_git_pass (git_treebuilder_new (& tb , repo1 , NULL ));
194
+ cl_git_pass (git_treebuilder_write (& empty_tree_id , tb ));
195
+ cl_git_pass (git_tree_lookup (& empty_tree , repo1 , & empty_tree_id ));
196
+ cl_git_pass (git_signature_default (& sig , repo1 ));
197
+ cl_git_pass (git_commit_create (commit1id , repo1 , REPO1_UNDERSCORE_REFNAME , sig ,
198
+ sig , NULL , "one" , empty_tree , 0 , NULL ));
199
+
200
+ git_tree_free (empty_tree );
201
+ git_signature_free (sig );
202
+ git_treebuilder_free (tb );
203
+ }
204
+
205
+ /* fetch the remote with negative refspec for references prefixed with '_' */
206
+ {
207
+ char * refspec_strs = { NEGATIVE_SPEC };
208
+ git_strarray refspecs = {
209
+ .count = 1 ,
210
+ .strings = & refspec_strs ,
211
+ };
212
+
213
+ git_remote * remote ;
214
+
215
+ cl_git_pass (git_remote_create_anonymous (& remote , repo2 ,
216
+ git_repository_path (repo1 )));
217
+ cl_git_pass (git_remote_fetch (remote , & refspecs , NULL , "some message" ));
218
+
219
+ git_remote_free (remote );
220
+ }
221
+ }
222
+
223
+ void test_remote_fetch__skip_negative_refspec_match (void ) {
224
+ git_oid commit1id ;
225
+ git_reference * ref1 ;
226
+ git_reference * ref2 ;
227
+
228
+ do_fetch_repo_with_ref_matching_negative_refspec (& commit1id );
229
+
230
+ /* assert that the reference in exists in repo1 but not in repo2 */
231
+ cl_git_pass (git_reference_lookup (& ref1 , repo1 , REPO1_UNDERSCORE_REFNAME ));
232
+ cl_assert_equal_b (git_reference_lookup (& ref2 , repo2 , REPO2_UNDERSCORE_REFNAME ), GIT_ENOTFOUND );
233
+
234
+ git_reference_free (ref1 );
235
+ git_reference_free (ref2 );
236
+ }
0 commit comments