use strict;
use warnings FATAL => 'all';
package SVN::Agent;
use base 'Class::Accessor';
__PACKAGE__->mk_accessors('path', 'changes');
use Carp;
our $VERSION = 0.02;
=head1 NAME
SVN::Agent - simple svn manipulation.
=head1 SYNOPSIS
use SVN::Agent;
my $sa = SVN::Agent->load({ path => 'my_checkout_dir' });
# find out modified files
print join(',', @{ $sa->modified }) . "\n";
# usual svn operations
$sa->add('file.pl');
$sa->commit("Message");
=head1 DESCRIPTION
This module provides regular svn operations on check out directory. It tries
to do this in a simplest form possible.
All operations are currently performed by running svn binary directly. Thus
it is probably unportable.
For a much more powerful way of working with svn repository see SVN::Client.
=cut
sub _svn_command {
my ($self, $cmd, @params) = @_;
my $cmd_line = "cd " . $self->path . " && svn $cmd ";
$cmd_line .= join(' ', map { quotemeta($_) } @params) if @params;
my @res = `$cmd_line 2>&1`;
confess "Unable to do $cmd_line\n" . join('', @res) if $?;
return @res;
}
sub _load_status {
my $self = shift;
foreach ($self->_svn_command('status')) {
chomp;
/^(.).{6}(.+)$/;
push @{ $self->{$1} }, $2;
}
}
=head1 METHODS
=head2 load OPTIONS
Constructs SVN::Agent instance. Loads current status of the directory
given by C<path> option.
=cut
sub new {
my $self = shift()->SUPER::new(@_);
$self->changes([]) unless $self->changes;
return $self;
}
sub load {
my $self = shift()->new(@_);
$self->_load_status;
return $self;
}
=head2 modified
Returns array of files which are currently modified.
=cut
sub modified { return shift()->{M} || []; }
=head2 added
Returns array of file which are scheduled for addition.
=cut
sub added { return shift()->{A} || []; }
=head2 unknown
Returns array of files which do not exist in svn repository.
=cut
sub unknown { return shift()->{'?'} || []; }
=head2 deleted
Returns array of files which are scheduled for deletion.
=cut
sub deleted { return shift()->{D} || []; }
=head2 missing
Returns array of files which are missing from the working directory.
=head2 changes
Returns array of files which are changes for the next commit. Note that
you can also modify this array to change next commit files.
=cut
sub missing { return shift()->{'!'} || []; }
=head2 add FILE
Adds a file into repository. If the file's directory is not under svn control,
L<SVN::Agent> adds it also.
=cut
sub add {
my ($self, $file) = @_;
my $p = '.';
my $res = '';
for (split('/', $file)) {
$p .= "/$_";
my $r = join('', $self->_svn_command('add -N', $p));
next if $r =~ /already under version/;
$res .= $r;
push @{ $self->changes }, $p;
}
return $res;
}
=head2 prepare_changes
Rolls modified, added and deleted arrays into changes array.
=cut
sub revert {
return shift()->_svn_command("revert", @_);
}
=head2 prepare_changes
Rolls modified, added and deleted arrays into changes array.
=cut
sub prepare_changes {
my $self = shift;
push @{ $self->changes }, @{ $self->$_ }
for qw(modified added deleted);
}
=head2 commit MESSAGE
Commits current changes using MESSAGE as a log message. The changes should
be listed in the changes array.
=cut
sub commit {
my ($self, $msg) = @_;
die "No message given" unless $msg;
my $ch = $self->changes;
confess "Empty commit" unless @$ch;
my $res = $self->_svn_command('commit -m', $msg, @$ch);
$self->changes([]);
return $res;
}
=head2 update
Updates current working directory from the latest repository contents.
=cut
sub update { return shift()->_svn_command('update'); }
=head2 remove FILE
Schedules FILE for removal. Note, that it doesn't physically removes the file
from the working directory.
=cut
sub remove {
my ($self, $file) = @_;
my $res = $self->_svn_command('remove', $file);
push @{ $self->changes }, $file;
return $res;
}
=head2 diff FILE
Diffs the file against the repository.
=cut
sub diff { return join('', shift()->_svn_command('diff', @_)); }
=head2 checkout REPOSITORY
Checks-out working copy from the REPOSITORY into directory given by C<path>
option.
=cut
sub checkout {
my ($self, $repository) = @_;
mkdir($self->path) or confess "Unable to create " . $self->path;
return $self->_svn_command('checkout', $repository, '.');
}
1;
=head1 AUTHOR
Boris Sukholitko <boriss@gmail.com>
=head1 LICENSE
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=head1 SEE ALSO
L<SVN::Client>, SVN manual.
=cut
syntax highlighted by Code2HTML, v. 0.9.1