Merge branch 'ph/diffopts'
authorJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2007 23:50:16 +0000 (15:50 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 18 Nov 2007 23:50:16 +0000 (15:50 -0800)
* ph/diffopts:
Reorder diff_opt_parse options more logically per topics.
Make the diff_options bitfields be an unsigned with explicit masks.
Use OPT_BIT in builtin-pack-refs
Use OPT_BIT in builtin-for-each-ref
Use OPT_SET_INT and OPT_BIT in builtin-branch
parse-options new features.

1  2 
builtin-for-each-ref.c
builtin-log.c
diff-lib.c
diff.h
git-compat-util.h
diff --combined builtin-for-each-ref.c
index bfde2e2bbeffaed68b369b25cfe1b5ef4b108e12,a5064441833ef1f69a245f2a9d11397b1f147caf..daf3a081650b6b39fe18f0fab61fa8b3f6c8be0f
@@@ -304,7 -304,7 +304,7 @@@ static const char *find_wholine(const c
                if (!eol)
                        return "";
                eol++;
 -              if (eol[1] == '\n')
 +              if (*eol == '\n')
                        return ""; /* end of header */
                buf = eol;
        }
@@@ -833,16 -833,19 +833,19 @@@ int cmd_for_each_ref(int argc, const ch
        int i, num_refs;
        const char *format = "%(objectname) %(objecttype)\t%(refname)";
        struct ref_sort *sort = NULL, **sort_tail = &sort;
-       int maxcount = 0, quote_style;
-       int quote_shell = 0, quote_perl = 0, quote_python = 0, quote_tcl = 0;
+       int maxcount = 0, quote_style = 0;
        struct refinfo **refs;
        struct grab_ref_cbdata cbdata;
  
        struct option opts[] = {
-               OPT_BOOLEAN('s', "shell", &quote_shell, "quote placeholders suitably for shells"),
-               OPT_BOOLEAN('p', "perl",  &quote_perl, "quote placeholders suitably for perl"),
-               OPT_BOOLEAN( 0 , "python", &quote_python, "quote placeholders suitably for python"),
-               OPT_BOOLEAN( 0 , "tcl",  &quote_tcl, "quote placeholders suitably for tcl"),
+               OPT_BIT('s', "shell", &quote_style,
+                       "quote placeholders suitably for shells", QUOTE_SHELL),
+               OPT_BIT('p', "perl",  &quote_style,
+                       "quote placeholders suitably for perl", QUOTE_PERL),
+               OPT_BIT(0 , "python", &quote_style,
+                       "quote placeholders suitably for python", QUOTE_PYTHON),
+               OPT_BIT(0 , "tcl",  &quote_style,
+                       "quote placeholders suitably for tcl", QUOTE_TCL),
  
                OPT_GROUP(""),
                OPT_INTEGER( 0 , "count", &maxcount, "show only <n> matched refs"),
                error("invalid --count argument: `%d'", maxcount);
                usage_with_options(for_each_ref_usage, opts);
        }
-       if (quote_shell + quote_perl + quote_python + quote_tcl > 1) {
+       if (HAS_MULTI_BITS(quote_style)) {
                error("more than one quoting style ?");
                usage_with_options(for_each_ref_usage, opts);
        }
        if (verify_format(format))
                usage_with_options(for_each_ref_usage, opts);
  
-       quote_style = QUOTE_SHELL * quote_shell + QUOTE_PERL * quote_perl +
-               QUOTE_PYTHON * quote_python + QUOTE_TCL * quote_tcl;
        if (!sort)
                sort = default_sort();
        sort_atom_limit = used_atom_cnt;
diff --combined builtin-log.c
index c5230106a0e8dfe32fc5859f6207ae78a58e2111,b69b0b42f1b9072fb4ac2372ac656abdba9226db..197f6eec03df49d4fac044377afd8d0c50e90c81
@@@ -55,13 -55,13 +55,13 @@@ static void cmd_log_init(int argc, cons
        rev->abbrev = DEFAULT_ABBREV;
        rev->commit_format = CMIT_FMT_DEFAULT;
        rev->verbose_header = 1;
-       rev->diffopt.recursive = 1;
+       DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
        rev->show_root_diff = default_show_root;
        rev->subject_prefix = fmt_patch_subject_prefix;
        argc = setup_revisions(argc, argv, rev, "HEAD");
        if (rev->diffopt.pickaxe || rev->diffopt.filter)
                rev->always_show_header = 0;
-       if (rev->diffopt.follow_renames) {
+       if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
                rev->always_show_header = 0;
                if (rev->diffopt.nr_paths != 1)
                        usage("git logs can only follow renames on one pathname at a time");
@@@ -185,11 -185,9 +185,9 @@@ int cmd_show(int argc, const char **arg
                        struct tag *t = (struct tag *)o;
  
                        printf("%stag %s%s\n\n",
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_COMMIT),
+                                       diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        t->tag,
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_RESET));
+                                       diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        ret = show_object(o->sha1, 1);
                        objects[i].item = (struct object *)t->tagged;
                        i--;
                }
                case OBJ_TREE:
                        printf("%stree %s%s\n\n",
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_COMMIT),
+                                       diff_get_color_opt(&rev.diffopt, DIFF_COMMIT),
                                        name,
-                                       diff_get_color(rev.diffopt.color_diff,
-                                               DIFF_RESET));
+                                       diff_get_color_opt(&rev.diffopt, DIFF_RESET));
                        read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
                                        show_tree_object);
                        break;
