mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 08:11:58 +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_INCLUDE_UNMODIFIED = (1 << 9),
|
||||||
GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10),
|
GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10),
|
||||||
GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11),
|
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 */
|
/* check if contained in ignored parent directory */
|
||||||
if (git_buf_len(&ignore_prefix) &&
|
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;
|
delta_type = GIT_DELTA_IGNORED;
|
||||||
|
|
||||||
if (S_ISDIR(nitem->mode)) {
|
if (S_ISDIR(nitem->mode)) {
|
||||||
@ -677,10 +678,23 @@ static int diff_from_iterators(
|
|||||||
* it or if the user requested the contents of untracked
|
* it or if the user requested the contents of untracked
|
||||||
* directories and it is not under an ignored directory.
|
* 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 &&
|
(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
|
/* if this directory is ignored, remember it as the
|
||||||
* "ignore_prefix" for processing contained items
|
* "ignore_prefix" for processing contained items
|
||||||
*/
|
*/
|
||||||
|
@ -321,6 +321,9 @@ static int get_workdir_content(
|
|||||||
if (file->mode == GIT_FILEMODE_COMMIT)
|
if (file->mode == GIT_FILEMODE_COMMIT)
|
||||||
return get_workdir_sm_content(ctxt, file, map);
|
return get_workdir_sm_content(ctxt, file, map);
|
||||||
|
|
||||||
|
if (S_ISDIR(file->mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (git_buf_joinpath(&path, wd, file->path) < 0)
|
if (git_buf_joinpath(&path, wd, file->path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -535,6 +538,11 @@ static int diff_patch_load(
|
|||||||
break;
|
break;
|
||||||
case GIT_DELTA_MODIFIED:
|
case GIT_DELTA_MODIFIED:
|
||||||
break;
|
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:
|
default:
|
||||||
delta->new_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
delta->new_file.flags |= GIT_DIFF_FILE_NO_DATA;
|
||||||
delta->old_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);
|
GIT_UNUSED(progress);
|
||||||
|
|
||||||
|
if (S_ISDIR(delta->new_file.mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!oldpfx)
|
if (!oldpfx)
|
||||||
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
|
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
|
||||||
|
|
||||||
@ -1134,6 +1145,9 @@ static int print_patch_hunk(
|
|||||||
{
|
{
|
||||||
diff_print_info *pi = data;
|
diff_print_info *pi = data;
|
||||||
|
|
||||||
|
if (S_ISDIR(d->new_file.mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
git_buf_clear(pi->buf);
|
git_buf_clear(pi->buf);
|
||||||
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
|
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -1158,6 +1172,9 @@ static int print_patch_line(
|
|||||||
{
|
{
|
||||||
diff_print_info *pi = data;
|
diff_print_info *pi = data;
|
||||||
|
|
||||||
|
if (S_ISDIR(delta->new_file.mode))
|
||||||
|
return 0;
|
||||||
|
|
||||||
git_buf_clear(pi->buf);
|
git_buf_clear(pi->buf);
|
||||||
|
|
||||||
if (line_origin == GIT_DIFF_LINE_ADDITION ||
|
if (line_origin == GIT_DIFF_LINE_ADDITION ||
|
||||||
|
@ -905,3 +905,15 @@ int git_iterator_cmp(
|
|||||||
return ITERATOR_PREFIXCMP(*iter, entry->path, path_prefix);
|
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 "common.h"
|
||||||
#include "git2/index.h"
|
#include "git2/index.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER).ignore_case) ? \
|
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER).ignore_case) ? \
|
||||||
git__prefixcmp_icase((STR), (PREFIX)) : \
|
git__prefixcmp_icase((STR), (PREFIX)) : \
|
||||||
@ -166,4 +167,11 @@ extern int git_iterator_advance_into_directory(
|
|||||||
extern int git_iterator_cmp(
|
extern int git_iterator_cmp(
|
||||||
git_iterator *iter, const char *path_prefix);
|
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
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user