--- shiela.pl 2002/12/21 17:02:59 1.27
+++ shiela.pl 2002/12/22 11:06:50 1.28
@@ -183,11 +183,14 @@
&find_program("cvs") ||
die "unable to find `cvs' program";
$RT->{diff} = $CF->{Environment}->{Program}->{diff} ||
- &find_program("diff") ||
- die "unable to find `diff' program";
+ &find_program("diff") ||
+ '';
+ $RT->{xdelta} = $CF->{Environment}->{Program}->{xdelta} ||
+ &find_program("xdelta") ||
+ '';
$RT->{uuencode} = $CF->{Environment}->{Program}->{uuencode} ||
&find_program("uuencode") ||
- die "unable to find `uuencode' program";
+ '';
# pre-calculate a reasonable MIME boundary tag
my $randtag;
@@ -1630,98 +1633,162 @@
}
}
- # determine change diff
+ # determine change difference summary
if ($Io eq 'A') {
- # file was added, so we show the whole contents
+ ##
+ ## ADDED FILE
+ ##
+
+ # retrieve whole file contents
+ unlink("$RT->{tmpfile}.all");
+ my $io = new IO::File ">$RT->{tmpfile}.all"
+ || die "unable to open temporary file $RT->{tmpfile}.all for writing";
+ if (not $RT->{useserver}) {
+ my $cvs = new IO::File "$RT->{cvs} -f -l -Q -n update -p -r$Iv '$Is'|"
+ || die "unable to open CVS command pipe for reading";
+ $io->print($_) while (<$cvs>);
+ $cvs->close;
+ }
+ else {
+ my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
+ $cvs->directory($cvsdir);
+ $cvs->entry($Is);
+ $cvs->arguments("-p", "-r$Iv", $Is);
+ $cvs->send("update");
+ $io->print(scalar $cvs->result);
+ $cvs->close;
+ }
+ $io->close;
+
if ($Ik eq 'b' or -B $Is) {
- # file seems to be a binary file
- $cvsdiff .=
- "<Diff $cvsdir/$Is>\n" .
- "Index: $cvsdir/$Is\n" .
- "============================================================\n" .
- "\$ cvs update -p -r$Iv $Is | uuencode $Is\n";
- if (not $RT->{useserver}) {
- my $io = new IO::File "$RT->{cvs} -f -l -Q -n update -p -r$Iv '$Is' | uuencode '$Is' |"
- || die "unable to open CVS command pipe for reading";
+ # generate binary change patch script
+ if ($RT->{xdelta} and $RT->{uuencode}) {
+ $cvsdiff .=
+ "<shiela:patch $cvsdir/$Is>\n" .
+ "(cd $cvsdir && uudecode <<'@@ .' && \\\n" .
+ " xdelta patch $Is.xdelta /dev/null $Is && \\\n" .
+ " rm -f $Is.xdelta)\n" .
+ "Index: $cvsdir/$Is\n" .
+ ("=" x 76) . "\n";
+ unlink("$RT->{tmpfile}.null");
+ unlink("$RT->{tmpfile}.xdelta");
+ my $io = new IO::File ">$RT->{tmpfile}.null"
+ || die "unable to open temporary file $RT->{tmpfile}.null for writing";
+ $io->close;
+ system("$RT->{xdelta} delta $RT->{tmpfile}.null " .
+ "$RT->{tmpfile}.all $RT->{tmpfile}.xdelta >/dev/null 2>&1");
+ $io = new IO::File "uuencode $RT->{tmpfile}.xdelta $Is.xdelta |"
+ || die "unable to open uuencode command pipe for reading";
$cvsdiff .= $_ while (<$io>);
$io->close;
+ $cvsdiff .= "@@ .\n";
+ $cvsdiff .= "</shiela:patch>\n";
+ unlink("$RT->{tmpfile}.null");
+ unlink("$RT->{tmpfile}.xdelta");
}
- else {
- my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
- $cvs->directory($cvsdir);
- $cvs->entry($Is);
- $cvs->arguments("-p", "-r$Iv", $Is);
- $cvs->send("update");
- $cvsdiff .= scalar $cvs->result;
- $cvs->close;
- }
- $cvsdiff .= "</Diff>\n";
}
else {
- # file seems to be a regular text file
- $cvsdiff .=
- "<Diff $cvsdir/$Is>\n" .
- "Index: $cvsdir/$Is\n" .
- "============================================================\n" .
- "\$ cvs update -p -r$Iv $Is\n";
- if (not $RT->{useserver}) {
- my $io = new IO::File "$RT->{cvs} -f -l -Q -n update -p -r$Iv '$Is'|"
+ # generate textual change patch script
+ if ($RT->{diff}) {
+ $cvsdiff .=
+ "<shiela:patch $cvsdir/$Is>\n" .
+ "patch -p0 <<'@@ .'\n" .
+ "Index: $cvsdir/$Is\n" .
+ ("=" x 76) . "\n" .
+ "\$ cvs diff -u -r0 -r$Iv $Is\n";
+ my $diff = '';
+ my $io = new IO::File "$RT->{diff} -u /dev/null $RT->{tmpfile}.all|"
|| die "unable to open CVS command pipe for reading";
- $cvsdiff .= $_ while (<$io>);
+ $diff .= $_ while (<$io>);
$io->close;
+ my $Is_quoted = quotemeta("$RT->{tmpfile}.all");
+ $diff =~ s|^(\+\+\+\s+)$Is_quoted|$1$Is|m;
+ $cvsdiff .= $diff;
+ $cvsdiff .= "@@ .\n";
+ $cvsdiff .= "</shiela:patch>\n";
}
- else {
- my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
- $cvs->directory($cvsdir);
- $cvs->entry($Is);
- $cvs->arguments("-p", "-r$Iv", $Is);
- $cvs->send("update");
- $cvsdiff .= scalar $cvs->result;
- $cvs->close;
- }
- $cvsdiff .= "</Diff>\n";
}
+
+ # cleanup
+ unlink("$RT->{tmpfile}.all");
}
elsif ($Io eq 'M') {
+ ##
+ ## MODIFIED FILE
+ ##
+
if ($Ik eq 'b' or -B $Is) {
- # file seems to be a binary file
- $cvsdiff .=
- "<Diff $cvsdir/$Is>\n" .
- "Index: $cvsdir/$Is\n" .
- "============================================================\n" .
- "\$ cvs update -p -r$IV $Is >$Is.old\n" .
- "\$ cvs update -p -r$Iv $Is >$Is.new\n" .
- "\$ diff -u $Is.old $Is.new\n";
- if (not $RT->{useserver}) {
- system("$RT->{cvs} -f -l -Q -n update -p -r$IV '$Is' | $RT->{uuencode} '$Is' >$Is.old");
- system("$RT->{cvs} -f -l -Q -n update -p -r$Iv '$Is' | $RT->{uuencode} '$Is' >$Is.new");
- }
- else {
- my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
- $cvs->directory($cvsdir);
- $cvs->entry($Is);
- $cvs->arguments("-p", "-r$IV", $Is);
- $cvs->send("update");
- my $data = scalar $cvs->result;
- my $io = new IO::File ">$Is.old" || die "cannot write to $Is.old";
- $io->print($data);
+ # generate binary change patch script
+
+ if ($RT->{xdelta} and $RT->{uuencode}) {
+ # retrieve whole file contents (old revision)
+ unlink("$RT->{tmpfile}.old");
+ my $io = new IO::File ">$RT->{tmpfile}.old"
+ || die "unable to open temporary file $RT->{tmpfile}.old for writing";
+ if (not $RT->{useserver}) {
+ my $cvs = new IO::File "$RT->{cvs} -f -l -Q -n update -p -r$IV '$Is'|"
+ || die "unable to open CVS command pipe for reading";
+ $io->print($_) while (<$cvs>);
+ $cvs->close;
+ }
+ else {
+ my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
+ $cvs->directory($cvsdir);
+ $cvs->entry($Is);
+ $cvs->arguments("-p", "-r$IV", $Is);
+ $cvs->send("update");
+ $io->print(scalar $cvs->result);
+ $cvs->close;
+ }
$io->close;
- $cvs->arguments("-p", "-r$Iv", $Is);
- $cvs->send("update");
- $data = scalar $cvs->result;
- $io = new IO::File ">$Is.new" || die "cannot write to $Is.old";
- $io->print($data);
+
+ # retrieve whole file contents (new revision)
+ unlink("$RT->{tmpfile}.new");
+ $io = new IO::File ">$RT->{tmpfile}.new"
+ || die "unable to open temporary file $RT->{tmpfile}.new for writing";
+ if (not $RT->{useserver}) {
+ my $cvs = new IO::File "$RT->{cvs} -f -l -Q -n update -p -r$Iv '$Is'|"
+ || die "unable to open CVS command pipe for reading";
+ $io->print($_) while (<$cvs>);
+ $cvs->close;
+ }
+ else {
+ my $cvs = new CVS ($RT->{cvs}, $RT->{cvsroot});
+ $cvs->directory($cvsdir);
+ $cvs->entry($Is);
+ $cvs->arguments("-p", "-r$Iv", $Is);
+ $cvs->send("update");
+ $io->print(scalar $cvs->result);
+ $cvs->close;
+ }
$io->close;
- $cvs->close;
+
+ # generate change patch script
+ $cvsdiff .=
+ "<shiela:patch $cvsdir/$Is>\n" .
+ "(cd $cvsdir && uudecode <<'@@ .' && \\\n" .
+ " mv $Is $Is.orig && xdelta patch $Is.xdelta $Is.orig $Is && \\\n" .
+ " rm -f $Is.orig $Is.xdelta)\n" .
+ "Index: $cvsdir/$Is\n" .
+ ("=" x 76) . "\n";
+ unlink("$RT->{tmpfile}.xdelta");
+ system("$RT->{xdelta} delta $RT->{tmpfile}.old " .
+ "$RT->{tmpfile}.new $RT->{tmpfile}.xdelta >/dev/null 2>&1");
+ $io = new IO::File "uuencode $RT->{tmpfile}.xdelta $Is.xdelta |"
+ || die "unable to open uuencode command pipe for reading";
+ $cvsdiff .= $_ while (<$io>);
+ $io->close;
+ $cvsdiff .= "@@ .\n";
+ $cvsdiff .= "</shiela:patch>\n";
+ unlink("$RT->{tmpfile}.xdelta");
+
+ # cleanup
+ unlink("$RT->{tmpfile}.old");
+ unlink("$RT->{tmpfile}.new");
}
- my $io = new IO::File "$RT->{diff} -u $Is.old $Is.new|"
- || die "unable to open diff command pipe for reading";
- $cvsdiff .= $_ while (<$io>);
- $io->close;
- $cvsdiff .= "</Diff>\n";
}
else {
- # file was modified, so we show the changed contents only
+ # generate textual change patch script
my $d = '';
if (not $RT->{useserver}) {
my $io = new IO::File "$RT->{cvs} -f -l -Q -n diff -u -r$IV -r$Iv '$Is'|"
@@ -1743,23 +1810,30 @@
$d =~ s|^(---\s+)${Is_quoted}(\s+)|$1$cvsdir/$Is$2|m;
$d =~ s|^(\+\+\+\s+)${Is_quoted}(\s+)|$1$cvsdir/$Is$2|m;
$cvsdiff .=
- "<Diff $cvsdir/$Is>\n" .
+ "<shiela:patch $cvsdir/$Is>\n" .
+ "patch -p0 <<'@@ .'\n" .
"Index: $cvsdir/$Is\n" .
- "============================================================\n" .
+ ("=" x 76) . "\n" .
"\$ cvs diff -u -r$IV -r$Iv $Is\n" .
$d .
- "</Diff>\n";
+ "@@ .\n" .
+ "</shiela:patch>\n";
}
}
elsif ($Io eq 'R') {
- if ($Ik eq 'b' or -B $Is) {
- # file seems to be a binary file
- # FIXME
- }
- else {
- # file seems to be a regular file
- # FIXME
- }
+ ##
+ ## REMOVED FILE
+ ##
+
+ # generate binary and textaual change patch script
+ $cvsdiff .=
+ "<shiela:patch $cvsdir/$Is>\n" .
+ "(cat <<'@@ .' >/dev/null && rm -f $cvsdir/$Is)\n" .
+ "Index: $cvsdir/$Is\n" .
+ ("=" x 76) . "\n" .
+ "[NO CHANGE SUMMARY BECAUSE FILE AS A WHOLE IS JUST REMOVED]\n" .
+ "@@ .\n" .
+ "</shiela:patch>\n";
}
$info = "$cvsdir/$Is,$IV,$Iv,$It,$Io,$Ik,$ID,$Id";
@@ -1825,7 +1899,7 @@
$e->{delta} = $Id;
$e->{diff} = '';
my $Is_quoted = quotemeta($Is);
- $cvsdiff =~ s|\n<Diff\s+${Is_quoted}>\n(.+?\n)</Diff>|$e->{diff} = $1, ''|se;
+ $cvsdiff =~ s|\n<shiela:patch\s+${Is_quoted}>\n(.+?\n)</shiela:patch>|$e->{diff} = $1, ''|se;
$IN->{file}->{$Is} = $e;
$handle_min = $ID if ($ID ne '' and $ID ne '0' and (not defined($handle_min) or $handle_min > $ID));
$handle_max = $ID if ($ID ne '' and $ID ne '0' and (not defined($handle_max) or $handle_max < $ID));
@@ -1897,7 +1971,7 @@
my $sm = new Sendmail ($RT, $logurl);
$sm->header('Subject', $subject);
if (defined($CF->{Logging}->{Report}->{$logtype}->{Details})) {
- if ($CF->{Logging}->{Report}->{$logtype}->{Details} eq 'diff:mime') {
+ if ($CF->{Logging}->{Report}->{$logtype}->{Details} eq 'patch:mime') {
$sm->header('Content-Type',
"multipart/mixed; boundary=\"".$RT->{mimeboundary}."\"");
}
@@ -1961,7 +2035,7 @@
my $RP = $CF->{Logging}->{Report}->{$type} || die "No report of type `$type' defined";
my $prefix = $RP->{Prefix} || '';
- my $style = $RP->{Details} || 'diff:plain';
+ my $style = $RP->{Details} || 'patch:plain';
my $O = '';
foreach my $content (@{$RP->{Content}}) {
@@ -2099,7 +2173,7 @@
$O .= "$prefix$url\n";
}
}
- elsif ($style eq 'diff:plain') {
+ elsif ($style eq 'patch:plain') {
foreach $file (sort(keys(%{$IN->{file}}))) {
next if ($IN->{file}->{$file}->{op} eq 'T');
my $diff = $IN->{file}->{$file}->{diff};
@@ -2107,7 +2181,7 @@
$O .= $diff;
}
}
- elsif ($style eq 'diff:mime') {
+ elsif ($style eq 'patch:mime') {
foreach $file (sort(keys(%{$IN->{file}}))) {
next if ($IN->{file}->{$file}->{op} eq 'T');
my $diff = $IN->{file}->{$file}->{diff};
@@ -2131,7 +2205,7 @@
$O =~ s|\n+$|\n|s;
# MIME post-processing
- if ($style eq 'diff:mime') {
+ if ($style eq 'patch:mime') {
$O = "This is a multi-part message in MIME format.\n" .
"--".$RT->{mimeboundary}."\n" .
"Content-Type: text/plain; charset=iso-8859-1\n" .
@@ -2147,4 +2221,3 @@
return $O;
}
-##EOF##
|