Merge branch 'jc/refactor-diff-stdin' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 22 Jul 2012 20:01:22 +0000 (13:01 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 22 Jul 2012 20:01:23 +0000 (13:01 -0700)
"git diff", "git status" and anything that internally uses the
comparison machinery was utterly broken when the difference
involved a file with "-" as its name.  This was due to the way "git
diff --no-index" was incorrectly bolted on to the system, making
any comparison that involves a file "-" at the root level
incorrectly read from the standard input.

* jc/refactor-diff-stdin:
  diff-index.c: "git diff" has no need to read blob from the standard input
  diff-index.c: unify handling of command line paths
  diff-index.c: do not pretend paths are pathspecs

1  2 
diff-no-index.c
diff.c
diffcore.h
t/t7501-commit.sh

diff --cc diff-no-index.c
index beec49b5ac98c6d3ea895adcf66265f3a2fc7875,09656bca1d192f21f36ff56f2446c6bcc73442f4..7d805a06afacae7eaa36a192e3a16406ef0fb41f
@@@ -51,8 -58,38 +58,38 @@@ static int get_mode(const char *path, i
        return 0;
  }
  
+ static int populate_from_stdin(struct diff_filespec *s)
+ {
+       struct strbuf buf = STRBUF_INIT;
+       size_t size = 0;
+       if (strbuf_read(&buf, 0, 0) < 0)
+               return error("error while reading from stdin %s",
+                                    strerror(errno));
+       s->should_munmap = 0;
+       s->data = strbuf_detach(&buf, &size);
+       s->size = size;
+       s->should_free = 1;
+       s->is_stdin = 1;
+       return 0;
+ }
+ static struct diff_filespec *noindex_filespec(const char *name, int mode)
+ {
+       struct diff_filespec *s;
+       if (!name)
+               name = "/dev/null";
+       s = alloc_filespec(name);
+       fill_filespec(s, null_sha1, mode);
+       if (name == file_from_standard_input)
+               populate_from_stdin(s);
+       return s;
+ }
  static int queue_diff(struct diff_options *o,
 -              const char *name1, const char *name2)
 +                    const char *name1, const char *name2)
  {
        int mode1 = 0, mode2 = 0;
  
@@@ -207,26 -253,26 +238,19 @@@ void diff_no_index(struct rev_info *rev
                }
        }
  
-       if (prefix) {
-               int len = strlen(prefix);
-               const char *paths[3];
-               memset(paths, 0, sizeof(paths));
 -      /*
 -       * If the user asked for our exit code then don't start a
 -       * pager or we would end up reporting its exit code instead.
 -       */
 -      if (!DIFF_OPT_TST(&revs->diffopt, EXIT_WITH_STATUS))
 -              setup_pager();
--
-               for (i = 0; i < 2; i++) {
-                       const char *p = argv[argc - 2 + i];
+       prefixlen = prefix ? strlen(prefix) : 0;
+       for (i = 0; i < 2; i++) {
+               const char *p = argv[argc - 2 + i];
+               if (!strcmp(p, "-"))
                        /*
-                        * stdin should be spelled as '-'; if you have
-                        * path that is '-', spell it as ./-.
+                        * stdin should be spelled as "-"; if you have
+                        * path that is "-", spell it as "./-".
                         */
-                       p = (strcmp(p, "-")
-                            ? xstrdup(prefix_filename(prefix, len, p))
-                            : p);
-                       paths[i] = p;
-               }
-               diff_tree_setup_paths(paths, &revs->diffopt);
+                       p = file_from_standard_input;
+               else if (prefixlen)
+                       p = xstrdup(prefix_filename(prefix, prefixlen, p));
+               paths[i] = p;
        }
-       else
-               diff_tree_setup_paths(argv + argc - 2, &revs->diffopt);
        revs->diffopt.skip_stat_unmatch = 1;
        if (!revs->diffopt.output_format)
                revs->diffopt.output_format = DIFF_FORMAT_PATCH;
        if (diff_setup_done(&revs->diffopt) < 0)
                die("diff_setup_done failed");
  
-       if (queue_diff(&revs->diffopt, revs->diffopt.pathspec.raw[0],
-                      revs->diffopt.pathspec.raw[1]))
 +      setup_diff_pager(&revs->diffopt);
 +      DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
 +
+       if (queue_diff(&revs->diffopt, paths[0], paths[1]))
                exit(1);
        diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/");
        diffcore_std(&revs->diffopt);
diff --cc diff.c
Simple merge
diff --cc diffcore.h
index 8f32b824cdc1bac1f094d743f3bee9f32890edca,ae43149620ee269ddddfcec06d618dcc76c52895..be0739c5c401c059a0d3030acbc99a7744f17065
@@@ -43,9 -43,10 +43,10 @@@ struct diff_filespec 
        unsigned should_free : 1; /* data should be free()'ed */
        unsigned should_munmap : 1; /* data should be munmap()'ed */
        unsigned dirty_submodule : 2;  /* For submodules: its work tree is dirty */
+       unsigned is_stdin : 1;
  #define DIRTY_SUBMODULE_UNTRACKED 1
  #define DIRTY_SUBMODULE_MODIFIED  2
 -
 +      unsigned has_more_entries : 1; /* only appear in combined diff */
        struct userdiff_driver *driver;
        /* data should be considered "binary"; -1 means "don't know yet" */
        int is_binary;
Simple merge