summaryrefslogtreecommitdiff
path: root/src/diff.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-10-08 15:14:12 -0700
committerRussell Belfer <rb@github.com>2012-10-08 15:22:40 -0700
commitdfbff793b8f39995d3a8744d6b7d75d5cc7201a0 (patch)
tree0ffa00f2e946fc65596b08b6064ac2fee25a0963 /src/diff.c
parent543864b677704845660085d2b2b2249cabb084a4 (diff)
downloadlibgit2-dfbff793b8f39995d3a8744d6b7d75d5cc7201a0.tar.gz
Fix a few diff bugs with directory content
There are a few cases where diff should leave directories in the diff list if we want to match core git, such as when the directory contains a .git dir. That feature was lost when I introduced some of the new submodule handling. This restores that and then fixes a couple of related to diff output that are triggered by having diffs with directories in them. Also, this adds a new flag that can be passed to diff if you want diff output to actually include the file content of any untracked files.
Diffstat (limited to 'src/diff.c')
-rw-r--r--src/diff.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/diff.c b/src/diff.c
index 7a0051ae3..8718e5ada 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -669,7 +669,8 @@ static int diff_from_iterators(
/* check if contained in ignored parent directory */
if (git_buf_len(&ignore_prefix) &&
- ITERATOR_PREFIXCMP(*old_iter, nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
+ ITERATOR_PREFIXCMP(*old_iter, nitem->path,
+ git_buf_cstr(&ignore_prefix)) == 0)
delta_type = GIT_DELTA_IGNORED;
if (S_ISDIR(nitem->mode)) {
@@ -677,10 +678,23 @@ static int diff_from_iterators(
* it or if the user requested the contents of untracked
* directories and it is not under an ignored directory.
*/
- if ((oitem && ITERATOR_PREFIXCMP(*old_iter, oitem->path, nitem->path) == 0) ||
+ bool contains_tracked =
+ (oitem &&
+ !ITERATOR_PREFIXCMP(*old_iter, oitem->path, nitem->path));
+ bool recurse_untracked =
(delta_type == GIT_DELTA_UNTRACKED &&
- (diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0))
- {
+ (diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0);
+
+ /* do not advance into directories that contain a .git file */
+ if (!contains_tracked && recurse_untracked) {
+ git_buf *full = NULL;
+ if (git_iterator_current_workdir_path(new_iter, &full) < 0)
+ goto fail;
+ if (git_path_contains_dir(full, DOT_GIT))
+ recurse_untracked = false;
+ }
+
+ if (contains_tracked || recurse_untracked) {
/* if this directory is ignored, remember it as the
* "ignore_prefix" for processing contained items
*/