#!/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 File::Basename;

$startdir=getcwd;
$scriptname="[svn-inject]";

sub help {
        print <<END
Usage: svn-inject [options] <package>.dsc <repository 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)

If the base repository URL is omited, svn-inject tries to get it from
the current directory. In this case, -c becomes ineffective.

END
;
exit 1;
}

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

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

use lib "/usr/share/svn-buildpackage";
use SDCommon;
$SDCommon::opt_verbose=$opt_verbose;

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

if(! defined($opt_svnurl)) {
   # we use the current directory and its reflection in the repository as
   # base for the package tree
   $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 = long_path($opt_dsc);

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

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

$SDCommon::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($opt_checkout && -d "$startdir/$package") {
   die "$startdir/$package already exists, aborting...\n";
}

# expanding the paths now, extracting upstream version
if($dscOrig) {
   $dscOrig=long_path($dscOrig);
   $dscOrig=~ /_(.*)\.orig.t/;
   $upsVersion=$1;
}
$dscDiff=long_path($dscDiff);

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

$SDCommon::c{"origDir"}=long_path($opt_tardir);

# creating the list of relevant files for mergeWithUpstream mode
if($opt_onlychanged && $dscDiff) {
   open($dl, "zcat $dscDiff|");
   while(<$dl>) {
      push(@difflist, $1) if(/^\+\+\+\ [^\/]+\/(.+)\n/);
   }
   close($dl);
}

chdir $tempdir;

# preparing a package tree that will be inserted into repository later
if($dscOrig) {
   # prepare the upstream source
   withecho "mkdir -p $package/branches/upstream";
   chdir "$package/branches/upstream";
   withecho "tar $TAR_QUIET -z -x -f $dscOrig";
   oldSvnDirsCheck ".";
   @filesInside=(<*>);
   if(@difflist) {
      if($#filesInside > 0) {
         mkdir $upsVersion;
      }
      withecho("mv",@filesInside, $upsVersion);
      #  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 {
      if($#filesInside > 0) {
         mkdir "current";
      }
      withecho("mv",@filesInside, "current");
      # withecho "mv * current";
   }
}
else {
   # native packages are easier
   mkdir $package;
   chdir $package;
   withecho "dpkg-source -x $opt_dsc";
   system "rm -f *.gz";
   withecho "mv * trunk";
}

chdir $tempdir;

# Final tree prepation before commit, preconfiguring already
mkdir "$package/tags";
$SDCommon::c{"tagsUrl"}="$opt_svnurl/$package/tags";
$SDCommon::c{"upsCurrentUrl"}="$opt_svnurl/$package/branches/upstream/current";
$SDCommon::c{"upsTagUrl"}="$opt_svnurl/$package/branches/upstream";

# go, go, go
withecho "svn $SVN_QUIET import -m\"$scriptname Installing original source of $package\" $package $opt_svnurl/$package";

# for non-native: create the trunk copy from the source and divert it
if($dscOrig) {
   withecho("svn", "-m", "$scriptname Tagging upstream source version of $package", "copy",
   "$opt_svnurl/$package/branches/upstream/current",
   "$opt_svnurl/$package/branches/upstream/$upsVersion", $SVN_QUIET);
   withecho("svn", "-m", "$scriptname Forking $package source 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";
   # now use svn_load_dirs to upgrade the trunk fork to Debian versions.
   # For mergeWithUpstream mode, extract the interessting files to a new
   # directory and load this one instead
   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";
   }
   elsif($opt_onlychanged) {
      # we may still need the trunk directory for workarounds
      # 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);

if ($opt_onlychanged) {
   withecho "svn propset mergeWithUpstream 1 debian";
   withecho "svn -m\"$scriptname Setting properties of $package/debian/\" commit debian $SVN_QUIET";
}

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