#!/usr/bin/perl

use 5.006;
use strict;
use warnings;

use File::Path;
use Getopt::Long qw/:config bundling require_order pass_through/;

sub usage
  {
    print STDERR <<END;
Usage: arch-recordpackage [OPTIONS]... [--upstream | --both] package [version]
 --upstream
             Create an upstream config, not a debian one
 --both
             Create both an upstream config and a debian one

Where OPTIONS can be:
 --no-act, -n
             Show the configuration, but don't save it
 --no-revision
             Don't include the revision components in the configuration
 --no-version
             Don't include the version components in the configuration
 --output=file, -o file
             Save the configuration to the named file, instead of
             picking a default based on the package and version
 --help
             Show this text

Records a configuration for the current state of the give package and
version.

If no version is specified, then --no-revision is assumed.
END
    exit 0;
  }

my ($debian, $both, $upstream, $no_act, $no_revision, $no_version, $output);
GetOptions('upstream' => \$upstream,
           'both' => \$both,
           'no-act|n' => \$no_act,
           'no-revision' => \$no_revision,
           'no-version' => \$no_version,
           'output|o=s' => \$output,
           'help' => \&usage,
          );
usage if $both and $upstream;
usage unless scalar @ARGV >= 1;
$debian = 0 if defined $upstream;

my $package = shift;
my $version = shift;

$no_revision = 1 unless defined $version;
$no_revision = 1 if $no_version;

$debian = 1 unless defined $debian;
$debian = 1 if $both;
$upstream = 1 if $both;

sub find_nested
  {
    my $tree = shift;
    my @nested = `tla inventory -t --nested '$tree'`;
    chomp $_ foreach @nested;
    unshift @nested, $tree;
    return @nested;
  }

sub find_version
  {
    my $tree = shift;
    my $version = `tla tree-version '$tree'`;
    chomp $version;

    if ($no_version)
      {
        $version =~ s/--[^-]+$//
          or die "Failed to remove version component from $version";
      }

    return $version;
  }

sub find_revision
  {
    my $tree = shift;
    my @logs = `tla logs -d '$tree'`;
    die "No patch logs found for current tree-version in $tree" unless scalar @logs;
    my $revision = $logs[-1];
    chomp $revision;
    return $revision;
  }

my $tree_root = `tla tree-root` or exit 1;
chomp $tree_root;

chdir $tree_root or die "Couldn't chdir to $tree_root";

if ($upstream)
  {
    my $tree = $version ? "$package/upstream/$package-$version"
                        : "$package/upstream/$package";

    die "Upstream source tree $tree not found" unless -d $tree;

    print "Upstream config:\n" if $both;

    my @config;
    foreach my $nested (find_nested($tree))
      {
        my $tree_version = find_version($nested);
        my $revision = $no_revision ? "" : ("--" . find_revision($nested));
        my $line = "./$nested $tree_version$revision\n";
        print $line;
        push @config, $line;
      }

    unless ($no_act)
      {
        mkpath("configs/$package/upstream");
        my $config = $output
          || ($version ? "configs/$package/upstream/$package-$version"
                       : "configs/$package/upstream/$package");
        open CONFIG, ">", $config or die "Couldn't open $config for writing: $!";
        print CONFIG $_ foreach @config;
        close CONFIG;
      }
  }

print "\n" if $both;

if ($debian)
  {
    my $upstreamversion = $version;

    my $tree = "$package/$package";
    if (defined $upstreamversion)
      {
        $upstreamversion =~ s/^[^:]+:// if defined $upstreamversion;
        if ($upstreamversion =~ s/-[^-]+$//)
          {
            $tree = "$package/$package-$upstreamversion";
          }
        else
          {
            # There's no -debianversion suffix here. We need to go
            # parse the changelog.
            $tree = "$package/$package-$upstreamversion";
            my $parsechangelog = `dpkg-parsechangelog -l$tree/debian/changelog`;
            unless ($parsechangelog =~ /^Version: (.*)$/m)
              {
                die "Failed to get version from changelog";
              }
            $version = $1;
            if ($version !~ /^(\d+:)?\Q$upstreamversion\E/)
              {
                die "Debian version from changelog ($version) does not match $upstreamversion";
              }
          }
      }

    die "Debian source tree $tree not found" unless -d $tree;

    print "Debian config:\n" if $both;

    my @config;
    foreach my $nested (find_nested($tree))
      {
        my $tree_version = find_version($nested);
        my $revision = $no_revision ? "" : ("--" . find_revision($nested));
        my $line = "./$nested $tree_version$revision\n";
        print $line;
        push @config, $line;
      }

    unless ($no_act)
      {
        mkpath("configs/$package/debian");
        my $config = $output
          || ($version ? "configs/$package/debian/$package-$version"
                       : "configs/$package/debian/$package");
        open CONFIG, ">", $config or die "Couldn't open $config for writing: $!";
        print CONFIG $_ foreach @config;
        close CONFIG;
      }
  }

exit 0;
