@@ -242,10 +242,15 @@ void test_online_shallow__shorten_four(void)
242
242
cl_assert_equal_b (true,git_repository_is_shallow (repo ));
243
243
244
244
cl_git_pass (git_repository__shallow_roots (& roots ,& roots_len ,repo ));
245
- cl_assert_equal_i (3 ,roots_len );
246
- cl_assert_equal_s ("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864" ,git_oid_tostr_s (& roots [0 ]));
247
- cl_assert_equal_s ("59706a11bde2b9899a278838ef20a97e8f8795d2" ,git_oid_tostr_s (& roots [1 ]));
245
+ cl_assert_equal_i (6 ,roots_len );
246
+ /* roots added during initial clone, not removed as not encountered during fetch */
247
+ cl_assert_equal_s ("c070ad8c08840c8116da865b2d65593a6bb9cd2a" ,git_oid_tostr_s (& roots [0 ]));
248
+ cl_assert_equal_s ("0966a434eb1a025db6b71485ab63a3bfbea520b6" ,git_oid_tostr_s (& roots [1 ]));
249
+ cl_assert_equal_s ("83834a7afdaa1a1260568567f6ad90020389f664" ,git_oid_tostr_s (& roots [3 ]));
250
+ /* roots added during fetch */
248
251
cl_assert_equal_s ("bab66b48f836ed950c99134ef666436fb07a09a0" ,git_oid_tostr_s (& roots [2 ]));
252
+ cl_assert_equal_s ("59706a11bde2b9899a278838ef20a97e8f8795d2" ,git_oid_tostr_s (& roots [4 ]));
253
+ cl_assert_equal_s ("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864" ,git_oid_tostr_s (& roots [5 ]));
249
254
250
255
git_revwalk_new (& walk ,repo );
251
256
git_revwalk_push_head (walk );
@@ -263,3 +268,140 @@ void test_online_shallow__shorten_four(void)
263
268
git_revwalk_free (walk );
264
269
git_repository_free (repo );
265
270
}
271
+
272
+ void test_online_shallow__preserve_unrelated_roots (void )
273
+ {
274
+ git_str path = GIT_STR_INIT ;
275
+ git_repository * repo ;
276
+ git_revwalk * walk ;
277
+ git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT ;
278
+ git_remote * origin = NULL ;
279
+ git_strarray refspecs ;
280
+ git_oid oid ;
281
+ git_oid * roots ;
282
+ size_t roots_len ;
283
+ size_t num_commits = 0 ;
284
+ int error = 0 ;
285
+ git_oid first_oid ;
286
+ git_oid second_oid ;
287
+ git_oid third_oid ;
288
+ char * first_commit = "c070ad8c08840c8116da865b2d65593a6bb9cd2a" ;
289
+ char * second_commit = "6e1475206e57110fcef4b92320436c1e9872a322" ;
290
+ char * third_commit = "7f822839a2fe9760f386cbbbcb3f92c5fe81def7" ;
291
+
292
+ #ifdef GIT_EXPERIMENTAL_SHA256
293
+ cl_git_pass (git_oid_fromstr (& first_oid ,first_commit ,GIT_OID_SHA1 ));
294
+ cl_git_pass (git_oid_fromstr (& second_oid ,second_commit ,GIT_OID_SHA1 ));
295
+ cl_git_pass (git_oid_fromstr (& third_oid ,third_commit ,GIT_OID_SHA1 ));
296
+ #else
297
+ cl_git_pass (git_oid_fromstr (& first_oid ,first_commit ));
298
+ cl_git_pass (git_oid_fromstr (& second_oid ,second_commit ));
299
+ cl_git_pass (git_oid_fromstr (& third_oid ,third_commit ));
300
+ #endif
301
+
302
+ /* setup empty repository without cloning */
303
+ git_str_joinpath (& path ,clar_sandbox_path (),"preserve_unrelated_roots" );
304
+ cl_git_pass (git_repository_init (& repo ,git_str_cstr (& path ), true));
305
+ cl_git_pass (git_remote_create (& origin ,repo ,"origin" ,"https://github.com/libgit2/TestGitRepository" ));
306
+ cl_assert_equal_b (false,git_repository_is_shallow (repo ));
307
+
308
+ /* shallow fetch for first commit */
309
+ fetch_opts .depth = 1 ;
310
+ refspecs .strings = & first_commit ;
311
+ refspecs .count = 1 ;
312
+ cl_git_pass (git_remote_fetch (origin ,& refspecs ,& fetch_opts ,NULL ));
313
+ cl_assert_equal_b (true,git_repository_is_shallow (repo ));
314
+
315
+ cl_git_pass (git_repository__shallow_roots (& roots ,& roots_len ,repo ));
316
+ cl_assert_equal_i (1 ,roots_len );
317
+ cl_assert_equal_s ("c070ad8c08840c8116da865b2d65593a6bb9cd2a" ,git_oid_tostr_s (& roots [0 ]));
318
+
319
+ cl_git_pass (git_revwalk_new (& walk ,repo ));
320
+ cl_git_pass (git_revwalk_push (walk ,& first_oid ));
321
+ while ((error = git_revwalk_next (& oid ,walk ))== GIT_OK ) {
322
+ num_commits ++ ;
323
+ }
324
+ cl_assert_equal_i (num_commits ,1 );
325
+ cl_assert_equal_i (error ,GIT_ITEROVER );
326
+
327
+ /* shallow fetch for second commit */
328
+ fetch_opts .depth = 1 ;
329
+ refspecs .strings = & second_commit ;
330
+ refspecs .count = 1 ;
331
+ cl_git_pass (git_remote_fetch (origin ,& refspecs ,& fetch_opts ,NULL ));
332
+ cl_assert_equal_b (true,git_repository_is_shallow (repo ));
333
+
334
+ git__free (roots );
335
+ cl_git_pass (git_repository__shallow_roots (& roots ,& roots_len ,repo ));
336
+ cl_assert_equal_i (2 ,roots_len );
337
+ cl_assert_equal_s ("c070ad8c08840c8116da865b2d65593a6bb9cd2a" ,git_oid_tostr_s (& roots [0 ]));
338
+ cl_assert_equal_s ("6e1475206e57110fcef4b92320436c1e9872a322" ,git_oid_tostr_s (& roots [1 ]));
339
+
340
+ git_revwalk_free (walk );
341
+ cl_git_pass (git_revwalk_new (& walk ,repo ));
342
+ cl_git_pass (git_revwalk_push (walk ,& second_oid ));
343
+ num_commits = 0 ;
344
+ while ((error = git_revwalk_next (& oid ,walk ))== GIT_OK ) {
345
+ num_commits ++ ;
346
+ }
347
+ cl_assert_equal_i (error ,GIT_ITEROVER );
348
+ cl_assert_equal_i (num_commits ,1 );
349
+
350
+ /* fetch full history for third commit, includes first commit which should be removed from shallow roots */
351
+ fetch_opts .depth = 100 ;
352
+ refspecs .strings = & third_commit ;
353
+ refspecs .count = 1 ;
354
+ cl_git_pass (git_remote_fetch (origin ,& refspecs ,& fetch_opts ,NULL ));
355
+ cl_assert_equal_b (true,git_repository_is_shallow (repo ));
356
+
357
+ git__free (roots );
358
+ cl_git_pass (git_repository__shallow_roots (& roots ,& roots_len ,repo ));
359
+ cl_assert_equal_i (1 ,roots_len );
360
+ cl_assert_equal_s ("6e1475206e57110fcef4b92320436c1e9872a322" ,git_oid_tostr_s (& roots [0 ]));
361
+
362
+ git_revwalk_free (walk );
363
+ cl_git_pass (git_revwalk_new (& walk ,repo ));
364
+ cl_git_pass (git_revwalk_push (walk ,& third_oid ));
365
+ num_commits = 0 ;
366
+ while ((error = git_revwalk_next (& oid ,walk ))== GIT_OK ) {
367
+ num_commits ++ ;
368
+ }
369
+ cl_assert_equal_i (error ,GIT_ITEROVER );
370
+ cl_assert_equal_i (num_commits ,12 );
371
+
372
+ cl_git_pass (git_revwalk_reset (walk ));
373
+ cl_git_pass (git_revwalk_push (walk ,& second_oid ));
374
+ num_commits = 0 ;
375
+ while ((error = git_revwalk_next (& oid ,walk ))== GIT_OK ) {
376
+ num_commits ++ ;
377
+ }
378
+ cl_assert_equal_i (error ,GIT_ITEROVER );
379
+ cl_assert_equal_i (num_commits ,1 );
380
+
381
+ /* unshallow repository without specifying any refspec */
382
+ fetch_opts .depth = GIT_FETCH_DEPTH_UNSHALLOW ;
383
+ cl_git_pass (git_remote_fetch (origin ,NULL ,& fetch_opts ,NULL ));
384
+ cl_assert_equal_b (false,git_repository_is_shallow (repo ));
385
+
386
+ git__free (roots );
387
+ cl_git_pass (git_repository__shallow_roots (& roots ,& roots_len ,repo ));
388
+ cl_assert_equal_i (0 ,roots_len );
389
+
390
+ git_revwalk_free (walk );
391
+ cl_git_pass (git_revwalk_new (& walk ,repo ));
392
+ cl_git_pass (git_revwalk_push (walk ,& first_oid ));
393
+ cl_git_pass (git_revwalk_push (walk ,& second_oid ));
394
+ cl_git_pass (git_revwalk_push (walk ,& third_oid ));
395
+ num_commits = 0 ;
396
+ while ((error = git_revwalk_next (& oid ,walk ))== GIT_OK ) {
397
+ num_commits ++ ;
398
+ }
399
+ cl_assert_equal_i (error ,GIT_ITEROVER );
400
+ cl_assert_equal_i (num_commits ,18 );
401
+
402
+ git__free (roots );
403
+ git_remote_free (origin );
404
+ git_str_dispose (& path );
405
+ git_revwalk_free (walk );
406
+ git_repository_free (repo );
407
+ }