#!/usr/bin/perl -w
use strict;
use warnings;
use Env qw($TEMP);

if (!$TEMP) {
  die("TEMP environment variable must be set!");
}

my $log = 1;
my $level = 0;

# Diagnostic logging: called at the beginning of a function, logs the function
# name and parameters, and increments the indent level.
sub enterLog($@)
{
  if ($log)
  {
    my ($f, @parms) = @_;
    $level++;
    my $format = "%" . $level * 2 . "s Enter %s";
    printf ($format, " ", $f);
    while (@parms)
    {
      print " ";
      my $parm = shift (@parms);
      print ($parm);
    }
    print "\n\n";
  }
}

# Diagnostic logging: called in the middle of functions, logs the data at the
# current indent level.
sub printLog($)
{
  if ($log)
  {
    my ($arg) = @_;
    my $format = "%" . $level * 2 . "s %s\n";
    printf ($format, " ", $arg);
  }
}

# Diagnostic logging: called at the end of functions, decrements the indent.
sub exitLog
{
  if ($log)
  {
    my ($f, @parms) = @_;
    my $format = "%" . $level * 2 . "s Exit %s";
    printf ($format, " ", $f);
    while (@parms)
    {
      print " ";
      my $parm = shift (@parms);
      print ($parm);
    }
    print "\n\n";
    $level--;
  }
}

sub checkPwd($)
{
  my ($pwd) = @_;
  my $nowPwd = `pwd`;

  if ($pwd ne $nowPwd)
  {
    die("checkPwd failed!\n begin: $pwd\n close: $nowPwd\n");
  }
}

# User documentation of command line parameters.
# Note: format to 80 character line length in cygwin shell window.
sub instructions {
  print <<"Instructions";

  usage: ipc-tarball --tarball (path/to/tarball)

Instructions
  exit;
}

my $tarball = "";

# Determine what to build: start with environment variables, override them with
# the command line parameters.
sub processParameters
{
  enterLog("processParameters", @_);

  # defaults
  my $tarballSet = 0;
  while (@ARGV)
  {
    my $param = shift (@ARGV);
    if ($param eq "--help")
    {
      instructions();
    }
    elsif ($param eq "--tarball")
    {
      if ($tarballSet) {
        die("ipc-tarball.pl aborted: You can't use the same argument twice!");
      }
      $tarball = shift (@ARGV);
      if (!(-e $tarball)) {
        die("ipc-tarball.pl aborted: The --tarball argument must point to an existing file!");
      }
      print "--tarball recognized\n";
      $tarballSet = 1;
    }
  }

  if (!$tarballSet)
  {
    die("ipc-tarball.pl aborted:  You must use the --tarball argument!");
  }
  $tarball =~ s/\n//;

  exitLog("processParameters", @_);
}

