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>

Brandon Williams committed Oct 31, 2017 at 11:19 UTC 02f2f56bc377c287c411947d0e1482aac888f8db
6 files changed +68 -49
builtin/commit.c
+4 -3
@@ -912,11 +912,12 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
912 * submodules which were manually staged, which would
913 * be really confusing.
914 */
915 - int diff_flags = DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG;
915 + struct diff_flags flags = DIFF_FLAGS_INIT;
916 + flags.OVERRIDE_SUBMODULE_CONFIG = 1;
917 if (ignore_submodule_arg &&
918 !strcmp(ignore_submodule_arg, "all"))
918 - diff_flags |= DIFF_OPT_IGNORE_SUBMODULES;
919 - commitable = index_differs_from(parent, diff_flags, 1);
919 + flags.IGNORE_SUBMODULES = 1;
920 + commitable = index_differs_from(parent, &flags, 1);
921 }
922 }
923 strbuf_release(&committer_ident);
builtin/log.c
+2 -1
@@ -134,7 +134,8 @@ static void cmd_log_init_defaults(struct rev_info *rev)
134
135 if (default_date_mode)
136 parse_date_format(default_date_mode, &rev->date_mode);
137 - rev->diffopt.touched_flags = 0;
137 +
138 + memset(&rev->diffopt.touched_flags, 0, sizeof(struct diff_flags));
139 }
140
141 static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
diff-lib.c
+4 -3
@@ -71,7 +71,7 @@ static int match_stat_with_submodule(struct diff_options *diffopt,
71 {
72 int changed = ce_match_stat(ce, st, ce_option);
73 if (S_ISGITLINK(ce->ce_mode)) {
74 - unsigned orig_flags = diffopt->flags;
74 + struct diff_flags orig_flags = diffopt->flags;
75 if (!DIFF_OPT_TST(diffopt, OVERRIDE_SUBMODULE_CONFIG))
76 set_diffopt_flags_from_submodule_config(diffopt, ce->name);
77 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)
534 return 0;
535 }
536
537 -int index_differs_from(const char *def, int diff_flags,
537 +int index_differs_from(const char *def, const struct diff_flags *flags,
538 int ita_invisible_in_index)
539 {
540 struct rev_info rev;
@@ -546,7 +546,8 @@ int index_differs_from(const char *def, int diff_flags,
546 setup_revisions(0, NULL, &rev, &opt);
547 DIFF_OPT_SET(&rev.diffopt, QUICK);
548 DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
549 - rev.diffopt.flags |= diff_flags;
549 + if (flags)
550 + diff_flags_or(&rev.diffopt.flags, flags);
551 rev.diffopt.ita_invisible_in_index = ita_invisible_in_index;
552 run_diff_index(&rev, 1);
553 object_array_clear(&rev.pending);
diff.c
+1 -1
@@ -5899,7 +5899,7 @@ int diff_can_quit_early(struct diff_options *opt)
5899 static int is_submodule_ignored(const char *path, struct diff_options *options)
5900 {
5901 int ignored = 0;
5902 - unsigned orig_flags = options->flags;
5902 + struct diff_flags orig_flags = options->flags;
5903 if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
5904 set_diffopt_flags_from_submodule_config(options, path);
5905 if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
diff.h
+54 -39
@@ -60,42 +60,56 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
60
61 #define DIFF_FORMAT_CALLBACK 0x1000
62
63 -#define DIFF_OPT_RECURSIVE (1 << 0)
64 -#define DIFF_OPT_TREE_IN_RECURSIVE (1 << 1)
65 -#define DIFF_OPT_BINARY (1 << 2)
66 -#define DIFF_OPT_TEXT (1 << 3)
67 -#define DIFF_OPT_FULL_INDEX (1 << 4)
68 -#define DIFF_OPT_SILENT_ON_REMOVE (1 << 5)
69 -#define DIFF_OPT_FIND_COPIES_HARDER (1 << 6)
70 -#define DIFF_OPT_FOLLOW_RENAMES (1 << 7)
71 -#define DIFF_OPT_RENAME_EMPTY (1 << 8)
72 -/* (1 << 9) unused */
73 -#define DIFF_OPT_HAS_CHANGES (1 << 10)
74 -#define DIFF_OPT_QUICK (1 << 11)
75 -#define DIFF_OPT_NO_INDEX (1 << 12)
76 -#define DIFF_OPT_ALLOW_EXTERNAL (1 << 13)
77 -#define DIFF_OPT_EXIT_WITH_STATUS (1 << 14)
78 -#define DIFF_OPT_REVERSE_DIFF (1 << 15)
79 -#define DIFF_OPT_CHECK_FAILED (1 << 16)
80 -#define DIFF_OPT_RELATIVE_NAME (1 << 17)
81 -#define DIFF_OPT_IGNORE_SUBMODULES (1 << 18)
82 -#define DIFF_OPT_DIRSTAT_CUMULATIVE (1 << 19)
83 -#define DIFF_OPT_DIRSTAT_BY_FILE (1 << 20)
84 -#define DIFF_OPT_ALLOW_TEXTCONV (1 << 21)
85 -#define DIFF_OPT_DIFF_FROM_CONTENTS (1 << 22)
86 -#define DIFF_OPT_DIRTY_SUBMODULES (1 << 24)
87 -#define DIFF_OPT_IGNORE_UNTRACKED_IN_SUBMODULES (1 << 25)
88 -#define DIFF_OPT_IGNORE_DIRTY_SUBMODULES (1 << 26)
89 -#define DIFF_OPT_OVERRIDE_SUBMODULE_CONFIG (1 << 27)
90 -#define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28)
91 -#define DIFF_OPT_FUNCCONTEXT (1 << 29)
92 -#define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
93 -#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1U << 31)
94 -
95 -#define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag)
96 -#define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags & DIFF_OPT_##flag)
97 -#define DIFF_OPT_SET(opts, flag) (((opts)->flags |= DIFF_OPT_##flag),((opts)->touched_flags |= DIFF_OPT_##flag))
98 -#define DIFF_OPT_CLR(opts, flag) (((opts)->flags &= ~DIFF_OPT_##flag),((opts)->touched_flags |= DIFF_OPT_##flag))
63 +#define DIFF_FLAGS_INIT { 0 }
64 +struct diff_flags {
65 + unsigned RECURSIVE:1;
66 + unsigned TREE_IN_RECURSIVE:1;
67 + unsigned BINARY:1;
68 + unsigned TEXT:1;
69 + unsigned FULL_INDEX:1;
70 + unsigned SILENT_ON_REMOVE:1;
71 + unsigned FIND_COPIES_HARDER:1;
72 + unsigned FOLLOW_RENAMES:1;
73 + unsigned RENAME_EMPTY:1;
74 + unsigned HAS_CHANGES:1;
75 + unsigned QUICK:1;
76 + unsigned NO_INDEX:1;
77 + unsigned ALLOW_EXTERNAL:1;
78 + unsigned EXIT_WITH_STATUS:1;
79 + unsigned REVERSE_DIFF:1;
80 + unsigned CHECK_FAILED:1;
81 + unsigned RELATIVE_NAME:1;
82 + unsigned IGNORE_SUBMODULES:1;
83 + unsigned DIRSTAT_CUMULATIVE:1;
84 + unsigned DIRSTAT_BY_FILE:1;
85 + unsigned ALLOW_TEXTCONV:1;
86 + unsigned DIFF_FROM_CONTENTS:1;
87 + unsigned DIRTY_SUBMODULES:1;
88 + unsigned IGNORE_UNTRACKED_IN_SUBMODULES:1;
89 + unsigned IGNORE_DIRTY_SUBMODULES:1;
90 + unsigned OVERRIDE_SUBMODULE_CONFIG:1;
91 + unsigned DIRSTAT_BY_LINE:1;
92 + unsigned FUNCCONTEXT:1;
93 + unsigned PICKAXE_IGNORE_CASE:1;
94 + unsigned DEFAULT_FOLLOW_RENAMES:1;
95 +};
96 +
97 +static inline void diff_flags_or(struct diff_flags *a,
98 + const struct diff_flags *b)
99 +{
100 + char *tmp_a = (char *)a;
101 + const char *tmp_b = (const char *)b;
102 + int i;
103 +
104 + for (i = 0; i < sizeof(struct diff_flags); i++)
105 + tmp_a[i] |= tmp_b[i];
106 +}
107 +
108 +#define DIFF_OPT_TST(opts, flag) ((opts)->flags.flag)
109 +#define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags.flag)
110 +#define DIFF_OPT_SET(opts, flag) (((opts)->flags.flag = 1),((opts)->touched_flags.flag = 1))
111 +#define DIFF_OPT_CLR(opts, flag) (((opts)->flags.flag = 0),((opts)->touched_flags.flag = 1))
112 +
113 #define DIFF_XDL_TST(opts, flag) ((opts)->xdl_opts & XDF_##flag)
114 #define DIFF_XDL_SET(opts, flag) ((opts)->xdl_opts |= XDF_##flag)
115 #define DIFF_XDL_CLR(opts, flag) ((opts)->xdl_opts &= ~XDF_##flag)
@@ -122,8 +136,8 @@ struct diff_options {
136 const char *a_prefix, *b_prefix;
137 const char *line_prefix;
138 size_t line_prefix_length;
125 - unsigned flags;
126 - unsigned touched_flags;
139 + struct diff_flags flags;
140 + struct diff_flags touched_flags;
141
142 /* diff-filter bits */
143 unsigned int filter;
@@ -388,7 +402,8 @@ extern int diff_result_code(struct diff_options *, int);
402
403 extern void diff_no_index(struct rev_info *, int, const char **);
404
391 -extern int index_differs_from(const char *def, int diff_flags, int ita_invisible_in_index);
405 +extern int index_differs_from(const char *def, const struct diff_flags *flags,
406 + int ita_invisible_in_index);
407
408 /*
409 * Fill the contents of the filespec "df", respecting any textconv defined by
sequencer.c
+3 -2
@@ -959,7 +959,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
959 unborn = get_oid("HEAD", &head);
960 if (unborn)
961 oidcpy(&head, &empty_tree_oid);
962 - if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD", 0, 0))
962 + if (index_differs_from(unborn ? EMPTY_TREE_SHA1_HEX : "HEAD",
963 + NULL, 0))
964 return error_dirty_index(opts);
965 }
966 discard_cache();
@@ -2279,7 +2280,7 @@ int sequencer_continue(struct replay_opts *opts)
2280 if (res)
2281 goto release_todo_list;
2282 }
2282 - if (index_differs_from("HEAD", 0, 0)) {
2283 + if (index_differs_from("HEAD", NULL, 0)) {
2284 res = error_dirty_index(opts);
2285 goto release_todo_list;
2286 }