#!/usr/bin/perl -w
#
# Creates debiff patches for all deb in the given directories
# 
# requires the following software in the PATH:
#  * debiff.pl

use Getopt::Long;

sub usage ($) {
  my($s) = shift;
  print "$s\n\n";
  print <<SUSAGE;
Usage: makedebiffs [--small-steps|--large-steps][<directory> [<directory>...]]
--small-steps makes debiffs to the nearest revision (default)
--large-steps makes debiffs to the latest revision
<directory> is the name of a directory that contains several debs
that are named <package>_<old-version>_<arch>.deb.
If no directory is given the current directory is taken.
SUSAGE

  exit 1;
}

sub get_debiff_name ($$$$) {
  my ($name, $oldversion, $newversion, $arch) = @_;
  return "$name"."_$oldversion"."_$newversion"."_$arch.debiff";
}

sub get_deb_name ($$$){
  my ($name, $version, $arch) = @_;
  return "$name"."_$version"."_$arch.deb";
}

sub create_smallstep_debiffs {
  my ($dir, $debsByName) = @_;
  my ($k, $i, $debiff, @versions);

  foreach $k (keys %$debsByName) {
    @versions = @{$debsByName->{$k}};
    for ($i = 0; $i < (@versions - 1); $i++) {
      $debiff = get_debiff_name($versions[$i]->{name},
				$versions[$i]->{version},
				$versions[$i+1]->{version},
				$versions[$i]->{arch});				
      (-f "$dir/".$debiff) && next;
      print "Creating $debiff\n";
      (system "cd $dir;debiff.pl $versions[$i]->{name} $versions[$i]->{version}	$versions[$i+1]->{version} $versions[$i]->{arch}") 
	&& (die "error calling debiff - not installed/in path?");

    }
  }
}

sub create_largestep_debiffs {
  my ($dir, $debsByName) = @_;
  my ($k, $i, $debiff, @versions);

  foreach $k (keys %$debsByName) {
    @versions = @{$debsByName->{$k}};
    for ($i = 0; $i < (@versions - 1); $i++) {
      $debiff = get_debiff_name($versions[$i]->{name},
				$versions[$i]->{version},
				$versions[@versions-1]->{version},
				$versions[$i]->{arch});				
      (-f "$dir/".$debiff) && next;
      print "Creating $debiff\n";
      (system "cd $dir;debiff.pl $versions[$i]->{name} $versions[$i]->{version}	$versions[@versions-1]->{version} $versions[$i]->{arch}") 
	&& (die "error calling debiff - not installed/in path?");

    }
  }
}


sub do_dir ($) {
  my ($dir) = shift;
  my (@debs, %debsByName, $deb, $d, $k);

  @debs =  glob "$dir/*.deb";
  foreach $d (@debs) {
 (($name, $version, $arch) = $d =~ m/.*\/([a-zA-Z0-9%+\-\.]+)_([a-zA-Z0-9%+\-\.]+)_([a-zA-Z0-9]+)\.deb/) || next;
    $deb = {};
    $deb->{name} = $name;
    $deb->{version} = $version;
    $deb->{arch} = $arch;
    print "Package $deb->{name}, Version $deb->{version}, Arch $deb->{arch}\n";
    push @{$debsByName{$name}}, $deb;
  }

  foreach $k (keys %debsByName) {
    sort { $a->{version} cmp $b->{version} } @{$debsByName{$k}};
  }

  ($smallsteps) && create_smallstep_debiffs($dir, \%debsByName);
  ($largesteps) && create_largestep_debiffs($dir, \%debsByName);
}


(GetOptions("small-steps" => \$smallsteps,
 	    "large-steps" => \$largesteps,)) || &usage("unknown option");

if ($smallsteps && $largesteps) {
  &usage("use only one command");
}
elsif (!($smallsteps || $largesteps)){
  $smallsteps = 1;
}


@dirs = @ARGV;
(@dirs) || (@dirs = ("."));

foreach $d (@dirs) {
  do_dir($d);
}


