@@ -3496,6 +3496,53 @@ static int parse_submodule_opt(struct diff_options *options, const char *value)
34963496 return 1 ;
34973497}
34983498
3499+ static const char diff_status_letters [] = {
3500+ DIFF_STATUS_ADDED ,
3501+ DIFF_STATUS_COPIED ,
3502+ DIFF_STATUS_DELETED ,
3503+ DIFF_STATUS_MODIFIED ,
3504+ DIFF_STATUS_RENAMED ,
3505+ DIFF_STATUS_TYPE_CHANGED ,
3506+ DIFF_STATUS_UNKNOWN ,
3507+ DIFF_STATUS_UNMERGED ,
3508+ DIFF_STATUS_FILTER_AON ,
3509+ DIFF_STATUS_FILTER_BROKEN ,
3510+ '\0' ,
3511+ };
3512+
3513+ static unsigned int filter_bit ['Z' + 1 ];
3514+
3515+ static void prepare_filter_bits (void )
3516+ {
3517+ int i ;
3518+
3519+ if (!filter_bit [DIFF_STATUS_ADDED ]) {
3520+ for (i = 0 ; diff_status_letters [i ]; i ++ )
3521+ filter_bit [(int ) diff_status_letters [i ]] = (1 << i );
3522+ }
3523+ }
3524+
3525+ static unsigned filter_bit_tst (char status , const struct diff_options * opt )
3526+ {
3527+ return opt -> filter & filter_bit [(int ) status ];
3528+ }
3529+
3530+ static int parse_diff_filter_opt (const char * optarg , struct diff_options * opt )
3531+ {
3532+ int i , optch ;
3533+
3534+ prepare_filter_bits ();
3535+ for (i = 0 ; (optch = optarg [i ]) != '\0' ; i ++ ) {
3536+ unsigned int bit ;
3537+
3538+ bit = (0 <= optch && optch <= 'Z' ) ? filter_bit [optch ] : 0 ;
3539+ if (!bit )
3540+ continue ; /* ignore unknown ones, like we always have */
3541+ opt -> filter |= bit ;
3542+ }
3543+ return 0 ;
3544+ }
3545+
34993546int diff_opt_parse (struct diff_options * options , const char * * av , int ac )
35003547{
35013548 const char * arg = av [0 ];
@@ -3717,7 +3764,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
37173764 return argcount ;
37183765 }
37193766 else if ((argcount = parse_long_opt ("diff-filter" , av , & optarg ))) {
3720- options -> filter = optarg ;
3767+ int offending = parse_diff_filter_opt (optarg , options );
3768+ if (offending )
3769+ die ("unknown change class '%c' in --diff-filter=%s" ,
3770+ offending , optarg );
37213771 return argcount ;
37223772 }
37233773 else if (!strcmp (arg , "--abbrev" ))
@@ -4513,26 +4563,25 @@ static int match_filter(const struct diff_options *options, const struct diff_fi
45134563{
45144564 return (((p -> status == DIFF_STATUS_MODIFIED ) &&
45154565 ((p -> score &&
4516- strchr ( options -> filter , DIFF_STATUS_FILTER_BROKEN )) ||
4566+ filter_bit_tst ( DIFF_STATUS_FILTER_BROKEN , options )) ||
45174567 (!p -> score &&
4518- strchr ( options -> filter , DIFF_STATUS_MODIFIED )))) ||
4568+ filter_bit_tst ( DIFF_STATUS_MODIFIED , options )))) ||
45194569 ((p -> status != DIFF_STATUS_MODIFIED ) &&
4520- strchr ( options -> filter , p -> status )));
4570+ filter_bit_tst ( p -> status , options )));
45214571}
45224572
45234573static void diffcore_apply_filter (struct diff_options * options )
45244574{
45254575 int i ;
45264576 struct diff_queue_struct * q = & diff_queued_diff ;
45274577 struct diff_queue_struct outq ;
4528- const char * filter = options -> filter ;
45294578
45304579 DIFF_QUEUE_CLEAR (& outq );
45314580
4532- if (!filter )
4581+ if (!options -> filter )
45334582 return ;
45344583
4535- if (strchr ( filter , DIFF_STATUS_FILTER_AON )) {
4584+ if (filter_bit_tst ( DIFF_STATUS_FILTER_AON , options )) {
45364585 int found ;
45374586 for (i = found = 0 ; !found && i < q -> nr ; i ++ ) {
45384587 if (match_filter (options , q -> queue [i ]))
0 commit comments