diff: convert flags to be stored in bitfields

We cannot add many more flags to the diff machinery due to the
limitations of the number of flags that can be stored in a single
unsigned int.  In order to allow for more flags to be added to the diff
machinery in the future this patch converts the flags to be stored in
bitfields in 'struct diff_flags'.

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Brandon Williams 2017-10-31 11:19:05 -07:00 committed by Junio C Hamano
parent c9f348e926
commit 02f2f56bc3
6 changed files with 67 additions and 48 deletions

View File

@ -912,11 +912,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
* submodules which were manually staged, which would * submodules which were manually staged, which would
* be really confusing. * be really confusing.
*/ */
int diff_flags = DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG; struct diff_flags flags = DIFF_FLAGS_INIT;
flags.OVERRIDE_SUBMODULE_CONFIG = 1;
if (ignore_submodule_arg && if (ignore_submodule_arg &&
!strcmp(ignore_submodule_arg, "all")) !strcmp(ignore_submodule_arg, "all"))
diff_flags |= DIFF_OPT_IGNORE_SUBMODULES; flags.IGNORE_SUBMODULES = 1;
commitable = index_differs_from(parent, diff_flags, 1); commitable = index_differs_from(parent, &flags, 1);
} }
} }
strbuf_release(&committer_ident); strbuf_release(&committer_ident);

View File

@ -134,7 +134,8 @@ static void cmd_log_init_defaults(struct rev_info *rev)
if (default_date_mode) if (default_date_mode)
parse_date_format(default_date_mode, &rev->date_mode); parse_date_format(default_date_mode, &rev->date_mode);
rev->diffopt.touched_flags = 0;
memset(&rev->diffopt.touched_flags, 0, sizeof(struct diff_flags));
} }
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,

View File

@ -71,7 +71,7 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
{ {
int changed = ce_match_stat(ce, st, ce_option); int changed = ce_match_stat(ce, st, ce_option);
if (S_ISGITLINK(ce->ce_mode)) { if (S_ISGITLINK(ce->ce_mode)) {
unsigned orig_flags = diffopt->flags; struct diff_flags orig_flags = diffopt->flags;
if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG)) if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(diffopt, ce->name); set_diffopt_flags_from_submodule_config(diffopt, ce->name);
if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES)) if (DIFF_OPT_TST(diffopt, IGNORE_SUBMODULES))
@ -534,7 +534,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
return 0; return 0;
} }
int index_differs_from(const char *def, int diff_flags, int index_differs_from(const char *def, const struct diff_flags *flags,
int ita_invisible_in_index) int ita_invisible_in_index)
{ {
struct rev_info rev; struct rev_info rev;
@ -546,7 +546,8 @@ int index_differs_from(const char *def, int diff_flags,
setup_revisions(0, NULL, &rev, &opt); setup_revisions(0, NULL, &rev, &opt);
DIFF_OPT_SET(&rev.diffopt, QUICK); DIFF_OPT_SET(&rev.diffopt, QUICK);
DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS); DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
rev.diffopt.flags |= diff_flags; if (flags)
diff_flags_or(&rev.diffopt.flags, flags);
rev.diffopt.ita_invisible_in_index = ita_invisible_in_index; rev.diffopt.ita_invisible_in_index = ita_invisible_in_index;
run_diff_index(&rev, 1); run_diff_index(&rev, 1);
object_array_clear(&rev.pending); object_array_clear(&rev.pending);

2
diff.c
View File

@ -5899,7 +5899,7 @@ int diff_can_quit_early(struct diff_options *opt)
static int is_submodule_ignored(const char *path, struct diff_options *options) static int is_submodule_ignored(const char *path, struct diff_options *options)
{ {
int ignored = 0; int ignored = 0;
unsigned orig_flags = options->flags; struct diff_flags orig_flags = options->flags;
if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG)) if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
set_diffopt_flags_from_submodule_config(options, path); set_diffopt_flags_from_submodule_config(options, path);
if (DIFF_OPT_TST(options, IGNORE_SUBMODULES)) if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))

91
diff.h
View File

