#!/usr/bin/env perl
# Fossil emulation of the "git log --patch / -p" feature: emit a stream
# of diffs from one version to the next for each file named on the
# command line.
#
# LIMITATIONS: It does not assume "all files" if you give no args, and
# it cannot take a directory to mean "all files under this parent".
#
# PREREQUISITES: This script needs several CPAN modules to run properly.
# There are multiple methods to install them:
#
# sudo dnf install perl-File-Which perl-IO-Interactive
# sudo apt install libfile-which-perl libio-interactive-perl
# sudo cpanm File::Which IO::Interactive
# ...etc...
use strict;
use warnings;
use Carp;
use File::Which;
use IO::Interactive qw(is_interactive);
die "usage: $0 <files...>\n\n" unless @ARGV;
my $out;
if (is_interactive()) {
my $pager = $ENV{PAGER} || which('less') || which('more');
open $out, '|-', $pager or croak "Cannot pipe to $pager: $!";
}
else {
$out = *STDOUT;
}
open my $bcmd, '-|', 'fossil branch current'
or die "Cannot get branch: $!\n";
my $cbranch = <$bcmd>;
chomp $cbranch;
close $bcmd;
for my $file (@ARGV) {
my $lastckid;
open my $finfo, '-|', "fossil finfo --brief --limit 0 '$file'"
or die "Failed to get file info: $!\n";
my @filines = <$finfo>;
close $finfo;
for my $line (@filines) {
my ($currckid, $date, $user, $branch, @cwords) = split ' ', $line;
next unless $branch eq $cbranch;
if (defined $lastckid and defined $branch) {
my $comment = join ' ', @cwords;
open my $diff, '-|', 'fossil', 'diff', $file,
'--from', $currckid,
'--to', $lastckid,
or die "Failed to diff $currckid -> $lastckid: $!\n";
my @dl = <$diff>;
close $diff;
my $patch = join '', @dl;
print $out <<"OUT"
Checkin ID $currckid to $branch by $user on $date
Comment: $comment
$patch
OUT
}
$lastckid = $currckid;
}
}