mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 02:16:21 +00:00
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.
This commit is contained in:
parent
543864b677
commit
dfbff793b8
@ -47,7 +47,8 @@ enum {
|
||||
GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9),
|
||||
GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10),
|
||||
GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11),
|
||||
GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12)
|
||||
GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12),
|
||||
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT = (1 << 13),
|
||||
};
|
||||
|
||||
/**
|
||||
|
22
src/diff.c
22
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
|
||||
*/
|
||||
|
@ -321,6 +321,9 @@ static int get_workdir_content(
|
||||
if (file->mode == GIT_FILEMODE_COMMIT)
|
||||
return get_workdir_sm_content(ctxt, file, map);
|
||||
|
||||
if (S_ISDIR(file->mode))
|
||||
return 0;
|
||||
|
||||
if (git_buf_joinpath(&path, wd, file->path) < 0)
|
||||
return -1;
|
||||
|
||||
@ -535,6 +538,11 @@ static int diff_patch_load(
|
||||
break;
|
||||
case GIT_DELTA_MODIFIED:
|
||||
break;
|
||||
case GIT_DELTA_UNTRACKED:
|
||||
delta->old_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
||||
if ((ctxt->opts->flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0)
|
||||
delta->new_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
||||
break;
|
||||
default:
|
||||
delta->new_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
||||
delta->old_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
||||
@ -1070,6 +1078,9 @@ static int print_patch_file(
|
||||
|
||||
GIT_UNUSED(progress);
|
||||
|
||||
if (S_ISDIR(delta->new_file.mode))
|
||||
return 0;
|
||||
|
||||
if (!oldpfx)
|
||||
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
|
||||
|
||||
@ -1134,6 +1145,9 @@ static int print_patch_hunk(
|
||||
{
|
||||
diff_print_info *pi = data;
|
||||
|
||||
if (S_ISDIR(d->new_file.mode))
|
||||
return 0;
|
||||
|
||||
git_buf_clear(pi->buf);
|
||||
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
|
||||
return -1;
|
||||
@ -1158,6 +1172,9 @@ static int print_patch_line(
|
||||
{
|
||||
diff_print_info *pi = data;
|
||||
|
||||
if (S_ISDIR(delta->new_file.mode))
|
||||
return 0;
|
||||
|
||||
git_buf_clear(pi->buf);
|
||||
|
||||
if (line_origin == GIT_DIFF_LINE_ADDITION ||
|
||||
|
@ -905,3 +905,15 @@ int git_iterator_cmp(
|
||||
return ITERATOR_PREFIXCMP(*iter, entry->path, path_prefix);
|
||||
}
|
||||
|
||||
int git_iterator_current_workdir_path(git_iterator *iter, git_buf **path)
|
||||
{
|
||||
workdir_iterator *wi = (workdir_iterator *)iter;
|
||||
|
||||
if (iter->type != GIT_ITERATOR_WORKDIR || !wi->entry.path)
|
||||
*path = NULL;
|
||||
else
|
||||
*path = &wi->path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common.h"
|
||||
#include "git2/index.h"
|
||||
#include "vector.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER).ignore_case) ? \
|
||||
git__prefixcmp_icase((STR), (PREFIX)) : \
|
||||
@ -166,4 +167,11 @@ extern int git_iterator_advance_into_directory(
|
||||
extern int git_iterator_cmp(
|
||||
git_iterator *iter, const char *path_prefix);
|
||||
|
||||
/**
|
||||
* Get the full path of the current item from a workdir iterator.
|
||||
* This will return NULL for a non-workdir iterator.
|
||||
*/
|
||||
extern int git_iterator_current_workdir_path(
|
||||
git_iterator *iter, git_buf **path);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user