#!/usr/bin/perl
#
# dh_automake - Script to automate most of the Debianization of a debian source archive
#

our $DH_AUTOMAKE_VERSION="0.1";

use Getopt::Long;
use strict;

our $force = 0;
our $sourcedir = "debian/tmp";
our $nobuild = 0;
our $debug = 0;

sub ask_overwrite
{
  my ($file) = @_;
  if ( ! -e $file or $force)
  {
    return 1;
  }
  while (1)
  {
    print "File $file has been found, overwrite it? (y/N) ";
    my $res = <>;
    chomp($res);
    if (lc $res eq "y")
    {
      return 1;
    }
    elsif (! $res or lc $res eq "n")
    {
      return 0;
    }
    else
    {
      print "Please say y or n.\n";
    }
  }
}

sub get_files
{
  my ($dir, $willdie) = @_;
  opendir (DIR, $dir) or ($willdie and die "Unable to open directory $dir: $! \n");
  my @files = grep { $_ ne "." and $_ ne ".." } readdir (DIR);
  closedir (DIR);
  return @files;
}

sub comment_rule
{
  my ($rule) = @_;
  my $file = "debian/rules";
  open IN, "<$file" or die "Unable to open $file file for reading: $! \n";
  open OUT, ">$file.new" or die "Unable to open temporary $file.new file for writing: $! \n";
  while (defined (my $line = <IN>))
  {
    $line =~ s/(\s+)$rule(\s.*)/#$1$rule$2/;
    print OUT $line;
  }
  close IN;
  close OUT;
  rename "$file.new", "$file" or die "Unable to rename $file.new to $file: $! \n";
  system "chmod +x $file";
}

sub update_rule
{
  my ($rule, $opt, $arg) = @_;
  print ">> Updating rule $rule $opt$arg\n" if $debug;
  my $file = "debian/rules";
  open IN, "<$file" or die "Unable to open $file file for reading: $! \n";
  open OUT, ">$file.new" or die "Unable to open temporary $file.new file for writing: $! \n";
  while (defined (my $line = <IN>))
  {
    if ($line =~ /$rule\s/ and $line =~ /$opt/)
    {
      $line =~ s/$opt.*?(\s+)/$1/;
    }
    $line =~ s/#?(\s+)$rule(\s.*)/$1$rule $opt$arg $2/;
    print OUT $line;
  }
  close IN;
  close OUT;
  rename "$file.new", "$file" or die "Unable to rename $file.new to $file: $! \n";
  system "chmod +x $file";
}

sub update_control
{
  my ($package, $section, $depends) = @_;
  print ">> Updating control for $package under section $section\n" if $debug;
  my $file = "debian/control";
  open IN, "<$file" or die "Unable to open $file file for reading: $! \n";
  open OUT, ">$file.new" or die "Unable to open temporary $file.new file for writing: $! \n";
  my $found = 0;
  while (defined (my $line = <IN>))
  {
    if ($line =~ /^Package: $package$/)
    {
      $found++;
    }
    # If section is UNKNOWN it's a binary not libs nor libdevel
    if ($found eq 1 and $section eq "UNKNOWN" and $line =~ /^Section: lib/)
    {
      $line =~ s/^Section:.*/Section: $section/;
      $found++;
    }
    if ($found eq 2 and $line =~ /^Depends:/)
    {
      $line =~ s/^Depends:.*$/Depends: $depends/;
      $found++;
    }
    print OUT $line;
  }
  close IN;
  if ( ! $found)
  {
    print OUT <<EOF
Package: $package
Section: $section
Architecture: any
Depends: $depends
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>

EOF
  }
  close OUT;
  rename "$file.new", "$file" or die "Unable to rename $file.new to $file: $! \n";
}

sub write_entries
{
  my ($name, $ext, @entries) = @_;
  my $file = "debian/$name.$ext";
  ask_overwrite ($file);
  print ">> Writing entries to $file\n" if $debug;
  open OUT, ">$file" or die "Unable to open $file for writing: $! \n";
  my $entry;
  foreach $entry (@entries)
  {
    print OUT $entry."\n";
  }
  close OUT;
}

sub create_binary
{
  my ($name) = @_;
  my @entries = ("usr/bin");
  write_entries ($name, "dirs", @entries);

  @entries = ("usr/bin/$name");
  write_entries ($name, "install", @entries);

  update_control ($name, "UNKNOWN", "\${shlibs:Depends}");
}

sub find_binaries
{
  my @binaries = get_files ($main::sourcedir . "/usr/bin", 0);
  my $binary;
  foreach $binary (@binaries)
  {
    print "Found binary package: $binary\n";
    create_binary ($binary);
  }
}

sub build_package
{
  print ">> Building package with dpkg-buildpackage -rfakeroot\n" if $debug;
  system("dpkg-buildpackage -rfakeroot") eq 0 or die;
}

sub check_sourcedir
{
  if ( ! -d $main::sourcedir)
  {
    die "Unable to find sourcedir $main::sourcedir: $! .\
Please check your debian/rules file.\n";
  }
}

sub show_version
{
  print "dh_automake - Script to automate most of the Debianization of a debian source\n";
  print "              archive, version $main::DH_AUTOMAKE_VERSION\n\n";
  print "Copyright (C) 2008 Luca Bruno <lethalman\@gmail.com>\n";
  print "This is free software, see the source fo copying conditions.  There is NO\n";
  print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
}

sub show_help
{
  show_version();
  print <<EOF

 Usage: dh_automake [options]
  -s, --sourcedir <dir>     specify the directory where to find installed files
                            (default: debian/tmp)
  -n, --norules             do not apply changes to debian/rules
  -f, --force               force rewrite of files, skip asking for overwrite
  -v, --verbose             print debug messages
  -h, --help                display this help screen and exit
      --version             show the version and exit

By Luca Bruno <lethalman\@gmail.com>
Based on dh_make by Craig Small <csmall\@debian.org>
EOF
}

sub parse_args
{
  my ($dohelp, $doversion);
  if (GetOptions(
                 'version|' => \$doversion,
                 'help|h' => \$dohelp,
                 'force|f' => \$main::force,
                 'sourcedir|s' => \$main::sourcedir,
                 'nobuild|n' => \$main::nobuild,
                 'verbose|v' => \$main::debug)
      == 0)
  {
    show_help ();
    exit;
  }

  if ($#ARGV != -1)
  {
    print "Extra parameters on command line\n";
    show_help ();
    exit;
  }

  if ($doversion)
  {
    show_version ();
    exit;
  }

  if ($dohelp)
  {
    show_help ();
    exit;
  }
}

parse_args ();

-d "debian" or die "Unable to find debian subdirectory: $! \n";

update_rule ("dh_install", "--sourcedir=", $main::sourcedir);

if (! $main::nobuild or ! -d $main::sourcedir)
{
  build_package ();
}

check_sourcedir ();

find_binaries ();
