#!/usr/bin/perl
# cpanel - cp_util/make_tar.pl                    Copyright(c) 2012 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
#
###############################################################################
#
# Make Tarballs
#
# This script will create the EasyApache tarballs from their unpacked source
# Generally called by cp_util/make_targzd_list.pl
#
# Usage:
#   --help          Print out a usage message
#   --verbose       Print progress messages during processing
#

use strict;
use warnings;

use Cwd          ();
use File::Find   ();
use Getopt::Long ();
use File::Temp   ();

my $opt_verbose = 0;
my $cwd         = Cwd::cwd();

sub make_tarball {
    my ($pmd) = @_;
    print "Processing $pmd ...\n";

    my $tgz_file = $pmd;
    $tgz_file =~ s{^.*/}{};    # Remove directory prefix
    $tgz_file =~ s{\.d$}{};    # Remove .d suffix
    my $ptar_file = $tgz_file . '.ptar';

    #my $local_changes = `git status --porcelain targz/$pmd`;
    my $local_changes = `git status --porcelain $pmd`;
    chomp $local_changes;

    chdir $pmd or die "Could not use directory $pmd: $!";

    my $ptar_exists = -e "../$ptar_file";

    if ( $local_changes || !$ptar_exists ) {
        print "Generating new tarball from sources\n" if $opt_verbose;

        # Get the list of top-level files and directories
        opendir my $dh, '.'
          or die "Could not open directory $pmd: $!";
        my @files = grep { !/^\.\.?$/ } ( readdir $dh );
        closedir $dh
          or die "Could not close directory handle";

        # Create the tarball
        system( 'tar', 'czf', "../$tgz_file", @files ) == 0
          or die "Could not create tarball $tgz_file: $!";

        # If there is no PTAR metadata file, create one
        if ( !$ptar_exists ) {
            print "Creating pristine tar data file\n" if $opt_verbose;
            system( 'pristine-tar', 'gendelta', "../$tgz_file", "../$ptar_file" ) == 0
              or die "Failed to create new $ptar_file";
        }
    }
    else {
        return if ( tarfile_is_valid( $tgz_file, $ptar_file ) );

        print "Regenerating the original tarball\n" if $opt_verbose;

        # Remove the existing tarball, if any
        if ( -e "../$tgz_file" ) {
            unlink "../$tgz_file" or die "Could not remove $tgz_file: $!";
        }

        # Regenerate the tarball
        system 'pristine-tar', '--skip-manifest-subdir', 'gentar', "../$ptar_file", "../$tgz_file"
          and die "Failed to regenerate $tgz_file from $ptar_file";
    }

    chdir $cwd
      or die "Could not use directory $cwd: $!";
    return 1;
}

sub tarfile_is_valid {
    my ( $tgz_file, $ptar_file ) = @_;

    return 0 if ( !-e "../$tgz_file" );

    print "Validating existing $tgz_file\n" if $opt_verbose;
    my $working_dir = Cwd::cwd();
    my $tmpdir      = File::Temp->newdir();

    print "Using temp dir $tmpdir\n" if $opt_verbose;
    chdir $tmpdir
      or die "Could not use temporary directory: $!";
    system( '/bin/tar', 'xzf', "$working_dir/../$ptar_file", 'delta' )
      and die "Failed to unpack ptar file: $!";
    my $xdelta = `/usr/local/cpanel/3rdparty/bin/xdelta info delta`
      or die "Failed to get delta data: $!";
    my $md5sum;
    $xdelta =~ m/output md5:\s+([0-9A-Fa-f]+)/s and $md5sum = $1;
    chdir $working_dir
      or die "Could not change back to original directory: $!";
    my $tarmd5sum = `/usr/bin/gzip -dc ../$tgz_file | /usr/bin/md5sum -`
      or die "Could not get md5sum of tarfile: $!";
    $tarmd5sum =~ s/\s+.*//s;

    return 1 if ( $md5sum eq $tarmd5sum );
    print "Checksum mismatch for $tgz_file: $md5sum $tarmd5sum\n" if $opt_verbose;
    return 0;

    # $tmpdir is cleaned up as it goes out of scope
}

Getopt::Long::GetOptions( 'verbose' => \$opt_verbose );
my $pmd = shift;
die "Missing directory argument" unless defined $pmd;
make_tarball($pmd);

exit 0;

