Fix "git diff --stat" for interesting - but empty - file changes

The behavior of "git diff --stat" is rather odd for files that have
zero lines of changes: it will discount them entirely unless they were
renames.

Which means that the stat output will simply not show files that only
had "other" changes: they were created or deleted, or their mode was
changed.

Now, those changes do show up in the summary, but so do renames, so
the diffstat logic is inconsistent. Why does it show renames with zero
lines changed, but not mode changes or added files with zero lines
changed?

So change the logic to not check for "is_renamed", but for
"is_interesting" instead, where "interesting" is judged to be any
action but a pure data change (because a pure data change with zero
data changed really isn't worth showing, if we ever get one in our
diffpairs).

So if you did

   chmod +x Makefile
   git diff --stat

before, it would show empty (" 0 files changed"), with this it shows

 Makefile | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

which I think is a more correct diffstat (and then with "--summary" it
shows *what* the metadata change to Makefile was - this is completely
consistent with our handling of renamed files).

Side note: the old behavior was *really* odd. With no changes at all,
"git diff --stat" output was empty. With just a chmod, it said "0
files changed". No way is our legacy behavior sane.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
reencode_string(): introduce and use same_encoding()

Callers of reencode_string() that re-encodes a string from one
encoding to another all used ad-hoc way to bypass the case where the
input and the output encodings are the same.  Some did strcmp(),
some did strcasecmp(), yet some others when converting to UTF-8 used
is_encoding_utf8().

Introduce same_encoding() helper function to make these callers use
the same logic.  Notably, is_encoding_utf8() has a work-around for
common misconfiguration to use "utf8" to name UTF-8 encoding, which
does not match "UTF-8" hence strcasecmp() would not consider the
same.  Make use of it in this helper function.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
test: add failing tests for "diff --stat" to t4049

There are a few problems in diff.c around --stat area, partially
caused by the recent 74faaa1 (Fix "git diff --stat" for interesting
- but empty - file changes, 2012-10-17), and largely caused by the
earlier change that introduced when --stat-count was added.

Add a few test pieces to t4049 to expose the issues.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --stat: status of unmodified pair in diff-q is not zero

It is spelled DIFF_STATUS_UNKNOWN these days, and is different from zero.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --stat: use "file" temporary variable to refer to data->files[i]

The generated code shouldn't change but it is easier to read.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --stat: move the "total count" logic to the last loop

The diffstat generation logic, with --stat-count limit, is
implemented as three loops.

 - The first counts the width necessary to show stats up to
   specified number of entries, and notes up to how many entries in
   the data we need to iterate to show the graph;

 - The second iterates that many times to draw the graph, adjusts
   the number of "total modified files", and counts the total
   added/deleted lines for the part that was shown in the graph;

 - The third iterates over the remainder and only does the part to
   count "total added/deleted lines" and to adjust "total modified
   files" without drawing anything.

Move the logic to count added/deleted lines and modified files from
the second loop to the third loop.

This incidentally fixes a bug.  The third loop was not filtering
binary changes (counted in bytes) from the total added/deleted as it
should.  The second loop implemented this correctly, so if a binary
change appeared earlier than the --stat-count cutoff, the code
counted number of added/deleted lines correctly, but if it appeared
beyond the cutoff, the number of lines would have mixed with the
byte count in the buggy third loop.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --stat: do not count "unmerged" entries

Even though we show a separate *UNMERGED* entry in the patch and
diffstat output (or in the --raw format, for that matter) in
addition to and separately from the diff against the specified stage
(defaulting to #2) for unmerged paths, they should not be counted in
the total number of files affected---that would lead to counting the
same path twice.

The separation done by the previous step makes this fix simple and
straightforward.  Among the filepairs in diff_queue, paths that
weren't modified, and the extra "unmerged" entries do not count as
total number of files.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --shortstat: do not count "unmerged" entries

Fix the same issue as the previous one for "git diff --stat";
unmerged entries was doubly-counted.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-push.txt: clarify the "push from satellite" workflow

The context of the example to push into refs/remotes/satellite/
hierarchy of the other repository needs to be spelled out explicitly
for the value of this example to be fully appreciated.  Make it so.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
t4049: refocus tests

The primary thing Linus's patch wanted to change was to make sure
that 0-line change appears for a mode-only change.  Update the
first test to chmod a file that we can see in the output (limited
by --stat-count) to demonstrate it.  Also make sure to use test_chmod
and compare the index and the tree, so that we can run this test
even on a filesystem without permission bits.

Later two tests are about fixes to separate issues that were
introduced and/or uncovered by Linus's patch as a side effect, but
the issues are not related to mode-only changes.  Remove chmod from
the tests.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Merge branch 'lt/diff-stat-show-0-lines' into maint

"git diff --stat" miscounted the total number of changed lines when
binary files were involved and hidden beyond --stat-count.  It also
miscounted the total number of changed files when there were
unmerged paths.

* lt/diff-stat-show-0-lines:
  t4049: refocus tests
  diff --shortstat: do not count "unmerged" entries
  diff --stat: do not count "unmerged" entries
  diff --stat: move the "total count" logic to the last loop
  diff --stat: use "file" temporary variable to refer to data->files[i]
  diff --stat: status of unmodified pair in diff-q is not zero
  test: add failing tests for "diff --stat" to t4049
  Fix "git diff --stat" for interesting - but empty - file changes
Merge branch 'jc/same-encoding' into maint

Various codepaths checked if two encoding names are the same using
ad-hoc code and some of them ended up asking iconv() to convert
between "utf8" and "UTF-8".  The former is not a valid way to spell
the encoding name, but often people use it by mistake, and we
equated them in some but not all codepaths. Introduce a new helper
function to make these codepaths consistent.

* jc/same-encoding:
  reencode_string(): introduce and use same_encoding()
Merge branch 'jc/doc-push-satellite' into maint

* jc/doc-push-satellite:
  Documentation/git-push.txt: clarify the "push from satellite" workflow
Update draft release notes to 1.8.0.2

Signed-off-by: Junio C Hamano <gitster@pobox.com>