@ -60,42 +60,56 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
#define DIFF_FORMAT_CALLBACK 0x1000 #define DIFF_FORMAT_CALLBACK 0x1000
#define DIFF_OPT_RECURSIVE (1 << 0) #define DIFF_FLAGS_INIT { 0 }
#define DIFF_OPT_TREE_IN_RECURSIVE (1 << 1) struct diff_flags {
#define DIFF_OPT_BINARY (1 << 2) unsigned RECURSIVE:1;
#define DIFF_OPT_TEXT (1 << 3) unsigned TREE_IN_RECURSIVE:1;
#define DIFF_OPT_FULL_INDEX (1 << 4) unsigned BINARY:1;
#define DIFF_OPT_SILENT_ON_REMOVE (1 << 5) unsigned TEXT:1;
#define DIFF_OPT_FIND_COPIES_HARDER (1 << 6) unsigned FULL_INDEX:1;
#define DIFF_OPT_FOLLOW_RENAMES (1 << 7) unsigned SILENT_ON_REMOVE:1;
#define DIFF_OPT_RENAME_EMPTY (1 << 8) unsigned FIND_COPIES_HARDER:1;
/* (1 << 9) unused */ unsigned FOLLOW_RENAMES:1;
#define DIFF_OPT_HAS_CHANGES (1 << 10) unsigned RENAME_EMPTY:1;
#define DIFF_OPT_QUICK (1 << 11) unsigned HAS_CHANGES:1;
#define DIFF_OPT_NO_INDEX (1 << 12) unsigned QUICK:1;
#define DIFF_OPT_ALLOW_EXTERNAL (1 << 13) unsigned NO_INDEX:1;
#define DIFF_OPT_EXIT_WITH_STATUS (1 << 14) unsigned ALLOW_EXTERNAL:1;
#define DIFF_OPT_REVERSE_DIFF (1 << 15) unsigned EXIT_WITH_STATUS:1;
#define DIFF_OPT_CHECK_FAILED (1 << 16) unsigned REVERSE_DIFF:1;
#define DIFF_OPT_RELATIVE_NAME (1 << 17) unsigned CHECK_FAILED:1;
#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18) unsigned RELATIVE_NAME:1;
#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19) unsigned IGNORE_SUBMODULES:1;
#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20) unsigned DIRSTAT_CUMULATIVE:1;
#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21) unsigned DIRSTAT_BY_FILE:1;
#define DIFF_OPT_DIFF_FROM_CONTENTS (1 << 22) unsigned ALLOW_TEXTCONV:1;
#define DIFF_OPT_DIRTY_SUBMODULES (1 << 24) unsigned DIFF_FROM_CONTENTS:1;
#define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25) unsigned DIRTY_SUBMODULES:1;
#define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26) unsigned IGNORE_UNTRACKED_IN_SUBMODULES:1;
#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27) unsigned IGNORE_DIRTY_SUBMODULES:1;
#define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28) unsigned OVERRIDE_SUBMODULE_CONFIG:1;
#define DIFF_OPT_FUNCCONTEXT (1 << 29) unsigned DIRSTAT_BY_LINE:1;
#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30) unsigned FUNCCONTEXT:1;
#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1U << 31) unsigned PICKAXE_IGNORE_CASE:1;
unsigned DEFAULT_FOLLOW_RENAMES:1;
};
static inline void diff_flags_or(struct diff_flags *a,
const struct diff_flags *b)
{
char *tmp_a = (char *)a;
const char *tmp_b = (const char *)b;
int i;
for (i = 0; i < sizeof(struct diff_flags); i++)
tmp_a[i] |= tmp_b[i];
}
#define DIFF_OPT_TST(opts, flag) ((opts)->flags.flag)
#define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags.flag)
#define DIFF_OPT_SET(opts, flag) (((opts)->flags.flag = 1),((opts)->touched_flags.flag = 1))
#define DIFF_OPT_CLR(opts, flag) (((opts)->flags.flag = 0),((opts)->touched_flags.flag = 1))
#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
#define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags & DIFF_OPT_##flag)
#define DIFF_OPT_SET(opts, flag) (((opts)->flags |= DIFF_OPT_##flag),((opts)->touched_flags |= DIFF_OPT_##flag))
#define DIFF_OPT_CLR(opts, flag) (((opts)->flags &= ~DIFF_OPT_##flag),((opts)->touched_flags |= DIFF_OPT_##flag))
#define DIFF_XDL_TST(opts, flag) ((opts)->xdl_opts & XDF_##flag) #define DIFF_XDL_TST(opts, flag) ((opts)->xdl_opts & XDF_##flag)
#define DIFF_XDL_SET(opts, flag) ((opts)->xdl_opts |= XDF_##flag) #define DIFF_XDL_SET(opts, flag) ((opts)->xdl_opts |= XDF_##flag)
#define DIFF_XDL_CLR(opts, flag) ((opts)->xdl_opts &= ~XDF_##flag) #define DIFF_XDL_CLR(opts, flag) ((opts)->xdl_opts &= ~XDF_##flag)
@ -122,8 +136,8 @@ struct diff_options {
const char *a_prefix, *b_prefix; const char *a_prefix, *b_prefix;
const char *line_prefix; const char *line_prefix;
size_t line_prefix_length; size_t line_prefix_length;
unsigned flags; struct diff_flags flags;
unsigned touched_flags; struct diff_flags touched_flags;
/* diff-filter bits */ /* diff-filter bits */
unsigned int filter; unsigned int filter;
@ -388,7 +402,8 @@ extern int diff_result_code(struct diff_options *, int);
extern void diff_no_index(struct rev_info *, int, const char **); extern void diff_no_index(struct rev_info *, int, const char **);
extern int index_differs_from(const char *def, int diff_flags, int ita_invisible_in_index); extern int index_differs_from(const char *def, const struct diff_flags *flags,
int ita_invisible_in_index);
/* /*
* Fill the contents of the filespec "df", respecting any textconv defined by * Fill the contents of the filespec "df", respecting any textconv defined by

View File

@ -959,7 +959,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
unborn = get_oid("HEAD", &head); unborn = get_oid("HEAD", &head);
if (unborn) if (unborn)
oidcpy(&head, &empty_tree_oid); oidcpy(&head, &empty_tree_oid);
if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0)) if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
NULL, 0))
return error_dirty_index(opts); return error_dirty_index(opts);
} }
discard_cache(); discard_cache();
@ -2279,7 +2280,7 @@ int sequencer_continue(struct replay_opts *opts)
if (res) if (res)
goto release_todo_list; goto release_todo_list;
} }
if (index_differs_from("HEAD", 0, 0)) { if (index_differs_from("HEAD", NULL, 0)) {
res = error_dirty_index(opts); res = error_dirty_index(opts);
goto release_todo_list; goto release_todo_list;
} }