@@@ -273,8 -269,6 +269,8 @@@ static int istitlechar(char c
  static char *extra_headers = NULL;
  static int extra_headers_size = 0;
  static const char *fmt_patch_suffix = ".patch";
 +static int numbered = 0;
 +static int auto_number = 0;
  
  static int git_format_config(const char *var, const char *value)
  {
        if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
                return 0;
        }
 +      if (!strcmp(var, "format.numbered")) {
 +              if (!strcasecmp(value, "auto")) {
 +                      auto_number = 1;
 +                      return 0;
 +              }
 +
 +              numbered = git_config_bool(var, value);
 +              return 0;
 +      }
  
        return git_log_config(var, value);
  }
@@@ -477,6 -462,7 +473,6 @@@ int cmd_format_patch(int argc, const ch
        struct rev_info rev;
        int nr = 0, total, i, j;
        int use_stdout = 0;
 -      int numbered = 0;
        int start_number = -1;
        int keep_subject = 0;
        int numbered_files = 0;         /* _just_ numbers */
        rev.combine_merges = 0;
        rev.ignore_merges = 1;
        rev.diffopt.msg_sep = "";
-       rev.diffopt.recursive = 1;
+       DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
  
        rev.subject_prefix = fmt_patch_subject_prefix;
        rev.extra_headers = extra_headers;
                else if (!strcmp(argv[i], "-n") ||
                                !strcmp(argv[i], "--numbered"))
                        numbered = 1;
 +              else if (!strcmp(argv[i], "-N") ||
 +                              !strcmp(argv[i], "--no-numbered")) {
 +                      numbered = 0;
 +                      auto_number = 0;
 +              }
                else if (!prefixcmp(argv[i], "--start-number="))
                        start_number = strtol(argv[i] + 15, NULL, 10);
                else if (!strcmp(argv[i], "--numbered-files"))
        if (!rev.diffopt.output_format)
                rev.diffopt.output_format = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_PATCH;
  
-       if (!rev.diffopt.text)
-               rev.diffopt.binary = 1;
+       if (!DIFF_OPT_TST(&rev.diffopt, TEXT))
+               DIFF_OPT_SET(&rev.diffopt, BINARY);
  
        if (!output_directory && !use_stdout)
                output_directory = prefix;
                list[nr - 1] = commit;
        }
        total = nr;
 +      if (!keep_subject && auto_number && total > 1)
 +              numbered = 1;
        if (numbered)
                rev.total = total + start_number - 1;
        rev.add_signoff = add_signoff;
