#!/usr/local/bin/perl -w =head1 NAME cvs.t - testing of vcp cvs i/o =cut use strict ; use Carp ; use Cwd ; use File::Spec ; use IPC::Run qw( run ) ; use Test ; use VCP::TestUtils ; ## CVS, when batch commiting, does the commits in an order I don't ## understand. So we need to sort the results by running them ## back through a revml->revml conversion with the time field ## stripped out, because if the system clock ticks over while CVS is ## doing a batch import, then we'll get them in the wrong order when ## they come back out of the repository. I think. my @vcp = vcp_cmd ; my $t = -d 't' ? 't/' : '' ; my $module = 'foo' ; ## Must match the rev_root in the testrevml files my $cvs_spec ; my @revml_out_spec = ( "revml:", "--sort-by=name,rev_id" ) ; my $max_change_id ; my $p4_spec_base ; my $p4d_borken = $ENV{P4DBORKEN} || p4d_borken ; my @tests = ( sub { my $cvs_options = init_cvs "cvs_", $module ; $cvs_spec = "cvs:$cvs_options->{repo}:$module/" ; $ENV{CVSROOT} = "foobar" ; ok 1 ; }, ## ## Empty import ## sub { run [ @vcp, "revml:-", $cvs_spec ], \"<revml/>" ; ok $?, 0, "`vcp revml:- $cvs_spec` return value" ; }, ## ## revml->cvs->revml idempotency ## sub {}, ## Mult. ok()s in next sub{}. sub { eval { my $infile = $t . "test-cvs-in-0.revml" ; ## $in and $out allow us to avoide execing diff most of the time. run [ @vcp, "revml:$infile", $cvs_spec ], \undef or die "`vcp revml:$infile $cvs_spec` returned $?" ; ok 1 ; my $out ; $ENV{VCPNODELETE} = ".*"; $ENV{VCPDEBUG} = ".*"; run [ @vcp, $cvs_spec, @revml_out_spec ], \undef, \$out or die "`vcp $cvs_spec` returned $?" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id ), \$in, \$out ; s_content qw( rev_root ), \$in, $module ; rm_elts qw( mod_time change_id cvs_info ), \$in ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $in =~ s{(id="|id>)/ignored}{$1/foo}g; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff'; die; }, ## ## cvs->revml, re-rooting a dir tree ## sub { eval { ## Hide global $cvs_spec for the nonce my $cvs_spec = "$cvs_spec/a/deeply/..." ; my $out ; run [ @vcp, $cvs_spec, @revml_out_spec ], \undef, \$out or die "`vcp $cvs_spec` returned $?" ; my $infile = $t . "test-cvs-in-0.revml" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id ), \$in, \$out ; rm_elts qw( mod_time change_id cvs_info ), \$in, \$out ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; ## Strip out all files from $in that shouldn't be there rm_elts qw( rev ), qr{(?:(?!a/deeply).)*?}s, \$in ; ## Adjust the $in paths to look like the result paths. $in is ## now the "expected" output. s_content qw( rev_root ), \$in, "foo/a/deeply" ; $in =~ s{(<name>)a/deeply/}{$1}g ; $in =~ s{(id="|id>)/ignored}{$1/foo}g; ## No branches in the output file $in =~ s{^\s*<branches.*?</branches>\r?\n}{}ms; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, ## ## cvs->p4->revml ## sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; $ENV{P4USER} = "foobar_user" ; $ENV{P4PORT} = "foobar_port" ; $ENV{P4CLIENT} = "foobar_client" ; $ENV{P4PASSWD} = "foobar_passwd" ; my $p4_options = launch_p4d "cvs_" ; $p4_spec_base = "p4:$p4_options->{user}:\@$p4_options->{port}:" ; ok 1 ; }, sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; my $p4_spec = "$p4_spec_base//depot" ; eval { run [ @vcp, $cvs_spec, "$p4_spec/..." ], \undef or die "`vcp $cvs_spec` returned $?" ; my $out ; run [ @vcp, "$p4_spec/...", @revml_out_spec ], \undef, \$out ; my $infile = $t . "test-cvs-in-0.revml" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id rep_type ), \$in, \$out ; s_content qw( rev_root ), \$in, "depot" ; rm_elts qw( cvs_info mod_time change_id ), \$in ; rm_elts qw( p4_info ), \$out ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $out =~ s{<rev_id>}{<rev_id>1.}g ; $out =~ s{<base_rev_id>}{<base_rev_id>1.}g ; $out =~ s{^.*<change_id>(.*?)</change_id>.*(\r\n|\n\r|\n)}{ $max_change_id = $1 if ! defined $max_change_id || $1 > $max_change_id ; "" ; }gem ; $in =~ s{(id="|id>)/ignored}{$1//depot}g; $out =~ s{((id="|id>)[^>]*)#}{$1#1.}g; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; ok $max_change_id, 3, "Max change_id in cvs->p4 transfer" ; }, ## ## cvs->p4->revml, re-rooting a dir tree ## sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; ## Hide global $cvs_spec for the nonce my $cvs_spec = "$cvs_spec/a/deeply/..." ; my $p4_spec = "$p4_spec_base//depot/new/..." ; eval { run [ @vcp, $cvs_spec, $p4_spec ], \undef or die "`vcp $cvs_spec $p4_spec` returned $?" ; my $out ; run [ @vcp, $p4_spec, @revml_out_spec ], \undef, \$out or die "`vcp $p4_spec` returned $?" ; my $infile = $t . "test-cvs-in-0.revml" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id rep_type ), \$in, \$out ; s_content qw( rev_root ), \$in, "depot/new" ; rm_elts qw( cvs_info mod_time change_id ), \$in ; rm_elts qw( p4_info ), \$out ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $out =~ s{<rev_id>}{<rev_id>1.}g ; $out =~ s{<base_rev_id>}{<base_rev_id>1.}g ; ## Strip out all files from $in that shouldn't be there rm_elts qw( rev ), qr{(?:(?!a/deeply).)*?}s, \$in ; ## Adjust the $in paths to look like the result paths. $in is ## now the "expected" output. $in =~ s{<name>a/deeply/}{<name>}g ; $out =~ s{^.*<change_id>(.*?)</change_id>.*(\r\n|\n\r|\n)}{ $max_change_id = $1 if ! defined $max_change_id || $1 > $max_change_id ; "" ; }gem ; $in =~ s{(id="|id>)/ignored/a/deeply}{$1//depot/new}g; $out =~ s{((id="|id>)[^>]*)#}{$1#1.}g; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; ok $max_change_id, 6, "Max change_id in cvs->p4 transfer" ; }, ## ## Idempotency test for an incremental revml->cvs->revml update ## sub {}, ## Mult. ok()s in next sub{}. sub { my $infile = $t . "test-cvs-in-1.revml" ; eval { ## $in and $out allow us to avoid execing diff most of the time. run [ @vcp, "revml:$infile", $cvs_spec ], \undef or die "`vcp revml:$infile $cvs_spec` returned $?" ; ok 1 ; my $out ; run [ @vcp, $cvs_spec, qw( -r ch_4: ), @revml_out_spec ], \undef, \$out or die "`vcp $cvs_spec -r ch_4:` returned $?" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id ), \$in, \$out ; s_content qw( rev_root ), \$in, $module ; rm_elts qw( mod_time change_id cvs_info ), \$in ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $in =~ s{(id="|id>)/ignored}{$1/foo}g; # ch_4 only exists on the main branch (it's ch_4_branch_1 on the # side branches). $in =~ s{^\s*?<rev id="/foo/branch-0/branched#1\.1\.2\..*?<name>branch-0/branched.*?<rev_id>1\.1\.2\.\d+.*?</rev>\r?\n}{}gsm; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, ## ## Incremental cvs->p4->revml update ## sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; my $p4_spec = "$p4_spec_base//depot" ; eval { run [ @vcp, $cvs_spec, "-r", "ch_4:", "$p4_spec/..." ], \undef or die "`vcp $cvs_spec -r ch_4:` returned $?" ; my $out ; my $first_change = $max_change_id + 1 ; run [ @vcp, "$p4_spec/...\@$first_change,#head", @revml_out_spec ], \undef, \$out or die "`vcp $p4_spec/...\@$first_change,#head` returned $?" ; my $infile = $t . "test-cvs-in-1.revml" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id rep_type ), \$in, \$out ; s_content qw( rev_root ), \$in, "depot" ; rm_elts qw( cvs_info mod_time change_id ), \$in ; rm_elts qw( p4_info ), \$out ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $out =~ s{<rev_id>}{<rev_id>1.}g ; $out =~ s{<base_rev_id>}{<base_rev_id>1.}g ; $out =~ s{^.*<change_id>(.*?)</change_id>.*(\r\n|\n\r|\n)}{ $max_change_id = $1 if ! defined $max_change_id || $1 > $max_change_id ; "" ; }gem ; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, sub { return skip $p4d_borken, 1, 1, $p4d_borken if $p4d_borken ; ok $max_change_id, 9, "Max change_id in cvs->p4 transfer" ; }, ## ## revml->cvs->revml Idempotency test, bootstrapping the second set of changes ## sub { my $infile = $t . "test-cvs-in-1-bootstrap.revml" ; eval { my $out ; run [ @vcp, $cvs_spec, qw( -r ch_4: --bootstrap=... ), @revml_out_spec ], \undef, \$out or die "`vcp $cvs_spec -r ch_4:` returned $?" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id ), \$in, \$out ; s_content qw( rev_root ), \$in, $module ; rm_elts qw( mod_time change_id cvs_info ), \$in ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; $in =~ s{(id="|id>)/ignored}{$1/foo}g; # ch_4 only exists on the main branch (it's ch_4_branch_1 on the # side branches). $in =~ s{^\s*?<rev id="/foo/branch-0/branched#1\.1\.2\..*?<name>branch-0/branched.*?<rev_id>1\.1\.2\.\d+.*?</rev>\r?\n}{}gsm; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, ## ## revml->cvs, re-rooting a dir tree ## ## Do this after the above tests so that we don't accidently introduce ## a bunch of additional changes, especially for the cvs->p4 tests. ## sub {}, ## Two ok()'s in next sub. sub { eval { ## Hide global $cvs_spec for the nonce my $cvs_spec = "$cvs_spec/newdir/..." ; my $infile = $t . "test-cvs-in-0.revml" ; ## $in and $out allow us to avoide execing diff most of the time. run [ @vcp, "revml:$infile", $cvs_spec ], \undef or die "`vcp revml:$infile $cvs_spec` returned $?" ; ok 1 ; my $out ; run [ @vcp, $cvs_spec, @revml_out_spec ], \undef, \$out or die "`vcp $cvs_spec ", join( " ", @revml_out_spec ), "` returned $?" ; my $in = slurp $infile ; s_content qw( rep_desc time user_id ), \$in, \$out ; rm_elts qw( mod_time change_id cvs_info ), \$in, \$out ; rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; ## Adjust the $in rev_root to look like the result paths. $in is ## now the "expected" output. s_content qw( rev_root ), \$in, "foo/newdir" ; $in =~ s{(id="|id>)/ignored}{$1/foo/newdir}g; assert_eq $infile, $in, $out ; } ; ok $@ || '', '', 'diff' ; }, ### ### cvs->revml, using the VCP::Source::cvs --cd option ### (also depends on being able to reroot on input. #sub { # eval { # my $infile = $t . "test-cvs-in-0.revml" ; # ## $in and $out allow us to avoide execing diff most of the time. # my $cvs_spec = "$cvs_spec/cd_test" ; # run [ @vcp, "revml:$infile", $cvs_spec ], \undef # or die "`vcp revml:$infile $cvs_spec` returned $?" ; # # ok 1 ; # # my $out ; # run [ @vcp, $cvs_spec ], \undef, \$out # or die "`vcp $cvs_spec` returned $?" ; # # my $in = slurp $infile ; # # s_content qw( rep_desc time user_id ), \$in, \$out ; # s_content qw( rev_root ), \$in, $module ; # rm_elts qw( mod_time change_id cvs_info ), \$in ; # rm_elts qw( label ), qr/r_\w+|ch_\w+/, \$out ; # # assert_eq $infile, $in, $out ; # } ; # ok $@ || '', '', 'diff '; #}, # ) ; plan tests => scalar( @tests ) ; my $why_skip ; $why_skip .= cvs_borken ; $why_skip ? skip( $why_skip, 0 ) : $_->() for @tests ;
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#36 | 2268 | Barrie Slaymaker | factor out 91revml2cvs.t | ||
#35 | 2267 | Barrie Slaymaker | factor out cvs2revml, test both --use-cvs and direct modes, with times | ||
#34 | 2265 | Barrie Slaymaker | factor out t/95cvs2p4.pm and allow it to reuse the cvs repo for speed. | ||
#33 | 2246 | Barrie Slaymaker | let FATALTEST control fatality of tests | ||
#32 | 2245 | Barrie Slaymaker | cvs -r (re)implemented for direct reads, passes all cvs-only tests | ||
#31 | 2241 | Barrie Slaymaker | RCS file scanning improvements, implement some of -r | ||
#30 | 2240 | Barrie Slaymaker | Start on cvs -r option support. | ||
#29 | 2236 | Barrie Slaymaker | Debug, speed up cvs file parsing | ||
#28 | 2235 | Barrie Slaymaker | Debugging cvs speed reader. | ||
#27 | 2044 | Barrie Slaymaker | Tweak to reflect branched => branch-#/branched | ||
#26 | 2042 | Barrie Slaymaker | Basic source::p4 branching support | ||
#25 | 2026 | Barrie Slaymaker | VCP::8::cvs now supoprt branching | ||
#24 | 2006 | Barrie Slaymaker |
more preparations for branching support, handling of cvs :foo:... CVSROOT specs, misc fixes, improvements |
||
#23 | 1728 | Barrie Slaymaker | CVS on win32, minor bugfixes | ||
#22 | 1366 | Barrie Slaymaker | Require Regexp::Shellish 0.93 for '...' support | ||
#21 | 1358 | Barrie Slaymaker | Win32 changes | ||
#20 | 1055 | Barrie Slaymaker |
add sorting, revamp test suite, misc cleanup. Dest/revml is not portable off my system yet (need to release ...::Diff) |
||
#19 | 825 | Barrie Slaymaker |
test, handle case where no revs are transferred and VCP::Dest::*::handle_footer() blew up. |
||
#18 | 812 | Barrie Slaymaker |
A more sensible name for on_first_rev(), and allow incremental foo->p4 updates to work by backfilling the base rev instead of trying to add it. |
||
#17 | 723 | Barrie Slaymaker | VCP::Dest::cvs tuning and cvs and p4 bugfixes | ||
#16 | 719 | Barrie Slaymaker | vcp 0.221 | ||
#15 | 705 | Barrie Slaymaker | Release 0.22. | ||
#14 | 701 | Barrie Slaymaker | Fixed VCP::Dest::p4 re-rooting problem, further t/* cleanup | ||
#13 | 699 | Barrie Slaymaker | test suite cleanup | ||
#12 | 692 | Barrie Slaymaker |
Add VCP::Utils::p4 and use it to get VCP::Dest::p4 to create it's own client view as needed. |
||
#11 | 689 | Barrie Slaymaker |
reinstate -f behavior as the default for VCP::Source::cvs, clean up -D --> -d doco. |
||
#10 | 687 | Barrie Slaymaker | remove -f, tweak deduce_rev_root | ||
#9 | 669 | Barrie Slaymaker |
0.1 Wed Jul 4 00:27:35 EDT 2001 Fix VCP::Dest::p4 to take the filespec from the p4:<dest> spec and use it as the rev_root. No --rev-root option at this time, not sure if it's needed. Reported by david d zuhn <zoo@bravara.com>. |
||
#8 | 615 | Barrie Slaymaker |
Detect p4d <= 99.2 and skip tests. Fix a use strict problem. Both reported by Nick Ing-Simmons. |
||
#7 | 610 | Barrie Slaymaker | Tweaked t/90cvs.t to not try to rmtree undef. | ||
#6 | 608 | Barrie Slaymaker |
Lots of changes to get vcp to install better, now up to 0.066. Many thanks to Matthew Attaway for testing & suggestions. |
||
#5 | 481 | Barrie Slaymaker | Made test suites use File::Spec->tmpdir and clean up after themselves | ||
#4 | 480 | Barrie Slaymaker |
0.06 Wed Dec 20 23:19:15 EST 2000 - bin/vcp: Added --versions, which loads all modules and checks them for a $VERSION and print the results out. This should help with diagnosing out-of-sync modules. - Added $VERSION vars to a few modules :-). Forgot to increment any $VERSION strings. - VCP::Dest::cvs: The directory "deeply" was not being `cvs add`ed on paths like "a/deeply/nested/file", assuming "deeply" had no files in it. - VCP::Dest::revml: fixed a bug that was causing files with a lot of linefeeds to be emitted in base64 instead of deltaed. This means most text files. - Various minor cleanups of diagnostics and error messages, including exposing "Can't locate Foo.pm" when a VCP::Source or VCP::Dest module depends on a module that's not installed, as reported by Jeff Anton. |
||
#3 | 478 | Barrie Slaymaker |
0.05 Mon Dec 18 07:27:53 EST 2000 - Use `p4 labels //...@label` command as per Rober Cowham's suggestion, with the '-s' flag recommended by Christopher Siewald and Amaury.FORGEOTDARC@atsm.fr. Though it's actually something like vcp: running /usr/bin/p4 -u safari -c safari -p localhost:5666 -s files //.../NtLkly //...@compiler_a3 //.../NtLkly //...@compiler_may3 and so //on //for 50 parameters to get the speed up. I use the //.../NtLkly "file" as //a separator between the lists of files in various //revisions. Hope nobody has any files named that :-). What I should do is choose a random label that doesn't occur in the labels list, I guess. - VCP::Source::revml and VCP::Dest::revml are now binary, control code, and "hibit ASCII" (I know, that's an oxymoron) clean. The <comment>, <delta>, and <content> elements now escape anything other than tab, line feed, space, or printable chars (32 <= c <= ASCII 126) using a tag like '<char code="0x09">'. The test suite tests all this. Filenames should also be escaped this way, but I didn't get to that. - The decision whether to do deltas or encode the content in base64 is now based on how many characters would need to be escaped. - We now depend on the users' diff program to have a "-a" option to force it to diff even if the files look binary to it. I need to use Diff.pm and adapt it for use on binary data. - VCP::Dest::cvs now makes sure that no two consecutive revisions of the same file have the same mod_time. VCP::Source::p4 got so fast at pulling revisions from the repositories the test suite sets up that CVS was not noticing that files had changed. - VCP::Plugin now allows you to set a list of acceptable result codes, since we now use p4 in ways that make it return non-zero result codes. - VCP::Revs now croaks if you try to add two entries of the same VCP::Rev (ie matching filename and rev_id). - The <type> tag is now limited to "text" or "binary", and is meant to pass that level of info between foreign repositories. - The <p4_info> on each file now carries the one line p4 description of the file so that p4->p4 transferes can pick out the more detailed info. VCP::Source::p4, VCP::Dest::p4 do this. - VCP::{Source,Dest}::{p4,cvs} now set binaryness on added files properly, I think. For p4->p4, the native p4 type is preserved. For CVS sources, seeing the keyword substitution flag 'o' or 'b' implies binaryness, for p4, seeing a filetype like qr/u?x?binary/ or qr/x?tempobj/ or "resource" implies binaryness (to non-p4 destinations). NOTE: Seeing a 'o' or 'b' in a CVS source only ends up setting the 'b' option on the destination. That should be ok for most uses, but we can make it smarter for cvs->cvs transfers if need be. |
||
#2 | 468 | Barrie Slaymaker |
- VCP::Dest::p4 now does change number aggregation based on the comment field changing or whenever a new revision of a file with unsubmitted changes shows up on the input stream. Since revisions of files are normally sorted in time order, this should work in a number of cases. I'm sure we'll need to generalize it, perhaps with a time thresholding function. - t/90cvs.t now tests cvs->p4 replication. - VCP::Dest::p4 now doesn't try to `p4 submit` when no changes are pending. - VCP::Rev now prevents the same label from being applied twice to a revision. This was occuring because the "r_1"-style label that gets added to a target revision by VCP::Dest::p4 could duplicate a label "r_1" that happened to already be on a revision. - Added t/00rev.t, the beginnings of a test suite for VCP::Rev. - Tweaked bin/gentrevml to comment revisions with their change number instead of using a unique comment for every revision for non-p4 t/test-*-in-0.revml files. This was necessary to test cvs->p4 functionality. |
||
#1 | 467 | Barrie Slaymaker | Version 0.01, initial checkin in perforce public depot. |