15
15
#include "commit-slab.h"
16
16
#include "commit-reach.h"
17
17
#include "object-store.h"
18
+ #include "dir.h"
18
19
19
20
static struct oid_array good_revs ;
20
21
static struct oid_array skipped_revs ;
@@ -88,15 +89,16 @@ static inline void weight_set(struct commit_list *elem, int weight)
88
89
* * commit_weight_at (& commit_weight , elem -> item ) = weight ;
89
90
}
90
91
91
- static int count_interesting_parents (struct commit * commit )
92
+ static int count_interesting_parents (struct commit * commit , unsigned bisect_flags )
92
93
{
93
94
struct commit_list * p ;
94
95
int count ;
95
96
96
97
for (count = 0 , p = commit -> parents ; p ; p = p -> next ) {
97
- if (p -> item -> object .flags & UNINTERESTING )
98
- continue ;
99
- count ++ ;
98
+ if (!(p -> item -> object .flags & UNINTERESTING ))
99
+ count ++ ;
100
+ if (bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY )
101
+ break ;
100
102
}
101
103
return count ;
102
104
}
@@ -135,7 +137,7 @@ static void show_list(const char *debug, int counted, int nr,
135
137
for (p = list ; p ; p = p -> next ) {
136
138
struct commit_list * pp ;
137
139
struct commit * commit = p -> item ;
138
- unsigned flags = commit -> object .flags ;
140
+ unsigned commit_flags = commit -> object .flags ;
139
141
enum object_type type ;
140
142
unsigned long size ;
141
143
char * buf = read_object_file (& commit -> object .oid , & type ,
@@ -144,9 +146,9 @@ static void show_list(const char *debug, int counted, int nr,
144
146
int subject_len ;
145
147
146
148
fprintf (stderr , "%c%c%c " ,
147
- (flags & TREESAME ) ? ' ' : 'T' ,
148
- (flags & UNINTERESTING ) ? 'U' : ' ' ,
149
- (flags & COUNTED ) ? 'C' : ' ' );
149
+ (commit_flags & TREESAME ) ? ' ' : 'T' ,
150
+ (commit_flags & UNINTERESTING ) ? 'U' : ' ' ,
151
+ (commit_flags & COUNTED ) ? 'C' : ' ' );
150
152
if (* commit_weight_at (& commit_weight , p -> item ))
151
153
fprintf (stderr , "%3d" , weight (p ));
152
154
else
@@ -171,9 +173,9 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)
171
173
best = list ;
172
174
for (p = list ; p ; p = p -> next ) {
173
175
int distance ;
174
- unsigned flags = p -> item -> object .flags ;
176
+ unsigned commit_flags = p -> item -> object .flags ;
175
177
176
- if (flags & TREESAME )
178
+ if (commit_flags & TREESAME )
177
179
continue ;
178
180
distance = weight (p );
179
181
if (nr - distance < distance )
@@ -212,9 +214,9 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
212
214
213
215
for (p = list , cnt = 0 ; p ; p = p -> next ) {
214
216
int distance ;
215
- unsigned flags = p -> item -> object .flags ;
217
+ unsigned commit_flags = p -> item -> object .flags ;
216
218
217
- if (flags & TREESAME )
219
+ if (commit_flags & TREESAME )
218
220
continue ;
219
221
distance = weight (p );
220
222
if (nr - distance < distance )
@@ -259,7 +261,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
259
261
*/
260
262
static struct commit_list * do_find_bisection (struct commit_list * list ,
261
263
int nr , int * weights ,
262
- int find_all )
264
+ unsigned bisect_flags )
263
265
{
264
266
int n , counted ;
265
267
struct commit_list * p ;
@@ -268,12 +270,12 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
268
270
269
271
for (n = 0 , p = list ; p ; p = p -> next ) {
270
272
struct commit * commit = p -> item ;
271
- unsigned flags = commit -> object .flags ;
273
+ unsigned commit_flags = commit -> object .flags ;
272
274
273
275
* commit_weight_at (& commit_weight , p -> item ) = & weights [n ++ ];
274
- switch (count_interesting_parents (commit )) {
276
+ switch (count_interesting_parents (commit , bisect_flags )) {
275
277
case 0 :
276
- if (!(flags & TREESAME )) {
278
+ if (!(commit_flags & TREESAME )) {
277
279
weight_set (p , 1 );
278
280
counted ++ ;
279
281
show_list ("bisection 2 count one" ,
@@ -314,11 +316,13 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
314
316
continue ;
315
317
if (weight (p ) != -2 )
316
318
continue ;
319
+ if (bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY )
320
+ BUG ("shouldn't be calling count-distance in fp mode" );
317
321
weight_set (p , count_distance (p ));
318
322
clear_distance (list );
319
323
320
324
/* Does it happen to be at exactly half-way? */
321
- if (!find_all && halfway (p , nr ))
325
+ if (!( bisect_flags & FIND_BISECTION_ALL ) && halfway (p , nr ))
322
326
return p ;
323
327
counted ++ ;
324
328
}
@@ -328,11 +332,14 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
328
332
while (counted < nr ) {
329
333
for (p = list ; p ; p = p -> next ) {
330
334
struct commit_list * q ;
331
- unsigned flags = p -> item -> object .flags ;
335
+ unsigned commit_flags = p -> item -> object .flags ;
332
336
333
337
if (0 <= weight (p ))
334
338
continue ;
335
- for (q = p -> item -> parents ; q ; q = q -> next ) {
339
+
340
+ for (q = p -> item -> parents ;
341
+ q ;
342
+ q = bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY ? NULL : q -> next ) {
336
343
if (q -> item -> object .flags & UNINTERESTING )
337
344
continue ;
338
345
if (0 <= weight (q ))
@@ -346,7 +353,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
346
353
* add one for p itself if p is to be counted,
347
354
* otherwise inherit it from q directly.
348
355
*/
349
- if (!(flags & TREESAME )) {
356
+ if (!(commit_flags & TREESAME )) {
350
357
weight_set (p , weight (q )+ 1 );
351
358
counted ++ ;
352
359
show_list ("bisection 2 count one" ,
@@ -356,21 +363,21 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
356
363
weight_set (p , weight (q ));
357
364
358
365
/* Does it happen to be at exactly half-way? */
359
- if (!find_all && halfway (p , nr ))
366
+ if (!( bisect_flags & FIND_BISECTION_ALL ) && halfway (p , nr ))
360
367
return p ;
361
368
}
362
369
}
363
370
364
371
show_list ("bisection 2 counted all" , counted , nr , list );
365
372
366
- if (!find_all )
373
+ if (!( bisect_flags & FIND_BISECTION_ALL ) )
367
374
return best_bisection (list , nr );
368
375
else
369
376
return best_bisection_sorted (list , nr );
370
377
}
371
378
372
379
void find_bisection (struct commit_list * * commit_list , int * reaches ,
373
- int * all , int find_all )
380
+ int * all , unsigned bisect_flags )
374
381
{
375
382
int nr , on_list ;
376
383
struct commit_list * list , * p , * best , * next , * last ;
@@ -386,16 +393,16 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
386
393
for (nr = on_list = 0 , last = NULL , p = * commit_list ;
387
394
p ;
388
395
p = next ) {
389
- unsigned flags = p -> item -> object .flags ;
396
+ unsigned commit_flags = p -> item -> object .flags ;
390
397
391
398
next = p -> next ;
392
- if (flags & UNINTERESTING ) {
399
+ if (commit_flags & UNINTERESTING ) {
393
400
free (p );
394
401
continue ;
395
402
}
396
403
p -> next = last ;
397
404
last = p ;
398
- if (!(flags & TREESAME ))
405
+ if (!(commit_flags & TREESAME ))
399
406
nr ++ ;
400
407
on_list ++ ;
401
408
}
@@ -406,9 +413,9 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
406
413
weights = xcalloc (on_list , sizeof (* weights ));
407
414
408
415
/* Do the real work of finding bisection commit. */
409
- best = do_find_bisection (list , nr , weights , find_all );
416
+ best = do_find_bisection (list , nr , weights , bisect_flags );
410
417
if (best ) {
411
- if (!find_all ) {
418
+ if (!( bisect_flags & FIND_BISECTION_ALL ) ) {
412
419
list -> item = best -> item ;
413
420
free_commit_list (list -> next );
414
421
best = list ;
@@ -454,6 +461,7 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
454
461
static GIT_PATH_FUNC (git_path_bisect_start , "BISECT_START ")
455
462
static GIT_PATH_FUNC (git_path_bisect_log , "BISECT_LOG ")
456
463
static GIT_PATH_FUNC (git_path_bisect_terms , "BISECT_TERMS ")
464
+ static GIT_PATH_FUNC (git_path_bisect_first_parent , "BISECT_FIRST_PARENT ")
457
465
static GIT_PATH_FUNC (git_path_head_name , "head - name ")
458
466
459
467
static void read_bisect_paths (struct strvec * array )
@@ -983,29 +991,39 @@ void read_bisect_terms(const char **read_bad, const char **read_good)
983
991
* If no_checkout is non-zero, the bisection process does not
984
992
* checkout the trial commit but instead simply updates BISECT_HEAD.
985
993
*/
986
- enum bisect_error bisect_next_all (struct repository * r , const char * prefix , int no_checkout )
994
+ enum bisect_error bisect_next_all (struct repository * r , const char * prefix )
987
995
{
988
996
struct rev_info revs ;
989
997
struct commit_list * tried ;
990
998
int reaches = 0 , all = 0 , nr , steps ;
991
999
enum bisect_error res = BISECT_OK ;
992
1000
struct object_id * bisect_rev ;
993
1001
char * steps_msg ;
1002
+ int no_checkout = ref_exists ("BISECT_HEAD" );
1003
+ unsigned bisect_flags = 0 ;
994
1004
995
1005
read_bisect_terms (& term_bad , & term_good );
996
1006
if (read_bisect_refs ())
997
1007
die (_ ("reading bisect refs failed" ));
998
1008
1009
+ if (file_exists (git_path_bisect_first_parent ()))
1010
+ bisect_flags |= FIND_BISECTION_FIRST_PARENT_ONLY ;
1011
+
1012
+ if (skipped_revs .nr )
1013
+ bisect_flags |= FIND_BISECTION_ALL ;
1014
+
999
1015
res = check_good_are_ancestors_of_bad (r , prefix , no_checkout );
1000
1016
if (res )
1001
1017
return res ;
1002
1018
1003
1019
bisect_rev_setup (r , & revs , prefix , "%s" , "^%s" , 1 );
1020
+
1021
+ revs .first_parent_only = !!(bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY );
1004
1022
revs .limited = 1 ;
1005
1023
1006
1024
bisect_common (& revs );
1007
1025
1008
- find_bisection (& revs .commits , & reaches , & all , !! skipped_revs . nr );
1026
+ find_bisection (& revs .commits , & reaches , & all , bisect_flags );
1009
1027
revs .commits = managed_skipped (revs .commits , & tried );
1010
1028
1011
1029
if (!revs .commits ) {
@@ -1133,6 +1151,7 @@ int bisect_clean_state(void)
1133
1151
unlink_or_warn (git_path_bisect_names ());
1134
1152
unlink_or_warn (git_path_bisect_run ());
1135
1153
unlink_or_warn (git_path_bisect_terms ());
1154
+ unlink_or_warn (git_path_bisect_first_parent ());
1136
1155
/* Cleanup head-name if it got left by an old version of git-bisect */
1137
1156
unlink_or_warn (git_path_head_name ());
1138
1157
/*
0 commit comments