summaryrefslogtreecommitdiff
path: root/combine-diff.c
AgeCommit message (Collapse)AuthorFilesLines
2015-05-27diff.h: rename DIFF_PLAIN color slot to DIFF_CONTEXTLibravatar Jeff King1-3/+3
The latter is a much more descriptive name (and we support "color.diff.context" now). This also updates the name of any local variables which were used to store the color. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-02Merge branch 'jk/pretty-empty-format'Libravatar Junio C Hamano1-1/+2
"git log --pretty/format=" with an empty format string did not mean the more obvious "No output whatsoever" but "Use default format", which was counterintuitive. * jk/pretty-empty-format: pretty: make empty userformats truly empty pretty: treat "--format=" as an empty userformat revision: drop useless string offset when parsing "--pretty"
2014-08-26Merge branch 'jk/diff-tree-t-fix'Libravatar Junio C Hamano1-1/+11
Fix (rarely used) "git diff-tree -t" regression in 2.0. * jk/diff-tree-t-fix: intersect_paths: respect mode in git's tree-sort
2014-08-20intersect_paths: respect mode in git's tree-sortLibravatar Jeff King1-1/+11
When we do a combined diff, we individually diff against each parent, and then use intersect_paths to do a parallel walk through the sorted results and come up with a final list of interesting paths. The sort order here is that returned by the diffs, which means it is in git's tree-order which sorts sub-trees as if their paths have "/" at the end. When we do our parallel walk, we need to use a comparison function which provides the same order. Since 8518ff8 (combine-diff: optimize combine_diff_path sets intersection, 2014-01-20), we use a simple strcmp to compare the pathnames, and get this wrong. It's somewhat hard to trigger because normally a diff does not produce tree entries at all, and therefore the sort order is the same as a strcmp. However, if the "-t" option is used with the diff, then we will produce diff_filepairs for both trees and files. We can use base_name_compare to do the comparison, just as the tree-diff code does. Even though what we have are not technically base names (they are full paths within the tree), the end result is the same (we do not care about interior slashes at all, only about the final character). However, since we do not have the length of each path stored, we take a slight shortcut: if neither of the entries is a sub-tree then the comparison is equivalent to a strcmp. This lets us skip the extra strlen calls in the common case without having to reimplement base_name_compare from scratch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-30pretty: make empty userformats truly emptyLibravatar Jeff King1-1/+2
If the user provides an empty format with "--format=", we end up putting in extra whitespace that the user cannot prevent. This comes from two places: 1. If the format is missing a terminating newline, we add one automatically. This makes sense for --format=%h, but not for a truly empty format. 2. We add an extra newline between the pretty-printed format and a diff or diffstat. If the format is empty, there's no point in doing so if there's nothing to separate. With this patch, one can get a diff with no other cruft out of "diff-tree --format= $commit". Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-06-06Merge branch 'mk/show-s-no-extra-blank-line-for-merges'Libravatar Junio C Hamano1-1/+2
* mk/show-s-no-extra-blank-line-for-merges: git-show: fix 'git show -s' to not add extra terminator after merge commit
2014-05-15git-show: fix 'git show -s' to not add extra terminator after merge commitLibravatar Max Kirillov1-1/+2
When git show -s is called for merge commit it prints extra newline after any merge commit. This differs from output for commits with one parent. Fix it by more thorough checking that diff output is disabled. The code in question exists since commit 3969cf7db1. The additional newline is really needed for cases when patch is requested, test t4013-diff-various.sh contains cases which can demonstrate behavior when the condition is restricted further. Tests: Added merge commit to 'set up a bit of history' case in t7007-show.sh to cover the fix. Existing tests are updated to demonstrate the new behaviour. Earlier, the tests that used "git show -s --pretty=format:%s", even though "--pretty=format:%s" calls for item separator semantics and does not ask for the terminating newline after the last item, expected the output to end with such a newline. They were relying on the buggy behaviour. Use of "--format=%s", which is equivalent to "--pretty=tformat:%s" that asks for a terminating newline after each item, is a more realistic way to use the command. In the test 'merge log messages' the expected data is changed, because it was explicitly listing the extra newline. Also the msg.nologff and msg.nolognoff expected files are replaced by one msg.nolog, because they were diffing because of the bug, and now there should be no difference. Signed-off-by: Max Kirillov <max@max630.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-04-07combine-diff: speed it up, by using multiparent diff tree-walker directlyLibravatar Kirill Smelkov1-5/+83
As was recently shown in "combine-diff: optimize combine_diff_path sets intersection", combine-diff runs very slowly. In that commit we optimized paths sets intersection, but that accounted only for ~ 25% of the slowness, and as my tracing showed, for linux.git v3.10..v3.11, for merges a lot of time is spent computing diff(commit,commit^2) just to only then intersect that huge diff to almost small set of files from diff(commit,commit^1). In previous commit, we described the problem in more details, and reworked the diff tree-walker to be general one - i.e. to work in multiple parent case too. Now is the time to take advantage of it for finding paths for combine diff. The implementation is straightforward - if we know, we can get generated diff paths directly, and at present that means no diff filtering or rename/copy detection was requested(*), we can call multiparent tree-walker directly and get ready paths. (*) because e.g. at present, all diffcore transformations work on diff_filepair queues, but in the future, that limitation can be lifted, if filters would operate directly on combine_diff_paths. Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log") and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges") before and after the patch are as follows: linux.git v3.10..v3.11 log log -c log -c --merges before 1.9s 16.4s 15.2s after 1.9s 2.4s 1.1s The result stayed the same. Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24combine-diff: move changed-paths scanning logic into its own functionLibravatar Kirill Smelkov1-27/+53
Move code for finding paths for which diff(commit,parent_i) is not-empty for all parents to separate function - at present we have generic (and slow) code for this job, which translates 1 n-parent problem to n 1-parent problems and then intersect results, and will be adding another limited, but faster, paths scanning implementation in the next patch. Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24combine-diff: move show_log_first logic/action out of paths scanningLibravatar Kirill Smelkov1-10/+14
Judging from sample outputs and tests nothing changes in diff -c output, and this change will help later patches, when we'll be refactoring paths scanning into its own function with several variants - the show_log_first logic / code will stay common to all of them. NOTE: only now we have to take care to explicitly not show anything if parents array is empty, as in fact there are some clients in Git code, which calls diff_tree_combined() in such a way. Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24combine-diff: simplify intersect_paths() furtherLibravatar Junio C Hamano1-22/+12
Linus once said: I actually wish more people understood the really core low-level kind of coding. Not big, complex stuff like the lockless name lookup, but simply good use of pointers-to-pointers etc. For example, I've seen too many people who delete a singly-linked list entry by keeping track of the "prev" entry, and then to delete the entry, doing something like if (prev) prev->next = entry->next; else list_head = entry->next; and whenever I see code like that, I just go "This person doesn't understand pointers". And it's sadly quite common. People who understand pointers just use a "pointer to the entry pointer", and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing a "*pp = entry->next". Applying that simplification lets us lose 7 lines from this function even while adding 2 lines of comment. I was tempted to squash this into the original commit, but because the benchmarking described in the commit log is without this simplification, I decided to keep it a separate follow-up patch. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24combine-diff: combine_diff_path.len is not needed anymoreLibravatar Kirill Smelkov1-21/+9
The field was used in order to speed-up name comparison and also to mark removed paths by setting it to 0. Because the updated code does significantly less strcmp and also just removes paths from the list and free right after we know a path will not be needed, it is not needed anymore. Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24combine-diff: optimize combine_diff_path sets intersectionLibravatar Kirill Smelkov1-21/+73
When generating combined diff, for each commit, we intersect diff paths from diff(parent_0,commit) to diff(parent_i,commit) comparing all paths pairs, i.e. doing it the quadratic way. That is correct, but could be optimized. Paths come from trees in sorted (= tree) order, and so does diff_tree() emits resulting paths in that order too. Now if we look at diffcore transformations, all of them, except diffcore_order, preserve resulting path ordering: - skip_stat_unmatch, grep, pickaxe, filter -- just skip elements -> order stays preserved - break -- just breaks diff for a path, adding path dup after the path -> order stays preserved - detect rename/copy -- resulting paths are emitted sorted (verified empirically) So only diffcore_order changes diff paths ordering. But diffcore_order meaning affects only presentation - i.e. only how to show the diff, so we could do all the internal computations without paths reordering, and order only resultant paths set. This is faster, since, if we know two paths sets are all ordered, their intersection could be done in linear time. This patch does just that. Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log") and with `-c` ("git log -c") before and after the patch are as follows: linux.git v3.10..v3.11 log log -c before 1.9s 20.4s after 1.9s 16.6s navy.git (private repo) log log -c before 0.83s 15.6s after 0.83s 2.1s P.S. I think linux.git case is sped up not so much as the second one, since in navy.git, there are more exotic (subtree, etc) merges. P.P.S. My tracing showed that the rest of the time (16.6s vs 1.9s) is usually spent in computing huge diffs from commit to second parent. Will try to deal with it, if I'll have time. P.P.P.S. For combine_diff_path, ->len is not needed anymore - will remove it in the next noisy cleanup path, to maintain good signal/noise ratio here. Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-09-09Merge branch 'jl/submodule-mv'Libravatar Junio C Hamano1-2/+2
"git mv A B" when moving a submodule A does "the right thing", inclusing relocating its working tree and adjusting the paths in the .gitmodules file. * jl/submodule-mv: (53 commits) rm: delete .gitmodules entry of submodules removed from the work tree mv: update the path entry in .gitmodules for moved submodules submodule.c: add .gitmodules staging helper functions mv: move submodules using a gitfile mv: move submodules together with their work trees rm: do not set a variable twice without intermediate reading. t6131 - skip tests if on case-insensitive file system parse_pathspec: accept :(icase)path syntax pathspec: support :(glob) syntax pathspec: make --literal-pathspecs disable pathspec magic pathspec: support :(literal) syntax for noglob pathspec kill limit_pathspec_to_literal() as it's only used by parse_pathspec() parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN parse_pathspec: make sure the prefix part is wildcard-free rename field "raw" to "_raw" in struct pathspec tree-diff: remove the use of pathspec's raw[] in follow-rename codepath remove match_pathspec() in favor of match_pathspec_depth() remove init_pathspec() in favor of parse_pathspec() remove diff_tree_{setup,release}_paths convert common_prefix() to use struct pathspec ...
2013-09-09Merge branch 'tr/log-full-diff-keep-true-parents'Libravatar Junio C Hamano1-1/+2
Output from "git log --full-diff -- <pathspec>" looked strange, because comparison was done with the previous ancestor that touched the specified <pathspec>, causing the patches for paths outside the pathspec to show more than the single commit has changed. Tweak "git reflog -p" for the same reason using the same mechanism. * tr/log-full-diff-keep-true-parents: log: use true parents for diff when walking reflogs log: use true parents for diff even when rewriting
2013-08-01log: use true parents for diff even when rewritingLibravatar Thomas Rast1-1/+2
When using pathspec filtering in combination with diff-based log output, parent simplification happens before the diff is computed. The diff is therefore against the *simplified* parents. This works okay, arguably by accident, in the normal case: simplification reduces to one parent as long as the commit is TREESAME to it. So the simplified parent of any given commit must have the same tree contents on the filtered paths as its true (unfiltered) parent. However, --full-diff breaks this guarantee, and indeed gives pretty spectacular results when comparing the output of git log --graph --stat ... git log --graph --full-diff --stat ... (--graph internally kicks in parent simplification, much like --parents). To fix it, store a copy of the parent list before simplification (in a slab) whenever --full-diff is in effect. Then use the stored parents instead of the simplified ones in the commit display code paths. The latter do not actually check for --full-diff to avoid duplicated code; they just grab the original parents if save_parents() has not been called for this revision walk. For ordinary commits it should be obvious that this is the right thing to do. Merge commits are a bit subtle. Observe that with default simplification, merge simplification is an all-or-nothing decision: either the merge is TREESAME to one parent and disappears, or it is different from all parents and the parent list remains intact. Redundant parents are not pruned, so the existing code also shows them as a merge. So if we do show a merge commit, the parent list just consists of the rewrite result on each parent. Running, e.g., --cc on this in --full-diff mode is not very useful: if any commits were skipped, some hunks will disagree with all sides of the merge (with one side, because commits were skipped; with the others, because they didn't have those changes in the first place). This triggers --cc showing these hunks spuriously. Therefore I believe that even for merge commits it is better to show the diffs wrt. the original parents. Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Helped-by: Junio C Hamano <gitster@pobox.com> Helped-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Thomas Rast <trast@inf.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-29many small typofixesLibravatar Ondřej Bílka1-1/+1
Signed-off-by: Ondřej Bílka <neleai@seznam.cz> Reviewed-by: Marc Branchaud <marcnarc@xiplink.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-07-15remove diff_tree_{setup,release}_pathsLibravatar Nguyễn Thái Ngọc Duy1-2/+2
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-06-11Merge branch 'cb/log-follow-with-combined'Libravatar Junio C Hamano1-0/+3
* cb/log-follow-with-combined: fix segfault with git log -c --follow
2013-06-02Merge branch 'mk/combine-diff-context-horizon-fix'Libravatar Junio C Hamano1-2/+5
"git diff -c -p" was not showing a deleted line from a hunk when another hunk immediately begins where the earlier one ends. * mk/combine-diff-context-horizon-fix: combine-diff.c: Fix output when changes are exactly 3 lines apart
2013-05-28fix segfault with git log -c --followLibravatar Clemens Buchacher1-0/+3
In diff_tree_combined we make a copy of diffopts. In try_to_follow_renames, called via diff_tree_sha1, we free and re-initialize diffopts->pathspec->items. Since we did not make a deep copy of diffopts in diff_tree_combined, the original diffopts does not get the update. By the time we return from diff_tree_combined, rev->diffopt->pathspec->items points to an invalid memory address. We get a segfault next time we try to access that pathspec. Instead, along with the copy of diffopts, make a copy pathspec->items as well. We would also have to make a copy of pathspec->raw to keep it consistent with pathspec->items, but nobody seems to rely on that. Signed-off-by: Clemens Buchacher <drizzd@aon.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-05-15combine-diff.c: Fix output when changes are exactly 3 lines apartLibravatar Matthijs Kooijman1-2/+5
When a deletion is followed by exactly 3 (or whatever the number of context lines) unchanged lines, followed by another change, the combined diff output would hide the first deletion, resulting in a malformed diff. This happened because the 3 lines before each change are painted interesting, but also marked as no_pre_delete to prevent showing deletes that were previously marked as uninteresting. This behaviour was introduced in c86fbe53 (diff -c/--cc: do not include uninteresting deletion before leading context). However, as a side effect, this could also mark deletes that were already interesting as no_pre_delete. This would happen only if the delete was exactly 3 lines away from the next change, since lines farther away would not be touched by the "paint three lines before the change" code and lines closer would be painted by the "merge two adjacent hunks" code instead, which does not set the no_pre_delete flag. This commit fixes this problem by only setting the no_pre_delete flag for changes that were previously uninteresting. Signed-off-by: Matthijs Kooijman <matthijs@stdin.nl> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-25combine-diff: coalesce lost lines optimallyLibravatar Antoine Pelisse1-64/+191
This replaces the greedy implementation to coalesce lost lines by using dynamic programming to find the Longest Common Subsequence. The O(n²) time complexity is obviously bigger than previous implementation but it can produce shorter diff results (and most likely easier to read). List of lost lines is now doubly-linked because we reverse-read it when reading the direction matrix. Signed-off-by: Antoine Pelisse <apelisse@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-03-14Allow combined diff to ignore white-spacesLibravatar Antoine Pelisse1-7/+50
The combined diff --cc output does not honor options to ignore whitespace changes (-b, -w, and --ignore-space-at-eol). Correct this by passing diff flags to diff engine, so that combined diff behaves as normal diff does with spaces, and by coalescing lines that are removed from both (or more) parents, honoring the same rule to ignore whitespace changes. With this change, a conflict-less merge done using a ignore-* strategy option will not show any conflict if shown in combined-diff using the same option. Signed-off-by: Antoine Pelisse <apelisse@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-02-14Merge branch 'jk/diff-graph-cleanup'Libravatar Junio C Hamano1-17/+32
Refactors a lot of repetitive code sequence from the graph drawing code and adds it to the combined diff output. * jk/diff-graph-cleanup: combine-diff.c: teach combined diffs about line prefix diff.c: use diff_line_prefix() where applicable diff: add diff_line_prefix function diff.c: make constant string arguments const diff: write prefix to the correct file graph: output padding for merge subsequent parents
2013-02-12combine-diff.c: teach combined diffs about line prefixLibravatar John Keeping1-17/+30
When running "git log --graph --cc -p" the diff output for merges is not indented by the graph structure, unlike the diffs of non-merge commits (added in commit 7be5761 - diff.c: Output the text graph padding before each diff line). Fix this by teaching the combined diff code to output diff_line_prefix() before each line. Signed-off-by: John Keeping <john@keeping.me.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-02-03combine-diff: lift 32-way limit of combined diffLibravatar Junio C Hamano1-14/+7
The "raw" format of combine-diff output is supposed to have as many colons as there are parents at the beginning, then blob modes for these parents, and then object names for these parents. We weren't however prepared to handle a more than 32-way merge and did not show the correct number of colons in such a case. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-09-10Merge branch 'jk/maint-null-in-trees' into maint-1.7.11Libravatar Junio C Hamano1-2/+2
"git diff" had a confusion between taking data from a path in the working tree and taking data from an object that happens to have name 0{40} recorded in a tree. * jk/maint-null-in-trees: fsck: detect null sha1 in tree entries do not write null sha1s to on-disk index diff: do not use null sha1 as a sentinel value
2012-08-27Merge branch 'jk/maint-null-in-trees'Libravatar Junio C Hamano1-2/+2
We do not want a link to 0{40} object stored anywhere in our objects. * jk/maint-null-in-trees: fsck: detect null sha1 in tree entries do not write null sha1s to on-disk index diff: do not use null sha1 as a sentinel value
2012-07-29diff: do not use null sha1 as a sentinel valueLibravatar Jeff King1-2/+2
The diff code represents paths using the diff_filespec struct. This struct has a sha1 to represent the sha1 of the content at that path, as well as a sha1_valid member which indicates whether its sha1 field is actually useful. If sha1_valid is not true, then the filespec represents a working tree file (e.g., for the no-index case, or for when the index is not up-to-date). The diff_filespec is only used internally, though. At the interfaces to the diff subsystem, callers feed the sha1 directly, and we create a diff_filespec from it. It's at that point that we look at the sha1 and decide whether it is valid or not; callers may pass the null sha1 as a sentinel value to indicate that it is not. We should not typically see the null sha1 coming from any other source (e.g., in the index itself, or from a tree). However, a corrupt tree might have a null sha1, which would cause "diff --patch" to accidentally diff the working tree version of a file instead of treating it as a blob. This patch extends the edges of the diff interface to accept a "sha1_valid" flag whenever we accept a sha1, and to use that flag when creating a filespec. In some cases, this means passing the flag through several layers, making the code change larger than would be desirable. One alternative would be to simply die() upon seeing corrupted trees with null sha1s. However, this fix more directly addresses the problem (while bogus sha1s in a tree are probably a bad thing, it is really the sentinel confusion sending us down the wrong code path that is what makes it devastating). And it means that git is more capable of examining and debugging these corrupted trees. For example, you can still "diff --raw" such a tree to find out when the bogus entry was introduced; you just cannot do a "--patch" diff (just as you could not with any other corrupted tree, as we do not have any content to diff). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-16Merge branch 'rs/combine-diff-zero-context-at-the-beginning'Libravatar Junio C Hamano1-1/+1
Fixes an age old corner case bug in combine diff (only triggered with -U0 and the hunk at the beginning of the file needs to be shown). By René Scharfe * rs/combine-diff-zero-context-at-the-beginning: combine-diff: fix loop index underflow
2012-03-25combine-diff: fix loop index underflowLibravatar René Scharfe1-1/+1
If both la and context are zero at the start of the loop, la wraps around and we end up reading from memory far away. Skip the loop in that case instead. Reported-by: Julia Lawall <julia.lawall@lip6.fr> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-17pass struct commit to diff_tree_combined_merge()Libravatar René Scharfe1-4/+3
Instead of passing the hash of a commit and then searching that same commit in the single caller, simply pass the commit directly. Signed-off-by: René Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-12-17use struct sha1_array in diff_tree_combined()Libravatar René Scharfe1-21/+13
Maintaining an array of hashes is easier using sha1_array than open-coding it. This patch also fixes a leak of the SHA1 array in diff_tree_combined_merge(). Signed-off-by: René Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-28Merge branch 'jk/color-and-pager'Libravatar Junio C Hamano1-4/+3
* jk/color-and-pager: want_color: automatically fallback to color.ui diff: don't load color config in plumbing config: refactor get_colorbool function color: delay auto-color decision until point of use git_config_colorbool: refactor stdout_is_tty handling diff: refactor COLOR_DIFF from a flag into an int setup_pager: set GIT_PAGER_IN_USE t7006: use test_config helpers test-lib: add helper functions for config t7006: modernize calls to unset Conflicts: builtin/commit.c parse-options.c
2011-08-28Merge branch 'jc/combine-diff-callback'Libravatar Junio C Hamano1-0/+69
* jc/combine-diff-callback: combine-diff: support format_callback
2011-08-20combine-diff: support format_callbackLibravatar Junio C Hamano1-0/+69
This teaches combine-diff machinery to feed a combined merge to a callback function when DIFF_FORMAT_CALLBACK is specified. So far, format callback functions are not used for anything but 2-way diffs. A callback is given a diff_queue_struct, which is an array of diff_filepair. As its name suggests, a diff_filepair is a _pair_ of diff_filespec that represents a single preimage and a single postimage. Since "diff -c" is to compare N parents with a single merge result and filter out any paths whose result match one (or more) of the parent(s), its output has to be able to represent N preimages and 1 postimage. For this reason, a callback function that inspects a diff_filepair that results from this new infrastructure can and is expected to view the preimage side (i.e. pair->one) as an array of diff_filespec. Each element in the array, except for the last one, is marked with "has_more_entries" bit, so that the same callback function can be used for 2-way diffs and combined diffs. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-18diff: refactor COLOR_DIFF from a flag into an intLibravatar Jeff King1-4/+3
This lets us store more than just a bit flag for whether we want color; we can also store whether we want automatic colors. This can be useful for making the automatic-color decision closer to the point of use. This mostly just involves replacing DIFF_OPT_* calls with manipulations of the flag. The biggest exception is that calls to DIFF_OPT_TST must check for "o->use_color > 0", which lets an "unknown" value (i.e., the default) stay at "no color". In the previous code, a value of "-1" was not propagated at all. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-17Merge branch 'jc/maint-combined-diff-work-tree'Libravatar Junio C Hamano1-4/+10
* jc/maint-combined-diff-work-tree: diff -c/--cc: do not mistake "resolved as deletion" as "use working tree" Conflicts: combine-diff.c
2011-08-04diff -c/--cc: do not mistake "resolved as deletion" as "use working tree"Libravatar Junio C Hamano1-4/+10
The combined diff machinery can be used to compare: - a merge commit with its parent commits; - a working-tree file with multiple stages in an unmerged index; or - a working-tree file with the HEAD and the index. The internal function combine-diff.c:show_patch_diff() checked if it needs to read the "result" from the working tree by looking at the object name of the result --- if it is null_sha1, it read from the working tree. This mistook a merge that records a deletion as the conflict resolution as if it is a cue to read from the working tree. Pass this information explicitly from the caller instead. Noticed and reported by Johan Herland. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-24combine-diff: respect textconv attributesLibravatar Jeff King1-9/+32
When doing a combined diff, we did not respect textconv attributes at all. This generally lead to us printing "Binary files differ" when we could show a combined diff of the converted text. This patch converts file contents according to textconv attributes. The implementation is slightly ugly; because the textconv code is tightly linked with the diff_filespec code, we temporarily create a diff_filespec during conversion. In practice, though, this should not create a performance problem. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-23combine-diff: handle binary files as binaryLibravatar Jeff King1-2/+35
The combined diff code path is totally different from the regular diff code path, and didn't handle binary files at all. The results of a combined diff on a binary file could range from annoying (since we spewed binary garbage, possibly upsetting the user's terminal), to wrong (embedded NULs caused us to show incorrect diffs, with lines truncated at the NUL character), to potential security problems (embedded NULs could interfere with "-z" output, possibly defeating policy hooks which parse diff output). Instead, we consider a combined diff to be binary if any of the input blobs is binary. To show a binary combined diff, we indicate "Binary blobs differ"; the "index" meta line will show which parents had which blob. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-23combine-diff: calculate mode_differs earlierLibravatar Jeff King1-2/+7
One loop combined both the patch generation and checking whether there was any mode change to report. Let's factor that into two separate loops, as we may care about the mode change even if we are not generating patches (e.g., because we are showing a binary diff, which will come in a future patch). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-05-23combine-diff: split header printing into its own functionLibravatar Jeff King1-61/+74
This is a pretty big logical chunk, so it makes the function a bit more readable to have it split out. In addition, it will make it easier to add an alternate code path for binary diffs in a future patch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-06-21Merge branch 'rs/diff-no-minimal' into maintLibravatar Junio C Hamano1-1/+1
* rs/diff-no-minimal: git diff too slow for a file
2010-06-13Merge branch 'rs/diff-no-minimal'Libravatar Junio C Hamano1-1/+1
* rs/diff-no-minimal: git diff too slow for a file
2010-05-04remove ecb parameter from xdi_diff_outf()Libravatar René Scharfe1-2/+1
xdi_diff_outf() overrides the structure members of its last parameter, ignoring any value that callers pass in. It's no surprise then that all callers pass a pointer to an uninitialized structure. They also don't read it after the call, so the parameter is neither used for input nor for output. Turn it into a local variable of xdi_diff_outf(). Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Acked-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-05-02git diff too slow for a fileLibravatar René Scharfe1-1/+1
Ever since the xdiff library had been introduced to git, all its callers have used the flag XDF_NEED_MINIMAL. It makes sure that the smallest possible diff is produced, but that takes quite some time if there are lots of differences that can be expressed in multiple ways. This flag makes a difference for only 0.1% of the non-merge commits in the git repo of Linux, both in terms of diff size and execution time. The patches there are mostly nice and small. SungHyun Nam however reported a case in a different repo where a diff took more than 20 times longer to generate with XDF_NEED_MINIMAL than without. Rebasing became really slow. This patch removes this flag from all callers. The default of xdiff is saner because it has minimal to no impact in the normal case of small diffs and doesn't incur that much of a speed penalty for large ones. A follow-up patch may introduce a command line option to set the flag if the user needs it, similar to GNU diff's -d/--minimal. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-17combined diff: correctly handle truncated fileLibravatar Thomas Rast1-6/+8
Consider an evil merge of two commits A and B, both of which have a file 'foo', but the merge result does not have that file. The combined-diff code learned in 4462731 (combine-diff: do not punt on removed or added files., 2006-02-06) to concisely show only the removal, since that is the evil part and the previous contents are presumably uninteresting. However, to diagnose an empty merge result, it overloaded the variable that holds the file's length. This means that the check also triggers for truncated files. Consequently, such files were not shown in the diff at all despite the merge being clearly evil. Fix this by adding a new variable that distinguishes whether the file was deleted (which is the case 4462731 handled) or truncated. In the truncated case, we show the full combined diff again, which is rather spammy but at least does not hide the evilness. Reported-by: David Martínez Martí <desarrollo@gestiweb.com> Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-11-28Give the hunk comment its own colorLibravatar Bert Wesarg1-1/+4
Inspired by the coloring of quilt. Introduce a separate color and paint the hunk comment part, i.e. the name of the function, in a separate color "diff.func" (defaults to plain). Whitespace between hunk header and hunk comment is printed in plain color. Signed-off-by: Bert Wesarg <bert.wesarg@googlemail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>