Merge branch 'jl/submodule-ignore-diff'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Aug 2010 19:36:25 +0000 (12:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Aug 2010 19:36:25 +0000 (12:36 -0700)
* jl/submodule-ignore-diff:
Add tests for the diff.ignoreSubmodules config option
Add the 'diff.ignoreSubmodules' config setting
Submodules: Use "ignore" settings from .gitmodules too for diff and status
Submodules: Add the new "ignore" config option for diff and status

Conflicts:
diff.c

1  2 
Documentation/config.txt
Documentation/diff-options.txt
builtin/commit.c
diff.c
diff --combined Documentation/config.txt
index 7fffee7e3de29181479da083b086bf537c6f9354,cf5562192d183911e93c998dc36a13b09764ec93..5e86a28f92b38865a767ba569ab453aeda454f8d
@@@ -128,7 -128,7 +128,7 @@@ advice.*:
                when writing commit messages. Default: true.
        commitBeforeMerge::
                Advice shown when linkgit:git-merge[1] refuses to
 -              merge to avoid overwritting local changes.
 +              merge to avoid overwriting local changes.
                Default: true.
        resolveConflict::
                Advices shown by various commands when conflicts
@@@ -418,7 -418,7 +418,7 @@@ Common unit suffixes of 'k', 'm', or 'g
  
  core.deltaBaseCacheLimit::
        Maximum number of bytes to reserve for caching base objects
 -      that multiple deltafied objects reference.  By storing the
 +      that may be referenced by multiple deltified objects.  By storing the
        entire decompressed base objects in a cache Git is able
        to avoid unpacking and decompressing frequently used base
        objects multiple times.
@@@ -563,7 -563,7 +563,7 @@@ not necessarily be the current director
  am.keepcr::
        If true, git-am will call git-mailsplit for patches in mbox format
        with parameter '--keep-cr'. In this case git-mailsplit will
 -      not remove `\r` from lines ending with `\r\n`. Can be overrriden
 +      not remove `\r` from lines ending with `\r\n`. Can be overridden
        by giving '--no-keep-cr' from the command line.
        See linkgit:git-am[1], linkgit:git-mailsplit[1].
  
@@@ -826,6 -826,11 +826,11 @@@ diff.renames:
        will enable basic rename detection.  If set to "copies" or
        "copy", it will detect copies, as well.
  
+ diff.ignoreSubmodules::
+       Sets the default value of --ignore-submodules. Note that this
+       affects only 'git diff' Porcelain, and not lower level 'diff'
+       commands such as 'git diff-files'.
  diff.suppressBlankEmpty::
        A boolean to inhibit the standard behavior of printing a space
        before each empty output line. Defaults to false.
@@@ -1002,7 -1007,7 +1007,7 @@@ gitcvs.usecrlfattr:
        If true, the server will look up the end-of-line conversion
        attributes for files to determine the '-k' modes to use. If
        the attributes force git to treat a file as text,
 -      the '-k' mode will be left blank so cvs clients will
 +      the '-k' mode will be left blank so CVS clients will
        treat it as text. If they suppress text conversion, the file
        will be set with '-kb' mode, which suppresses any newline munging
        the client might otherwise do. If the attributes do not allow
@@@ -1275,9 -1280,7 +1280,9 @@@ instaweb.local:
        be bound to the local IP (127.0.0.1).
  
  instaweb.modulepath::
 -      The module path for an apache httpd used by linkgit:git-instaweb[1].
 +      The default module path for linkgit:git-instaweb[1] to use
 +      instead of /usr/lib/apache2/modules.  Only used if httpd
 +      is Apache.
  
  instaweb.port::
        The port number to bind the gitweb httpd to. See
@@@ -1560,10 -1563,6 +1565,10 @@@ receive.denyDeletes:
        If set to true, git-receive-pack will deny a ref update that deletes
        the ref. Use this to prevent such a ref deletion via a push.
  
 +receive.denyDeleteCurrent::
 +      If set to true, git-receive-pack will deny a ref update that
 +      deletes the currently checked out branch of a non-bare repository.
 +
  receive.denyCurrentBranch::
        If set to true or "refuse", git-receive-pack will deny a ref update
        to the currently checked out branch of a non-bare repository.
@@@ -1749,6 -1748,19 +1754,19 @@@ submodule.<name>.update:
        URL and other values found in the `.gitmodules` file.  See
        linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
  
+ submodule.<name>.ignore::
+       Defines under what circumstances "git status" and the diff family show
+       a submodule as modified. When set to "all", it will never be considered
+       modified, "dirty" will ignore all changes to the submodules work tree and
+       takes only differences between the HEAD of the submodule and the commit
+       recorded in the superproject into account. "untracked" will additionally
+       let submodules with modified tracked files in their work tree show up.
+       Using "none" (the default when this option is not set) also shows
+       submodules that have untracked files in their work tree as changed.
+       This setting overrides any setting made in .gitmodules for this submodule,
+       both settings can be overriden on the command line by using the
+       "--ignore-submodules" option.
  tar.umask::
        This variable can be used to restrict the permission bits of
        tar archive entries.  The default is 0002, which turns off the
index eecedaab6e172f227f2451f4b3d35c9e6e99bf1e,faa467b03297fa61584a6a75745e3fe1b78c8e21..4656a97e6012796f182a725e14c13dc03f71bba2
@@@ -206,29 -206,10 +206,29 @@@ endif::git-format-patch[
        the diff-patch output format.  Non default number of
        digits can be specified with `--abbrev=<n>`.
  
 --B::
 -      Break complete rewrite changes into pairs of delete and create.
 -
 --M::
 +-B[<n>][/<m>]::
 +      Break complete rewrite changes into pairs of delete and
 +      create. This serves two purposes:
 ++
 +It affects the way a change that amounts to a total rewrite of a file
 +not as a series of deletion and insertion mixed together with a very
 +few lines that happen to match textually as the context, but as a
 +single deletion of everything old followed by a single insertion of
 +everything new, and the number `m` controls this aspect of the -B
 +option (defaults to 60%). `-B/70%` specifies that less than 30% of the
 +original should remain in the result for git to consider it a total
 +rewrite (i.e. otherwise the resulting patch will be a series of
 +deletion and insertion mixed together with context lines).
 ++
 +When used with -M, a totally-rewritten file is also considered as the
 +source of a rename (usually -M only considers a file that disappeared
 +as the source of a rename), and the number `n` controls this aspect of
 +the -B option (defaults to 50%). `-B20%` specifies that a change with
 +addition and deletion compared to 20% or more of the file's size are
 +eligible for being picked up as a possible source of a rename to
 +another file.
 +
 +-M[<n>]::
  ifndef::git-log[]
        Detect renames.
  endif::git-log[]
@@@ -237,15 -218,9 +237,15 @@@ ifdef::git-log[
        For following files across renames while traversing history, see
        `--follow`.
  endif::git-log[]
 +      If `n` is specified, it is a is a threshold on the similarity
 +      index (i.e. amount of addition/deletions compared to the
 +      file's size). For example, `-M90%` means git should consider a
 +      delete/add pair to be a rename if more than 90% of the file
 +      hasn't changed.
  
 --C::
 +-C[<n>]::
        Detect copies as well as renames.  See also `--find-copies-harder`.
 +      If `n` is specified, it has the same meaning as for `-M<n>`.
  
  ifndef::git-format-patch[]
  --diff-filter=[ACDMRTUXB*]::
@@@ -355,7 -330,11 +355,11 @@@ endif::git-format-patch[
  
  --ignore-submodules[=<when>]::
        Ignore changes to submodules in the diff generation. <when> can be
-       either "untracked", "dirty" or "all", which is the default. When
+       either "none", "untracked", "dirty" or "all", which is the default
+       Using "none" will consider the submodule modified when it either contains
+       untracked or modified files or its HEAD differs from the commit recorded
+       in the superproject and can be used to override any settings of the
+       'ignore' option in linkgit:git-config[1] or linkgit:gitmodules[5]. When
        "untracked" is used submodules are not considered dirty when they only
        contain untracked content (but they are still scanned for modified
        content). Using "dirty" ignores all changes to the work tree of submodules,
diff --combined builtin/commit.c
index c4a577d5c5595a6c50ecaaba90690c286d30b7e2,9456f4a58b7097e8b880619feb4a19b3cd6fd447..66fdd2202495b2893c79b4f92b0fc2e715f5b7bb
@@@ -25,6 -25,7 +25,7 @@@
  #include "rerere.h"
  #include "unpack-trees.h"
  #include "quote.h"
+ #include "submodule.h"
  
  static const char * const builtin_commit_usage[] = {
        "git commit [options] [--] <filepattern>...",
@@@ -147,7 -148,7 +148,7 @@@ static struct option builtin_commit_opt
                    "terminate entries with NUL"),
        OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
        OPT_BOOLEAN(0, "no-post-rewrite", &no_post_rewrite, "bypass post-rewrite hook"),
 -      { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 +      { OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
        /* end commit contents options */
  
        { OPTION_BOOLEAN, 0, "allow-empty", &allow_empty, NULL,
@@@ -1073,6 -1074,7 +1074,7 @@@ int cmd_status(int argc, const char **a
                status_format = STATUS_FORMAT_PORCELAIN;
  
        wt_status_prepare(&s);
+       gitmodules_config();
        git_config(git_status_config, &s);
        in_merge = file_exists(git_path("MERGE_HEAD"));
        argc = parse_options(argc, argv, prefix,
@@@ -1163,6 -1165,7 +1165,6 @@@ static void print_summary(const char *p
        init_revisions(&rev, prefix);
        setup_revisions(0, NULL, &rev, NULL);
  
 -      rev.abbrev = 0;
        rev.diff = 1;
        rev.diffopt.output_format =
                DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
diff --combined diff.c
index bf65892f78f84a31b6bf87b0f82cfc5938485862,1ddfdfbc2cf0e147cd5991d022fb16736389d4eb..ccc9f1f64d094b1943c905f4060dce555745d48b
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -31,6 -31,7 +31,7 @@@ static const char *external_diff_cmd_cf
  int diff_auto_refresh_index = 1;
  static int diff_mnemonic_prefix;
  static int diff_no_prefix;
+ static struct diff_options default_diff_options;
  
  static char diff_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_RESET,
@@@ -107,6 -108,9 +108,9 @@@ int git_diff_ui_config(const char *var
        if (!strcmp(var, "diff.wordregex"))
                return git_config_string(&diff_word_regex_cfg, var, value);
  
+       if (!strcmp(var, "diff.ignoresubmodules"))
+               handle_ignore_submodules_arg(&default_diff_options, value);
        return git_diff_basic_config(var, value, cb);
  }
  
@@@ -141,6 -145,9 +145,9 @@@ int git_diff_basic_config(const char *v
                return 0;
        }
  
+       if (!prefixcmp(var, "submodule."))
+               return parse_submodule_config_option(var, value);
        return git_color_default_config(var, value, cb);
  }
  
@@@ -2704,16 -2711,10 +2711,16 @@@ static void diff_fill_sha1_info(struct 
  static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
  {
        /* Strip the prefix but do not molest /dev/null and absolute paths */
 -      if (*namep && **namep != '/')
 +      if (*namep && **namep != '/') {
                *namep += prefix_length;
 -      if (*otherp && **otherp != '/')
 +              if (**namep == '/')
 +                      ++*namep;
 +      }
 +      if (*otherp && **otherp != '/') {
                *otherp += prefix_length;
 +              if (**otherp == '/')
 +                      ++*otherp;
 +      }
  }
  
  static void run_diff(struct diff_filepair *p, struct diff_options *o)
@@@ -2819,7 -2820,8 +2826,7 @@@ static void run_checkdiff(struct diff_f
  
  void diff_setup(struct diff_options *options)
  {
-       memset(options, 0, sizeof(*options));
+       memcpy(options, &default_diff_options, sizeof(*options));
 -      memset(&diff_queued_diff, 0, sizeof(diff_queued_diff));
  
        options->file = stdout;
  
@@@ -3171,11 -3173,13 +3178,13 @@@ int diff_opt_parse(struct diff_options 
                DIFF_OPT_SET(options, ALLOW_TEXTCONV);
        else if (!strcmp(arg, "--no-textconv"))
                DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
-       else if (!strcmp(arg, "--ignore-submodules"))
+       else if (!strcmp(arg, "--ignore-submodules")) {
+               DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(options, "all");
-       else if (!prefixcmp(arg, "--ignore-submodules="))
+       } else if (!prefixcmp(arg, "--ignore-submodules=")) {
+               DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(options, arg + 20);
-       else if (!strcmp(arg, "--submodule"))
+       else if (!strcmp(arg, "--submodule"))
                DIFF_OPT_SET(options, SUBMODULE_LOG);
        else if (!prefixcmp(arg, "--submodule=")) {
                if (!strcmp(arg + 12, "log"))
@@@ -4108,6 -4112,24 +4117,24 @@@ int diff_result_code(struct diff_option
        return result;
  }
  
+ /*
+  * Shall changes to this submodule be ignored?
+  *
+  * Submodule changes can be configured to be ignored separately for each path,
+  * but that configuration can be overridden from the command line.
+  */
+ static int is_submodule_ignored(const char *path, struct diff_options *options)
+ {
+       int ignored = 0;
+       unsigned orig_flags = options->flags;
+       if (!DIFF_OPT_TST(options, OVERRIDE_SUBMODULE_CONFIG))
+               set_diffopt_flags_from_submodule_config(options, path);
+       if (DIFF_OPT_TST(options, IGNORE_SUBMODULES))
+               ignored = 1;
+       options->flags = orig_flags;
+       return ignored;
+ }
  void diff_addremove(struct diff_options *options,
                    int addremove, unsigned mode,
                    const unsigned char *sha1,
  {
        struct diff_filespec *one, *two;
  
-       if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
+       if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options))
                return;
  
        /* This may look odd, but it is a preparation for
@@@ -4162,8 -4184,8 +4189,8 @@@ void diff_change(struct diff_options *o
  {
        struct diff_filespec *one, *two;
  
-       if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
-                       && S_ISGITLINK(new_mode))
+       if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
+           is_submodule_ignored(concatpath, options))
                return;
  
        if (DIFF_OPT_TST(options, REVERSE_DIFF)) {