#! /usr/bin/perl
use strict;
use File::ReadBackwards;
use Getopt::Long;
use P4;


# Should be invoked with a lock file wrapper, like FreeBSD's lockf, or
# unixwiz.net's lockrun, to insure that there is no overlap between
# periodic executions.


# Assume Perforce configuration is controlled by a .p4config file
# in the converter's Perforce client workspace.  The p4 user doing
# the conversion should have a previously instantiated ticket that
# does not expire (user is member of a group that allows non-expiring
# tickets).
$ENV{'P4CONFIG'} = ".p4config";

# Assume SVN and convertion utilities are in /usr/local/bin
$ENV{'PATH'} .= ":/usr/local/bin";

### XXX Use getopt processing for this.
my $localTimeZone  = 'America/Denver';
my $conversionRoot = '/vmpool/FreeBSD-importer';
my $usersuffix     = '-fbsd';
my $svnRoot        = "file://" . $conversionRoot . '/svn';
my $p4Root         = $conversionRoot . '/perforce';
my $revmapFile     = $p4Root . '/revmap.csv';
my $svnLogFile     = $p4Root . '/svn_log.xml';

#### Update local copy of remote repository with svnsync
my $rc = system("svnsync", "--non-interactive", "--trust-server-cert",
		"sync", $svnRoot);
die "svnsync of $svnRoot failed: Exit status $rc" unless ($rc == 0);

# Determine the last revision in the SVN repository.
my $svnInfo = `svn info $svnRoot`;
my $lastSvnRev;;
foreach my $line (split /\n/, $svnInfo)
{
    if( $line =~ /Revision: (\d+)/ )
    {
        $lastSvnRev = $1;
        last;
    }
}
die "Unable to determine latest SVN revision" unless defined($lastSvnRev);

# Determine the next revision to import based on the last imported SVN
# revision that is recorded in $revmapFile.
my $nextSvnImportRev = 1;
if( my $fh = File::ReadBackwards->new( $revmapFile ) )
{
    $nextSvnImportRev = $fh->readline;
    $nextSvnImportRev =~ s/(\d+) \d+$/\1/
                      or die "Unable to determine last imported SVN revision";
    $nextSvnImportRev++;
}

if( $lastSvnRev < $nextSvnImportRev )
{
   print "Import already up to date.  Exiting\n";
   exit(0);
}
print "Importing SVN revisions $nextSvnImportRev - $lastSvnRev\n";

# Extract an XML revision log of unimported revisions
$rc = system("svn log --xml --stop-on-copy -v -r $nextSvnImportRev:HEAD $svnRoot > $svnLogFile");
die "svn log extraction failed: Exit status $rc" unless ($rc == 0);

# Operate from the root of the Perforce client in which we are performing
# the conversion.  This allows us to make use of any P4CONFIG based
# configuration settings.
chdir $p4Root;

# Save most recent Perforce changeset number.  This allows us to limit
# the number of revisions changemap_search.pl must process to only those
# created during this run.
my $p4 = new P4;
$p4->SetCwd($p4Root);
$p4->Connect()
    or die( "Failed to connect to Perforce Server.  Verify P4CONFIG setup.\n" );
my $lastP4Rev = $p4->RunCounter('change')->[0]->{ 'value' };
$p4->Disconnect();
print $lastP4Rev, "\n";

# Import revisions into Perforce.
$rc = system("echo 'y' | p4convert-svn_freebsd7x86_64 -S $svnRoot svn $svnLogFile $nextSvnImportRev HEAD");
die "p4convert-svn failed: Exit status $rc" unless ($rc == 0);

# Update author and date fields to match the source repository for
# all added revisions.
$rc = system("$p4Root/changemap_search.pl --startrev=$lastP4Rev --usersuffix=$usersuffix --non-interactive --localtimezone=\'$localTimeZone\'");
die "changemap_search.pll failed: Exit status $rc" unless ($rc == 0);

exit(0);
