@@ -2167,9 +2167,9 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,
21672167 * obtain the commit using the 'oid' available and discard all
21682168 * non-commits early. The actual filtering is done later.
21692169 */
2170- if (filter -> merge_commit || filter -> with_commit || filter -> no_commit || filter -> verbose ) {
2171- commit = lookup_commit_reference_gently ( the_repository , oid ,
2172- 1 );
2170+ if (filter -> reachable_from || filter -> unreachable_from ||
2171+ filter -> with_commit || filter -> no_commit || filter -> verbose ) {
2172+ commit = lookup_commit_reference_gently ( the_repository , oid , 1 );
21732173 if (!commit )
21742174 return 0 ;
21752175 /* We perform the filtering for the '--contains' option... */
@@ -2231,13 +2231,19 @@ void ref_array_clear(struct ref_array *array)
22312231 }
22322232}
22332233
2234- static void do_merge_filter (struct ref_filter_cbdata * ref_cbdata )
2234+ #define EXCLUDE_REACHED 0
2235+ #define INCLUDE_REACHED 1
2236+ static void reach_filter (struct ref_array * array ,
2237+ struct commit_list * check_reachable ,
2238+ int include_reached )
22352239{
22362240 struct rev_info revs ;
22372241 int i , old_nr ;
2238- struct ref_filter * filter = ref_cbdata -> filter ;
2239- struct ref_array * array = ref_cbdata -> array ;
22402242 struct commit * * to_clear = xcalloc (sizeof (struct commit * ), array -> nr );
2243+ struct commit_list * cr ;
2244+
2245+ if (!check_reachable )
2246+ return ;
22412247
22422248 repo_init_revisions (the_repository , & revs , NULL );
22432249
@@ -2247,8 +2253,11 @@ static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
22472253 to_clear [i ] = item -> commit ;
22482254 }
22492255
2250- filter -> merge_commit -> object .flags |= UNINTERESTING ;
2251- add_pending_object (& revs , & filter -> merge_commit -> object , "" );
2256+ for (cr = check_reachable ; cr ; cr = cr -> next ) {
2257+ struct commit * merge_commit = cr -> item ;
2258+ merge_commit -> object .flags |= UNINTERESTING ;
2259+ add_pending_object (& revs , & merge_commit -> object , "" );
2260+ }
22522261
22532262 revs .limited = 1 ;
22542263 if (prepare_revision_walk (& revs ))
@@ -2263,14 +2272,19 @@ static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
22632272
22642273 int is_merged = !!(commit -> object .flags & UNINTERESTING );
22652274
2266- if (is_merged == ( filter -> merge == REF_FILTER_MERGED_INCLUDE ) )
2275+ if (is_merged == include_reached )
22672276 array -> items [array -> nr ++ ] = array -> items [i ];
22682277 else
22692278 free_array_item (item );
22702279 }
22712280
22722281 clear_commit_marks_many (old_nr , to_clear , ALL_REV_FLAGS );
2273- clear_commit_marks (filter -> merge_commit , ALL_REV_FLAGS );
2282+
2283+ while (check_reachable ) {
2284+ struct commit * merge_commit = pop_commit (& check_reachable );
2285+ clear_commit_marks (merge_commit , ALL_REV_FLAGS );
2286+ }
2287+
22742288 free (to_clear );
22752289}
22762290
@@ -2322,8 +2336,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
23222336 clear_contains_cache (& ref_cbdata .no_contains_cache );
23232337
23242338 /* Filters that need revision walking */
2325- if ( filter -> merge_commit )
2326- do_merge_filter ( & ref_cbdata );
2339+ reach_filter ( array , filter -> reachable_from , INCLUDE_REACHED );
2340+ reach_filter ( array , filter -> unreachable_from , EXCLUDE_REACHED );
23272341
23282342 return ret ;
23292343}
@@ -2541,31 +2555,22 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
25412555{
25422556 struct ref_filter * rf = opt -> value ;
25432557 struct object_id oid ;
2544- int no_merged = starts_with ( opt -> long_name , "no" ) ;
2558+ struct commit * merge_commit ;
25452559
25462560 BUG_ON_OPT_NEG (unset );
25472561
2548- if (rf -> merge ) {
2549- if (no_merged ) {
2550- return error (_ ("option `%s' is incompatible with --merged" ),
2551- opt -> long_name );
2552- } else {
2553- return error (_ ("option `%s' is incompatible with --no-merged" ),
2554- opt -> long_name );
2555- }
2556- }
2557-
2558- rf -> merge = no_merged
2559- ? REF_FILTER_MERGED_OMIT
2560- : REF_FILTER_MERGED_INCLUDE ;
2561-
25622562 if (get_oid (arg , & oid ))
25632563 die (_ ("malformed object name %s" ), arg );
25642564
2565- rf -> merge_commit = lookup_commit_reference_gently (the_repository ,
2566- & oid , 0 );
2567- if (!rf -> merge_commit )
2565+ merge_commit = lookup_commit_reference_gently (the_repository , & oid , 0 );
2566+
2567+ if (!merge_commit )
25682568 return error (_ ("option `%s' must point to a commit" ), opt -> long_name );
25692569
2570+ if (starts_with (opt -> long_name , "no" ))
2571+ commit_list_insert (merge_commit , & rf -> unreachable_from );
2572+ else
2573+ commit_list_insert (merge_commit , & rf -> reachable_from );
2574+
25702575 return 0 ;
25712576}
0 commit comments