@@@ -764,7 -743,7 +760,7 @@@ int cmd_cherry(int argc, const char **a
        revs.diff = 1;
        revs.combine_merges = 0;
        revs.ignore_merges = 1;
-       revs.diffopt.recursive = 1;
+       DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
  
        if (add_pending_commit(head, &revs, 0))
                die("Unknown commit %s", head);
diff --combined diff-lib.c
index ec1b5e3d446c4e5a56fb5f3e4420499c4e8918eb,290a170b053c87b281570eccfa9f4e4b3fed1794..f8e936ae1008fdb7ef8e1722afb839d84c724f6c
@@@ -121,7 -121,7 +121,7 @@@ static int queue_diff(struct diff_optio
        } else {
                struct diff_filespec *d1, *d2;
  
-               if (o->reverse_diff) {
+               if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
                        unsigned tmp;
                        const char *tmp_c;
                        tmp = mode1; mode1 = mode2; mode2 = tmp;
@@@ -173,10 -173,9 +173,10 @@@ static int is_in_index(const char *path
  }
  
  static int handle_diff_files_args(struct rev_info *revs,
 -              int argc, const char **argv, int *silent)
 +                                int argc, const char **argv,
 +                                unsigned int *options)
  {
 -      *silent = 0;
 +      *options = 0;
  
        /* revs->max_count == -2 means --no-index */
        while (1 < argc && argv[1][0] == '-') {
                else if (!strcmp(argv[1], "-n") ||
                                !strcmp(argv[1], "--no-index")) {
                        revs->max_count = -2;
-                       revs->diffopt.exit_with_status = 1;
-                       revs->diffopt.no_index = 1;
+                       DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
+                       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
                }
                else if (!strcmp(argv[1], "-q"))
 -                      *silent = 1;
 +                      *options |= DIFF_SILENT_ON_REMOVED;
                else
                        return error("invalid option: %s", argv[1]);
                argv++; argc--;
                if (!is_in_index(revs->diffopt.paths[0]) ||
                                        !is_in_index(revs->diffopt.paths[1])) {
                        revs->max_count = -2;
-                       revs->diffopt.no_index = 1;
+                       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
                }
        }
  
@@@ -259,7 -258,7 +259,7 @@@ int setup_diff_no_index(struct rev_inf
                        break;
                } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) {
                        i = argc - 3;
-                       revs->diffopt.exit_with_status = 1;
+                       DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
                        break;
                }
        if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) &&
        else
                revs->diffopt.paths = argv + argc - 2;
        revs->diffopt.nr_paths = 2;
-       revs->diffopt.no_index = 1;
+       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
        revs->max_count = -2;
        if (diff_setup_done(&revs->diffopt) < 0)
                die("diff_setup_done failed");
  
  int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
  {
 -      int silent_on_removed;
 +      unsigned int options;
  
 -      if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
 +      if (handle_diff_files_args(revs, argc, argv, &options))
                return -1;
  
-       if (revs->diffopt.no_index) {
+       if (DIFF_OPT_TST(&revs->diffopt, NO_INDEX)) {
                if (revs->diffopt.nr_paths != 2)
                        return error("need two files/directories with --no-index");
                if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
                perror("read_cache");
                return -1;
        }
 -      return run_diff_files(revs, silent_on_removed);
 +      return run_diff_files(revs, options);
  }
  
 -int run_diff_files(struct rev_info *revs, int silent_on_removed)
 +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 (diff_unmerged_stage < 0)
                diff_unmerged_stage = 2;
                struct cache_entry *ce = active_cache[i];
                int changed;
  
-               if (revs->diffopt.quiet && revs->diffopt.has_changes)
+               if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
+                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
                        break;
  
                if (!ce_path_match(ce, revs->prune_data))
                                       ce->sha1, ce->name, NULL);
                        continue;
                }
 -              changed = ce_match_stat(ce, &st, 0);
 +              changed = ce_match_stat(ce, &st, ce_option);
