#!/usr/bin/perl
# (c) Eduard Bloch <blade@debian.org>, 2003
# License: GPL

use Getopt::Long qw(:config no_ignore_case bundling);
use File::Basename;
use Cwd;
use Cwd 'abs_path';
use File::Basename;

$startdir=getcwd;

sub help {
        print <<END
Usage: svn-inject  [options] [ <package>.dsc ] [ URL ]
Options: 
  -h           print this message
  -v           Make the commands verbose
  -q           Don't show command calls
  -l <digit>   Layout type (1=pkg/function, 2=function/pkg/)
                           (2 not implemented yet)
  -t <string>  Directory where you like to store the .orig files
  -o           Only keep modified files under SVN control (experimental)
  -c <digit>   Checkout the tree after injecting 
               (0=don't do, 1=trunk only (default), 2=complete tree)

Note that that svn-inject expects to be executed from the core directory
of the Debian-SVN repository (containing trunk/tags/branch directories).
If URL is omited, svn-inject tries to get it from the current directory.
In this case, -c becomes ineffective.

END
;
exit 1;
}

# The defaults
chomp($tempdir=`mktemp -d`);

my $initial_run;
my $opt_debug;
my $opt_svnurl;
my $opt_layout;
my $opt_quiet;
my $opt_tardir;
my $opt_checkout=1;

# parse Command line
# Note that we use `"$@"' to let each command-line parameter expand to a 
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.

%options = (
   "h|help"                => \$opt_help,
   "v|verbose"             => \$opt_verbose,
   "q|quiet"             => \$opt_quiet,
   "t"                     => \$opt_tardir,
   "l"                     => \$opt_layout,
   "o"                     => \$opt_onlychanged,
   "c=i"                   => \$opt_checkout
);

&help unless ( GetOptions(%options));
&help if ($opt_help);
&help if $#ARGV < 0;

use SD;

$opt_dsc=$ARGV[0];
$opt_svnurl=$ARGV[1];

if(! defined($opt_svnurl)) {
   $use_this_repo=1;
   $opt_svnurl=url(".");
}

if(! ($opt_dsc && $opt_svnurl)) {
   die "Need two arguments: <dsc file> <SVN url>\n";
}

die "Dsc file not readable!\n" if (! -r $opt_dsc);

$opt_dsc = Cwd::abs_path($opt_dsc);

$SVN_QUIET="-q";
$TAR_QUIET="";
$PATCH_QUIET="--silent";

if($opt_verbose) {
   $SVN_QUIET="";
   $TAR_QUIET="-v";
   $PATCH_QUIET="";
}

$SD::opt_quiet=$opt_quiet;

open($dsc, "<$opt_dsc");
while(<$dsc>) {
   # NEVER USE abs_path HERE, it resolves the links
   $package=$1 if(/^Source: (.+)\n/);
#   $dscVersion = $1 if(/^Version: (\S+)\n/);
   $dscOrig = dirname($opt_dsc)."/$1" if(/^\s\w+\s\d+\s(.+orig.tar.gz)\n/);
   $dscDiff = dirname($opt_dsc)."/$1" if(/^\s\w+\s\d+\s(.+\.diff.gz)\n/);
#   $dscNat  = abs_path($1) if( (!$dscOrig) && /^\s\w+\s\d+\s(.+tar.gz)\n/);
}

if($dscOrig) {
   $dscOrig=~ /_(.*)\.orig.t/;
   $upsVersion=$1;
}

# expanding the paths now

$dscOrig=abs_path($dscOrig);
$dscDiff=abs_path($dscDiff);

if($dscOrig) {
   $opt_tardir=abs_path("$startdir/tarballs") if(!$opt_tardir);
   mkdir $opt_tardir if(!-d $opt_tardir);
   withecho "cp $dscOrig $opt_tardir || true";
}

$SD::c{"origDir"}=abs_path($opt_tardir);

if($opt_onlychanged && $dscDiff) {
   open($dl, "zcat $dscDiff|");
   while(<$dl>) {
      push(@difflist, $1) if(/^\+\+\+\ [^\/]+\/(.+)\n/);
   }
   close($dl);
}

chdir $tempdir;

if($dscOrig) {
   withecho "mkdir -p $package/branches/upstream";
   chdir "$package/branches/upstream";
   withecho "tar $TAR_QUIET -z -x -f $dscOrig";
   if(@difflist) {
      # .../upstream/ was empty
      withecho "mv * $upsVersion";
      mkdir "current";
      chdir $upsVersion;
      withecho("tar $TAR_QUIET -c ".join(' ',@difflist)." 2>/dev/null | tar x $TAR_QUIET -C ../current");
      chdir "..";
      withecho "rm -rf $upsVersion";
   }
   else {
      withecho "mv * current";
   }
}
else {
   mkdir $package;
   chdir $package;
   withecho "dpkg-source -x $opt_dsc";
   system "rm -f *.gz";
   withecho "mv * trunk";
}
chdir $tempdir;
mkdir "$package/tags";
$SD::c{"tagsUrl"}="$opt_svnurl/$package/tags";
$SD::c{"upsCurrentUrl"}="$opt_svnurl/$package/branches/upstream/current";
$SD::c{"upsTagUrl"}="$opt_svnurl/$package/branches/upstream";

withecho "svn $SVN_QUIET import -m\"Installing original source version\" $package $opt_svnurl/$package";
if($dscOrig) {
   withecho("svn", "-m", "Tagging upstream source version", "copy",
   "$opt_svnurl/$package/branches/upstream/current",
   "$opt_svnurl/$package/branches/upstream/$upsVersion", $SVN_QUIET);
   withecho("svn", "-m", "Forking to Trunk", "copy",
   "$opt_svnurl/$package/branches/upstream/current",
   "$opt_svnurl/$package/trunk", $SVN_QUIET);
   mkdir "tmp";
   chdir "tmp";
   withecho "dpkg-source -x $opt_dsc";
   system "rm -f *.gz";
   if(@difflist) {
      withecho "mv * $upsVersion";
      mkdir "newtrunk";
      chdir $upsVersion; withecho "tar $TAR_QUIET -c ".join(' ',@difflist)." 2>/dev/null | tar $TAR_QUIET x -C ../newtrunk"; 
      chdir "..";
      withecho "svn_load_dirs $opt_svnurl/$package/trunk . newtrunk";
   }
   else {
      withecho "svn_load_dirs $opt_svnurl/$package/trunk . *";
   }
}

chdir $startdir;
if($use_this_repo) {
   withecho "svn up";
   $trunkdir = "$package/trunk";
}
else {
   if($opt_checkout==2) {
      print "Storing copy of your repository tree in $startdir/$package.\n";
      withecho "svn co $opt_svnurl/$package $startdir/$package $SVN_QUIET";
      $trunkdir = "$startdir/$package/trunk";
   }
   elsif ($opt_checkout==1) {
      print "Storing trunk copy in $startdir/$package.\n";
      withecho "svn co $opt_svnurl/$package/trunk $startdir/$package $SVN_QUIET";
      $trunkdir = "$startdir/$package";
   }
   else {
      # we still need the trunk directory to apply the ugly workaround
      # for svn's lack of propset function on remote targets
      withecho "svn co $opt_svnurl/$package/trunk $tempdir/trunk $SVN_QUIET";
      chdir "$tempdir/trunk";
   }
}

chdir $trunkdir if($trunkdir);
withecho "svn propset mergeWithUpstream 1 debian" if ($opt_onlychanged);
withecho "svn propset svn:executable 1 debian/rules $SVN_QUIET";
withecho "svn -m\"Fixing debian/rules permissions\" commit debian $SVN_QUIET";

SD::writeCfg;
print "Done! Removing tempdir.\n";
system "rm -rf $tempdir";
print ("Your working directory is $trunkdir - have fun!\n") if($trunkdir);
