package VCfs; our $VERSION = v0.0.1; use warnings; use strict; use Carp; use File::chdir; use List::Util qw(first); use Class::Accessor::Classy; ro qw( dir vcs vcs_cmd ); no Class::Accessor::Classy; use IPC::Run (); =head1 NAME VCfs - Version Control agnostic interface on the local system =head1 Synopsis my $vc = VCfs->new("."); my %status = $vc->status; my @tags = $vc->taglist; =head1 About I need somewhere to put all of this repeated code. There are probably other modules on the CPAN which do this sort of thing differently. The basic idea is to just capture output from shelling-out to the appropriate frontend command for a given version control tool. Examples of usage can be found in the 'bin/' directory of this distribution. Where necessary, assumes a typical "trunk,branches,tags" layout. This currently supports svn and svk. Your help and input is welcome. =cut =head1 Constructor =head2 new $vc = VCfs->new($dir|$file, \%options); =cut sub new { my $class = shift; my $dir = shift; $dir or croak("new() requires a directory or file"); unless(-d $dir) { $dir = dirname($dir); } (-d $dir) or croak("eek"); my $subclass = $class->_detect($dir); return $subclass->new($dir, @_); } sub _init { my $class = shift; my($dir, $opts) = @_; my $self = bless {$opts ? %$opts : ()}, $class; $self->{dir} = $dir; return $self; } =head1 Methods =begin private =head2 _detect Tries to guess at what sort of VCS by examining the directory. $vc->_detect; =end private =cut my @classes = ( "VCfs::Subversion", "VCfs::SVK", "VCfs::Git", ); sub _detect { my $class = shift; my $dir = shift; my $detected_class; for my $class (@classes) { eval "require $class" or die $@; if( $class->_detect($dir) ) { $detected_class = $class; last } } return $detected_class; } =head2 _do_run $res = $vc->_do_run(@command); =cut sub _do_run { my $self = shift; my @command = @_; my ($in, $out, $err); 0 and warn "run $self->{vcs_cmd} @command\n"; local $CWD = $self->dir; my $ret = IPC::Run::run([$self->vcs_cmd, @command], \$in, \$out, \$err); die "command @command died $err" if $ret != 0 and $ret != 1; chomp $out; chomp $err; return { out => $out, err => $err, status => ($? >> 8), ret => $ret }; } =head2 is_ Returns true if the underlying VCS is . These are mostly used internally to handle special cases. =over =item is_svn =item is_svk =back =cut # Put this in for testing sub _vcs_types { return qw(svn svk git); } foreach my $type (__PACKAGE__->_vcs_types()) { no strict 'refs'; *{__PACKAGE__ . "::is_$type"} = sub { 0; }; } =head2 get_log $vc->get_log($target); =head2 get_log_times $vc->get_log_times($target); =head2 get_info my %vals = $vc->get_info; =head2 taglist my @tags = $vc->taglist; =head2 tag_dir my $dir = $vc->tag_dir; =head2 taggit (Currently) assumes a proj/trunk, proj/tags layout and that we're looking at trunk. I guess you could tag a branch, but, uh... $vc->taggit($tagname, message => $message); Big issue: There is no syntax of copy that prevents writing into an existing tag directory. The subversion developers seem to think this should be handled via pre-commit hooks (see http://svn.haxx.se/users/archive-2005-11/0056.shtml for details.) =head1 normal methods Just abstraction for standard commands. =head2 add $vc->add(@files); =head2 remove $vc->remove(@files); =head2 commit $vc->commit($message, @files); =head2 update $vc->update; =head2 list my @list = $vc->list($path); =head2 revert $vc->revert(@files); =head2 status Returns a hash of files and their status codes. %status = $vc->status(@files); =head2 propget $vc->propget($propname, $url||$file); =head2 propset Takes an array reference or string for propvals. $vc->propset($propname, \@vals, @files); $vc->propset($propname, $valstring, @files); =head1 AUTHOR Eric Wilhelm @ http://scratchcomputing.com/ =head1 BUGS If you found this module on CPAN, please report any bugs or feature requests 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. If you pulled this development version from my /svn/, please contact me directly. =head1 COPYRIGHT Copyright (C) 2004-2009 Eric L. Wilhelm, All Rights Reserved. =head1 NO WARRANTY Absolutely, positively NO WARRANTY, neither express or implied, is offered with this software. You use this software at your own risk. In case of loss, no person or entity owes you anything whatsoever. You have been warned. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut # vi:sw=2:ts=2:et:sta 1;