-               if (!changed && !revs->diffopt.find_copies_harder)
+               if (!changed && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                        continue;
                oldmode = ntohl(ce->ce_mode);
                newmode = ntohl(ce_mode_from_stat(ce, st.st_mode));
@@@ -565,7 -562,7 +566,7 @@@ static int show_modified(struct rev_inf
  
        oldmode = old->ce_mode;
        if (mode == oldmode && !hashcmp(sha1, old->sha1) &&
-           !revs->diffopt.find_copies_harder)
+           !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                return 0;
  
        mode = ntohl(mode);
@@@ -585,7 -582,8 +586,8 @@@ static int diff_cache(struct rev_info *
                struct cache_entry *ce = *ac;
                int same = (entries > 1) && ce_same_name(ce, ac[1]);
  
-               if (revs->diffopt.quiet && revs->diffopt.has_changes)
+               if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
+                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
                        break;
  
                if (!ce_path_match(ce, pathspec))
diff --combined diff.h
index efaa8f711a35c1339aba2bcaffeab6bf95343983,6ff2b0e3189550afeb1a27c0adec0bfee90261f4..a52496a1086ccbe8ea90acd6800dd355b1d7ff68
--- 1/diff.h
--- 2/diff.h
+++ b/diff.h
@@@ -43,26 -43,32 +43,32 @@@ typedef void (*diff_format_fn_t)(struc
  
  #define DIFF_FORMAT_CALLBACK  0x1000
  
+ #define DIFF_OPT_RECURSIVE           (1 <<  0)
+ #define DIFF_OPT_TREE_IN_RECURSIVE   (1 <<  1)
+ #define DIFF_OPT_BINARY              (1 <<  2)
+ #define DIFF_OPT_TEXT                (1 <<  3)
+ #define DIFF_OPT_FULL_INDEX          (1 <<  4)
+ #define DIFF_OPT_SILENT_ON_REMOVE    (1 <<  5)
+ #define DIFF_OPT_FIND_COPIES_HARDER  (1 <<  6)
+ #define DIFF_OPT_FOLLOW_RENAMES      (1 <<  7)
+ #define DIFF_OPT_COLOR_DIFF          (1 <<  8)
+ #define DIFF_OPT_COLOR_DIFF_WORDS    (1 <<  9)
+ #define DIFF_OPT_HAS_CHANGES         (1 << 10)
+ #define DIFF_OPT_QUIET               (1 << 11)
+ #define DIFF_OPT_NO_INDEX            (1 << 12)
+ #define DIFF_OPT_ALLOW_EXTERNAL      (1 << 13)
+ #define DIFF_OPT_EXIT_WITH_STATUS    (1 << 14)
+ #define DIFF_OPT_REVERSE_DIFF        (1 << 15)
+ #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
+ #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
+ #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
  struct diff_options {
        const char *filter;
        const char *orderfile;
        const char *pickaxe;
        const char *single_follow;
-       unsigned recursive:1,
-                tree_in_recursive:1,
-                binary:1,
-                text:1,
-                full_index:1,
-                silent_on_remove:1,
-                find_copies_harder:1,
-                follow_renames:1,
-                color_diff:1,
-                color_diff_words:1,
-                has_changes:1,
-                quiet:1,
-                no_index:1,
-                allow_external:1,
-                exit_with_status:1;
+       unsigned flags;
        int context;
        int break_opt;
        int detect_rename;
@@@ -71,7 -77,6 +77,6 @@@
        int output_format;
        int pickaxe_opts;
        int rename_score;
-       int reverse_diff;
        int rename_limit;
        int setup;
        int abbrev;
@@@ -105,6 -110,9 +110,9 @@@ enum color_diff 
        DIFF_WHITESPACE = 7,
  };
  const char *diff_get_color(int diff_use_color, enum color_diff ix);
+ #define diff_get_color_opt(o, ix) \
+       diff_get_color(DIFF_OPT_TST((o), COLOR_DIFF), ix)
  
  extern const char mime_boundary_leader[];
  
@@@ -224,11 -232,7 +232,11 @@@ extern void diff_flush(struct diff_opti
  
  extern const char *diff_unique_abbrev(const unsigned char *, int);
  
 -extern int run_diff_files(struct rev_info *revs, int silent_on_removed);
 +/* do not report anything on removed paths */
 +#define DIFF_SILENT_ON_REMOVED 01
 +/* report racily-clean paths as modified */
 +#define DIFF_RACY_IS_MODIFIED 02
 +extern int run_diff_files(struct rev_info *revs, unsigned int option);
  extern int setup_diff_no_index(struct rev_info *revs,
                int argc, const char ** argv, int nongit, const char *prefix);
  extern int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv);
diff --combined git-compat-util.h
index ede9408bbd14880b3534110586562c2e6df8b07b,f86b19f162fdc64daf88e5013efe0c90be3f6c1c..276a43724d91781a6c6d79b283ef526e09917c87
@@@ -20,6 -20,7 +20,7 @@@
  #endif
  
  #define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
+ #define HAS_MULTI_BITS(i)  ((i) & ((i) - 1))  /* checks if an integer has more than 1 bit set */
  
  /* Approximation of the length of the decimal representation of this type. */
  #define decimal_length(x)     ((int)(sizeof(x) * 2.56 + 0.5) + 1)
@@@ -183,22 -184,6 +184,22 @@@ void *gitmemmem(const void *haystack, s
                  const void *needle, size_t needlelen);
  #endif
  
 +#ifdef __GLIBC_PREREQ
 +#if __GLIBC_PREREQ(2, 1)
 +#define HAVE_STRCHRNUL
 +#endif
 +#endif
 +
 +#ifndef HAVE_STRCHRNUL
 +#define strchrnul gitstrchrnul
 +static inline char *gitstrchrnul(const char *s, int c)
 +{
 +      while (*s && *s != c)
 +              s++;
 +      return (char *)s;
 +}
 +#endif
 +
  extern void release_pack_memory(size_t, int);
  
  static inline char* xstrdup(const char *str)