Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 43 additions & 25 deletions src/filterdiff.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ static int
do_git_diff_no_hunks (FILE *f, char **header, unsigned int num_headers,
int match, char **line, size_t *linelen,
unsigned long *linenum, unsigned long start_linenum,
char status, const char *bestname, const char *patchname,
char *status, const char *bestname, const char *patchname,
int *orig_file_exists, int *new_file_exists,
enum git_diff_type git_type)
{
Expand All @@ -386,6 +386,16 @@ do_git_diff_no_hunks (FILE *f, char **header, unsigned int num_headers,
break;
}

/* Update status based on file existence (do this early so returns below have correct status) */
if (status != NULL && mode != mode_filter && show_status &&
orig_file_exists != NULL && new_file_exists != NULL) {
if (!*orig_file_exists)
*status = '+';
else if (!*new_file_exists)
*status = '-';
/* else: keep existing '!' value for modifications */
}

/* If this diff matches the filter, display it */
if (match) {
if (mode == mode_filter) {
Expand All @@ -394,7 +404,7 @@ do_git_diff_no_hunks (FILE *f, char **header, unsigned int num_headers,
fputs (header[i], stdout);
} else if (mode == mode_list && !displayed_filename) {
if (!show_status) {
display_filename (start_linenum, status,
display_filename (start_linenum, *status,
bestname, patchname);
}
displayed_filename = 1;
Expand Down Expand Up @@ -455,7 +465,7 @@ static int
do_unified (FILE *f, char **header, unsigned int num_headers,
int match, char **line,
size_t *linelen, unsigned long *linenum,
unsigned long start_linenum, char status,
unsigned long start_linenum, char *status,
const char *bestname, const char *patchname,
int *orig_file_exists, int *new_file_exists)
{
Expand Down Expand Up @@ -671,7 +681,7 @@ do_unified (FILE *f, char **header, unsigned int num_headers,
if (!displayed_filename) {
displayed_filename = 1;
display_filename (start_linenum,
status, bestname,
*status, bestname,
patchname);
}

Expand Down Expand Up @@ -746,14 +756,24 @@ do_unified (FILE *f, char **header, unsigned int num_headers,
*new_file_exists = 0;
}

/* Update status based on final file existence after empty file processing */
if (status != NULL && mode != mode_filter && show_status &&
orig_file_exists != NULL && new_file_exists != NULL) {
if (!*orig_file_exists)
*status = '+';
else if (!*new_file_exists)
*status = '-';
/* else: keep existing '!' value for modifications */
}

return ret;
}

static int
do_context (FILE *f, char **header, unsigned int num_headers,
int match, char **line,
size_t *linelen, unsigned long *linenum,
unsigned long start_linenum, char status,
unsigned long start_linenum, char *status,
const char *bestname, const char *patchname,
int *orig_file_exists, int *new_file_exists)
{
Expand Down Expand Up @@ -1020,7 +1040,7 @@ do_context (FILE *f, char **header, unsigned int num_headers,
if (!displayed_filename) {
displayed_filename = 1;
display_filename(start_linenum,
status,
*status,
bestname,
patchname);
}
Expand Down Expand Up @@ -1150,6 +1170,16 @@ do_context (FILE *f, char **header, unsigned int num_headers,
*new_file_exists = 0;
}

/* Update status based on final file existence after empty file processing */
if (status != NULL && mode != mode_filter && show_status &&
orig_file_exists != NULL && new_file_exists != NULL) {
if (!*orig_file_exists)
*status = '+';
else if (!*new_file_exists)
*status = '-';
/* else: keep existing '!' value for modifications */
}

return ret;
}

Expand Down Expand Up @@ -1180,7 +1210,7 @@ static int filterdiff (FILE *f, const char *patchname)
int (*do_diff) (FILE *, char **, unsigned int,
int, char **, size_t *,
unsigned long *, unsigned long,
char, const char *, const char *,
char *, const char *, const char *,
int *, int *);

orig_file_exists = 0; // shut gcc up
Expand Down Expand Up @@ -1375,19 +1405,13 @@ static int filterdiff (FILE *f, const char *patchname)
/* Process the git diff (it will handle filename display) */
result = do_git_diff_no_hunks (f, header, num_headers,
match, &line, &linelen, &linenum,
start_linenum, status, p, patchname,
start_linenum, &status, p, patchname,
&orig_file_exists, &new_file_exists,
git_type);

/* Print filename with status if in list mode and matches */
if (match && show_status && mode == mode_list) {
if (!orig_file_exists)
status = '+';
else if (!new_file_exists)
status = '-';

if (match && show_status && mode == mode_list)
display_filename (start_linenum, status, p, patchname);
}

/* Clean up */
free (git_old_name);
Expand Down Expand Up @@ -1476,19 +1500,13 @@ static int filterdiff (FILE *f, const char *patchname)
result = do_diff (f, header, num_headers,
match, &line,
&linelen, &linenum,
start_linenum, status, p, patchname,
start_linenum, &status, p, patchname,
&orig_file_exists, &new_file_exists);

// print if it matches.
if (match && show_status && mode == mode_list) {
if (!orig_file_exists)
status = '+';
else if (!new_file_exists)
status = '-';

if (match && show_status && mode == mode_list)
display_filename (start_linenum, status,
p, patchname);
}

switch (result) {
case EOF:
Expand Down Expand Up @@ -1587,8 +1605,8 @@ const char * syntax_str =
" prefix pathnames in old files with PREFIX\n"
" --addnewprefix=PREFIX\n"
" prefix pathnames in new files with PREFIX\n"
" -s, --status (lsdiff)\n"
" show file additions and removals (lsdiff)\n"
" -s, --status (lsdiff, grepdiff)\n"
" show file additions (+), removals (-), and modifications (!) (lsdiff, grepdiff)\n"
" -v, --verbose\n"
" verbose output -- use more than once for extra verbosity\n"
" -E, --extended-regexp (grepdiff)\n"
Expand Down
69 changes: 69 additions & 0 deletions tests/grepdiff-status/run-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh

# Test grepdiff -s/--status option
# According to the documentation, -s should show:
# + for file additions
# - for file removals
# ! for file modifications

. ${top_srcdir-.}/tests/common.sh

cat << EOF > diff
--- /dev/null
+++ newfile
@@ -0,0 +1 @@
+content
--- oldfile
+++ /dev/null
@@ -1 +0,0 @@
-content
--- modified
+++ modified
@@ -1 +1 @@
-old
+new
--- another-modified
+++ another-modified
@@ -1,2 +1,2 @@
context
-old content
+new content
EOF

# Test additions and deletions (files with 'content' pattern)
${GREPDIFF} -s 'content' diff 2>errors >output || exit 1
[ -s errors ] && exit 1

cat << EOF | cmp - output || exit 1
+ newfile
- oldfile
! another-modified
EOF

# Test modification only (file with 'new' pattern)
${GREPDIFF} -s 'new' diff 2>errors >output2 || exit 1
[ -s errors ] && exit 1

cat << EOF | cmp - output2 || exit 1
! modified
! another-modified
EOF

# Test with --empty-files-as-absent
# File with only additions should be treated as new file
cat << EOF > diff3
--- emptyfile
+++ emptyfile
@@ -0,0 +1 @@
+content
@@ -60 +60 @@
-old
+new
EOF

${GREPDIFF} -s --empty-files-as-absent 'content' diff3 2>errors >output3 || exit 1
[ -s errors ] && exit 1

cat << EOF | cmp - output3 || exit 1
+ emptyfile
EOF