Merge branch 'jc/diff-filter-negation'
Teach "git diff --diff-filter" to express "I do not want to see these classes of changes" more directly by listing only the unwanted ones in lowercase (e.g. "--diff-filter=d" will show everything but deletion) and deprecate "diff-files -q" which did the same thing as "--diff-filter=d". * jc/diff-filter-negation: diff: deprecate -q option to diff-files diff: allow lowercase letter to specify what change class to exclude diff: reject unknown change class given to --diff-filter diff: preparse --diff-filter string argument diff: factor out match_filter() diff: pass the whole diff_options to diffcore_apply_filter()maint
						commit
						01a2a03c56
					
				|  | @ -87,10 +87,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option) | |||
| { | ||||
| 	int entries, i; | ||||
| 	int diff_unmerged_stage = revs->max_count; | ||||
| 	int silent_on_removed = option & DIFF_SILENT_ON_REMOVED; | ||||
| 	unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED) | ||||
| 			      ? CE_MATCH_RACY_IS_DIRTY : 0); | ||||
|  | ||||
| 	if (option & DIFF_SILENT_ON_REMOVED) | ||||
| 		handle_deprecated_show_diff_q(&revs->diffopt); | ||||
|  | ||||
| 	diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/"); | ||||
|  | ||||
| 	if (diff_unmerged_stage < 0) | ||||
|  | @ -137,8 +139,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option) | |||
| 					perror(ce->name); | ||||
| 					continue; | ||||
| 				} | ||||
| 				if (silent_on_removed) | ||||
| 					continue; | ||||
| 				wt_mode = 0; | ||||
| 			} | ||||
| 			dpath->mode = wt_mode; | ||||
|  | @ -204,8 +204,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option) | |||
| 				perror(ce->name); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (silent_on_removed) | ||||
| 				continue; | ||||
| 			diff_addremove(&revs->diffopt, '-', ce->ce_mode, | ||||
| 				       ce->sha1, !is_null_sha1(ce->sha1), | ||||
| 				       ce->name, 0); | ||||
|  |  | |||
|  | @ -187,7 +187,7 @@ void diff_no_index(struct rev_info *revs, | |||
| { | ||||
| 	int i, prefixlen; | ||||
| 	int no_index = 0; | ||||
| 	unsigned options = 0; | ||||
| 	unsigned deprecated_show_diff_q_option_used = 0; | ||||
| 	const char *paths[2]; | ||||
|  | ||||
| 	/* Were we asked to do --no-index explicitly? */ | ||||
|  | @ -225,7 +225,7 @@ void diff_no_index(struct rev_info *revs, | |||
| 		if (!strcmp(argv[i], "--no-index")) | ||||
| 			i++; | ||||
| 		else if (!strcmp(argv[i], "-q")) { | ||||
| 			options |= DIFF_SILENT_ON_REMOVED; | ||||
| 			deprecated_show_diff_q_option_used = 1; | ||||
| 			i++; | ||||
| 		} | ||||
| 		else if (!strcmp(argv[i], "--")) | ||||
|  | @ -260,6 +260,9 @@ void diff_no_index(struct rev_info *revs, | |||
| 	revs->max_count = -2; | ||||
| 	diff_setup_done(&revs->diffopt); | ||||
|  | ||||
| 	if (deprecated_show_diff_q_option_used) | ||||
| 		handle_deprecated_show_diff_q(&revs->diffopt); | ||||
|  | ||||
| 	setup_diff_pager(&revs->diffopt); | ||||
| 	DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS); | ||||
|  | ||||
|  |  | |||
							
								
								
									
										125
									
								
								diff.c
								
								
								
								
							
							
						
						
									
										125
									
								
								diff.c
								
								
								
								
							|  | @ -3503,6 +3503,88 @@ static int parse_submodule_opt(struct diff_options *options, const char *value) | |||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static const char diff_status_letters[] = { | ||||
| 	DIFF_STATUS_ADDED, | ||||
| 	DIFF_STATUS_COPIED, | ||||
| 	DIFF_STATUS_DELETED, | ||||
| 	DIFF_STATUS_MODIFIED, | ||||
| 	DIFF_STATUS_RENAMED, | ||||
| 	DIFF_STATUS_TYPE_CHANGED, | ||||
| 	DIFF_STATUS_UNKNOWN, | ||||
| 	DIFF_STATUS_UNMERGED, | ||||
| 	DIFF_STATUS_FILTER_AON, | ||||
| 	DIFF_STATUS_FILTER_BROKEN, | ||||
| 	'\0', | ||||
| }; | ||||
|  | ||||
| static unsigned int filter_bit['Z' + 1]; | ||||
|  | ||||
| static void prepare_filter_bits(void) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	if (!filter_bit[DIFF_STATUS_ADDED]) { | ||||
| 		for (i = 0; diff_status_letters[i]; i++) | ||||
| 			filter_bit[(int) diff_status_letters[i]] = (1 << i); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static unsigned filter_bit_tst(char status, const struct diff_options *opt) | ||||
| { | ||||
| 	return opt->filter & filter_bit[(int) status]; | ||||
| } | ||||
|  | ||||
| static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt) | ||||
| { | ||||
| 	int i, optch; | ||||
|  | ||||
| 	prepare_filter_bits(); | ||||
|  | ||||
| 	/* | ||||
| 	 * If there is a negation e.g. 'd' in the input, and we haven't | ||||
| 	 * initialized the filter field with another --diff-filter, start | ||||
| 	 * from full set of bits, except for AON. | ||||
| 	 */ | ||||
| 	if (!opt->filter) { | ||||
| 		for (i = 0; (optch = optarg[i]) != '\0'; i++) { | ||||
| 			if (optch < 'a' || 'z' < optch) | ||||
| 				continue; | ||||
| 			opt->filter = (1 << (ARRAY_SIZE(diff_status_letters) - 1)) - 1; | ||||
| 			opt->filter &= ~filter_bit[DIFF_STATUS_FILTER_AON]; | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; (optch = optarg[i]) != '\0'; i++) { | ||||
| 		unsigned int bit; | ||||
| 		int negate; | ||||
|  | ||||
| 		if ('a' <= optch && optch <= 'z') { | ||||
| 			negate = 1; | ||||
| 			optch = toupper(optch); | ||||
| 		} else { | ||||
| 			negate = 0; | ||||
| 		} | ||||
|  | ||||
| 		bit = (0 <= optch && optch <= 'Z') ? filter_bit[optch] : 0; | ||||
| 		if (!bit) | ||||
| 			return optarg[i]; | ||||
| 		if (negate) | ||||
| 			opt->filter &= ~bit; | ||||
| 		else | ||||
| 			opt->filter |= bit; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* Used only by "diff-files" and "diff --no-index" */ | ||||
| void handle_deprecated_show_diff_q(struct diff_options *opt) | ||||
| { | ||||
| 	warning("'diff -q' and 'diff-files -q' are deprecated."); | ||||
| 	warning("Use 'diff --diff-filter=d' instead to ignore deleted filepairs."); | ||||
| 	parse_diff_filter_opt("d", opt); | ||||
| } | ||||
|  | ||||
| static void enable_patch_output(int *fmt) { | ||||
| 	*fmt &= ~DIFF_FORMAT_NO_OUTPUT; | ||||
| 	*fmt |= DIFF_FORMAT_PATCH; | ||||
|  | @ -3732,7 +3814,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) | |||
| 		return argcount; | ||||
| 	} | ||||
| 	else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) { | ||||
| 		options->filter = optarg; | ||||
| 		int offending = parse_diff_filter_opt(optarg, options); | ||||
| 		if (offending) | ||||
| 			die("unknown change class '%c' in --diff-filter=%s", | ||||
| 			    offending, optarg); | ||||
| 		return argcount; | ||||
| 	} | ||||
| 	else if (!strcmp(arg, "--abbrev")) | ||||
|  | @ -4524,27 +4609,32 @@ free_queue: | |||
| 	} | ||||
| } | ||||
|  | ||||
| static void diffcore_apply_filter(const char *filter) | ||||
| static int match_filter(const struct diff_options *options, const struct diff_filepair *p) | ||||
| { | ||||
| 	return (((p->status == DIFF_STATUS_MODIFIED) && | ||||
| 		 ((p->score && | ||||
| 		   filter_bit_tst(DIFF_STATUS_FILTER_BROKEN, options)) || | ||||
| 		  (!p->score && | ||||
| 		   filter_bit_tst(DIFF_STATUS_MODIFIED, options)))) || | ||||
| 		((p->status != DIFF_STATUS_MODIFIED) && | ||||
| 		 filter_bit_tst(p->status, options))); | ||||
| } | ||||
|  | ||||
| static void diffcore_apply_filter(struct diff_options *options) | ||||
| { | ||||
| 	int i; | ||||
| 	struct diff_queue_struct *q = &diff_queued_diff; | ||||
| 	struct diff_queue_struct outq; | ||||
|  | ||||
| 	DIFF_QUEUE_CLEAR(&outq); | ||||
|  | ||||
| 	if (!filter) | ||||
| 	if (!options->filter) | ||||
| 		return; | ||||
|  | ||||
| 	if (strchr(filter, DIFF_STATUS_FILTER_AON)) { | ||||
| 	if (filter_bit_tst(DIFF_STATUS_FILTER_AON, options)) { | ||||
| 		int found; | ||||
| 		for (i = found = 0; !found && i < q->nr; i++) { | ||||
| 			struct diff_filepair *p = q->queue[i]; | ||||
| 			if (((p->status == DIFF_STATUS_MODIFIED) && | ||||
| 			     ((p->score && | ||||
| 			       strchr(filter, DIFF_STATUS_FILTER_BROKEN)) || | ||||
| 			      (!p->score && | ||||
| 			       strchr(filter, DIFF_STATUS_MODIFIED)))) || | ||||
| 			    ((p->status != DIFF_STATUS_MODIFIED) && | ||||
| 			     strchr(filter, p->status))) | ||||
| 			if (match_filter(options, q->queue[i])) | ||||
| 				found++; | ||||
| 		} | ||||
| 		if (found) | ||||
|  | @ -4562,14 +4652,7 @@ static void diffcore_apply_filter(const char *filter) | |||
| 		/* Only the matching ones */ | ||||
| 		for (i = 0; i < q->nr; i++) { | ||||
| 			struct diff_filepair *p = q->queue[i]; | ||||
|  | ||||
| 			if (((p->status == DIFF_STATUS_MODIFIED) && | ||||
| 			     ((p->score && | ||||
| 			       strchr(filter, DIFF_STATUS_FILTER_BROKEN)) || | ||||
| 			      (!p->score && | ||||
| 			       strchr(filter, DIFF_STATUS_MODIFIED)))) || | ||||
| 			    ((p->status != DIFF_STATUS_MODIFIED) && | ||||
| 			     strchr(filter, p->status))) | ||||
| 			if (match_filter(options, p)) | ||||
| 				diff_q(&outq, p); | ||||
| 			else | ||||
| 				diff_free_filepair(p); | ||||
|  | @ -4676,7 +4759,7 @@ void diffcore_std(struct diff_options *options) | |||
| 	if (!options->found_follow) | ||||
| 		/* See try_to_follow_renames() in tree-diff.c */ | ||||
| 		diff_resolve_rename_copy(); | ||||
| 	diffcore_apply_filter(options->filter); | ||||
| 	diffcore_apply_filter(options); | ||||
|  | ||||
| 	if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) | ||||
| 		DIFF_OPT_SET(options, HAS_CHANGES); | ||||
|  |  | |||
							
								
								
									
										7
									
								
								diff.h
								
								
								
								
							
							
						
						
									
										7
									
								
								diff.h
								
								
								
								
							|  | @ -103,12 +103,15 @@ enum diff_words_type { | |||
| }; | ||||
|  | ||||
| struct diff_options { | ||||
| 	const char *filter; | ||||
| 	const char *orderfile; | ||||
| 	const char *pickaxe; | ||||
| 	const char *single_follow; | ||||
| 	const char *a_prefix, *b_prefix; | ||||
| 	unsigned flags; | ||||
|  | ||||
| 	/* diff-filter bits */ | ||||
| 	unsigned int filter; | ||||
|  | ||||
| 	int use_color; | ||||
| 	int context; | ||||
| 	int interhunkcontext; | ||||
|  | @ -338,6 +341,8 @@ extern int parse_rename_score(const char **cp_p); | |||
|  | ||||
| extern long parse_algorithm_value(const char *value); | ||||
|  | ||||
| extern void handle_deprecated_show_diff_q(struct diff_options *); | ||||
|  | ||||
| extern int print_stat_summary(FILE *fp, int files, | ||||
| 			      int insertions, int deletions); | ||||
| extern void setup_diff_pager(struct diff_options *); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano