#!/usr/bin/perl

#  Copyright 2003-2006 Eduard Bloch <blade@debian.org>
#
#  This package is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

use Getopt::Long qw(:config no_ignore_case bundling pass_through);
use File::Basename;
use Cwd qw/getcwd chdir/;

use strict;
use warnings;
#use diagnostics;

my $startdir=getcwd;
chomp(my $tmpfile=`mktemp`);
my $scriptname="[svn-buildpackage]";

sub mychdir {
    my $dir = shift;
    chdir $dir || die "Could not change directories to $dir...";
}

sub help {
print "
Usage: svn-buildpackage [ OPTIONS... ] [ OPTIONS for dpkg-buildpackage ]
Builds Debian package within the SVN repository. The source code
repository must be in the format created by svn-inject, and this script
must be executed from the work directory (trunk/package).

Building and working directory management:
  --svn-builder CMD    Use CMD as build command instead of dpkg-buildpackage
  --svn-ignore-new     Don't stop on svn conflicts or new/changed files
  --svn-dont-clean     Don't run debian/rules clean (default: clean first)
  --svn-savecfg        Create a .svn/deb-layout file from the detected/imported
                       layout information. (replicates old behaviour)
Source copying behavior:
  --svn-no-links       Don't use file links (default: use links where possible)
  --svn-dont-purge     Don't wipe the build directory (default: purge after build)
  --svn-reuse          Reuse an existing build directory, copy trunk over it
  --svn-rm-prev-dir    Remove an existing build directory instead of making a
                       copy; if --svn-reuse is specified, this option is reset
  --svn-export         Just prepares the build directory and exits
Tagging and post-tagging:
  --svn-tag            Final build: Export && build && tag && dch -i
  --svn-retag          Replace an existing tag directory if found while tagging
  --svn-only-tag       Tags the current trunk directory without building
  --svn-noautodch      Don't add a new Debian changelog entry when done
Post-build processing:
  --svn-lintian        Run lintian after the build
  --svn-move           Move package files to .. after successful build
  --svn-move-to XYZ    Move package files to XYZ, implies --svn-move
Miscelaneous:
  --svn-pkg PACKAGE    Specifies the package name
  --svn-override a=b   Override some config variable (comma separated list)
  --svn-arch ARCH      Allows specifying the build architecture
  --svn-verbose        More verbose program output
  --svn-noninteractive Turn off interactive mode
  --svn-download-orig  Use apt and uscan to download the .orig.tar.gz
  -h, --help           Show this help message

If the debian directory has the mergeWithUpstream property, svn-buildpackage
will extract .orig.tar.gz file first and add the Debian files to it.

"; exit 1;
}
my $quiet="-q";
my $opt_verbose;
my $opt_dontclean;
my $opt_dontpurge;
my $opt_reuse;
my $opt_rmprevbuilddir;
my $opt_ignnew;
my $opt_tag;
my $opt_only_tag;
my $opt_lintian;
my $opt_nolinks;
my $opt_noninteractive;
my $opt_pretag;
my $opt_prebuild;
my $opt_posttag;
my $opt_postbuild;
my $opt_retag;
my $opt_buildcmd;
my $opt_export;
my $opt_pass_diff;
my @opt_override;
my $opt_move;
my $opt_move_to;
my $opt_moved_to;
my $opt_noautodch;
my $opt_download_tarball;
my $package;
my $opt_savecfg;
my $opt_architecture;

# deprecated; to be completely removed in next major release?
my $opt_linda;
my $linda_warning = <<EOLINDAW;

################################################################################

   !!!!!!!! WARNING: linda is deprecated and no longer developed !!!!!!!!
         The corresponding option is still accepted, but is ignored.

   If the option svn-linda is present in your ~/.svn-buildpackage.conf
   or any scripts you might use to call svn-buildpackage, please remove
   it! This option is scheduled for complete  removal in the near
   future, so using it would lead to broken builds with such future
   versions of svn-buildpackage.

   !!!!!!! PLEASE STOP USING THE OPTION --svn-linda / svn-linda  !!!!!!!

################################################################################

EOLINDAW

my %options = (
#   "h|help"                => \&help,
   "svn-savecfg"           => \$opt_savecfg,
   "svn-verbose"           => \$opt_verbose,
   "svn-ignore-new|svn-ignore"        => \$opt_ignnew,
   "svn-dont-clean"        => \$opt_dontclean,
   "svn-export"            => \$opt_export,
   "svn-dont-purge"        => \$opt_dontpurge,
   "svn-reuse"             => \$opt_reuse,
   "svn-rm-prev-dir"       => \$opt_rmprevbuilddir,
   "svn-only-tag"          => \$opt_only_tag,
   "svn-tag-only"          => \$opt_only_tag,
   "svn-tag"               => \$opt_tag,
   "svn-retag"             => \$opt_retag,
   "svn-lintian"           => \$opt_lintian,
   "svn-linda"             => \$opt_linda,
   "svn-no-links"          => \$opt_nolinks,
   "svn-noninteractive"    => \$opt_noninteractive,
   "svn-pass-diff"         => \$opt_pass_diff,
   "svn-prebuild=s"        => \$opt_prebuild,
   "svn-postbuild=s"       => \$opt_postbuild,
   "svn-pretag=s"          => \$opt_pretag,
   "svn-posttag=s"         => \$opt_posttag,
   "svn-arch:s"            => \$opt_architecture,
   "svn-download-orig"     => \$opt_download_tarball,
   # and for compatibility with old config directives
   "pre-tag-action=s"      => \$opt_pretag,
   "post-tag-action=s"     => \$opt_posttag,
   "pre-build-action=s"    => \$opt_prebuild,
   "post-build-action=s"   => \$opt_postbuild,
   "svn-move"              => \$opt_move,
   "svn-moved-to=s"             => \$opt_moved_to,
   "svn-move-to=s"         => \$opt_move_to,
   "svn-builder=s"         => \$opt_buildcmd,
   "svn-override=s"        => \@opt_override,
   "svn-pkg=s"             => \$package,
   "svn-noautodch"         => \$opt_noautodch,
);

use lib (split(/:/, $ENV{SVNBPPERLLIB} || "/usr/share/svn-buildpackage"));

use SDCommon;

my $tagVersion;
my $upVersion;
my $tagVersionNonEpoch;
my @builder;
my $origExpect;
my $origfile;
my @dirs;
my @files;
my $retval=0;
my $orig_target;

# get only --help here, do before init because init needs to run after the main Getopt call, but may fail and ignore --help
#
{
   my $gethelp;
   &help unless GetOptions('h|help' => \$gethelp);
   &help if $gethelp;
}

SDCommon::init();

sub setenv {
   my ($key, $val) = @_;
   return 0 if(!defined($val));
   print "ENV: $key=$val\n" if $opt_verbose;
   $ENV{$key}=$val;
}

sub setallenv {
   $tagVersion=$SDCommon::tagVersion;
   $upVersion=$SDCommon::upVersion;
   $tagVersionNonEpoch = $tagVersion;
   $tagVersionNonEpoch =~ s/^[^:]*://;

   #this sucks but the config file needs to be processed before the options and there should be reasonable default
   $package = $SDCommon::package?$SDCommon::package:'' unless $package;
   setenv("PACKAGE", $package);
   setenv("package", $package);
   setenv "TAG_VERSION", $tagVersion;
   setenv "debian_version", $tagVersion;
   setenv "non_epoch_version", $tagVersionNonEpoch;
   setenv "upstream_version", $upVersion;
   setenv "SVN_BUILDPACKAGE", $SDCommon::version;
   setenv "guess_loc", ( ($package=~/^(lib.)/)?$1:substr($package,0,1))."/$package"."_$upVersion.orig.tar.gz";
}

&setallenv;

my @CONFARGS;
for my $file ($ENV{"HOME"}."/.svn-buildpackage.conf", ".svn/svn-buildpackage.conf") {

    if(open(RC, $file)) {
        SKIP: while(<RC>) {
            chomp;
            next SKIP if /^#/;
            # drop leading spaces
            s/^\s+//;
            if(/^\w/) {
                # remove spaces between
                s/^(\S+)\s*=\s*/$1=/;
                # convert to options and push to args
                s/^/--/;
                $_=`echo -n $_` if(/[\$`~]/);
                push(@CONFARGS, $_);
            }
        }
        close(RC);
    }
}

if($#CONFARGS>=0) {
   @ARGV=(@CONFARGS, @ARGV);
   print "Imported config directives:\n\t".join("\n\t", @CONFARGS)."\n";
}

&help unless ( GetOptions(%options));
$quiet="" if ($opt_verbose);
# if opt_only_tag is used, set opt_tag too. Should not hurt because the
# real function of opt_tag at the end of the script is never reached
$opt_tag = 1 if($opt_only_tag);
$opt_move=1 if $opt_move_to;
$opt_dontpurge=1 if $opt_reuse;
$opt_rmprevbuilddir=0 if $opt_reuse;
my $destdir=long_path($opt_move_to ? $opt_move_to : "$startdir/..");
$SDCommon::opt_verbose=$opt_verbose;
$package = $SDCommon::package if(!$package);
$SDCommon::opt_noninteractive = 1 if$opt_noninteractive;
$SDCommon::opt_noninteractive = 1 if exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} =~ /^noninteractive$/;

$SDCommon::opt_nosave = 0 if (defined $opt_savecfg) ;

print "D: Configuration will not be saved.\n" if (defined $opt_verbose && ($SDCommon::opt_nosave==1));

SDCommon::configure(@opt_override);
my $c=\%SDCommon::c;

if($opt_tag){
    start_ssh();
    needs_tagsUrl();
}

# linda is deprecated - big fat warning since we found it
print $linda_warning if (defined $opt_linda);

@ARGV=grep {!/^--svn-/} @ARGV;

#some things may have been overriden by user options
&setallenv;
if($opt_buildcmd) { # pass @ARGV but carefully
   foreach(@ARGV) { s/"/\\"/g ; s/^/"/; s/$/"/;}
   @builder = ("/bin/sh", "-c", $opt_buildcmd." ".join(" ", @ARGV));
}
else {
   push(@builder, "dpkg-buildpackage",@ARGV);
   # a simple "helper". Only executed if:
   #  neither --svn-tag-only nor --evn-export is used and
   #  no custom command is choosen
   #  and no -d switch is there
   #  and no prebuild hook is set
   if(! $opt_only_tag && ! $opt_export && (!grep {$_ eq "-d"} @ARGV)
      && (! withechoNoPrompt("dpkg-checkbuilddeps")) 
      && ! $opt_prebuild )
   {
         die "Insufficient Build-Deps, stop!\n";
   }
}

withecho "fakeroot debian/rules clean || debian/rules clean" if ! ($opt_dontclean || (`svn proplist debian` =~ /mergeWithUpstream/i));
SDCommon::check_uncommited if(!$opt_ignnew);

my $parsechangelogret = `dpkg-parsechangelog`;
if (($? >> 8)!=0) {
  die "Failed to parse changelog";
}
if($parsechangelogret =~ /(\*\s+NOT.RELEASED.YET)|(UNRELEASED.*urgency)/m) {
   print STDERR "UNRELEASED tag found - you don't want to release with it, do you?\n";
   die "Aborting now, set \$FORCETAG to ignore it.\n" if($opt_tag && !$ENV{"FORCETAG"});
}

sub checktag {
   SDCommon::svnMkdirP ( $$c{"tagsUrl"}, $scriptname ) ;
   if(insvn($$c{"tagsUrl"}."/$tagVersion")) {
      if($opt_retag) {
         withecho ("svn", "-m", "$scriptname Removing old tag $package-$tagVersion", "rm", $$c{"tagsUrl"}."/$tagVersion");
      }
      else {
         die "Could not create tag copy\n".
         $$c{"tagsUrl"}."/$tagVersion - it
does already exist. Add the --svn-retag option to replace that tag.\n";
      }
   }
}

sub dchIfNeeded {
      if ($opt_noautodch) {
          print "\nI: Done! No pending changelog entry was created since it was not requested.\n";
      }
      else {
          withecho "dch", "-D", "UNRELEASED", "-i", "NOT RELEASED YET";
          print "\nI: Done! Created the next changelog entry, please commit later or revert.\n";
      }
}

for(keys %{$c}) {
   setenv $_, $$c{$_};
}

if($opt_only_tag) {
   checktag;
   mychdir $$c{"trunkDir"};
   system "$opt_pretag" if($opt_pretag);
   withecho ("svn", "-m", "$scriptname Tagging $package ($tagVersion)", "cp", $$c{"trunkUrl"}, $$c{"tagsUrl"}."/$tagVersion");
   system "$opt_posttag" if($opt_posttag);
   dchIfNeeded;
   SDCommon::sd_exit 0;
}

print "D: ",$opt_prebuild if $opt_verbose;

system "$opt_prebuild" if($opt_prebuild);

$$c{"buildArea"}=long_path($startdir."/..")."/build-area" if(!$$c{"buildArea"});

mkdir $$c{"buildArea"} if (! -d $$c{"buildArea"});

my $orig = $package."_".$upVersion.".orig.tar.gz";

if ($$c{"origDir"}) {
   $origExpect = $$c{"origDir"}."/$orig"; # just for the messages
   if (-f $origExpect) {
      $origfile = long_path($origExpect); # for the actual operation
   }
} else {
    $origExpect = "(location unknown, guessed: ../tarballs/$orig)";
    if(-f ($startdir . "/../tarballs/$orig")) {
        $origfile = long_path($startdir . "/../tarballs/$orig");
    }
};

if(!defined($origfile)) {
    $$c{"origDir"} = $startdir . "/../tarballs/" if(!defined($$c{"origDir"}));
    system("mkdir", "-p", $$c{"origDir"}) if (! -d $$c{"origDir"});
    print "Orig tarball not found (expected $origExpect)\n";
    if ($$c{"origUrl"}) {
        my $oUrl = $$c{"origUrl"};
        print "fetching tarball from $oUrl...\n";
        system "wget -O $origExpect $oUrl" ;
        $origfile = long_path($origExpect); # now the file should exist
    }
}
if($opt_download_tarball) {
    if(!defined($origfile)) {
        print "Trying to download tarball using apt\n";
        my $olddir = getcwd();
        mychdir $$c{"origDir"};
        my @archive_versions = split("\n", `apt-cache policy $package`);
        @archive_versions = grep /^(( \*\*\* |     )[0-9])/, @archive_versions;
        map {$_ =~ s/^ \*\*\* /     /; $_ =~ s/^     ([^ ]+) .*$/$1/; $_} @archive_versions;
        foreach(@archive_versions) {
            my $upstream_version = "$_";
            $upstream_version =~ s/^.*://;
            $upstream_version =~ s/(.*)-([^-]+)/$1/;
            if($upstream_version eq $upVersion) {
                system("apt-get source --tar-only $package=$_");
                if(($? >> 8) == 0 && -f $orig) {
                    $origfile = long_path($orig);
                    last;
                }
            }
        }
        mychdir $olddir;
    }
    if(-f "debian/watch" && !defined($origfile)) {
        print "Trying to download tarball using uscan\n";
        system("uscan", "--destdir", $$c{"origDir"}, "--repack", "--download-version", $upVersion, "--force-download");
        if(-f $$c{"origDir"} . "/$orig") {
            $origfile = long_path($$c{"origDir"} . "/$orig");
        }
    };
    if($opt_download_tarball && !defined($origfile)) {
        print STDERR ("Couldn't find a tarball\n");
    }
}

my $ba=$$c{"buildArea"};
my $ra=$ba;
if ($opt_moved_to) { $ra = $opt_moved_to; }
my $bdir="$ba/$package-$upVersion";

if($opt_rmprevbuilddir && -e "$bdir") {
   print STDERR "$bdir exists, removing it, as requested\n";
   system "rm -fr $bdir" ;
}

if(!$opt_reuse && -e "$bdir") {
   my $backupNr=rand;
   print STDERR "$bdir exists, renaming to $bdir.obsolete.$backupNr\n";
   rename("$bdir","$bdir.obsolete.$backupNr");
}

mkdir "$ba" if(! -d "$ba");

if(`svn proplist debian` =~ /mergeWithUpstream/i) {
   print "mergeWithUpstream mode detected, looking for $origExpect\n";
}

# gets the upstream branch out of svn into .orig directory
sub exportToOrigDir {
   # no upstream source export by default and never in mergeWithUpstream mode
   if((!$ENV{"FORCEEXPORT"}) || `svn proplist debian` =~ /mergeWithUpstream/i) {
      return 0;
   }
   needs_upsCurrentUrl;
   defined($$c{"upsCurrentUrl"}) || print STDERR "upsCurrentUrl not set and not located, expect problems...\n";
   withecho("rm", "-rf", "$bdir.orig");
   withecho "svn", "export",$$c{"upsCurrentUrl"},"$bdir.orig";
}

# bold-ifies the output
sub boldify {
   system ( "tput", "smso" ) if ( (defined $ENV{"TERM"}) && ($ENV{"TERM"}) ) ;
}
# unbold-ifies the output
sub unboldify {
   system ( "tput", "rmso" ) if ( (defined $ENV{"TERM"}) && ($ENV{"TERM"}) ) ;
}

# non-Debian-native package detected, needing some kind of upstream source for
# dpkg-buildpackage (most likely, spew error messages but continue on native
# packages with dashes)
if($tagVersion =~ /-/) {
   my $abs_origfile=long_path($origfile);
   $orig_target="$ba/".$orig;
   if($opt_verbose) {
      print "Trying different methods to export the upstream source:\n";
      print " - making hard or symbolic link from $origExpect\n" if (!$opt_nolinks);
      print " - copying the tarball to the expected destination file\n";
   }
   else {
      print "W: $abs_origfile not found, expect problems...\n" if(! -e $abs_origfile);
   }
   if($origfile && -e $abs_origfile) {
      if(-e $orig_target) {
         if(((stat($abs_origfile))[7]) != ((stat($orig_target))[7]))
         {
            die "$orig_target exists but differs from $abs_origfile!\nAborting, fix this manually...";
         }
      }
      else {
         # orig in tarball-dir but not in build-area
         if($opt_nolinks) {
            withechoNoPrompt("cp", long_path($origfile), "$ba/$orig")
            ||
            exportToOrigDir;
         }
         else {
            link(long_path($origfile),"$ba/".$orig)
            ||
            symlink(long_path($origfile),"$ba/".$orig)
            ||
            withechoNoPrompt("cp",long_path($origfile),"$ba/$orig")
            ||
            exportToOrigDir;
         }
      }
   }
   else {
      # no orig at all, try exporting
      exportToOrigDir;
   }
}

# contents examination for "cp -l" emulation
print STDERR "Creating file list...\n" if $opt_verbose;
my %tmp;
set_statusref(\%tmp);
my $ctx = new SVN::Client;
$ctx->status("", "BASE", \&SDCommon::collect_name, 1, 1, 0, 1);


# contents examination for "cp -l" emulation
print STDERR "Creating file list...\n" if $opt_verbose;
$ctx->status("", "BASE", \&SDCommon::collect_name, 1, 1, 0, 1);

for(keys %tmp) {
    s#/$##;
    next if !length($_);
    next if ($tmp{$_} eq 2 || $tmp{$_} eq 5 || $tmp{$_} eq 11); # skip junk and deleted files
    next if /^\s*$/;
    if(-d $_ and not -l $_ ) {
        push(@dirs,$_);
        print STDERR "DIR: $_\n" if $opt_verbose;
    }
    else {
        push(@files,$_);
        print STDERR "FILE: $_\n" if $opt_verbose;
    }
}

if(`svn proplist debian` =~ /mergeWithUpstream/i) {
   print STDERR "I: mergeWithUpstream property set, looking for upstream source tarball...\n";
   die "E: Could not find the origDir directory, please check the settings!\n" if(!(defined($$c{"origDir"}) && -e $$c{"origDir"}));
   die "E: Could not find the upstream source file! (should be $origExpect)\n" if(! ($origfile && -e $origfile));
   my $mod=rand;
   mkdir "$ba/tmp-$mod";
   if($opt_reuse && -d $bdir) {
      print "Reusing old build directory\n" if $opt_verbose;
   }
   else {
      withecho "tar", "--no-same-owner", "--no-same-permissions", "--extract", "--gzip", "--file", $origfile, "--directory", "$ba/tmp-$mod";
      my @entries = (<$ba/tmp-$mod/*>);
      if (@entries == 1) {
         # The files are stored in the archive under a top directory, we
         # presume
         withecho "mv", (<$ba/tmp-$mod/*>), $bdir;
      }
      else {
         # Otherwise, we put them into a new directory
         withecho "mv", "$ba/tmp-$mod", $bdir;
      }
   }
   if($opt_nolinks || $opt_ignnew) {
      withecho ("svn", "--force", "export", $$c{"trunkDir"},"$bdir");
   }
   else {
      mkdir $bdir;
      #fixme maybe rewrite to withecho
      if( !withechoNoPrompt("mkdir","-p", map { "$bdir/$_" } @dirs) || !withechoNoPrompt("cp", "--parents", "-laf", @files, $bdir))
      { # cp failed...
         withecho "svn", "--force", "export", $$c{"trunkDir"},"$bdir";
      }
   }
   withecho "rm", "-rf", "$ba/tmp-$mod";
}
else {
   if($opt_nolinks) {
      withecho "svn","--force", "export",$$c{"trunkDir"},"$bdir";
   }
   else {
      mkdir $bdir;
      # stupid autodevtools are confused but... why?
      #if(system("mkdir", map { "$bdir/$_" } sort(@dirs)) + system ("cp", "--parents", "-laf", @files, $bdir) )
      if( !withechoNoPrompt("mkdir","-p", map { "$bdir/$_" } @dirs) || !withechoNoPrompt("cp", "--parents", "-laf", @files, $bdir))
      #open(tpipe, "| tar c --no-recursion | tar --atime-preserve -x -f- -C $bdir");
      #for(@dirs) {print tpipe "$_\n"}
      #close(tpipe);
      #if(system ("cp", "--parents", "-laf", @files, $bdir))
      { # cp failed...
         system "rm", "-rf", $bdir;
         withecho "svn", "--force", "export",$$c{"trunkDir"},$bdir;
      }
   }
}

# clean up file permissions in bdir
# "stolen" from dpkg-source, see #390915
my ($mode, $modes_set, $i, $j);
$mode = 0777 & ~umask;
for ($i=0; $i<9; $i+=3) {
    $modes_set .= ',' if $i;
    $modes_set .= qw(u g o)[$i/3];
    for ($j=0; $j<3; $j++) {
	$modes_set .= $mode & (0400 >> ($i+$j)) ? '+' : '-';
	$modes_set .= qw(r w X)[$j];
    }
}
withecho 'chmod', '-R', $modes_set, '--', $bdir;

# a cludge...
my $afile;
my $bfile;
my $cfile;
if($opt_pass_diff) {
   my $dirname="$package-$upVersion";
   needs_upsCurrentUrl;

   if(`env LC_ALL=C svn status $$c{"trunkDir"}` =~ /(^|\n)(A|M|D)/m) {
      print STDERR "Warning, uncommited changes found, using combinediff to merge them...\n";
      chomp($afile=`mktemp`);
      chomp($bfile=`mktemp`);
      chomp($cfile=`mktemp`);
      withecho "svn diff ".$$c{"upsCurrentUrl"}." ".$$c{"trunkUrl"}." > $afile";
      withecho "cd ".$$c{"trunkDir"}." ; svn diff > $bfile";
      withecho "combinediff $afile $bfile > $cfile";
      open(DIFFIN, "cat $cfile |");
   }
   else {
      open(DIFFIN, "svn diff ".$$c{"upsCurrentUrl"}." ".$$c{"trunkUrl"}." |");
   }
   open(DIFFOUT,">$tmpfile");
   # fix some diff junk
   my $invalid=1;
   while(<DIFFIN>) {
      s!^--- (\S+).*!--- $dirname.orig/$1!;
      s!^\+\+\+ (\S+).*!+++ $dirname/$1!;
      $invalid=0 if(/^---/);
      $invalid=1 if( (!$invalid) && /^[^+\-\t\ @]/);
      $invalid || print DIFFOUT $_;
   }
   close(DIFFIN);
   close(DIFFOUT);
   $ENV{"DIFFSRC"}=$tmpfile;
}

mychdir($bdir);

if($opt_export) { print "Build directory exported to $bdir\n"; exit 0;}

if (!withecho(@builder)) {
   system "$opt_postbuild" if($opt_postbuild);
   print STDERR "build command failed in $bdir\nAborting.\n";
   print STDERR "W: build directory not purged!\n";
   print STDERR "W: no lintian checks done!\n" if($opt_lintian);
   print STDERR "W: package not tagged!\n" if($opt_tag);
   SDCommon::sd_exit 1;
}
else {

    system "$opt_postbuild" if($opt_postbuild);

    mychdir "..";

    if( ! $opt_postbuild) {
        my $chfile='';
        my @newfiles=();
        my $determined_arch;
        if(grep {$_ eq "-S" or $_ eq "\"-S\""} @ARGV) {
            $determined_arch = 'source';
        } else {
            $determined_arch = `dpkg --print-architecture`;
        }
        for my $arch ($determined_arch, $opt_architecture) {
            next if ! $arch;
            my $file="$package"."_$tagVersionNonEpoch"."_$arch.changes";
            $file=~s/\r|\n//g; # something like chomp before does not work on constant values, 'source'
            push(@newfiles, "$ra/$file") if -e "$ra/$file";
            $chfile=$file if(-r "$ra/$file");
        }

        if(-f "$ra/$chfile" && open(CH, "<$ra/$chfile")) {
            while(<CH>) { push(@newfiles, $1) if(/^\s\w+\s\d+\s\S+\s\w+\s(.+)\n/); }
            close(CH);

            if($opt_move) {
                $retval=!withechoNoPrompt("mv", @newfiles, $destdir);
                if (-e $orig_target) {
                    $retval=!withechoNoPrompt("mv", $orig_target, $destdir);
                    push(@newfiles, $orig_target);
                }
            }
            else { $destdir=$ra; }

            # expand the paths in the list and kick non-binary packages
	          my $multi=0;
            map { if(/\.deb$/){ $_=" $destdir/$_"; $multi++}else{$_=""}} @newfiles;

            &boldify;
            print STDERR "build command was successful";
            print STDERR "; binaries are in $destdir/" if ($multi > 0);
            print STDERR ". The changes file is:\n $destdir/$chfile\n";
            &unboldify;
            print STDERR "Binary package", ($multi > 1 ? "s:\n" : ":\n"), @newfiles, "\n" if($multi > 0);

            &boldify;
            print STDERR
               "Warning: $package should have an orig tarball but it does not!\nExpected filename: $origExpect\n"
               if(($upVersion ne $tagVersionNonEpoch) && ($tagVersionNonEpoch =~/-1$/) && !-e "$destdir/$orig");
            &unboldify;

            if($opt_lintian) {
                withecho "lintian", "$destdir/$chfile";
            }
        }
        else
        {
            &boldify if ($opt_move or $opt_lintian);
            print STDERR "Could not read the .changes file: $ra/$chfile";
            print STDERR " and thus failed to move the resulting files" if ($opt_move);
            if($opt_lintian) {
                if ($opt_move) {
                    print STDERR " and run lintian";
                } else {
                    print STDERR " and thus failed to run lintian";
                }
            }
            print STDERR ".\n";
            &unboldify if ($opt_move or $opt_lintian);
        }

        print $linda_warning if($opt_linda);
    }

   if($opt_tag) {
      system "$opt_pretag" if($opt_pretag);
      checktag;
      withecho ("svn", "-m", "$scriptname Tagging $package ($tagVersion)", "cp", $$c{"trunkUrl"}, $$c{"tagsUrl"}."/$tagVersion");
      system "$opt_posttag" if($opt_posttag);
      mychdir $$c{"trunkDir"};
      dchIfNeeded;
   }

   # cleanup
   if(!$opt_dontpurge) {
      withecho "rm", "-rf", $bdir if(length($tagVersion));
      for($tmpfile, $afile, $bfile, $cfile) {
         unlink $_ if(defined $_ and -e $_);
      }
   }
}
SDCommon::sd_exit 0+$retval;


