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
4 changes: 2 additions & 2 deletions bash-completion-patchutils
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ _patchutils_common_opts() {
}

_patchutils_filter_opts() {
echo "--exclude -x --exclude-from-file -X --include -i --include-from-file -I --hunks -# --lines --files -F --annotate --as-numbered-lines --format --remove-timestamps --clean --decompress -z --strip-match -p --strip --addprefix --addoldprefix --addnewprefix"
echo "--exclude -x --exclude-from-file -X --include -i --include-from-file -I --hunks -# --lines --files -F --annotate --as-numbered-lines --format --remove-timestamps --clean --in-place --decompress -z --strip-match -p --strip --addprefix --addoldprefix --addnewprefix"
}

_patchutils_list_opts() {
Expand Down Expand Up @@ -214,7 +214,7 @@ _rediff() {
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"

opts="--help --version"
opts="--help --version --in-place"

if [[ ${cur} == -* ]]; then
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
Expand Down
21 changes: 21 additions & 0 deletions doc/patchutils.xml
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@
<arg>--verbose</arg>
</group>
<arg choice="opt">--clean</arg>
<arg choice="opt">--in-place</arg>
<group choice="opt">
<arg>-z</arg>
<arg>--decompress</arg>
Expand Down Expand Up @@ -925,6 +926,15 @@
</listitem>
</varlistentry>

<varlistentry>
<term><option>--in-place</option></term>
<listitem>
<para>Write output to the original input files instead of
standard output. This allows filtering multiple patch files
without manual redirection loops.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>-z</option>, <option>--decompress</option></term>
<listitem>
Expand Down Expand Up @@ -2009,12 +2019,14 @@ will pipe patch of file #2 to vim - -R
<refsynopsisdiv>
<cmdsynopsis>
<command>rediff</command>
<arg choice="opt">--in-place</arg>
<arg choice="plain"><replaceable>ORIGINAL</replaceable></arg>
<arg choice="plain"><replaceable>EDITED</replaceable></arg>
</cmdsynopsis>

<cmdsynopsis>
<command>rediff</command>
<arg choice="opt">--in-place</arg>
<arg choice="plain"><replaceable>EDITED</replaceable></arg>
</cmdsynopsis>

Expand Down Expand Up @@ -2097,6 +2109,15 @@ will pipe patch of file #2 to vim - -R

<variablelist>

<varlistentry>
<term><option>--in-place</option></term>
<listitem>
<para>Write output to the original edited file instead of
standard output. When used with two arguments, the result
is written back to the EDITED file.</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>--help</option></term>
<listitem>
Expand Down
46 changes: 43 additions & 3 deletions src/filterdiff.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ file_matches (void)
{
int f = 0;
struct range *r;

// See if the file range list includes this file. -1UL is a
// wildcard.
for (r = files; r; r = r->next)
Expand Down Expand Up @@ -1231,6 +1231,8 @@ const char * syntax_str =
" don't show timestamps from output (filterdiff, patchview, grepdiff)\n"
" --clean (filterdiff)\n"
" remove all comments (non-diff lines) from output (filterdiff)\n"
" --in-place (filterdiff)\n"
" write output to the original input files (filterdiff)\n"
" -z, --decompress\n"
" decompress .gz and .bz2 files\n"
" -n, --line-number (lsdiff, grepdiff)\n"
Expand Down Expand Up @@ -1454,6 +1456,7 @@ int main (int argc, char *argv[])
char format = '\0';
int regex_file_specified = 0;
int have_switches = 0;
int inplace_mode = 0;

setlocale (LC_TIME, "C");
determine_mode_from_name (argv[0]);
Expand Down Expand Up @@ -1495,14 +1498,15 @@ int main (int argc, char *argv[])
{"extended-regexp", 0, 0, 'E'},
{"empty-files-as-removed", 0, 0, 'E'},
{"file", 1, 0, 'f'},
{"in-place", 0, 0, 1000 + 'w'},
{0, 0, 0, 0}
};
char *end;
int c = getopt_long (argc, argv, "vp:i:I:x:X:zns#:F:Ef:HhN",
long_options, NULL);
if (c == -1)
break;

have_switches = 1;
switch (c) {
case 'g':
Expand Down Expand Up @@ -1665,6 +1669,9 @@ int main (int argc, char *argv[])
case 1000 + 'c':
clean_comments = 1;
break;
case 1000 + 'w':
inplace_mode = 1;
break;
default:
syntax(1);
}
Expand Down Expand Up @@ -1708,6 +1715,14 @@ int main (int argc, char *argv[])
error (EXIT_FAILURE, 0, "can't use --verbose and "
"--clean options simultaneously");

if (inplace_mode && unzip)
error (EXIT_FAILURE, 0,
"--in-place and --decompress are mutually exclusive");

if (inplace_mode && mode != mode_filter)
error (EXIT_FAILURE, 0,
"--in-place only applies to filter mode");

if (mode == mode_grep && !regex_file_specified) {
int err;

Expand Down Expand Up @@ -1739,6 +1754,10 @@ int main (int argc, char *argv[])
print_patchnames = 0;
}

if (inplace_mode && optind == argc)
error (EXIT_FAILURE, 0,
"--in-place cannot be used with standard input");

if (optind == argc) {
f = convert_format (stdin, format);
filterdiff (f, "(standard input)");
Expand All @@ -1752,7 +1771,28 @@ int main (int argc, char *argv[])
}

f = convert_format (f, format);
filterdiff (f, argv[i]);

if (inplace_mode) {
/* Redirect stdout to temporary file for in-place processing */
FILE *temp_output = xtmpfile();
FILE *old_stdout = stdout;
stdout = temp_output;

filterdiff (f, argv[i]);

/* Restore stdout */
stdout = old_stdout;

/* Write temp file contents back to original file */
if (write_file_inplace(argv[i], temp_output) != 0) {
error (EXIT_FAILURE, errno, "failed to write %s", argv[i]);
}

fclose (temp_output);
} else {
filterdiff (f, argv[i]);
}

fclose (f);
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/interdiff.c
Original file line number Diff line number Diff line change
Expand Up @@ -2095,13 +2095,13 @@ interdiff (FILE *p1, FILE *p2, const char *patch1, const char *patch2)
rewind (flip2);

if (flipdiff_inplace) {
FILE *pp1 = xopen (patch1, "wb");
FILE *pp2 = xopen (patch2, "wb");

copy (flip1, pp2);
copy (flip2, pp1);
fclose (pp1);
fclose (pp2);
/* Use atomic in-place writing for safety */
if (write_file_inplace(patch2, flip1) != 0) {
error (EXIT_FAILURE, errno, "failed to write %s", patch2);
}
if (write_file_inplace(patch1, flip2) != 0) {
error (EXIT_FAILURE, errno, "failed to write %s", patch1);
}
} else {
copy (flip1, stdout);
puts ("\n=== 8< === cut here === 8< ===\n");
Expand Down
89 changes: 57 additions & 32 deletions src/rediff.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct file_info
int info_pending;
};

struct hunk
struct hunk
{
fpos_t filepos;
struct file_info *info;
Expand Down Expand Up @@ -938,7 +938,7 @@ static int rediff (const char *original, const char *edited, FILE *out)
if (getline (&line, &linelen, m) == -1)
break;
}

if (feof (m))
break;

Expand Down Expand Up @@ -1023,8 +1023,8 @@ static int rediff (const char *original, const char *edited, FILE *out)

return 0;
}
static char * syntax_str = "usage: %s ORIGINAL EDITED\n"
" %s EDITED\n";
static char * syntax_str = "usage: %s [--in-place] ORIGINAL EDITED\n"
" %s [--in-place] EDITED\n";

NORETURN
static void syntax (int err)
Expand All @@ -1037,64 +1037,89 @@ int main (int argc, char *argv[])
{
/* name to use in error messages */
set_progname ("rediff");

int inplace_mode = 0;

while (1) {
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{"in-place", 0, 0, 1000 + 'w'},
{0, 0, 0, 0}
};
int c = getopt_long (argc, argv, "vh",
long_options, NULL);
if (c == -1)
break;

switch (c) {
case 'v':
printf("rediff - patchutils version %s\n", VERSION);
exit(0);
case 'h':
syntax (0);
break;
case 1000 + 'w':
inplace_mode = 1;
break;
default:
syntax(1);
}

}

if (argc - optind < 1)
syntax (1);

if (argc - optind == 1) {
char *p = xmalloc (strlen (argv[0]) +
strlen ("recountdiff") + 1);
char *f;
char **const new_argv = xmalloc (sizeof (char *) * (argc + 1));
memcpy (new_argv, argv, sizeof (char *) * (argc + 1));
new_argv[0] = p;
strcpy (p, argv[0]);
f = strrchr (p, '/');
if (!f)
f = p;
else f++;
strcpy (f, "recountdiff");
execvp (new_argv[0], new_argv);
p = xstrdup (new_argv[0]);
f = strstr (p, "src/");
if (f) {
while (*(f + 4)) {
*f = *(f + 4);
f++;
}
*f = '\0';
if (inplace_mode) {
/* For single argument with --in-place, we need to handle recountdiff differently */
error (EXIT_FAILURE, 0, "--in-place with single argument not yet implemented");
} else {
char *p = xmalloc (strlen (argv[0]) +
strlen ("recountdiff") + 1);
char *f;
char **const new_argv = xmalloc (sizeof (char *) * (argc + 1));
memcpy (new_argv, argv, sizeof (char *) * (argc + 1));
new_argv[0] = p;
execv (new_argv[0], new_argv);
strcpy (p, argv[0]);
f = strrchr (p, '/');
if (!f)
f = p;
else f++;
strcpy (f, "recountdiff");
execvp (new_argv[0], new_argv);
p = xstrdup (new_argv[0]);
f = strstr (p, "src/");
if (f) {
while (*(f + 4)) {
*f = *(f + 4);
f++;
}
*f = '\0';
new_argv[0] = p;
execv (new_argv[0], new_argv);
}
error (EXIT_FAILURE, 0, "couldn't execute recountdiff");
}
error (EXIT_FAILURE, 0, "couldn't execute recountdiff");
}

if (access (argv[optind + 1], R_OK))
error (EXIT_FAILURE, errno, "can't read edited file");

return rediff (argv[optind], argv[optind + 1], stdout);
if (inplace_mode) {
/* For in-place mode, write result back to the edited file */
FILE *temp_output = xtmpfile();
int result = rediff (argv[optind], argv[optind + 1], temp_output);

if (result == 0) {
if (write_file_inplace(argv[optind + 1], temp_output) != 0) {
error (EXIT_FAILURE, errno, "failed to write %s", argv[optind + 1]);
}
}

fclose (temp_output);
return result;
} else {
return rediff (argv[optind], argv[optind + 1], stdout);
}
}
Loading