SVN-Dump-0.08/0000775000175000017500000000000013627150365011472 5ustar bookbookSVN-Dump-0.08/README0000644000175000017500000000062313627150365012351 0ustar bookbookSVN::Dump --------- This module lets you manage SVN dumps with Perl. The reference document for Subversion dumpfiles is at: http://svn.apache.org/repos/asf/subversion/trunk/notes/dump-load-format.txt PLEASE NOTE THAT THIS CODE IS OF IN ALPHA QUALITY. I DO NOT MASTER YET ALL THE CONCEPTS BEHIND THE SUBVERSION FILESYSTEM, BUT WILL EVENTUALLY LEARN. THE INTERFACE IS SUBJECT TO CHANGE IN THE FUTURE. SVN-Dump-0.08/Changes0000644000175000017500000000623113627150365012765 0ustar bookbookRevision history for SVN-Dump 0.08 2020-03-02 BOOK - Make SVN::Dump::Reader more liberal in what it accepts for 'fh' - RT #24032 0.07 2020-01-30 BOOK [DOCUMENTATION] - Fix a code example - RT #130903 (DJERIUS) [TESTS] - Ensure the test suite works when @INC does not contain '.' [PACKAGING] - Switch to Dist::Zilla as the distribution builder 0.06 2013-05-31 BOOK [ENHANCEMENTS] - speed optimization when reading a dump (thanks to Andrew Sayers) [DOCUMENTATION] - a few documentation tweaks (thanks to David Landgren) - imoproved inter-documentation links 0.05 2011-02-19 BOOK [ENHANCEMENTS] - Add support for Text-content-sha1 node property - Don't create text or property blocks if they don't exist in a dump. (Rocco Caputo) - Add a digest() method to SVN::Dump::Text (Inspired by a patch by Scott MacPhee, RT #56868) - Add support for Text-content-sha1 / Text-copy-source-sha1 (RT #60207) - New option check_digest that will, when reading a non-delta dump, ensure that the content digest are valid - Properly ignore blank lines between records (RT #25467, #28645) 0.04 2008-06-12 BOOK [ENHANCEMENTS] - doesn't lose the PerlIO layers when given a filehandle (e.g. after a binmode( $fh, ':gzip' ) call) 0.03 2006-11-21 BOOK [ENHANCEMENTS] - Allow the use of '_' for '-' for header names in SVN::Dump::Headers - SVN::Dump::new() now accepts parameters 'version' and 'uuid' - SVN::Dump::format() is an alias for SVN::Dump::version() - SVN::Dump::Record::update_headers() will recompute the record headers after a text or properties modification - SVN::Dump::Property::delete() can remove property keys - SVN::Dump::Record::delete_property() does the same - SVN::Dump::Headers::new() can initialise the headers with a hashref 0.02 2006-11-04 BOOK *** WARNING: INCOMPATIBLES API CHANGES FROM VERSION 0.01 *** [ENHANCEMENTS] - SVN::Dump->new() now also accepts a filehandle (fh) (thanks to clkao, RT ticket #22429) - Renamed the record manipulation methods of SVN::Dump::Record to set_headers_block() / get_headers_block(), set_property_block() / get_property_block(), set_text_block() / get_text_block(), set_included_bloc() / get_included_block. - Added new methods to SVN::Dump::Record to handle the blocks' data: set_header() / get_header(), set_property() / get_property(), set_text() / get_text(). - new helper methods: property_length() and text_length() [TESTS] - 100% coverage for SVN::Dump too [EXAMPLES] - eg/svndump_replace_author.pl - replace an author by another in a dump *** WARNING: INCOMPATIBLES API CHANGES FROM VERSION 0.01 *** 0.01 2006-10-18 BOOK [FEATURES] - SVN::Dump is able to read dumps in version 2 and 3 and output an identical dump [TESTS] - 100% coverage for SVN::Dump::Headers, SVN::Dump::Property, SVN::Dump::Reader, SVN::Dump::Record, SVN::Dump::Text [EXAMPLES] - eg/svndump_identidy.pl - read a dump and prints it out - eg/svndump_stats.pl - produces a set of statistic about a dump SVN-Dump-0.08/t/0000775000175000017500000000000013627150365011735 5ustar bookbookSVN-Dump-0.08/t/15dump.t0000644000175000017500000000255713627150365013244 0ustar bookbookuse Test::More; use strict; use warnings; use File::Spec::Functions; use SVN::Dump; plan tests => 10; # non-existing dumpfile eval { my $dump = SVN::Dump->new( { file => 'krunch' } ); }; like( $@, qr/^Can't open krunch: /, "new() fails with non-existing file" ); # a SVN::Dump with a reader my $dump = SVN::Dump->new( { file => catfile(qw( t dump full test123-r0.svn)) } ); is( $dump->version(), '', 'No dump format version yet' ); $dump->next_record(); is( $dump->version(), '2', 'Read dump format version' ); is( $dump->uuid(), '', 'No UUID yet' ); $dump->next_record(); is( $dump->uuid(), '2785358f-ed1c-0410-8d81-93a2a39f1216', 'Read UUID' ); my $as_string = join "\012", 'SVN-fs-dump-format-version: 2', "\012UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216", "\012"; is( $dump->as_string(), $as_string, 'as_string()' ); # a SVN::Dump without a reader $dump = SVN::Dump->new( { version => 3 } ); is( $dump->version(), '3', 'version set by new()' ); $dump = SVN::Dump->new( { uuid => 'bc4ef365-ce1c-0410-99c4-bdd0034106c0' } ); is( $dump->uuid(), 'bc4ef365-ce1c-0410-99c4-bdd0034106c0', 'uuid set by new()' ); $dump = SVN::Dump->new( { version => 2, uuid => '77f6eb63-2709-0410-a607-da1692a51919' } ); is( $dump->version(), '2', 'version set by new()' ); is( $dump->uuid(), '77f6eb63-2709-0410-a607-da1692a51919', 'uuid set by new()' ); SVN-Dump-0.08/t/11property.t0000644000175000017500000000506013627150365014147 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use SVN::Dump::Property; my @tests = ( [ bloop => 'zwapp' ], [ zap => 'glipp' ], [ bap => 'kapow' ], [ thwapp => 'owww' ], ); # the expected string representation my $as_string = << 'END_OF_PROPERTY'; K 5 bloop V 5 zwapp K 3 zap V 5 glipp K 3 bap V 5 kapow K 6 thwapp V 4 owww PROPS-END END_OF_PROPERTY plan tests => 20 + 2 * @tests; # create a new empty property block my $p = SVN::Dump::Property->new(); isa_ok( $p, 'SVN::Dump::Property' ); is( $p->as_string(), "PROPS-END\012", 'empty property block' ); # try setting some values for my $kv (@tests) { is( $p->set(@$kv), $kv->[1], "Set $kv->[0] => $kv->[1]" ); is( $p->get($kv->[0]), $kv->[1], "Get $kv->[0] as $kv->[1]" ); } # check the order of the keys is_deeply( [ $p->keys() ], [ map { $_->[0] } @tests ], "Keys in order" ); is_deeply( [ $p->values() ], [ map { $_->[1] } @tests ], "Values in order" ); # check the string serialisation is_same_string( $p->as_string(), $as_string, 'Property serialisation' ); # change a value is( $p->set( bap => 'urkkk' ), 'urkkk', "Changed 'bap' value" ); is( $p->get('bap'), 'urkkk', "Really changed 'bap' value" ); # check the order $tests[2] = [ bap => 'urkkk' ]; is_deeply( [ $p->keys() ], [ map { $_->[0] } @tests ], "Keys in order" ); is_deeply( [ $p->values() ], [ map { $_->[1] } @tests ], "Values in order" ); # add a new key is( $p->set( swish => 'ker_sploosh' ), 'ker_sploosh', "Added 'swish' value" ); is( $p->get('swish'), 'ker_sploosh', "Really added 'swish' value" ); # check the order again push @tests, [swish => 'ker_sploosh' ]; is_deeply( [ $p->keys() ], [ map { $_->[0] } @tests ], "Keys in order" ); is_deeply( [ $p->values() ], [ map { $_->[1] } @tests ], "Values in order" ); # delete the new key is( $p->delete('swish'), 'ker_sploosh', 'delete() returns the value' ); is( $p->delete('swish'), undef, 'delete() non-existing key' ); is( $p->delete(), undef, 'delete() no key' ); # update the expected result $as_string =~ s/kapow/urkkk/; # same length is_same_string( $p->as_string(), $as_string, 'Property serialisation' ); # check that delete() behaves like the builtin delete() $p->set(@$_) for ( [ foo => 11 ], [ bar => 22 ], [ baz => 33 ] ); my $scalar = $p->delete('foo'); is( $scalar, 11, '$scalar is 11 (perldoc -f delete)' ); $scalar = $p->delete(qw(foo bar)); is( $scalar, 22, '$scalar is 22 (perldoc -f delete)' ); my @array = $p->delete(qw(foo bar baz)); is_deeply( \@array, [ undef, undef, 33 ], '@array is (undef, undef,33)' ); SVN-Dump-0.08/t/20headers.t0000644000175000017500000000120213627150365013670 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump::Reader; my @files = glob catfile( 't', 'dump', 'headers', '*' ); plan tests => 3 * @files; for my $f (@files) { my $expected = file_content($f); open my $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 3; next; }; my $dump = SVN::Dump::Reader->new($fh); my $h = $dump->read_header_block(); is_same_string( $h->as_string(), $expected, "Read $f headers" ); like( $f, qr/@{[$h->type()]}/, "Correct type detected for $f" ); is( tell($fh), -s $f, "Read all of $f" ); } SVN-Dump-0.08/t/00-report-prereqs.dd0000644000175000017500000000461413627150365015460 0ustar bookbookdo { my $x = { 'build' => { 'requires' => { 'Pod::Coverage::TrustPod' => '0', 'Test::CPAN::Meta' => '0', 'Test::Pod' => '0', 'Test::Pod::Coverage' => '0' } }, 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0' } }, 'develop' => { 'requires' => { 'Pod::Coverage::TrustPod' => '0', 'Test::CPAN::Meta' => '0', 'Test::Pod' => '1.41', 'Test::Pod::Coverage' => '1.08' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'Digest' => '0', 'IO::Handle' => '0', 'Scalar::Util' => '0', 'perl' => '5.006', 'strict' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900', 'Test::LongString' => '0' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'File::Spec::Functions' => '0', 'File::Temp' => '0', 'IO::Handle' => '0', 'IPC::Open3' => '0', 'List::Util' => '0', 'PerlIO::gzip' => '0', 'Test::More' => '0.88', 'lib' => '0', 'perl' => '5.006' } } }; $x; }SVN-Dump-0.08/t/29fail.t0000644000175000017500000000136113627150365013207 0ustar bookbookuse strict; use Test::More; use File::Spec::Functions; use SVN::Dump::Reader; my @files = glob catfile( 't', 'dump', 'fail', '*' ); plan tests => 2 * @files; for my $f (@files) { open my $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 2; next; }; # read the test information from the test file itself my $func = <$fh>; # first line contains the method name my $err = <$fh>; # second line contains the error regexp chop for ($err, $func); ($func, my @args) = split / /, $func; my $r = SVN::Dump::Reader->new( $fh, { check_digest => 1 } ); eval { $r->$func(@args); }; ok( $@, "$func(@{[join',',@args]}) failed for $f" ); like( $@, qr/$err/, " with the expected error ($err)" ); } SVN-Dump-0.08/t/13record.t0000644000175000017500000000655713627150365013557 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use SVN::Dump::Record; plan tests => 30; # the record object my $rec = SVN::Dump::Record->new(); isa_ok( $rec, 'SVN::Dump::Record' ); # no headers yet is( $rec->type(), '', q{No headers yet, can't determine type} ); # create some headers $rec->set_header( @$_ ) for ( [ 'Node-path' => 'trunk/latin' ], [ 'Node-kind' => 'file' ], [ 'Node-action' => 'add' ], ); # give the record some headers is( $rec->type(), 'node', 'Type given by the headers' ); ok( !$rec->has_prop(), 'Record has no property block' ); is( $rec->property_length(), 0, 'Prop-length == 0' ); ok( ! $rec->has_text(), 'Record has no text block' ); is( $rec->text_length(), 0, 'Text-length == 0' ); is( $rec->get_text(), undef, 'No text block' ); # create a property block my @props = ( [ 'svn:log' => 'lorem ipsum sint' ], [ 'svn:author' => 'book' ], [ 'svn:date' => '2006-01-06T02:36:55.834244Z' ], ); $rec->set_property( @$_ ) for @props; # check the headers were updated is( $rec->get_header( $_->[0] ), $_->[1], "$_->[0] header" ) for ( [ 'Prop-content-length' => '115' ], [ 'Content-length' => '115' ], ); # check the properties were updated is( $rec->get_property( $_->[0] ), $_->[1], "$_->[0] property" ) for @props; ok( $rec->has_prop(), 'Record has a property block' ); ok( ! $rec->has_text(), 'Record has no text block' ); ok( $rec->has_prop_only(), 'Record has only a property block' ); ok( $rec->has_prop_or_text(), 'Record has a property or text block' ); # create a text block my $t = << 'EOT'; eos magnam a incidunt ipsum enim sint sed voluptatum adipisicing temporibus officia earum accusamus animi et possimus deserunt eveniet esse reiciendis laboriosam facere voluptas repellendus mollitia hic ipsam aliquid illum qui numquam amet quisquam provident lorem similique minus sapiente exercitation cupiditate nostrum EOT # set some text $rec->set_text( 'zlonk bam kapow' ); is( $rec->text_length(), 15, 'Text-length == 15' ); # add some text $rec->set_text( $t ); # check the headers were updated is( $rec->get_header( $_->[0] ), $_->[1], "$_->[0] header" ) for ( [ 'Text-content-length' => '322' ], [ 'Content-length' => '437' ], ); # check the text is available is( $rec->text_length(), length($t), "Text-length = @{[length($t)]}" ); is( $rec->get_text(), $t, 'Text block' ); ok( $rec->has_prop(), 'Record has a property block' ); ok( $rec->has_text(), 'Record has a text block' ); ok( ! $rec->has_prop_only(), 'Record has not only a property block' ); ok( $rec->has_prop_or_text(), 'Record has a property or text block' ); # check that delete_property() behaves like the builtin delete() $rec->set_property(@$_) for ( [ foo => 11 ], [ bar => 22 ], [ baz => 33 ] ); my $scalar = $rec->delete_property('foo'); is( $scalar, 11, '$scalar is 11 (perldoc -f delete)' ); $scalar = $rec->delete_property(qw(foo bar)); is( $scalar, 22, '$scalar is 22 (perldoc -f delete)' ); my @array = $rec->delete_property(qw(foo bar baz)); is_deeply( \@array, [ undef, undef, 33 ], '@array is (undef, undef,33)' ); # test a record without properties $rec = SVN::Dump::Record->new; $rec->set_header( "Node-path", "trunk/fubar.txt" ); $rec->set_header( "Node-kind", "file" ); $rec->set_header( "Node-action", "change" ); $rec->set_text("some text"); ok( $rec->as_string !~ /^Prop-content-length: 0$/m, "No Prop-content-length: 0" ); SVN-Dump-0.08/t/author-pod-coverage.t0000644000175000017500000000053613627150365015777 0ustar bookbook#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests. use Test::Pod::Coverage 1.08; use Pod::Coverage::TrustPod; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); SVN-Dump-0.08/t/dump/0000775000175000017500000000000013627150365012702 5ustar bookbookSVN-Dump-0.08/t/dump/fail/0000775000175000017500000000000013627150365013615 5ustar bookbookSVN-Dump-0.08/t/dump/fail/p_eof.svn0000644000175000017500000000012313627150365015427 0ustar bookbookread_property_block ^Unexpected EOF line \d+ K 7 svn:log V 20 standard directories SVN-Dump-0.08/t/dump/fail/p_noval.svn0000644000175000017500000000022613627150365016001 0ustar bookbookread_property_block ^Corrupted property K 7 svn:log V 20 standard directories K 10 svn:author K 8 svn:date V 27 2005-11-18T11:07:02.060507Z PROPS-END SVN-Dump-0.08/t/dump/fail/p_noend.svn0000644000175000017500000000024213627150365015763 0ustar bookbookread_property_block ^Corrupted property K 7 svn:log V 20 standard directories K 10 svn:author V 4 book K 8 svn:date V 27 2005-11-18T11:07:02.060507Z PROPS-FINISH SVN-Dump-0.08/t/dump/fail/h_noblank.svn0000644000175000017500000000036713627150365016304 0ustar bookbookread_header_block ^Unexpected EOF line \d+ Node-path: css/style.css Node-kind: file Node-action: add Prop-content-length: 87 Text-content-length: 970 Text-content-md5: 1f97ca311e48901bfc430d9f3e335dd0 Content-length: 1057 SVN-Dump-0.08/t/dump/fail/r_badsum.svn0000644000175000017500000000263413627150365016144 0ustar bookbookread_record ^md5 checksum mismatch: got 60262fd14bd1b59416820cc37e4ee982, expected 6772871c2cf5bcf281c5ee148135a2db Node-path: trunk/loremipsum.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 1090 Text-content-md5: 6772871c2cf5bcf281c5ee148135a2db Content-length: 1130 K 13 svn:eol-style V 6 native PROPS-END quo fugiat quos quam voluptate nostrum perferendis eum animi fugit unde nam accusantium laboriosam quaerat asperiores assumenda praesentium iure eaque dicta explicabo autem vero voluptates sed itaque repellat dignissimos quia laudantium temporibus consequuntur beatae dolore eligendi doloremque quas recusandae proident sapiente mollit aliqua veniam culpa cillum voluptatem tempore exercitationem ullamco nobis nihil corrupti anim dolores soluta reiciendis necessitatibus sequi officia do dolorum a nisi consectetur quisquam illum amet delectus minim porro provident error dolorem repudiandae pariatur occaecat rem aspernatur tempora excepturi ab similique repellendus voluptatum neque totam aliquip adipisicing cum vitae eveniet minus placeat nemo quibusdam laborum velit saepe aute fuga reprehenderit eius ratione magnam aperiam sit mollitia lorem facilis debitis distinctio non facere natus maiores alias iste aliquid rerum ullam sunt possimus minima qui nostrud nesciunt at et deleniti tempor hic corporis suscipit commodo odio quis quae harum molestiae exercitation inventore cumque SVN-Dump-0.08/t/dump/fail/r_badsize.svn0000644000175000017500000000251613627150365016311 0ustar bookbookread_record ^Inconsistent record size Node-path: trunk/loremipsum.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 1090 Text-content-md5: 60262fd14bd1b59416820cc37e4ee982 Content-length: 1100 K 13 svn:eol-style V 6 native PROPS-END quo fugiat quos quam voluptate nostrum perferendis eum animi fugit unde nam accusantium laboriosam quaerat asperiores assumenda praesentium iure eaque dicta explicabo autem vero voluptates sed itaque repellat dignissimos quia laudantium temporibus consequuntur beatae dolore eligendi doloremque quas recusandae proident sapiente mollit aliqua veniam culpa cillum voluptatem tempore exercitationem ullamco nobis nihil corrupti anim dolores soluta reiciendis necessitatibus sequi officia do dolorum a nisi consectetur quisquam illum amet delectus minim porro provident error dolorem repudiandae pariatur occaecat rem aspernatur tempora excepturi ab similique repellendus voluptatum neque totam aliquip adipisicing cum vitae eveniet minus placeat nemo quibusdam laborum velit saepe aute fuga reprehenderit eius ratione magnam aperiam sit mollitia lorem facilis debitis distinctio non facere natus maiores alias iste aliquid rerum ullam sunt possimus minima qui nostrud nesciunt at et deleniti tempor hic corporis suscipit commodo odio quis quae harum molestiae exercitation inventore cumque SVN-Dump-0.08/t/dump/fail/t_eof.svn0000644000175000017500000000023613627150365015440 0ustar bookbookread_text_block 200 ^Unexpected EOF line \d+ wham_eth crunch blurp powie aiieee spla_a_t glipp whamm awkkkkkk swish qunckkk clunk krunch pam bam rip ker_plop SVN-Dump-0.08/t/dump/fail/p_eofval.svn0000644000175000017500000000014313627150365016134 0ustar bookbookread_property_block ^Unexpected EOF line \d+ K 7 svn:log V 20 standard directories K 10 svn:author SVN-Dump-0.08/t/dump/fail/p_empty.svn0000644000175000017500000000005513627150365016020 0ustar bookbookread_property_block ^Unexpected EOF line \d+ SVN-Dump-0.08/t/dump/property/0000775000175000017500000000000013627150365014566 5ustar bookbookSVN-Dump-0.08/t/dump/property/revision.svn0000644000175000017500000000016713627150365017156 0ustar bookbookK 7 svn:log V 20 standard directories K 10 svn:author V 4 book K 8 svn:date V 27 2005-11-18T11:07:02.060507Z PROPS-END SVN-Dump-0.08/t/dump/property/file-node.svn0000644000175000017500000000005013627150365017151 0ustar bookbookK 13 svn:eol-style V 6 native PROPS-END SVN-Dump-0.08/t/dump/headers/0000775000175000017500000000000013627150365014315 5ustar bookbookSVN-Dump-0.08/t/dump/headers/dir-node.svn0000644000175000017500000000006013627150365016540 0ustar bookbookNode-path: css Node-kind: dir Node-action: add SVN-Dump-0.08/t/dump/headers/uuid-record.svn0000644000175000017500000000005413627150365017264 0ustar bookbookUUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 SVN-Dump-0.08/t/dump/headers/format-record.svn0000644000175000017500000000003713627150365017607 0ustar bookbookSVN-fs-dump-format-version: 3 SVN-Dump-0.08/t/dump/headers/file-node.svn0000644000175000017500000000031513627150365016704 0ustar bookbookNode-path: css/style.css Node-kind: file Node-action: add Prop-content-length: 87 Text-content-length: 970 Text-content-md5: 1f97ca311e48901bfc430d9f3e335dd0 Content-length: 1057 SVN-Dump-0.08/t/dump/headers/revision-record.svn0000644000175000017500000000010113627150365020145 0ustar bookbookRevision-number: 1 Prop-content-length: 116 Content-length: 116 SVN-Dump-0.08/t/dump/full/0000775000175000017500000000000013627150365013644 5ustar bookbookSVN-Dump-0.08/t/dump/full/test123-r0-r10.svn0000644000175000017500000001337113627150365016523 0ustar bookbookSVN-fs-dump-format-version: 2 UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 Revision-number: 0 Prop-content-length: 56 Content-length: 56 K 8 svn:date V 27 2006-09-08T09:09:02.348832Z PROPS-END Revision-number: 1 Prop-content-length: 125 Content-length: 125 K 7 svn:log V 26 Standard repository layout K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:48:32.736884Z PROPS-END Node-path: branches Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: tags Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: trunk Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Revision-number: 2 Prop-content-length: 116 Content-length: 116 K 7 svn:log V 17 Add an empty file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:49:03.913665Z PROPS-END Node-path: trunk/empty.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 0 Text-content-md5: d41d8cd98f00b204e9800998ecf8427e Content-length: 40 K 13 svn:eol-style V 6 native PROPS-END Revision-number: 3 Prop-content-length: 120 Content-length: 120 K 7 svn:log V 21 some dummy latin text K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T12:35:49.304317Z PROPS-END Node-path: trunk/loremipsum.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 1090 Text-content-md5: 60262fd14bd1b59416820cc37e4ee982 Content-length: 1130 K 13 svn:eol-style V 6 native PROPS-END quo fugiat quos quam voluptate nostrum perferendis eum animi fugit unde nam accusantium laboriosam quaerat asperiores assumenda praesentium iure eaque dicta explicabo autem vero voluptates sed itaque repellat dignissimos quia laudantium temporibus consequuntur beatae dolore eligendi doloremque quas recusandae proident sapiente mollit aliqua veniam culpa cillum voluptatem tempore exercitationem ullamco nobis nihil corrupti anim dolores soluta reiciendis necessitatibus sequi officia do dolorum a nisi consectetur quisquam illum amet delectus minim porro provident error dolorem repudiandae pariatur occaecat rem aspernatur tempora excepturi ab similique repellendus voluptatum neque totam aliquip adipisicing cum vitae eveniet minus placeat nemo quibusdam laborum velit saepe aute fuga reprehenderit eius ratione magnam aperiam sit mollitia lorem facilis debitis distinctio non facere natus maiores alias iste aliquid rerum ullam sunt possimus minima qui nostrud nesciunt at et deleniti tempor hic corporis suscipit commodo odio quis quae harum molestiae exercitation inventore cumque Revision-number: 4 Prop-content-length: 134 Content-length: 134 K 7 svn:log V 35 renamed loremipsum.txt to latin.txt K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T14:02:27.413127Z PROPS-END Node-path: trunk/latin.txt Node-kind: file Node-action: add Node-copyfrom-rev: 3 Node-copyfrom-path: trunk/loremipsum.txt Node-path: trunk/loremipsum.txt Node-action: delete Revision-number: 5 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 22 add a file without EOL K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T14:42:37.600634Z PROPS-END Node-path: trunk/no-eol.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 25 Text-content-md5: bf9d9536e2997b9bf13ac679e041f9ab Content-length: 65 K 13 svn:eol-style V 6 native PROPS-END swish bloop krunch z_zwap Revision-number: 6 Prop-content-length: 136 Content-length: 136 K 7 svn:log V 37 a log message ending with a newline K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T15:35:27.869414Z PROPS-END Node-path: trunk/zlonk Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Revision-number: 7 Prop-content-length: 191 Content-length: 191 K 7 svn:log V 92 A copy from the working dir to a URL: svn cp . svn://localhost/test123/tags/cp-WC-URL K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T16:59:51.034755Z PROPS-END Node-path: tags/cp-WC-URL Node-kind: dir Node-action: add Node-copyfrom-rev: 1 Node-copyfrom-path: trunk Node-path: tags/cp-WC-URL/empty.txt Node-kind: file Node-action: add Node-copyfrom-rev: 2 Node-copyfrom-path: trunk/empty.txt Node-path: tags/cp-WC-URL/latin.txt Node-kind: file Node-action: add Node-copyfrom-rev: 4 Node-copyfrom-path: trunk/latin.txt Node-path: tags/cp-WC-URL/no-eol.txt Node-kind: file Node-action: add Node-copyfrom-rev: 5 Node-copyfrom-path: trunk/no-eol.txt Node-path: tags/cp-WC-URL/zlonk Node-kind: dir Node-action: add Node-copyfrom-rev: 6 Node-copyfrom-path: trunk/zlonk Revision-number: 8 Prop-content-length: 109 Content-length: 109 K 7 svn:log V 10 a new file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T17:01:06.786524Z PROPS-END Node-path: trunk/whap.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 58 Text-content-md5: 25c219035d2ecbdae652ca145e9e780d Content-length: 98 K 13 svn:eol-style V 6 native PROPS-END WINK_WINK_WINKITY_WINK_BLINK FERRIP PAK_POW SPLAPPLE_PLAP Revision-number: 9 Prop-content-length: 112 Content-length: 112 K 7 svn:log V 13 rename a file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T17:06:34.131741Z PROPS-END Node-path: trunk/crunchle.txt Node-kind: file Node-action: add Node-copyfrom-rev: 8 Node-copyfrom-path: trunk/whap.txt Node-path: trunk/whap.txt Node-action: delete Revision-number: 10 Prop-content-length: 141 Content-length: 141 K 7 svn:log V 42 replace a file by another of the same name K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-09T07:32:54.158084Z PROPS-END Node-path: trunk/crunchle.txt Node-kind: file Node-action: replace Prop-content-length: 40 Text-content-length: 40 Text-content-md5: e50c6d0bd09735b520e49893ee70864d Content-length: 80 K 13 svn:eol-style V 6 native PROPS-END aiieee zok clash bang_eth plop ker_plop SVN-Dump-0.08/t/dump/full/test123-r11-r14-v3.svn0000644000175000017500000000306513627150365017136 0ustar bookbookSVN-fs-dump-format-version: 3 UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 Revision-number: 11 Prop-content-length: 118 Content-length: 118 K 7 svn:log V 19 Test a cp URL URL K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-11T11:34:28.406692Z PROPS-END Node-path: tags/cp-URL-URL Node-kind: dir Node-action: add Node-copyfrom-rev: 10 Node-copyfrom-path: trunk Revision-number: 12 Prop-content-length: 119 Content-length: 119 K 7 svn:log V 20 yet another new file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-11T11:53:41.757784Z PROPS-END Node-path: trunk/new.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-delta: true Text-content-length: 58 Text-content-md5: 3f74276a776c3dd34f5bdcd6bcc094c8 Content-length: 98 K 13 svn:eol-style V 6 native PROPS-END SVN1-D'whack_eth slosh glurpp bang zgruppp flrb rip Revision-number: 13 Prop-content-length: 117 Content-length: 117 K 7 svn:log V 18 file modification K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-13T21:54:28.949558Z PROPS-END Node-path: trunk/latin.txt Node-kind: file Node-action: change Text-delta: true Text-content-length: 41 Text-content-md5: f04bdc198c0c25db5393941059a640c8 Content-length: 41 SVNB g[ horribilis delenda Revision-number: 14 Prop-content-length: 116 Content-length: 116 K 7 svn:log V 17 remove a property K 10 svn:author V 4 book K 8 svn:date V 27 2006-10-17T08:33:58.535365Z PROPS-END Node-path: trunk/empty.txt Node-kind: file Node-action: change Prop-delta: true Prop-content-length: 29 Content-length: 29 D 13 svn:eol-style PROPS-END SVN-Dump-0.08/t/dump/full/test123-r0-r10-v16.svn0000644000175000017500000001517013627150365017134 0ustar bookbookSVN-fs-dump-format-version: 2 UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 Revision-number: 0 Prop-content-length: 56 Content-length: 56 K 8 svn:date V 27 2006-09-08T09:09:02.348832Z PROPS-END Revision-number: 1 Prop-content-length: 125 Content-length: 125 K 7 svn:log V 26 Standard repository layout K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:48:32.736884Z PROPS-END Node-path: branches Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: tags Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: trunk Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Revision-number: 2 Prop-content-length: 116 Content-length: 116 K 7 svn:log V 17 Add an empty file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:49:03.913665Z PROPS-END Node-path: trunk/empty.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 0 Text-content-md5: d41d8cd98f00b204e9800998ecf8427e Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 Content-length: 40 K 13 svn:eol-style V 6 native PROPS-END Revision-number: 3 Prop-content-length: 120 Content-length: 120 K 7 svn:log V 21 some dummy latin text K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T12:35:49.304317Z PROPS-END Node-path: trunk/loremipsum.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 1090 Text-content-md5: 60262fd14bd1b59416820cc37e4ee982 Text-content-sha1: aacc83edca66456d10777c9a4c9bd9dd604f0898 Content-length: 1130 K 13 svn:eol-style V 6 native PROPS-END quo fugiat quos quam voluptate nostrum perferendis eum animi fugit unde nam accusantium laboriosam quaerat asperiores assumenda praesentium iure eaque dicta explicabo autem vero voluptates sed itaque repellat dignissimos quia laudantium temporibus consequuntur beatae dolore eligendi doloremque quas recusandae proident sapiente mollit aliqua veniam culpa cillum voluptatem tempore exercitationem ullamco nobis nihil corrupti anim dolores soluta reiciendis necessitatibus sequi officia do dolorum a nisi consectetur quisquam illum amet delectus minim porro provident error dolorem repudiandae pariatur occaecat rem aspernatur tempora excepturi ab similique repellendus voluptatum neque totam aliquip adipisicing cum vitae eveniet minus placeat nemo quibusdam laborum velit saepe aute fuga reprehenderit eius ratione magnam aperiam sit mollitia lorem facilis debitis distinctio non facere natus maiores alias iste aliquid rerum ullam sunt possimus minima qui nostrud nesciunt at et deleniti tempor hic corporis suscipit commodo odio quis quae harum molestiae exercitation inventore cumque Revision-number: 4 Prop-content-length: 134 Content-length: 134 K 7 svn:log V 35 renamed loremipsum.txt to latin.txt K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T14:02:27.413127Z PROPS-END Node-path: trunk/latin.txt Node-kind: file Node-action: add Node-copyfrom-rev: 3 Node-copyfrom-path: trunk/loremipsum.txt Text-copy-source-md5: 60262fd14bd1b59416820cc37e4ee982 Text-copy-source-sha1: aacc83edca66456d10777c9a4c9bd9dd604f0898 Node-path: trunk/loremipsum.txt Node-action: delete Revision-number: 5 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 22 add a file without EOL K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T14:42:37.600634Z PROPS-END Node-path: trunk/no-eol.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 25 Text-content-md5: bf9d9536e2997b9bf13ac679e041f9ab Text-content-sha1: 9f80a2341c3152e4cd75bf35f383e26da5bdac0c Content-length: 65 K 13 svn:eol-style V 6 native PROPS-END swish bloop krunch z_zwap Revision-number: 6 Prop-content-length: 136 Content-length: 136 K 7 svn:log V 37 a log message ending with a newline K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T15:35:27.869414Z PROPS-END Node-path: trunk/zlonk Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Revision-number: 7 Prop-content-length: 191 Content-length: 191 K 7 svn:log V 92 A copy from the working dir to a URL: svn cp . svn://localhost/test123/tags/cp-WC-URL K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T16:59:51.034755Z PROPS-END Node-path: tags/cp-WC-URL Node-kind: dir Node-action: add Node-copyfrom-rev: 1 Node-copyfrom-path: trunk Node-path: tags/cp-WC-URL/empty.txt Node-kind: file Node-action: add Node-copyfrom-rev: 2 Node-copyfrom-path: trunk/empty.txt Text-copy-source-md5: d41d8cd98f00b204e9800998ecf8427e Text-copy-source-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 Node-path: tags/cp-WC-URL/latin.txt Node-kind: file Node-action: add Node-copyfrom-rev: 4 Node-copyfrom-path: trunk/latin.txt Text-copy-source-md5: 60262fd14bd1b59416820cc37e4ee982 Text-copy-source-sha1: aacc83edca66456d10777c9a4c9bd9dd604f0898 Node-path: tags/cp-WC-URL/no-eol.txt Node-kind: file Node-action: add Node-copyfrom-rev: 5 Node-copyfrom-path: trunk/no-eol.txt Text-copy-source-md5: bf9d9536e2997b9bf13ac679e041f9ab Text-copy-source-sha1: 9f80a2341c3152e4cd75bf35f383e26da5bdac0c Node-path: tags/cp-WC-URL/zlonk Node-kind: dir Node-action: add Node-copyfrom-rev: 6 Node-copyfrom-path: trunk/zlonk Revision-number: 8 Prop-content-length: 109 Content-length: 109 K 7 svn:log V 10 a new file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T17:01:06.786524Z PROPS-END Node-path: trunk/whap.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-content-length: 58 Text-content-md5: 25c219035d2ecbdae652ca145e9e780d Text-content-sha1: 0650f1b40e124613d4104c4f66635b9c241a6ab4 Content-length: 98 K 13 svn:eol-style V 6 native PROPS-END WINK_WINK_WINKITY_WINK_BLINK FERRIP PAK_POW SPLAPPLE_PLAP Revision-number: 9 Prop-content-length: 112 Content-length: 112 K 7 svn:log V 13 rename a file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T17:06:34.131741Z PROPS-END Node-path: trunk/crunchle.txt Node-kind: file Node-action: add Node-copyfrom-rev: 8 Node-copyfrom-path: trunk/whap.txt Text-copy-source-md5: 25c219035d2ecbdae652ca145e9e780d Text-copy-source-sha1: 0650f1b40e124613d4104c4f66635b9c241a6ab4 Node-path: trunk/whap.txt Node-action: delete Revision-number: 10 Prop-content-length: 141 Content-length: 141 K 7 svn:log V 42 replace a file by another of the same name K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-09T07:32:54.158084Z PROPS-END Node-path: trunk/crunchle.txt Node-kind: file Node-action: replace Prop-content-length: 40 Text-content-length: 40 Text-content-md5: e50c6d0bd09735b520e49893ee70864d Text-content-sha1: fda30bf04d3898a6fbdf2240dc3a7e689d399120 Content-length: 80 K 13 svn:eol-style V 6 native PROPS-END aiieee zok clash bang_eth plop ker_plop SVN-Dump-0.08/t/dump/full/test123-r0.svn0000644000175000017500000000030313627150365016112 0ustar bookbookSVN-fs-dump-format-version: 2 UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 Revision-number: 0 Prop-content-length: 56 Content-length: 56 K 8 svn:date V 27 2006-09-08T09:09:02.348832Z PROPS-END SVN-Dump-0.08/t/dump/full/test123-v3.svn0000644000175000017500000001475213627150365016136 0ustar bookbookSVN-fs-dump-format-version: 3 UUID: 2785358f-ed1c-0410-8d81-93a2a39f1216 Revision-number: 0 Prop-content-length: 56 Content-length: 56 K 8 svn:date V 27 2006-09-08T09:09:02.348832Z PROPS-END Revision-number: 1 Prop-content-length: 125 Content-length: 125 K 7 svn:log V 26 Standard repository layout K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:48:32.736884Z PROPS-END Node-path: branches Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: tags Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: trunk Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Revision-number: 2 Prop-content-length: 116 Content-length: 116 K 7 svn:log V 17 Add an empty file K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T11:49:03.913665Z PROPS-END Node-path: trunk/empty.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-delta: true Text-content-length: 4 Text-content-md5: d41d8cd98f00b204e9800998ecf8427e Content-length: 44 K 13 svn:eol-style V 6 native PROPS-END SVN Revision-number: 3 Prop-content-length: 120 Content-length: 120 K 7 svn:log V 21 some dummy latin text K 10 svn:author V 4 book K 8 svn:date V 27 2006-09-08T12:35:49.304317Z PROPS-END Node-path: trunk/loremipsum.txt Node-kind: file Node-action: add Prop-content-length: 40 Text-delta: true Text-content-length: 964 Text-content-md5: 60262fd14bd1b59416820cc37e4ee982 Content-length: 1004 K 13 svn:eol-style V 6 native PROPS-END SVNBEDERJEE GQDD-F DENKHkD7G E-EDtD{F D4FwDEEeD+D6F:G DGG1DBEkEVFmDDQHFIDDIDQDhDDWD!DGVDhE&DDfw~T8FB|YufJe[EgX7Vͺj)G:p:XyܒRx7H6]ob)~9e'n$rY>MOqVVq*w.5^ۨQHO ztsDnUd5ǽoֹǯMmj,}13TL*M=c쎭Ht̪(cW+V{EFgoMbVgc)>ʞñպj[gz~ݮC|NTnmLD,*<o+ieK,tߵxBAx)|i޺ԭ˳XFXPcԛfam S MU/,eݛݚjXղK .n>c%S;6[51^In@2y< 3VAe`o={c(?<權4w*&t,]#Ch Б~d,|T44c95ƸG܄GgLφO(7^8i26}WӄKPwOR?q-i)' O5(#%4( }q~t )1dtrGf%S'b'O{,?$GfOf+?iJT P֦qd"ӍC"#[#͗=! $Q  SnԳh~rܳNNJ5fN[qt3ן^(K%[yA876|Ӟo+^mf!i`B#_.\\y~oqSڪ}uvcXx:﹗wIaR7&=[ڥ SVN-Dump-0.08/t/09reader.t0000644000175000017500000000062013627150365013531 0ustar bookbookuse strict; use Test::More; use SVN::Dump::Reader; # the many way to fail my %test = ( false => '', string => 'file', reference => \'file', object => bless( {}, 'Zlonk'), ); plan tests => scalar keys %test; for my $t ( keys %test ) { eval { my $r = SVN::Dump::Reader->new( $test{$t} ); }; like( $@, qr/^SVN::Dump::Reader parameter is not a filehandle/, $t ); } SVN-Dump-0.08/t/00-report-prereqs.t0000644000175000017500000001342613627150365015335 0ustar bookbook#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.027 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do './t/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; my $cpan_meta_error; if ( $source && $HAS_CPAN_META && (my $meta = eval { CPAN::Meta->load_file($source) } ) ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } else { $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( $cpan_meta_error || @dep_errors ) { diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; } if ( $cpan_meta_error ) { my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; } if ( @dep_errors ) { diag join("\n", "\nThe following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: SVN-Dump-0.08/t/21property.t0000644000175000017500000000110113627150365014140 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump::Reader; my @files = glob catfile( 't', 'dump', 'property', '*' ); plan tests => 2 * @files; for my $f (@files) { my $expected = file_content($f); open my $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 2; next; }; my $dump = SVN::Dump::Reader->new($fh); my $h = $dump->read_property_block(); is_same_string( $h->as_string(), $expected, "Read $f property" ); is( tell($fh), -s $f, "Read all of $f" ); } SVN-Dump-0.08/t/27transform.t0000644000175000017500000000303313627150365014303 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use File::Temp qw( tempfile ); use SVN::Dump; my @files = glob catfile( 't', 'dump', 'full', '*' ); plan tests => 4 * @files; my $i = 0; for my $f (@files) { # open the original dump my $dump = SVN::Dump->new( { file => $f } ); my $expected = file_content($f); # open a target file my ( $fh, $tempfile ) = tempfile( 'dump-XXXX', SUFFIX => '.svn' ); # read the dump my $as_string = ''; while ( my $r = $dump->next_record() ) { $as_string .= $r->as_string(); # transform the dump $r->set_text('dummy') if defined $r->get_text(); # replace text delete ${ $r->get_headers_block() }{'Text-delta'} # no more delta if $r->get_header('Text-delta'); print $fh $r->as_string(); } close $fh; # quick check that identity still works is_same_string( $as_string, $expected, "Read $f dump" ); is( tell( $dump->{reader} ), -s $f, "Read all of $f (@{[-s $f]} bytes)" ); # read the transformed version $expected = file_content($tempfile); # check round trip $dump = SVN::Dump->new( { file => $tempfile } ); $as_string = ''; while ( my $r = $dump->next_record() ) { $as_string .= $r->as_string(); } is_same_string( $as_string, $expected, "Read $tempfile dump (transformed $f)" ); is( tell( $dump->{reader} ), -s $tempfile, "Read all of $tempfile (@{[-s $tempfile]} bytes)" ); unlink $tempfile; } SVN-Dump-0.08/t/00-compile.t0000644000175000017500000000303413627150365013765 0ustar bookbookuse 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058 use Test::More; plan tests => 6 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'SVN/Dump.pm', 'SVN/Dump/Headers.pm', 'SVN/Dump/Property.pm', 'SVN/Dump/Reader.pm', 'SVN/Dump/Record.pm', 'SVN/Dump/Text.pm' ); # no fake home requested my @switches = ( -d 'blib' ? '-Mblib' : '-Ilib', ); use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} } $^X, @switches, '-e', "require q[$lib]")) if $ENV{PERL_COMPILE_TEST_DEBUG}; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/ and not eval { +require blib; blib->VERSION('1.01') }; if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; SVN-Dump-0.08/t/12text.t0000644000175000017500000000070313627150365013247 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use SVN::Dump::Text; plan tests => 5; # create a text block my $t = SVN::Dump::Text->new( 'clash sock swish bam' ); isa_ok( $t, 'SVN::Dump::Text' ); is( $t->get(), 'clash sock swish bam', 'Got the text' ); is( $t->set( 'urkkk whamm' ), 'urkkk whamm', 'Changed the text'); is( $t->get(), 'urkkk whamm', 'Changed the text'); is( $t->as_string(), $t->get(), 'as_string()' ); SVN-Dump-0.08/t/26dump_gz.t0000644000175000017500000000150213627150365013733 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump; eval { require PerlIO::gzip; }; plan skip_all => 'PerlIO::gzip required to test gziped streams' if $@; my @files = glob catfile( 't', 'dump', 'gzip', '*' ); plan tests => scalar @files; for my $f (@files) { my $src = $f; $src =~ s/gzip/full/; $src =~ s/\.gz$//; my $expected = file_content($src); my $dump; # open a gzipped filehandle open my $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 2; next; }; binmode( $fh, ':gzip' ); $dump = SVN::Dump->new( { fh => $fh } ); my $as_string = ''; while ( my $r = $dump->next_record() ) { $as_string .= $r->as_string(); } is_same_string( $as_string, $expected, "Read $f dump" ); } SVN-Dump-0.08/t/10headers.t0000644000175000017500000000357013627150365013701 0ustar bookbookuse strict; use warnings; use Test::More; use List::Util 'shuffle'; use SVN::Dump::Headers; my @valid = ( [ 'Revision-number' => 1 ], [ 'Prop-content-length' => 125 ], [ 'Content-length' => 125 ], ); my %init = ( Zlonk => 'Kapow', Bam_Kapow => 'Zowie', 'Eee-yow' => 'Glurpp' ); plan tests => 14 + 2 * @valid + 2 * keys %init; # test new() for my $args ( 'zlonk', [], ( bless [], 'zlonk' ) ) { eval { my $h = SVN::Dump::Headers->new('zlonk'); }; like( $@, qr/^First parameter must be a HASH reference/, 'new() expects a hashref' ); } my $h = SVN::Dump::Headers->new(); isa_ok( $h, 'SVN::Dump::Headers' ); eval { $h->type() }; like( $@, qr/^Unable to determine the record type/, 'No type yet (type)' ); eval { $h->keys() }; like( $@, qr/^Unable to determine the record type/, 'No type yet (keys)' ); # test the set/get methods is( $h->set( Zlonk => 'Kapow' ), 'Kapow', 'set() returns the new value' ); is( $h->get('Zlonk'), 'Kapow', 'get() method returns the value' ); is( $h->get('Vronk'), undef, 'get() returns undef for non-existent header' ); is( $h->set( Bam_Kapow => 'Zowie' ), 'Zowie', 'set() returns the new value' ); is( $h->get( 'Bam-Kapow' ), 'Zowie', '_ and - work the same' ); is( $h->get( 'Bam_Kapow' ), 'Zowie', '_ and - work the same' ); eval { $h->keys() }; like( $@, qr/^Unable to determine the record type/, 'No type yet (keys)' ); my $c = 0; for my $p (@valid) { is( $h->set(@$p), $p->[1], "set() method returns the new value for $p->[0]" ); $c++; is( scalar $h->keys(), $c, "$c valid keys" ); } is_deeply( [ $h->keys() ], [ map { $_->[0] } @valid ], 'keys() return the valid keys in order' ); # test new() with parameters for my $init ( \%init, ( bless { %init }, 'zlonk' ) ) { $h = SVN::Dump::Headers->new( $init ); is( $h->get($_), $init{$_}, "$_ value" ) for keys %init; } SVN-Dump-0.08/t/README.txt0000644000175000017500000000172713627150365013440 0ustar bookbookThe test suite is written so as to make it easy to tests various dump formats. The t/dump directory contains various bits and pieces of both valid and broken dumps. It contains several subdirectories: t/dump/full contains full dumps (such as those produced by svnadmin dump) the tests read the dump with SVN::Dump, and compare the dump produced by SVN::Dump to the original. Any difference is a bug in SVN::Dump. t/dump/records contains individual records (uuid, format, headers, revision, node, dir, etc) t/dump/property contains only property blocks t/dump/headers contains only header blocks t/dump/fail contains broken elements (record, headers, property or text blocks). The first line is actually a regular expression that should match the error message produced by SVN::Dump. To add new dump excerpts to be tested, simply copy them in the relevant directory. SVN-Dump-0.08/t/24reader.t0000644000175000017500000000121313627150365013525 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump::Reader; my @files = glob catfile( 't', 'dump', 'full', '*' ); plan tests => 2 * @files; for my $f (@files) { my $expected = file_content($f); open my $fh, $f or do { fail( "Failed to open $f: $!" ) for 1..2; next; }; my $dump = SVN::Dump::Reader->new($fh); my $as_string = ''; while( my $r = $dump->read_record() ) { $as_string .= $r->as_string(); } is_same_string( $as_string, $expected, "Read $f dump" ); is( tell($fh), -s $f, "Read all of $f (@{[-s $f]} bytes)" ); } SVN-Dump-0.08/t/lib/0000775000175000017500000000000013627150365012503 5ustar bookbookSVN-Dump-0.08/t/lib/TestUtils.pm0000644000175000017500000000120113627150365014771 0ustar bookbookuse strict; use warnings; eval { require Test::LongString; import Test::LongString; }; my $has_test_longstring = $@ eq ''; # our own string comparison test function sub is_same_string { my ($got, $expected, $name) = @_; if ($has_test_longstring) { is_string( $got, $expected, $name); } else { is( $got, $expected, $name); } } sub file_content { my ($file) = @_; local $/; open my $fh, $file or do { diag "Can't open $file: $!"; return '' }; my $content = join '', <$fh>; close $fh; return $content; } 1; __END__ =head1 NAME t::Util - Some utility functions for the tests = SVN-Dump-0.08/t/release-distmeta.t0000644000175000017500000000040113627150365015343 0ustar bookbook#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { print qq{1..0 # SKIP these tests are for release candidate testing\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::MetaTests. use Test::CPAN::Meta; meta_yaml_ok(); SVN-Dump-0.08/t/author-pod-syntax.t0000644000175000017500000000045413627150365015531 0ustar bookbook#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); SVN-Dump-0.08/t/25dump.t0000644000175000017500000000163013627150365013234 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump; my @files = glob catfile( 't', 'dump', 'full', '*' ); plan tests => 2 * @files; my $i = 0; for my $f (@files) { my $expected = file_content($f); my $dump; # test each file twice my $fh; # once with a filehandle if ( $i % 2 ) { open $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 2; next; }; $dump = SVN::Dump->new( { fh => $fh, check_digest => 1 } ); } # once with a filename else { $dump = SVN::Dump->new( { file => $f } ); } my $as_string = ''; while ( my $r = $dump->next_record() ) { $as_string .= $r->as_string(); } is_same_string( $as_string, $expected, "Read $f dump" ); is( tell($dump->{reader}), -s $f, "Read all of $f (@{[-s $f]} bytes)" ); $i++; } SVN-Dump-0.08/t/23record.t0000644000175000017500000000113613627150365013544 0ustar bookbookuse strict; use warnings; use Test::More; use lib 't/lib'; use TestUtils; use File::Spec::Functions; use SVN::Dump::Reader; my @files = glob catfile( 't', 'dump', 'records', '*' ); plan tests => 2 * @files; for my $f (@files) { my $expected = file_content($f); open my $fh, $f or do { fail("Failed to open $f: $!") for 1 .. 2; next; }; my $dump = SVN::Dump::Reader->new($fh); my $r = $dump->read_record(); is_same_string( $r->as_string(), $expected, "Read $f record" ); $r = $dump->read_record(); ok( !$r && tell($fh) == -s $f, "Read all of $f" ); } SVN-Dump-0.08/META.json0000644000175000017500000000640513627150365013116 0ustar bookbook{ "abstract" : "A Perl interface to Subversion dumps", "author" : [ "Philippe Bruhat (BooK) " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010", "keywords" : [ "svn", "subversion", "dump" ], "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "SVN-Dump", "prereqs" : { "build" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Meta" : "0", "Test::Pod" : "0", "Test::Pod::Coverage" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::CPAN::Meta" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08" } }, "runtime" : { "requires" : { "Carp" : "0", "Digest" : "0", "IO::Handle" : "0", "Scalar::Util" : "0", "perl" : "5.006", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900", "Test::LongString" : "0" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "File::Spec::Functions" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "List::Util" : "0", "PerlIO::gzip" : "0", "Test::More" : "0.88", "lib" : "0", "perl" : "5.006" } } }, "provides" : { "SVN::Dump" : { "file" : "lib/SVN/Dump.pm", "version" : "0.08" }, "SVN::Dump::Headers" : { "file" : "lib/SVN/Dump/Headers.pm", "version" : "0.08" }, "SVN::Dump::Property" : { "file" : "lib/SVN/Dump/Property.pm", "version" : "0.08" }, "SVN::Dump::Reader" : { "file" : "lib/SVN/Dump/Reader.pm", "version" : "0.08" }, "SVN::Dump::Record" : { "file" : "lib/SVN/Dump/Record.pm", "version" : "0.08" }, "SVN::Dump::Text" : { "file" : "lib/SVN/Dump/Text.pm", "version" : "0.08" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "mailto" : "bug-svn-dump@rt.cpan.org", "web" : "http://rt.cpan.org/NoAuth/Bugs.html?Dist=SVN-Dump" }, "repository" : { "type" : "git", "url" : "http://github.com/book/SVN-Dump.git", "web" : "http://github.com/book/SVN-Dump" } }, "version" : "0.08", "x_contributors" : [ "fschlich ", "Andrew Sayers ", "David Landgren ", "Roderich Schupp ", "Rocco Caputo ", "Nicholas Clark " ], "x_generated_by_perl" : "v5.28.1", "x_serialization_backend" : "JSON::XS version 3.04" } SVN-Dump-0.08/eg/0000775000175000017500000000000013627150365012065 5ustar bookbookSVN-Dump-0.08/eg/svndump_replace_author.pl0000644000175000017500000000100713627150365017167 0ustar bookbook#!/usr/bin/perl use strict; use warnings; use SVN::Dump; die "svndump_replace_author.pl [file]" if @ARGV < 2; my ( $from, $to ) = splice( @ARGV, 0, 2 ); my $dump = SVN::Dump->new( { file => @ARGV ? $ARGV[0] : '-' } ); while ( my $rec = $dump->next_record() ) { if ( $rec->type() eq 'revision' && $rec->get_header( 'Revision-number' ) != 0 && $rec->get_property('svn:author') eq $from ) { $rec->set_property( 'svn:author' => $to ); } print $rec->as_string(); } SVN-Dump-0.08/eg/svndump_stats.pl0000644000175000017500000000125513627150365015335 0ustar bookbook#!/usr/bin/perl use strict; use warnings; use SVN::Dump; my $dump = SVN::Dump->new( { file => @ARGV ? $ARGV[0] : '-' } ); my $file = @ARGV ? $ARGV[0] : "on STDIN"; # compute some stats my %type; my %kind; while ( my $record = $dump->next_record() ) { $type{ $record->type() }++; $kind{ $record->get_header('Node-action') }++ if $record->type() eq 'node'; } # print the results print "Statistics for dump $file:\n", " version: ", $dump->version(), "\n", " uuid: ", $dump->uuid(), "\n", " revisions: ", $type{revision}, "\n", " nodes: ", $type{node}, "\n"; print map { sprintf " - %-7s: %d\n", $_, $kind{$_} } sort keys %kind; SVN-Dump-0.08/eg/svndump_identity.pl0000644000175000017500000000030313627150365016021 0ustar bookbook#!/usr/bin/perl use strict; use warnings; use SVN::Dump; my $dump = SVN::Dump->new({file => @ARGV ? $ARGV[0] : '-'}); while ( my $rec = $dump->next_record() ) { print $rec->as_string(); } SVN-Dump-0.08/Makefile.PL0000644000175000017500000000355413627150365013451 0ustar bookbook# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.012. use strict; use warnings; use 5.006; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "A Perl interface to Subversion dumps", "AUTHOR" => "Philippe Bruhat (BooK) ", "BUILD_REQUIRES" => { "Pod::Coverage::TrustPod" => 0, "Test::CPAN::Meta" => 0, "Test::Pod" => 0, "Test::Pod::Coverage" => 0 }, "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "SVN-Dump", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.006", "NAME" => "SVN::Dump", "PREREQ_PM" => { "Carp" => 0, "Digest" => 0, "IO::Handle" => 0, "Scalar::Util" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "File::Spec::Functions" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "List::Util" => 0, "PerlIO::gzip" => 0, "Test::More" => "0.88", "lib" => 0 }, "VERSION" => "0.08", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Digest" => 0, "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "File::Spec::Functions" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "List::Util" => 0, "PerlIO::gzip" => 0, "Pod::Coverage::TrustPod" => 0, "Scalar::Util" => 0, "Test::CPAN::Meta" => 0, "Test::More" => "0.88", "Test::Pod" => 0, "Test::Pod::Coverage" => 0, "lib" => 0, "strict" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); SVN-Dump-0.08/dist.ini0000644000175000017500000000344113627150365013136 0ustar bookbook; the basics name = SVN-Dump author = Philippe Bruhat (BooK) license = Perl_5 copyright_holder = Philippe Bruhat (BooK) ; copyright_year = 2006-2020 ; file modifiers [PkgVersion] [PodVersion] [Encoding] encoding = bytes matches = t/dump/.*\.svn ; file generators [ManifestSkip] [Manifest] [License] [MakeMaker] [PruneCruft] [PruneFiles] match = mess/.* match = cover_db [GatherDir] ; metadata [MetaYAML] [MetaJSON] [AutoPrereqs] skip = Test::LongString [Prereqs] perl = 5.006 [Prereqs / BuildRequires] Test::CPAN::Meta = Test::Pod = Test::Pod::Coverage = Pod::Coverage::TrustPod = [Prereqs / TestRecommends] Test::LongString = [Prereqs / TestRequires] Test::More = 0.88 [ExecDir] [ShareDir] [Keywords] keywords = svn subversion dump [MetaResources] repository.web = http://github.com/book/SVN-Dump repository.url = http://github.com/book/SVN-Dump.git repository.type = git bugtracker.web = http://rt.cpan.org/NoAuth/Bugs.html?Dist=SVN-Dump bugtracker.mailto = bug-svn-dump@rt.cpan.org [MetaProvides::Package] [Meta::Contributors] contributor = fschlich contributor = Andrew Sayers contributor = David Landgren contributor = Roderich Schupp contributor = Rocco Caputo contributor = Nicholas Clark ; tests [MetaTests] [ExtraTests] [Test::Compile] [Test::ReportPrereqs] [PodSyntaxTests] [PodCoverageTests] ; release [NextRelease] format = %v %{yyyy-MM-dd}d %P [Git::NextVersion] [TestRelease] [ConfirmRelease] [UploadToCPAN] ; git [Git::Check] [Git::Commit] commit_msg = Changes for version %v changelog = Changes [Git::Tag] tag_format = v%v tag_message = %N v%v [Git::Push] push_to = origin push_to = github SVN-Dump-0.08/MANIFEST0000644000175000017500000000337313627150365012627 0ustar bookbook# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.012. Changes LICENSE MANIFEST META.json META.yml Makefile.PL README dist.ini eg/svndump_identity.pl eg/svndump_replace_author.pl eg/svndump_stats.pl lib/SVN/Dump.pm lib/SVN/Dump/Headers.pm lib/SVN/Dump/Property.pm lib/SVN/Dump/Reader.pm lib/SVN/Dump/Record.pm lib/SVN/Dump/Text.pm t/00-compile.t t/00-report-prereqs.dd t/00-report-prereqs.t t/09reader.t t/10headers.t t/11property.t t/12text.t t/13record.t t/15dump.t t/20headers.t t/21property.t t/23record.t t/24reader.t t/25dump.t t/26dump_gz.t t/27transform.t t/29fail.t t/README.txt t/author-pod-coverage.t t/author-pod-syntax.t t/dump/fail/h_noblank.svn t/dump/fail/p_empty.svn t/dump/fail/p_eof.svn t/dump/fail/p_eofval.svn t/dump/fail/p_noend.svn t/dump/fail/p_noval.svn t/dump/fail/r_badsize.svn t/dump/fail/r_badsum.svn t/dump/fail/t_eof.svn t/dump/full/test123-r0-r10-v16.svn t/dump/full/test123-r0-r10.svn t/dump/full/test123-r0-r3.svn t/dump/full/test123-r0-r4.svn t/dump/full/test123-r0-r6.svn t/dump/full/test123-r0.svn t/dump/full/test123-r11-r14-v3.svn t/dump/full/test123-v3.svn t/dump/full/test456-replace.svn t/dump/gzip/test123-r0-r4.svn.gz t/dump/headers/dir-node.svn t/dump/headers/file-node.svn t/dump/headers/format-record.svn t/dump/headers/revision-record.svn t/dump/headers/uuid-record.svn t/dump/property/file-node.svn t/dump/property/revision.svn t/dump/records/format-record.svn t/dump/records/included.svn t/dump/records/node-dir-add.svn t/dump/records/node-file-add-copy.svn t/dump/records/node-file-add-empty.svn t/dump/records/node-file-add-noeol.svn t/dump/records/node-file-add.svn t/dump/records/node-file-delete.svn t/dump/records/revision-record.svn t/dump/records/uuid-record.svn t/lib/TestUtils.pm t/release-distmeta.t SVN-Dump-0.08/LICENSE0000644000175000017500000004371313627150365012505 0ustar bookbookThis software is copyright (c) 2020 by Philippe Bruhat (BooK). This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2020 by Philippe Bruhat (BooK). This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2020 by Philippe Bruhat (BooK). This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End SVN-Dump-0.08/lib/0000775000175000017500000000000013627150365012240 5ustar bookbookSVN-Dump-0.08/lib/SVN/0000775000175000017500000000000013627150365012706 5ustar bookbookSVN-Dump-0.08/lib/SVN/Dump/0000775000175000017500000000000013627150365013613 5ustar bookbookSVN-Dump-0.08/lib/SVN/Dump/Record.pm0000644000175000017500000002033213627150365015365 0ustar bookbookpackage SVN::Dump::Record; $SVN::Dump::Record::VERSION = '0.08'; use strict; use warnings; use SVN::Dump::Headers; use SVN::Dump::Property; use SVN::Dump::Text; my $NL = "\012"; sub new { my ($class, @args) = @_; return bless {}, $class } for my $attr (qw( headers_block property_block text_block included_record )) { no strict 'refs'; *{"set_$attr"} = sub { $_[0]->{$attr} = $_[1]; }; *{"get_$attr"} = sub { $_[0]->{$attr} }; } sub type { my ($self) = @_; return $self->{headers_block} ? $self->{headers_block}->type() : ''; } sub has_text { return defined $_[0]->get_text_block(); } sub has_prop { return defined $_[0]->get_property_block(); } sub has_prop_only { return defined $_[0]->get_property_block() && !defined $_[0]->get_text_block(); } sub has_prop_or_text { return defined $_[0]->get_property_block() || defined $_[0]->get_text_block(); } # length methods sub property_length { my ($self) = @_; my $prop = $self->get_property_block(); return defined $prop ? length( $prop->as_string() ) : 0; } sub text_length { my ($self) = @_; my $text = $self->get_text(); return defined $text ? length($text) : 0; } sub as_string { my ($self) = @_; my $headers_block = $self->get_headers_block(); # the headers block my $string = $headers_block->as_string(); # the properties $string .= $self->get_property_block()->as_string() if $self->has_prop(); # the text $string .= $self->get_text_block()->as_string() if $self->has_text(); # is there an included record? if( my $included = $self->get_included_record() ) { $string .= $included->as_string() . $NL; } # add a record separator if needed my $type = $self->type(); return $string if $type =~ /\A(?:format|uuid)\z/; $string .= $type eq 'revision' ? $NL : $self->has_prop_or_text() ? $NL x 2 : $NL ; return $string; } sub update_headers { my ($self) = @_; my $proplen = $self->property_length(); my $textlen = $self->text_length(); $self->set_header( 'Text-content-length' => $textlen ) if defined $self->get_text_block(); $self->set_header( 'Prop-content-length', $proplen ) if $proplen; $self->set_header( 'Content-length' => $proplen + $textlen ); } # access methods to the inner blocks sub set_header { my ($self, $h, $v) = @_; my $headers = $self->get_headers_block() || $self->set_headers_block( SVN::Dump::Headers->new() ); $headers->set( $h, $v ); } sub get_header { my ($self, $h) = @_; return $self->get_headers_block()->get($h); } sub set_property { my ( $self, $k, $v ) = @_; my $prop = $self->get_property_block() || $self->set_property_block( SVN::Dump::Property->new() ); $prop->set( $k, $v ); $self->update_headers(); return $v; } sub get_property { my ($self, $k) = @_; return $self->get_property_block()->get($k); } sub delete_property { my ( $self, @keys ) = @_; my $prop = $self->get_property_block() || $self->set_property_block( SVN::Dump::Property->new() ); my @result = $prop->delete(@keys); $self->update_headers(); return wantarray ? @result : pop @result; # behave like delete() } sub set_text { my ($self, $t) = @_; my $text_block = $self->get_text_block() || $self->set_text_block( SVN::Dump::Text->new() ); $text_block->set( $t ); $self->update_headers(); return $t; } sub get_text { my ($self) = @_; my $text_block = $self->get_text_block(); return defined $text_block ? $text_block->get() : undef; } 1; __END__ =head1 NAME SVN::Dump::Record - A SVN dump record =head1 VERSION version 0.08 =head1 SYNOPSIS # SVN::Dump::Record objects are returned by the next_record() # method of SVN::Dump =head1 DESCRIPTION An SVN::Dump::Record object represents a Subversion dump record. =head1 METHODS L provides the following gourps of methods: =head2 Record methods =over 4 =item new() Create a new empty SVN::Dump::Record object. =item type() Return the record type, as guessed from its headers. The method dies if the record type cannot be determined. =item set_header( $h, $v ) Set the header C<$h> to the value C<$v>. =item get_header( $h ) Get the value of header C<$h>. =item set_property( $p, $v ) Set the property C<$p> to the value C<$v>. =item get_property( $p ) Get the value of property C<$p>. =item delete_property( @k ) Delete the properties named in C<@p>. Properties that do not exist in the record will be silently ignored. =item set_text( $t ) Set the value of the text block. =item get_text() Get the value of the text block. =back =head2 Inner blocks manipulation A SVN::Dump::Record is composed of several inner blocks of various kinds: L, L and L. The following methods provide access to these blocks: =over 4 =item set_headers_block( $headers ) =item get_headers_block() Get or set the L object that represents the record headers. =item set_property_block( $property ) =item get_property_block() Get or set the L object that represents the record property block. =item delete_property( @keys ) Delete the given properties. Behaves like the builtin C. =item set_text_block( $text ) =item get_text_block() Get or set the L object that represents the record text block. =item set_included_record( $record ) =item get_included_record() Some special record are actually output recursiveley by B. The "record in the record" is stored within the parent record, so they are parsed as a single record with an included record. C / C give access to the included record. According to the Subversion sources (F), this is a "delete original, then add-with-history" node. The dump looks like this: Node-path: tags/mytag/myfile Node-kind: file Node-action: delete Node-path: tags/mytag/myfile Node-kind: file Node-action: add Node-copyfrom-rev: 23 Node-copyfrom-path: trunk/myfile Note that there is a single blank line after the first header block, and four after the included one. =item update_headers() Update the various C<...-length> headers. Used internally. B will be inconsistent.> =back =head2 Information methods =over 4 =item has_prop() Return a boolean value indicating if the record has a property block. =item has_text() Return a boolean value indicating if the record has a text block. =item has_prop_only() Return a boolean value indicating if the record has only a property block (and no text block). =item has_prop_or_text() Return a boolean value indicating if the record has a property block or a text block. =item property_length() Return the length of the property block. =item text_length() Return the length of the text block. =back =head2 Output method =over 4 =item as_string() Return a string representation of the record that will be understood by other Subversion tools, such as C. B dumping a record currently returns the information that was read from the original dump. This means that if you modified the property or text block of a record, the headers will be inconsistent. =back =head1 ENCAPSULATION When using L to manipulate a SVN dump, one should not access the L, L and L components of a L object directly, but use the appropriate C and C methods of the record object. These methods compute the appropriate modifications of the header values, so that the C method outputs the correct information after any modification of the record. =head1 SEE ALSO L, L, L, L, L. =head1 COPYRIGHT Copyright 2006-2013 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/lib/SVN/Dump/Property.pm0000644000175000017500000000442013627150365015773 0ustar bookbookpackage SVN::Dump::Property; $SVN::Dump::Property::VERSION = '0.08'; use strict; use warnings; my $NL = "\012"; # FIXME should I use Tie::Hash::IxHash or Tie::Hash::Indexed? sub new { my ( $class, @args ) = @_; return bless { keys => [], hash => {}, }, $class; } sub set { my ( $self, $k, $v ) = @_; push @{ $self->{keys} }, $k if !exists $self->{hash}->{$k}; $self->{hash}{$k} = $v; } sub get { return $_[0]{hash}{ $_[1] }; } sub keys { return @{ $_[0]{keys} }; } sub values { return @{ $_[0]{hash} }{ @{ $_[0]{keys} } }; } sub delete { my ( $self, @keys ) = @_; return if !@keys; my $re = qr/^@{[join '|', map { quotemeta } @keys]}$/; $self->{keys} = [ grep { !/$re/ } @{ $self->{keys} } ]; delete @{ $self->{hash} }{@keys}; } sub as_string { my ($self) = @_; my $string = ''; $string .= defined $self->{hash}{$_} # existing key ? ( "K " . length($_) . $NL ) . "$_$NL" . ( "V " . length( $self->{hash}{$_} ) . $NL ) . "$self->{hash}{$_}$NL" # deleted key (v3) : ( "D " . length($_) . "$NL$_$NL" ) for @{ $self->{keys} }; # end marker $string .= "PROPS-END$NL"; return $string; } 1; __END__ =head1 NAME SVN::Dump::Property - A property block from a svn dump =head1 VERSION version 0.08 =head1 SYNOPSIS =head1 DESCRIPTION The SVN::Dump::Property class represents a property block in a svn dump. =head1 METHODS The following methods are available: =over 4 =item new() Create a new empty property block. =item set( $key => $value) Set the C<$key> property with value C<$value>. =item get( $key ) Get the value of property C<$key>. =item delete( @keys ) Delete the keys C<@keys>. Behaves like the builtin C on a hash. =item keys() Return the property block keys, in the order they were entered. =item values() Return the property block values, in the order they were entered. =item as_string() Return a string representation of the property block. =back =head1 SEE ALSO L, L. =head1 COPYRIGHT Copyright 2006-2013 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/lib/SVN/Dump/Text.pm0000644000175000017500000000316313627150365015076 0ustar bookbookpackage SVN::Dump::Text; $SVN::Dump::Text::VERSION = '0.08'; use strict; use warnings; my $NL = "\012"; # blessed string reference sub new { my ( $class, @args ) = @_; return bless \( join '', @args ), $class; } sub set { my ( $self, $text ) = @_; $$self = $text; } sub get { ${ $_[0] } } *as_string = \&get; sub digest { my ( $self, $algo ) = @_; return eval { require Digest; Digest->new( uc $algo )->add($$self)->hexdigest; }; } 1; __END__ =head1 NAME SVN::Dump::Text - A text block from a svn dump =head1 VERSION version 0.08 =head1 SYNOPSIS # SVN::Dump::Text objects are returned by the read_text_block() # method of SVN::Dump::Reader =head1 DESCRIPTION A SVN::Dump::Text object represents the text of a SVN dump record. =head1 METHODS The following methods are available: =over 4 =item new( $text ) Create a new SVN::Dump::Text object, initialised with the given text. =item get() Return the text of the SVN::Dump::Text object. =item set( $text ) Set the text of the SVN::Dump::Text object. =item as_string() Return a string representation of the text block. =item digest( $algo ) Return a digest of the text computed with the C<$algo> algorithm in hexadecimal form. See the L module for valid values of C<$algo>. Return C if the digest algorithm is not supported. =back =head1 SEE ALSO L, L. =head1 COPYRIGHT Copyright 2006-2013 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/lib/SVN/Dump/Headers.pm0000644000175000017500000000757713627150365015542 0ustar bookbookpackage SVN::Dump::Headers; $SVN::Dump::Headers::VERSION = '0.08'; use strict; use warnings; use Carp; use Scalar::Util qw( reftype ); my $NL = "\012"; sub new { my ( $class, $headers ) = @_; croak 'First parameter must be a HASH reference' if defined $headers && !( ref $headers && reftype $headers eq 'HASH' ); my $self = bless {}, $class; $self->set( $_ => $headers->{$_} ) for keys %{ $headers || {} }; return $self; } my %headers = ( revision => [ qw( Revision-number Prop-content-length Content-length ) ], node => [ qw( Node-path Node-kind Node-action Node-copyfrom-rev Node-copyfrom-path Prop-delta Prop-content-length Text-copy-source-md5 Text-copy-source-sha1 Text-delta Text-content-length Text-content-md5 Text-content-sha1 Content-length ) ], uuid => ['UUID'], format => ['SVN-fs-dump-format-version'], ); # FIXME Prop-delta and Text-delta in version 3 sub as_string { my ($self) = @_; my $string = ''; for my $k ( @{ $headers{ $self->type() } } ) { $string .= "$k: $self->{$k}$NL" if exists $self->{$k}; } return $string . $NL; } sub type { my ($self) = @_; my $type = exists $self->{'Node-path'} ? 'node' : exists $self->{'Revision-number'} ? 'revision' : exists $self->{'UUID'} ? 'uuid' : exists $self->{'SVN-fs-dump-format-version'} ? 'format' : croak 'Unable to determine the record type'; return $type; } sub set { my ($self, $h, $v) = @_; # FIXME shall we check that the header value is valid? $h =~ tr/_/-/; # allow _ for - simplification return $self->{$h} = $v; } sub get { my ($self, $h) = @_; $h =~ tr/_/-/; # allow _ for - simplification return $self->{$h}; } sub keys { my ($self) = @_; return grep { exists $self->{$_} } @{ $headers{$self->type()} }; } 1; __END__ =head1 NAME SVN::Dump::Headers - Headers of a SVN dump record =head1 VERSION version 0.08 =head1 SYNOPSIS # SVN::Dump::Headers objects are returned by the read_header_block() # method of SVN::Dump::Reader =head1 DESCRIPTION A SVN::Dump::Headers object represents the headers of a SVN dump record. =head1 METHODS SVN::Dump::Headers provides the following methods: =over 4 =item new( [$hashref] ) Create and return a new empty L object. If C<$hashref> is given (it can be a blessed hash reference), the keys from the hash are used to initialise the headers. =item set($h, $v) Set the C<$h> header to the value C<$v>. C<_> can be used as a replacement for C<-> in the header name. =item get($h) Get the value of header C<$h>. C<_> can be used as a replacement for C<-> in the header name. =item keys() Return the list of headers, in canonical order. =item as_string() Return a string that represents the record headers. =item type() It is possible to guess the record type from its headers. This method returns a string that represents the record type. The string is one of C, C, C or C. The method dies if it can't determine the record type. =back =head1 ENCAPSULATION When using L to manipulate a SVN dump, one should not directly access the L component of a L, but use the C and C methods of the record object. =head1 SEE ALSO L, L, L. =head1 COPYRIGHT Copyright 2006-2011 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/lib/SVN/Dump/Reader.pm0000644000175000017500000001545713627150365015365 0ustar bookbookpackage SVN::Dump::Reader; $SVN::Dump::Reader::VERSION = '0.08'; use strict; use warnings; use IO::Handle; use Carp; our @ISA = qw( IO::Handle ); # SVN::Dump elements use SVN::Dump::Headers; use SVN::Dump::Property; use SVN::Dump::Text; use SVN::Dump::Record; # some useful definitions my $NL = "\012"; # prepare the digest checkers my @digest = grep { eval { require Digest; Digest->new(uc) } } qw( md5 sha1 ); # the object is a filehandle sub new { my ($class, $fh, $args) = @_; croak 'SVN::Dump::Reader parameter is not a filehandle' unless eval { $fh && ref $fh && $fh->can('getline') && $fh->can('read') }; %{*$fh} = %{ $args || {} }; return bless $fh, $class; } sub read_record { my ($fh) = @_; my $record = SVN::Dump::Record->new(); # first get the headers my $headers = $fh->read_header_block() or return; $record->set_headers_block( $headers ); # get the property block $record->set_property_block( $fh->read_property_block() ) if ( exists $headers->{'Prop-content-length'} and $headers->{'Prop-content-length'} ); # get the text block if ( exists $headers->{'Text-content-length'} and $headers->{'Text-content-length'} ) { my $text = $fh->read_text_block( $headers->{'Text-content-length'} ); # verify checksums (but not in delta dumps) if (${*$fh}{check_digest} && ( !$headers->{'Text-delta'} || $headers->{'Text-delta'} ne 'true' ) ) { for my $algo ( grep { $headers->{"Text-content-$_"} } @digest ) { my $digest = $text->digest($algo); croak qq{$algo checksum mismatch: got $digest, expected $headers->{"Text-content-$algo"}} if $headers->{"Text-content-$algo"} ne $digest; } } $record->set_text_block($text); } # some safety checks croak "Inconsistent record size" if ( $headers->{'Prop-content-length'} || 0 ) + ( $headers->{'Text-content-length'} || 0 ) != ( $headers->{'Content-length'} || 0 ); # if we have a delete record with a 'Node-kind' header # we have to recurse for an included record if ( exists $headers->{'Node-action'} && $headers->{'Node-action'} eq 'delete' && exists $headers->{'Node-kind'} ) { my $included = $fh->read_record(); $record->set_included_record( $included ); } # uuid and format record only contain headers return $record; } sub read_header_block { my ($fh) = @_; local $/ = $NL; # skip empty lines my $line; while(1) { $line = <$fh>; return if !defined $line; chop $line; last unless $line eq ''; } my $headers = SVN::Dump::Headers->new(); while(1) { my ($key, $value) = split /: /, $line, 2; $headers->{$key} = $value; $line = <$fh>; croak _eof() if !defined $line; chop $line; last if $line eq ''; # stop on empty line } croak "Empty line found instead of a header block line $." if ! keys %$headers; return $headers; } sub read_property_block { my ($fh) = @_; my $property = SVN::Dump::Property->new(); local $/ = $NL; my @buffer; while(1) { my $line = <$fh>; croak _eof() if !defined $line; chop $line; # read a key/value pair if( $line =~ /\AK (\d+)\z/ ) { my $key = $fh->_read_string( $1 ); $line = <$fh>; croak _eof() if !defined $line; chop $line; if( $line =~ /\AV (\d+)\z/ ) { my $value = $fh->_read_string( $1 ); $property->set( $key => $value ); # FIXME what happens if we see duplicate keys? } else { croak "Corrupted property"; # FIXME better error message } } # or a deleted key (only with fs-format-version >= 3) # FIXME shall we fail if fs-format-version < 3? elsif( $line =~ /\AD (\d+)\z/ ) { my $key = $fh->_read_string( $1 ); $property->set( $key => undef ); # undef means deleted } # end of properties elsif( $line =~ /\APROPS-END\z/ ) { last; } # inconsistent data else { croak "Corrupted property"; # FIXME better error message } } return $property; } sub read_text_block { my ($fh, $size) = @_; return SVN::Dump::Text->new( $fh->_read_string( $size ) ); } sub _read_string { my ( $fh, $size ) = @_; local $/ = $NL; my $text; my $characters_read = read( $fh, $text, $size ); if ( defined($characters_read) ) { if ( $characters_read != $size ) { croak _eof(); }; } else { croak $!; }; <$fh>; # clear trailing newline return $text; }; # FIXME make this more explicit sub _eof { return "Unexpected EOF line $.", } __END__ =head1 NAME SVN::Dump::Reader - A Subversion dump reader =head1 VERSION version 0.08 =head1 SYNOPSIS # !!! You should use SVN::Dump, not SVN::Dump::Reader !!! use SVN::Dump::Reader; my $reader = SVN::Dump::Reader->new( $fh ); my $record = $reader->read_record(); =head1 DESCRIPTION The SVN::Dump::Reader class implements a reader object for Subversion dumps. =head1 METHODS The following methods are available: =over 4 =item new( $fh, \%options ) Create a new SVN::Dump::Reader attached to the C<$fh> filehandle. The only supported option is C, which is disabled by default. =item read_record( ) Read and return a new L object from the dump filehandle. If the option C is enabled, this method will recompute the digests for a dump without deltas, based on the information in the C and C headers (if the corresponding L module is available). In case of a mismatch, the routine will C with an exception complaining about a C. =item read_header_block( ) Read and return a new L object from the dump filehandle. =item read_property_block( ) Read and return a new L object from the dump filehandle. =item read_text_block( ) Read and return a new L object from the dump filehandle. =back The C methods will die horribly if asked to read inconsistent data from a stream. =head1 SEE ALSO L, L, L, L, L. =head1 COPYRIGHT Copyright 2006-2013 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/lib/SVN/Dump.pm0000644000175000017500000001223713627150365014154 0ustar bookbookpackage SVN::Dump; use strict; use warnings; use Carp; use SVN::Dump::Reader; our $VERSION = '0.06'; sub new { my ( $class, $args ) = @_; my $self = bless {}, $class; # FIXME - croak() if incompatible options # we have a reader if ( exists $args->{fh} || exists $args->{file} ) { my ( $fh, $file ) = delete @{$args}{qw( fh file )}; if ( !$fh ) { open $fh, $file or croak "Can't open $file: $!"; } $self->{reader} = SVN::Dump::Reader->new( $fh, $args ); } # we don't have a reader else { if( exists $args->{version} ) { $self->{format} = SVN::Dump::Record->new(); $self->{format}->set_header( 'SVN-fs-dump-format-version' => $args->{version} ); } if( exists $args->{uuid} ) { $self->{uuid} = SVN::Dump::Record->new(); $self->{uuid}->set_header( 'UUID' => $args->{uuid} ); } } return $self; } sub next_record { my ($self) = @_; my $record; RECORD: { $record = $self->{reader}->read_record(); return unless $record; # keep the first records in the dump itself my $type = $record->type(); if ( $type =~ /\A(?:format|uuid)\z/ ) { $self->{$type} = $record; } } return $record; } sub version { my ($self) = @_; return $self->{format} ? $self->{format}->get_header('SVN-fs-dump-format-version') : ''; } *format = \&version; sub uuid { my ($self) = @_; return $self->{uuid} ? $self->{uuid}->get_header('UUID') : ''; } sub as_string { return join '', map { $_[0]->{$_}->as_string() } qw( format uuid ); } 1; __END__ =head1 NAME SVN::Dump - A Perl interface to Subversion dumps =head1 VERSION version 0.08 =head1 SYNOPSIS #!/usr/bin/perl use strict; use warnings; use SVN::Dump; my $file = shift; my $dump = SVN::Dump->new( { file => $file } ); # compute some stats my %type; my %kind; while ( my $record = $dump->next_record() ) { $type{ $record->type() }++; $kind{ $record->get_header('Node-action') }++ if $record->type() eq 'node'; } # print the results print "Statistics for dump $file:\n", " version: ", $dump->version(), "\n", " uuid: ", $dump->uuid(), "\n", " revisions: ", $type{revision}, "\n", " nodes: ", $type{node}, "\n"; print map { sprintf " - %-7s: %d\n", $_, $kind{$_} } sort keys %kind; =head1 DESCRIPTION An SVN::Dump object represents a Subversion dump. This module follow the semantics used in the reference document (the file F in the Subversion source tree): =over 4 =item * A dump is a collection of records (L objects). =item * A record is composed of a set of headers (a L object), a set of properties (a L object) and an optional bloc of text (a L object). =item * Some special records (C records with a C header) recursively contain included records. =back Each class has a C method that prints its content in the dump format. The most basic thing you can do with SVN::Dump is simply copy a dump: use SVN::Dump; my $dump = SVN::Dump->new( { file => 'mydump.svn' } ); $dump->next_record; # read the format header $dump->next_record; # read the uuid header print $dump->as_string(); # only print the dump header while( $rec = $dump->next_record() ) { print $rec->as_string(); } After the operation, the resulting dump should be identical to the original dump. =head1 METHODS SVN::Dump provides the following methods: =over 4 =item new( \%args ) Return a new SVN::Dump object. The argument list is a hash reference. If the SVN::Dump object will read information from a file, the arguments C is used (as usal, C<-> means C); if the dump is read from a filehandle, C is used. Extra options will be passed to the L object that is created. If the SVN::Dump isn't used to read information, the parameters C and C can be used to initialise the values of the C and C headers. =item next_record() Return the next record read from the dump. This is a L object. =item version() =item format() Return the dump format version, if the version record has already been read, or if it was given in the constructor. =item uuid() Return the dump UUID, if there is an UUID record and it has been read, or if it was given in the constructor. =item as_string() Return a string representation of the dump specific blocks (the C and C blocks only). =back =head1 SEE ALSO L, L. The reference document for Subversion dumpfiles is at: L =head1 COPYRIGHT Copyright 2006-2020 Philippe Bruhat (BooK), All Rights Reserved. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Dump-0.08/META.yml0000644000175000017500000000340613627150365012744 0ustar bookbook--- abstract: 'A Perl interface to Subversion dumps' author: - 'Philippe Bruhat (BooK) ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' File::Spec::Functions: '0' File::Temp: '0' IO::Handle: '0' IPC::Open3: '0' List::Util: '0' PerlIO::gzip: '0' Pod::Coverage::TrustPod: '0' Test::CPAN::Meta: '0' Test::More: '0.88' Test::Pod: '0' Test::Pod::Coverage: '0' lib: '0' perl: '5.006' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010' keywords: - svn - subversion - dump license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: SVN-Dump provides: SVN::Dump: file: lib/SVN/Dump.pm version: '0.08' SVN::Dump::Headers: file: lib/SVN/Dump/Headers.pm version: '0.08' SVN::Dump::Property: file: lib/SVN/Dump/Property.pm version: '0.08' SVN::Dump::Reader: file: lib/SVN/Dump/Reader.pm version: '0.08' SVN::Dump::Record: file: lib/SVN/Dump/Record.pm version: '0.08' SVN::Dump::Text: file: lib/SVN/Dump/Text.pm version: '0.08' requires: Carp: '0' Digest: '0' IO::Handle: '0' Scalar::Util: '0' perl: '5.006' strict: '0' warnings: '0' resources: bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=SVN-Dump repository: http://github.com/book/SVN-Dump.git version: '0.08' x_contributors: - 'fschlich ' - 'Andrew Sayers ' - 'David Landgren ' - 'Roderich Schupp ' - 'Rocco Caputo ' - 'Nicholas Clark ' x_generated_by_perl: v5.28.1 x_serialization_backend: 'YAML::Tiny version 1.73'