SVN-Class-0.17/000755 000766 000024 00000000000 11656220115 013603 5ustar00karpetstaff000000 000000 SVN-Class-0.17/Changes000644 000766 000024 00000006221 11656220102 015073 0ustar00karpetstaff000000 000000 Revision history for SVN-Class 0.01 27 Sept 2007 First version, released on an unsuspecting world. 0.02 16 Oct 2007 Added missing .pm files to MANIFEST (did I just ignore make distcheck?) t/01-svn.t only runs if svn is found in PATH 0.03 16 Oct 2007 Added missing Path::Class::File::Stat to dependency list. 0.04 17 Oct 2007 Prefix all svn_run() calls with LANG=C to standardize svn output. Thanks to uwe.voelker@gmx.de for the fix. 0.05 18 Oct 2007 **dev release only** -- turned on debugging in tests 0.06 17 Jan 2008 * documented all the accessors in SVN::Class * turned off debugging in tests 0.07 13 Feb 2008 * added SVN::Class::Info and parent info() method * added outstr() method * added SVN::Class::Repos 0.08_01 4 July 2008 * **developer release only** -- trying to track down 50% fail rate in CPANTS. * no idea why tests fail after 20 tests in t/01-svn.t so switched to File::Temp for that test, along with using local repos for author test. * turned on debugging for tests. 0.08_02 7 July 2008 * another debugging release 0.08_03 10 July 2008 * dumb error after all. Needed to SKIP the right number of tests when svn bin not found. 0.08 22 July 2008 * no code changes, just an official release now that 0.07 test snafu is resolved. 0.09 16 Oct 2008 * fix bug with commit() not passing opts on to svn_run() * fix bug with status() returning wrong value if $obj is dir 0.10 22 Nov 2008 * catch SIG{CHLD} issue when running under CatalystX::CMS by local()izing sig handler 0.11 24 Nov 2008 * set success value if undef, always. 0.12 3 Feb 2009 * added IPC::Run to Makefile for Win32 cpan testers 0.13_01 4 Feb 2009 * some debugging for Win32 0.13_02 10 Feb 2009 * drop Class::Accessor::Fast in favor of Rose::Object since we already required Rose::Object via Rose::URI. One less dependency, plus Rose::Object now has an XS option if Class::XSAccessor is installed. 0.13_03 16 April 2009 * Class::XSAccessor now triggers Pod::Coverage warnings if methods are documented. Added docs in SVN::Class::Info. * made stdout/stdin aliasing conditional based on SVN_CLASS_ALIAS_STDOUT env var. default is now *off* so that things work as you would expect, and the hack of aliasing them now used only when explicitly asked for. * added Text::ParseWords to Makefile deps so IPC::Run works. 0.13 22 April 2009 * fix test for Mac OS X TMPDIR issue where repos url contained '+' characters 0.14 18 Aug 2009 * fix svn_run command debugging 0.15 22 Aug 2009 * fix http://rt.cpan.org/Ticket/Display.html?id=48748 by writing commit() message to a temp file. 0.16 02 April 2010 * fix temp commit message file path for Windows. See https://rt.cpan.org/Ticket/Display.html?id=54969 0.17 8 Nov 2011 * add support for svn 1.7 working copy root path via https://rt.cpan.org/Ticket/Display.html?id=72218 SVN-Class-0.17/lib/000755 000766 000024 00000000000 11656220115 014351 5ustar00karpetstaff000000 000000 SVN-Class-0.17/Makefile.PL000644 000766 000024 00000001444 11173764266 015576 0ustar00karpetstaff000000 000000 use strict; use warnings; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'SVN::Class', AUTHOR => 'Peter Karman ', VERSION_FROM => 'lib/SVN/Class.pm', ABSTRACT_FROM => 'lib/SVN/Class.pm', PL_FILES => {}, PREREQ_PM => { 'Test::More' => 0, 'Data::Dump' => 0, 'IPC::Cmd' => '0.40', 'IPC::Run' => 0, # Win32 needs for sure 'Path::Class' => 0, 'Path::Class::File::Stat' => 0, 'Rose::Object' => 0, 'Rose::URI' => 0, 'File::Temp' => 0, # tests only 'Text::ParseWords' => 0, # for IPC::Run }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'SVN-Class-*' }, ); SVN-Class-0.17/MANIFEST000644 000766 000024 00000000507 11656220115 014736 0ustar00karpetstaff000000 000000 Changes MANIFEST #META.yml # Will be created by "make dist" Makefile.PL README lib/SVN/Class.pm lib/SVN/Class/File.pm lib/SVN/Class/Dir.pm lib/SVN/Class/Info.pm lib/SVN/Class/Repos.pm t/00-load.t t/01-svn.t t/boilerplate.t t/pod-coverage.t t/pod.t META.yml Module meta-data (added by MakeMaker) SVN-Class-0.17/META.yml000644 000766 000024 00000001500 11656220115 015050 0ustar00karpetstaff000000 000000 --- #YAML:1.0 name: SVN-Class version: 0.17 abstract: manipulate Subversion workspaces with Perl objects author: - Peter Karman license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: Data::Dump: 0 File::Temp: 0 IPC::Cmd: 0.40 IPC::Run: 0 Path::Class: 0 Path::Class::File::Stat: 0 Rose::Object: 0 Rose::URI: 0 Test::More: 0 Text::ParseWords: 0 no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.54 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 SVN-Class-0.17/README000644 000766 000024 00000001462 11054667503 014476 0ustar00karpetstaff000000 000000 SVN-Class INSTALLATION To install SVN::Class, run the following commands: perl Makefile.PL make make test make install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: Search CPAN http://search.cpan.org/dist/SVN-Class CPAN Request Tracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=SVN-Class AnnoCPAN, annotated CPAN documentation: http://annocpan.org/dist/SVN-Class CPAN Ratings: http://cpanratings.perl.org/d/SVN-Class COPYRIGHT AND LICENCE Copyright (C) 2007 the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. SVN-Class-0.17/t/000755 000766 000024 00000000000 11656220115 014046 5ustar00karpetstaff000000 000000 SVN-Class-0.17/t/00-load.t000644 000766 000024 00000000215 11054667502 015374 0ustar00karpetstaff000000 000000 ##!perl -T use Test::More tests => 1; BEGIN { use_ok( 'SVN::Class' ); } diag( "Testing SVN::Class $SVN::Class::VERSION, Perl $], $^X" ); SVN-Class-0.17/t/01-svn.t000644 000766 000024 00000006404 11173771026 015271 0ustar00karpetstaff000000 000000 use Test::More tests => 26; BEGIN { use_ok('SVN::Class'); } use IPC::Cmd qw( can_run run ); use File::Temp qw( tempdir ); use Data::Dump qw( dump ); my $debug = $ENV{PERL_DEBUG} || 0; # turn on to help debug CPANTS # create a repos # # Mac OSX 10.5 workaround if ($ENV{TMPDIR} =~ m/\w+\+/) { $ENV{TMPDIR} = '/tmp'; } #diag( File::Spec->tmpdir() ); my $tmpdir = $ENV{SVN_CLASS_TMP_DIR} || tempdir( CLEANUP => ( $debug > 1 ) ? 0 : 1 ); my $repos = Path::Class::Dir->new( $tmpdir, 'svn-class', 'repos' ); my $work = Path::Class::Dir->new( $tmpdir, 'svn-class', 'work' ); # if we don't have svn in PATH can't do much. SKIP: { skip "svn is not in PATH", 25 unless can_run('svn'); diag( "svn command = " . can_run('svn') ); # if running multiple times, test for existence of our repos & work dirs SKIP: { if ( -d $repos && -s "$repos/format" ) { skip "repos setup already complete", 5; } ok( $repos->mkpath(1), "repos path made" ); ok( $work->mkpath(1), "work path made" ); ok( run( command => "svnadmin create $repos" ), "repos $repos created" ); # create a project in repos and check it out in $work ok( run( command => "svn mkdir file://$repos/test -m init" ), "test project created in repos" ); ok( run( command => "svn co file://$repos/test $work" ), "test checked out" ); } # set up is done. now let's test our SYNOPSIS. # SVN::Class::File ok( my $file = svn_file( $work, 'test1' ), "new svn_file" ); # 1 #$file->_debug_stdin_fh; #$file->_debug_stdout_fh; $file->debug(1) if $debug; ok( my $fh = $file->open('>>'), "filehandle created" ); ok( print( {$fh} "hello world\n" ), "hello world" ); ok( $fh->close, "filehandle closed" ); ok( $file->add, "$file scheduled for commit" ); ok( $file->modified, "$file status == modified" ); # 6 ok( $file->commit('the file changed'), "$file committed" ); diag( "error: " . $file->errstr . " : $!" ) if $file->error_code; ok( my $log = $file->log, "$file has a log" ); is( $file->outstr, join( "\n", @$log, "" ), "outstr" ); # SVN::Class::Dir ok( my $dir = svn_dir( $work, 'testdir' ), "new svn_dir" ); $dir->debug(1) if $debug; ok( -d $dir ? 1 : $dir->mkpath, "$dir mkpath" ); # 11 ok( $dir->add, "$dir scheduled for commit" ); is( $dir->status, 'A', "dir status is schedule for Add" ); #diag( join( "", `ls -l $work` ) ); ok( $dir->commit('new dir'), "$dir committed" ); diag( "error: " . $dir->errstr . " : $!" ) if $dir->error_code; is( $dir->status, 0, "dir status is 0 since it has not changed" ); # SVN::Class::Info ok( my $info = $dir->info, "get info" ); # 16 is( $info->path, $dir, "working path" ); # SVN::Class::Repos #diag(dump $info); #diag($info->url); #diag(dump $info->url); is( $info->url, $info->url->info->url, "recursive URL" ); ok( my $repos = SVN::Class::Repos->new( 'file://' . $repos ), "new repos object" ); my $thisuser = getpwuid($<); is( $repos->info->author, $thisuser, "$thisuser was last author to commit to $repos" ); # 20 } # end global SKIP SVN-Class-0.17/t/boilerplate.t000644 000766 000024 00000002320 11054667502 016541 0ustar00karpetstaff000000 000000 #!perl -T use strict; use warnings; use Test::More tests => 3; sub not_in_file_ok { my ($filename, %regex) = @_; open my $fh, "<", $filename or die "couldn't open $filename for reading: $!"; my %violated; while (my $line = <$fh>) { while (my ($desc, $regex) = each %regex) { if ($line =~ $regex) { push @{$violated{$desc}||=[]}, $.; } } } if (%violated) { fail("$filename contains boilerplate text"); diag "$_ appears on lines @{$violated{$_}}" for keys %violated; } else { pass("$filename contains no boilerplate text"); } } not_in_file_ok(README => "The README is used..." => qr/The README is used/, "'version information here'" => qr/to provide version information/, ); not_in_file_ok(Changes => "placeholder date/time" => qr(Date/time) ); sub module_boilerplate_ok { my ($module) = @_; not_in_file_ok($module => 'the great new $MODULENAME' => qr/ - The great new /, 'boilerplate description' => qr/Quick summary of what the module/, 'stub function definition' => qr/function[12]/, ); } module_boilerplate_ok('lib/SVN/Class.pm'); SVN-Class-0.17/t/pod-coverage.t000644 000766 000024 00000000242 11054667502 016613 0ustar00karpetstaff000000 000000 use Test::More; eval "use Test::Pod::Coverage 1.04"; plan skip_all => "Test::Pod::Coverage 1.04 required for testing POD coverage" if $@; all_pod_coverage_ok(); SVN-Class-0.17/t/pod.t000644 000766 000024 00000000214 11054667502 015021 0ustar00karpetstaff000000 000000 #!perl -T use Test::More; eval "use Test::Pod 1.14"; plan skip_all => "Test::Pod 1.14 required for testing POD" if $@; all_pod_files_ok(); SVN-Class-0.17/lib/SVN/000755 000766 000024 00000000000 11656220115 015017 5ustar00karpetstaff000000 000000 SVN-Class-0.17/lib/SVN/Class/000755 000766 000024 00000000000 11656220115 016064 5ustar00karpetstaff000000 000000 SVN-Class-0.17/lib/SVN/Class.pm000644 000766 000024 00000027110 11656220104 016421 0ustar00karpetstaff000000 000000 package SVN::Class; use strict; use warnings; use base qw( Path::Class Rose::Object ); use Rose::Object::MakeMethods::Generic ( scalar => [qw( svn stdout stderr error error_code verbose debug )] ); use Carp; use Data::Dump; use IPC::Cmd qw( can_run run ); use SVN::Class::File; use SVN::Class::Dir; use SVN::Class::Info; use Text::ParseWords; use File::Temp; $ENV{LC_ALL} = 'C'; # we expect our responses in ASCII #$IPC::Cmd::DEBUG = 1; #$IPC::Cmd::VERBOSE = 1; unless ( IPC::Cmd->can_capture_buffer ) { croak "IPC::Cmd is not configured to capture buffers. " . "Do you have IPC::Run installed?"; } # IPC::Run fails tests because we use built-in shell commands # not found in PATH $IPC::Cmd::USE_IPC_RUN = 1; # this trick cribbed from mst's Catalyst::Controller::WrapCGI # we alias STDIN and STDOUT since Catalyst (and presumaly other code) # might be messing with STDOUT or STDIN my $REAL_STDIN = *STDIN; my $REAL_STDOUT = *STDOUT; my $REAL_STDERR = *STDERR; if ( $ENV{SVN_CLASS_ALIAS_STDOUT} ) { open $REAL_STDIN, "<&=" . CORE::fileno(*STDIN); open $REAL_STDOUT, ">>&=" . CORE::fileno(*STDOUT); open $REAL_STDERR, ">>&=" . CORE::fileno(*STDERR); } sub _debug_stdin_fh { #warn " stdin fileno = " . CORE::fileno(*STDIN); #warn "real_stdin fileno = " . CORE::fileno($REAL_STDIN); } sub _debug_stdout_fh { #warn " stdout fileno = " . CORE::fileno(*STDOUT); #warn "real_stdout fileno = " . CORE::fileno($REAL_STDOUT); } our @EXPORT = qw( svn_file svn_dir ); our @EXPORT_OK = qw( svn_file svn_dir ); our $VERSION = '0.17'; =head1 NAME SVN::Class - manipulate Subversion workspaces with Perl objects =head1 SYNOPSIS use SVN::Class; my $file = svn_file( 'path/to/file' ); my $fh = $file->open('>>'); print {$fh} "hello world\n"; $fh->close; $file->add; if ($file->modified) { my $rev = $file->commit('the file changed'); print "$file was committed with revision $rev\n"; } else { croak "$file was not committed: " . $file->errstr; } my $dir = svn_dir( 'path/to/dir' ); $dir->mkpath unless -d $dir; $dir->add; # recurses by default $dir->commit('added directory') if $dir->modified; =head1 DESCRIPTION SVN::Class extends Path::Class to allow for basic Subversion workspace management. SVN::Class::File and SVN::Class::Dir are subclasses of Path::Class::File::Stat and Path::Class::Dir respectively. SVN::Class does not use the SVN::Core Subversion SWIG bindings. Instead, the C binary tool is used for all interactions, using IPC::Cmd. This design decision was made for maximum portability and to eliminate non-CPAN dependencies. =head1 EXPORT SVN::Class exports two functions by default: svn_file() and svn_dir(). These work just like the dir() and file() functions in Path::Class. If you do not want to export them, just invoke SVN::Class like: use SVN::Class (); =head2 svn_file( I ) Works just like Path::Class::file(). =head2 svn_dir( I ) Works just like Path::Class::dir(). =cut sub svn_file { SVN::Class::File->new(@_); } sub svn_dir { SVN::Class::Dir->new(@_); } =head1 METHODS SVN::Class inherits from Path::Class. Only new or overridden methods are documented here. =cut =head2 svn Path to the svn binary. Defaults to C and thus relies on environment's PATH to find and execute the correct command. =head2 stdout Get the stdout from the last svn_run(). =head2 stderr Get the stderr from the last svn_run(). =head2 error If the last svn_run() exited with non-zero, error() will return same as stderr(). If svn_run() was successful, returns the empty string. =head2 error_code Returns the last exit value of svn_run(). =head2 verbose Get/set a true value to enable IPC output in svn_run(). =head2 debug Get/set a true value to see debugging output printed on stderr. =cut =head2 svn_run( I, I, I ) Execute I given I and I as arguments. This is a wrapper around the IPC::Run run() function. I should be an array ref of options to pass to I. I defaults to $self->stringify(). Returns the success code from IPC::Run run(). Sets the stdout, stderr, err, errstr, and error_code values in the SVN::Class object. This method is used internally by all the Subversion commands. B In order to standardize the output of Subversion commands into a locale that is easily parse-able by other methods that call svn_run() internally, all commands are run with C to make sure output is ASCII only. =cut sub svn_run { my $self = shift; my $cmd = shift or croak "svn command required"; my $opts = shift || []; my $file = shift || "$self"; # since $opts may contain whitespace, must pass command as array ref # to IPC::Run my $command = [ $self->svn, $cmd, shellwords( join( ' ', @$opts ) ), $file ]; my @out; $self->_debug_stdin_fh; $self->_debug_stdout_fh; { local *STDIN = $REAL_STDIN; # restore the real ones so the filenos local *STDOUT = $REAL_STDOUT; # are 0 and 1 for the env setup local *STDERR = $REAL_STDERR; my $old = select($REAL_STDOUT); # in case somebody just calls 'print' # Use local signal handler so global handler # does not result in bad values in $? and $! # http://www.perlmonks.org/?node_id=197500 # useful for running under Catalyst (e.g.) local $SIG{CHLD} = ''; $self->_debug_stdin_fh; $self->_debug_stdout_fh; (@out) = run( command => $command, verbose => $self->verbose ); select($old); } my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) = @out; # buffers do not always split on \n so force them to. my @stdout = split( m/\n/, join( '', @$stdout_buf ) ); my @stderr = split( m/\n/, join( '', @$stderr_buf ) ); # return code is a little murky as $error_code is often -1 # which sometimes signals success, while $success is undef. if ( !defined($success) ) { if ( $error_code eq '-1' && !@stderr ) { $success = 1; } else { $success = 0; } } $self->stdout( \@stdout ); $self->stderr( \@stderr ); $self->error( $success ? "" : \@stderr ); $self->error_code($error_code); if ( $self->debug || $ENV{PERL_DEBUG} ) { carp "command: " . Data::Dump::dump($command); carp Data::Dump::dump \@out; $self->dump; carp "success = $success"; } return $success; } =head2 log Returns svn log of the file or 0 on error. The log is returned as an arrayref (same as accessing stdout()). =cut sub log { my $self = shift; my $ret = $self->svn_run( 'log', @_ ); return 0 unless $ret > 0; return $self->stdout; } =head2 add Schedule the object for addition to the repository. =cut sub add { shift->svn_run( 'add', @_ ); } =head2 delete Schedule the object for removal from the repository. =cut sub delete { shift->svn_run( 'rm', @_ ); } =head2 update Get the latest version of the object from the repository. =cut sub update { shift->svn_run( 'update', @_ ); } =head2 up Alias for update(). =cut *up = \&update; =head2 revert Undo the last Subversion action on the object. =cut sub revert { shift->svn_run( 'revert', @_ ); } =head2 commit( I ) Commit the object to the repository with the log I. Returns the revision number of the commit on success, 0 on failure. =cut sub commit { # croak if failure but set error() and error_code() # first in case wrapped in eval(). my $self = shift; my $message = shift or croak "commit message required"; my $opts = shift || []; # create temp file to print message to. see RT #48748 my $message_fh = File::Temp->new(); print $message_fh $message; my $message_file = $message_fh->filename; $message_file =~ s!\\!/!g; # escape literal \ for Windows users. see RT#54969 my $ret = $self->svn_run( 'commit', [ '--file', $message_file, @$opts ] ); # confirm temp file is removed undef $message_fh; if ( -s $message_file ) { warn "temp file not removed: $message_file"; } # $ret is empty string on success. that's odd. if ( defined( $self->{stdout}->[0] ) && $self->{stdout}->[-1] =~ m/Committed revision (\d+)/ ) { return $1; } return 0; } =head2 status Returns the workspace status of the object. =cut sub status { my $self = shift; $self->svn_run('status'); if ( $self->is_dir ) { # find the arg that matches $self if ( defined $self->stdout->[0] ) { for my $line ( @{ $self->stdout } ) { if ( $line =~ m/^(\S)\s+\Q$self\E$/ ) { return $1; } } return 0; } } if ( defined $self->stdout->[0] ) { my ($stat) = ( $self->stdout->[0] =~ m/^([A-Z\?])/ ); return $stat; } return 0; } =head2 modified Returns true if the status() of the object is C or C. =cut sub modified { return $_[0]->status =~ m/^[MA]$/ ? 1 : 0; } =head2 conflicted Returns true if the status() of the object is C. =cut sub conflicted { return $_[0]->status eq 'C'; } =head2 diff Diff the workspace version of the object against either the repository or the current working baseline version. =cut sub diff { shift->svn_run( 'diff', @_ ); } =head2 blame Annotated accounting of who modified what lines of the object. =cut sub blame { shift->svn_run( 'blame', @_ ); } =head2 info Returns SVN::Class::Info instance with information about the current object or 0 on failure. =cut sub info { my $self = shift; return 0 unless $self->svn_run( 'info', @_ ); return SVN::Class::Info->new( $self->stdout ); } =head2 dump Returns a Data::Dump serialization of the object. Useful for debugging. =cut sub dump { Data::Dump::dump(shift); } =head2 errstr Returns the contents of error() as a newline-joined string. =cut sub errstr { my $self = shift; my $err = $self->error; return ref($err) ? join( "\n", @$err ) : $err; } =head2 outstr Returns the contents of stdout() as a newline-joined string. =cut sub outstr { my $self = shift; my $out = $self->stdout; return ( ref($out) ? join( "\n", @$out ) : $out ) . "\n"; } 1; __END__ =head1 AUTHOR Peter Karman, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS I looked at SVN::Agent before starting this project. It has a different API, more like SVN::Client in the SVN::Core, but I cribbed some of the ideas. The Minnesota Supercomputing Institute C<< http://www.msi.umn.edu/ >> sponsored the development of this software. =head1 COPYRIGHT Copyright 2007 by the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO Path::Class, Class::Accessor::Fast, SVN::Agent, IPC::Cmd SVN-Class-0.17/lib/SVN/Class/Dir.pm000644 000766 000024 00000004541 11656220104 017142 0ustar00karpetstaff000000 000000 package SVN::Class::Dir; use strict; use warnings; use base qw( Path::Class::Dir SVN::Class ); use SVN::Class::File; our $VERSION = '0.17'; # override some Path::Class stuff to return SVN::Class objects instead sub file { local $Path::Class::Foreign = $_[0]->{file_spec_class} if $_[0]->{file_spec_class}; return SVN::Class::File->new(@_); } sub new { my $self = Path::Class::Entity::new(shift); my $s = $self->_spec; my $first = ( @_ == 0 ? $s->curdir : $_[0] eq '' ? ( shift, $s->rootdir ) : shift() ); ( $self->{volume}, my $dirs ) = $s->splitpath( $s->canonpath($first) || '', 1 ); $self->{dirs} = [ $s->splitdir( $s->catdir( $dirs, @_ ) ) ]; $self->{svn} ||= 'svn'; return $self; } 1; __END__ =head1 NAME SVN::Class::Dir - represents a directory in a Subversion workspace =head1 SYNOPSIS # see SVN::Class; =head1 DESCRIPTION This class subclasses Path::Class::Dir and SVN::Class. A SVN::Class::Dir object behaves like a Path::Class::Dir object, but with the extra Subversion functionality of SVN::Class. =head1 METHODS There are no new methods implemented in this class. The following methods are overridden to return SVN::Class-derived objects instead of Path::Class-derived objects. =over =item new =item file =back =head1 AUTHOR Peter Karman, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 COPYRIGHT & LICENSE Copyright 2007 by the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO SVN::Class, Path::Class::Dir SVN-Class-0.17/lib/SVN/Class/File.pm000644 000766 000024 00000004525 11656220104 017305 0ustar00karpetstaff000000 000000 package SVN::Class::File; use strict; use warnings; use base qw( Path::Class::File::Stat SVN::Class ); use SVN::Class::Dir; our $VERSION = '0.17'; # override Path::Class stuff to use SVN::Class instead sub new { my $self = Path::Class::Entity::new(shift); my $file = pop(); my @dirs = @_; my ( $volume, $dirs, $base ) = $self->_spec->splitpath($file); if ( length $dirs ) { push @dirs, $self->_spec->catpath( $volume, $dirs, '' ); } $self->{dir} = @dirs ? SVN::Class::Dir->new(@dirs) : undef; $self->{file} = $base; $self->{svn} ||= 'svn'; return $self; } sub dir { my $self = shift; return $self->{dir} if defined $self->{dir}; return SVN::Class::Dir->new( $self->_spec->curdir ); } 1; __END__ =head1 NAME SVN::Class::File - represents a file in a Subversion workspace =head1 SYNOPSIS # see SVN::Class; =head1 DESCRIPTION This class subclasses Path::Class::File::Stat and SVN::Class. A SVN::Class::File object behaves like a Path::Class::File::Stat object, but with the extra Subversion functionality of SVN::Class. =head1 METHODS There are no new methods implemented in this class. The following methods are overridden to return SVN::Class-derived objects instead of Path::Class-derived objects. =over =item new =item dir =back =head1 AUTHOR Peter Karman, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 COPYRIGHT & LICENSE Copyright 2007 by the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO SVN::Class, Path::Class::File::Stat SVN-Class-0.17/lib/SVN/Class/Info.pm000644 000766 000024 00000010036 11656220104 017313 0ustar00karpetstaff000000 000000 package SVN::Class::Info; use strict; use warnings; use base qw( Rose::Object ); use Rose::Object::MakeMethods::Generic ( scalar => [ qw( path name wc_root _url root rev node schedule author last_rev date updated checksum uuid ) ] ); use Carp; use Data::Dump; use SVN::Class::Repos; our $VERSION = '0.17'; =head1 NAME SVN::Class::Info - Subversion workspace info =head1 SYNOPSIS use SVN::Class; my $file = svn_file( 'path/to/file' ); my $info = $file->info; printf "repository URL = %s\n", $info->url; =head1 DESCRIPTION SVN::Class::Info represents the output of the C command. =head1 METHODS SVN::Class::Info B inherit from SVN::Class, but only Class::Accessor::Fast. =cut =head2 new( $dir->stdout ) Creates new SVN::Class::Info instance. The lone argument should be an array ref of output from a call to the SVN::Class object's info() method. You normally do not need to use this method directly. See the SVN::Class info() method. =cut sub new { my $class = shift; my $buf = shift; if ( !$buf or !ref($buf) or ref($buf) ne 'ARRAY' ) { croak "need array ref of 'svn info' output"; } return $class->SUPER::new( _make_hash(@$buf) ); } =head2 dump Returns dump() of the object, just like SVN::Class->dump(). =cut sub dump { return Data::Dump::dump(@_); } my %fieldmap = ( Path => 'path', Name => 'name', URL => '_url', 'Working Copy Root Path' => 'wc_root', 'Repository Root' => 'root', 'Repository UUID' => 'uuid', 'Revision' => 'rev', 'Node Kind' => 'node', 'Schedule' => 'schedule', 'Last Changed Author' => 'author', 'Last Changed Rev' => 'last_rev', 'Last Changed Date' => 'date', 'Text Last Updated' => 'updated', 'Checksum' => 'checksum' ); sub _make_hash { my %hash; for (@_) { my ( $field, $value ) = (m/^([^:]+):\ (.+)$/); if ( !exists $fieldmap{$field} ) { croak "unknown field name in svn info: $field"; } $hash{ $fieldmap{$field} } = $value; } return %hash; } =head2 url Get the URL value. Returns a SVN::Class::Repos object. =cut sub url { my $self = shift; return SVN::Class::Repos->new( $self->_url ); } =head2 path =head2 wc_root Working Copy Root Path =head2 name =head2 root =head2 rev =head2 node =head2 schedule =head2 author =head2 last_rev =head2 date =head2 updated =head2 checksum =head2 uuid Get/set the info params. These are really only useful as accessors (getters). =cut 1; __END__ =head1 AUTHOR Peter Karman, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS I looked at SVN::Agent before starting this project. It has a different API, more like SVN::Client in the SVN::Core, but I cribbed some of the ideas. The Minnesota Supercomputing Institute C<< http://www.msi.umn.edu/ >> sponsored the development of this software. =head1 COPYRIGHT Copyright 2008 by the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO Path::Class, Class::Accessor::Fast, SVN::Agent, IPC::Cmd SVN-Class-0.17/lib/SVN/Class/Repos.pm000644 000766 000024 00000004135 11656220104 017513 0ustar00karpetstaff000000 000000 package SVN::Class::Repos; use strict; use warnings; use Carp; use Data::Dump; use base qw( Rose::URI SVN::Class ); our $VERSION = '0.17'; =head1 NAME SVN::Class::Repos - represents the repository of a Subversion workspace =head1 SYNOPSIS use SVN::Class; my $file = svn_file( 'path/to/file' ); my $info = $file->info; my $url = $info->url; print "repository URL is $url\n"; =head1 DESCRIPTION SVN::Class::URL represents the source repository for a workspace. =head1 METHODS SVN::Class::URL inherits from Rose::URI and SVN::Class. =cut =head2 init Override the base Rose::URI method to set some default values in object. =cut sub init { my $self = shift; $self->SUPER::init(@_); $self->{svn} ||= 'svn'; } 1; __END__ =head1 AUTHOR Peter Karman, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc SVN::Class You can also look for information at: =over 4 =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * RT: CPAN's request tracker L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS I looked at SVN::Agent before starting this project. It has a different API, more like SVN::Client in the SVN::Core, but I cribbed some of the ideas. The Minnesota Supercomputing Institute C<< http://www.msi.umn.edu/ >> sponsored the development of this software. =head1 COPYRIGHT Copyright 2008 by the Regents of the University of Minnesota. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO Rose::URI, Path::Class, Class::Accessor::Fast, SVN::Agent, IPC::Cmd