#!/usr/local/bin/perl -w

=head1 NAME

p4.t - testing of vcp p4 i/o

=cut

use strict ;

use Carp ;
use File::Spec ;
use Test ;
use VCP::TestUtils ;

my $t = -d 't' ? 't/' : '' ;

my @vcp = ( vcp_cmd, "vcp:-" );

my $project = "revml2vss";

## Repositories to read from
my $vssroot_0 = "${t}vssroot_0";
my $vssroot_1 = "${t}vssroot_1";

my $vssspec_0 = "vss:Admin\@$vssroot_0:$project";
my $vssspec_1 = "vss:Admin\@$vssroot_1:$project";

## where to put the destination repository
my $destroot = tmpdir "destp4root";

my $state_location = tmpdir "vcp_state";

## where to write to in the destination repo
my $dest_spec = "p4:$destroot://depot/...";

my $repo_id;

sub _clean_up_in_and_out {
   my ( $in_ref, $out_ref ) = @_;

   $$out_ref =~ s/(<action\s*>)add/$1edit/g;
      ## P4 does "add", VSS doesn't.

   s_content qw( rep_type ),        $in_ref,           "p4";
   s_content qw( user_id ),         $in_ref,           "Admin";
   rm_elts   qw( mod_time ),        $in_ref;
   rm_elts   qw( p4_info ),                  $out_ref;
   s_content qw( rev_root ),        $in_ref,           "depot";
   s_content qw( source_repo_id ),  $in_ref,           "p4:test_repository";
   s_content qw(
      rep_desc time rev_id source_rev_id change_id source_change_id
   ), $in_ref, $out_ref;
   $$in_ref =~ s{(id="|_id>)/+ignored}{$1//depot}g;

   rm_elts qw( placeholder ), $in_ref;
   rm_elts qw( comment ), qr{create_branches\r?\n}, $out_ref;

   rm_elts qw( change_id source_change_id ), $in_ref, $out_ref;
      ## vss has no change_ids

   rm_elts qw( comment ), qr/[^<]*\[vcp\][^<]*/, $out_ref;
      ## remove the "[vcp] using estimated..." comments

   rm_elts qw( user_id ), qr/unknown_vss_user/, $out_ref;

   ## VSS provides neither type nor time on deletions
   $$out_ref =~
       s{(<action\s*>delete.*?)[ \t]*<type>[^<]*</type>\r?\n}{$1}gs;

   $$out_ref =~
       s{(<action\s*>delete.*?)[ \t]*<time>[^<]*</time>\r?\n}{$1}gs;

   ## p4 is more parsimonious with its version numbers than vss
   $$in_ref  =~ s{#[0-9.]+("|<)}{#deleted by test suite$1}g;
   $$out_ref =~ s{#[0-9.]+("|<)}{#deleted by test suite$1}g;

}

my @tests = (
##
## vss->p4 bootstrap
##
## read p4root_0 into destroot
sub {
   my $vcp_spec = <<VCP_FILE;
Source:      $vssspec_0/...
               --repo-id=vss:test_repository

Destination: $dest_spec
               --init-p4d
               --delete-p4d-dir
               --db-dir=$state_location
               --repo-id=p4:dest_test_repository

VCP_FILE

   eval { run \@vcp, \$vcp_spec };
   ok $@ || '', '';
},

## read repository built in previous test, and compare it to the
## test-vss-in-0.revml to see how it compares to a file that hasn't been
## through a revml->vss->p4->revml pipeline.
sub {
   return skip "previous test failed", 1 if $@;

   my $infile  = $t . "test-vss-in-0.revml" ;
   my $in = slurp $infile ;
   my $out = get_vcp_output $dest_spec, "--run-p4d",
      "--repo-id=p4:test_repository",
      { revml_out_spec => [ "--db-dir=$state_location", "--repo-id=revml:test_repository" ] } ;

   _clean_up_in_and_out \$in, \$out;

   ok_or_diff $out, $in;
},

## --repo-id here should agree with the other one above that writes to
## the same destination.  because we are faking by reading from two
## different repositories that are really for test purposes snapshots
## of the same repository at two different moments in time.  
##
## because vcp would by default use the paths to these two
## repositories as the repo_ids, vcp would refuse to add an
## incremental export from the second repository on top of the
## revisions from the first repository.  by specifying the same
## repo_id in both places, we make vcp think that the revisions came
## from the same repository.

##
## vss->p4 incremental export
##
## read from vssroot_1 repository into p4.
##
sub {
   eval { run \@vcp, \<<VCP_END; } or die $@;
Source:      $vssspec_1/...
               --repo-id=vss:test_repository
               --continue

Destination: $dest_spec
               --run-p4d
               --db-dir=$state_location
               --repo-id=p4:dest_test_repository

VCP_END

   ok 1;
},


## extract stuff inserted into cvs in the previous test and compare
## to the source revml to see that it got there ok.
sub {
   my $infile  = $t . "test-vss-in-1.revml" ;
   my $in = slurp $infile ;
   my $out = get_vcp_output $dest_spec, "--continue", "--run-p4d",
      "--repo-id=p4:test_repository",
      { revml_out_spec => [ "--db-dir=$state_location", "--repo-id=revml:test_repository" ] } ;
   
   _clean_up_in_and_out \$in, \$out;

   ok_or_diff $out, $in;
},

);  # end @tests.


plan tests => scalar @tests;

my $p4d_borken = $ENV{P4BORKEN}  || p4d_borken ;


my $why_skip ;
$why_skip .= "p4 command not found"  unless ( `p4 -V`  || 0 ) =~ /^Perforce/ ;
$why_skip .= "p4 missing or broken"  if $p4d_borken ;
$why_skip .= "vss missing or broken" if vss_borken;

$why_skip ? skip( $why_skip, '' ) : $_->() for @tests ;


syntax highlighted by Code2HTML, v. 0.9.1