sub executeCommands($)
{
  enterLog("executeCommands");
  my ($cmdSource) = @_;
  # No one exits this command in a different directory than they started.
  my $pwd = `pwd`;

  my @cmdArray = split(/\n/, $cmdSource);
  my $cmd;
  foreach $cmd (@cmdArray) {
    print $cmd . "\n";

    # blank lines
    if (!($cmd =~ /\S/))
    {
      next;
    }

    # comments
    # XXX ajvincent We leave the possibility for ifdefs by requiring a space
    #     after the #.
    if ($cmd =~ /^# /)
    {
      next;
    }

    # changing directories
    if ($cmd =~ /^cd /)
    {
      $cmd =~ s/^cd //;
      my $dir = $cmd;
      if (index($cmd, "/") != 0)
      {
        $dir = `pwd`;
        $dir =~ s/\n//;
        $dir .= "/$cmd";
      }
      chdir $dir;
      next;
    }

    my $cmd_status = system($cmd);
    if ($cmd_status != 0)
    {
      exit 2;
    }
  }
  checkPwd($pwd);
  exitLog("executeCommands");
}


processParameters();

sub extractTarball() {
  enterLog("extractTarball", @_);
  my $cmd = <<TARBALL
cd extensions
rm -rvf ipc
tar -xzvf $tarball
cd ..
TARBALL
;
  executeCommands($cmd);
  exitLog("extractTarball", @_);
}

sub processDir($$) {
  enterLog("processDir", @_);
  my ($dir, $topdir) = @_;

  # Makefile.in handling.
  my $Makefile_in_path = $dir . "Makefile.in";
  rename($Makefile_in_path, $Makefile_in_path . ".bak");
  my $Makefile_bak = $Makefile_in_path . ".bak";

  # sed -e 's/\/..\/..$//g' $Makefile_bak
  my $cmd = "sed -e 's/\\\/..\\\/..\$//g' $Makefile_bak";
  print $cmd . "\n";
  my $Makefile_in = `$cmd`;

  open (MAKEFILE_IN, ">$Makefile_in_path");
  print MAKEFILE_IN $Makefile_in;
  close(MAKEFILE_IN);

  # CVS/Entries handling.
  my $CVS_Entries_path = $dir . "CVS/Entries";

  my $CVS_Entries = "";
  open (ENTRIES, "<$CVS_Entries_path") || die("Can't open file $CVS_Entries_path!");
  while (my $line = <ENTRIES>)
  {
    chomp($line);
    if ($line =~ /^\//)
    {
      my $index = index($line, "/", 1);
      $line = substr($line, 0, $index) . "/0/dummy timestamp//";
    }
    if (($line =~ /Makefile.in.ipc/) ||
        ($line =~ /makefile.win/))
    {
      next;
    }
    if ($topdir)
    {
      if (($line =~ /makemake/) ||
          ($line =~ /changelog.txt/) ||
          ($line =~ /response.txt/) ||
          ($line =~ /review.txt/))
      {
        next;
      }
    }
    $CVS_Entries .= $line . "\n";
  }
  close(ENTRIES);

  # makefiles.sh
  if ($topdir) {
    $CVS_Entries .= "/makefiles.sh/0/dummy timestamp//\n";
  }

  open(ENTRIES, ">$CVS_Entries_path") || die("Can't open file $CVS_Entries_path for writing!");
  print ENTRIES $CVS_Entries;
  close(ENTRIES);

  # CVS/Repository handling.
  my $CVS_Repository_path = $dir . "CVS/Repository";
  # sed -e 's/^enigmail\/src\//mozilla\/extensions\//'
  my $CVS_Repository = `sed -e 's/^enigmail\\\/src\\\//mozilla\\\/extensions\\\//' $CVS_Repository_path`;

  open(REPO, ">$CVS_Repository_path");
  print REPO $CVS_Repository;
  close(REPO);

  # CVS/Root handling.
  $cmd = <<"COPY_ROOT"
rm -rf $dir/CVS/Root
cp $dir/../CVS/Root $dir/CVS/Root
COPY_ROOT
;
  executeCommands($cmd);

  # Go recursive.
  opendir(DIR, $dir);
  my @DIR_FILES = readdir DIR;
  foreach my $i (@DIR_FILES)
  {
    chomp($i);
    if (($i eq "CVS") ||
        ($i eq ".") ||
        ($i eq ".."))
    {
      next;
    }

    if (-d "$dir/$i")
    {
      processDir("$dir/$i/", 0);

      next;
    }
  }
  closedir(DIR);

  exitLog("processDir", @_);
}

sub addToMozillaTree($) {
  enterLog("addToMozillaTree", @_);
  my ($dir) = @_;
  if (!(-e $dir . "/extensions/CVS/Entries.ipc")) {
    my $cmd = <<"COPY"
cp $dir/extensions/CVS/Entries $dir/extensions/CVS/Entries.ipc
COPY
;
    executeCommands($cmd);

    open(ENTRIES, ">>$dir/extensions/CVS/Entries");
    print ENTRIES "D/ipc////\n";
    close ENTRIES;
  }

  # makefiles.sh
  my $cmd = "ls -R $dir/extensions/ipc";
  my $full_list = `$cmd`;
  chomp($full_list);

  my @lines = split(/\n/, $full_list);

  my @FILES = grep(/^\//, @lines);
  my $path_len = length($dir) + 1;

  my $makefiles_sh = <<"MAKEFILES_SH"
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "MPL"); you may not use this file
# except in compliance with the MPL. You may obtain a copy of
# the MPL at http://www.mozilla.org/MPL/
#
# Software distributed under the MPL is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the MPL for the specific language governing
# rights and limitations under the MPL.
#
# The Original Code is protoZilla.
#
# The Initial Developer of the Original Code is Ramalingam Saravanan.
# Portions created by Ramalingam Saravanan <svn\@xmlterm.org> are
# Copyright (C) 2001 Ramalingam Saravanan. All Rights Reserved.
#
# Contributor(s):
# Patrick Brunschwig <patrick\@mozilla-enigmail.org>
# Alexander J. Vincent <ajvincent\@gmail.com>
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU General Public License (the "GPL"), in which case
# the provisions of the GPL are applicable instead of
# those above. If you wish to allow use of your version of this
# file only under the terms of the GPL and not to allow
# others to use your version of this file under the MPL, indicate
# your decision by deleting the provisions above and replace them
# with the notice and other provisions required by the GPL.
# If you do not delete the provisions above, a recipient
# may use your version of this file under either the MPL or the
# GPL.
#

add_makefiles "
MAKEFILES_SH
;

  foreach my $i (@FILES)
  {
    my $path = substr($i, $path_len, -1);
    if (($path !~ /\/CVS$/) && ($path ne "CVS"))
    {
      $makefiles_sh .= "  $path/Makefile\n"
    }
  }

  $makefiles_sh .= "\"\n";

  open(MAKEFILES_SH, ">$dir/extensions/ipc/makefiles.sh");
  print MAKEFILES_SH $makefiles_sh;
  close(MAKEFILES_SH);

  exitLog("addToMozillaTree", @_);
}

sub main() {
  enterLog("main", @_);
  extractTarball();

  my $currentdir = `pwd`;
  $currentdir =~ s/\n//;

  processDir($currentdir . "/extensions/ipc/", 1);
  addToMozillaTree($currentdir);

  my $cvs_cmd = "cvs diff -pu8N extensions/ipc > ../ipc-patch.diff";
  executeCommands($cvs_cmd);

  exitLog("main", @_);
}

main();
