App-KGB

 view release on metacpan or  search on metacpan

lib/App/KGB/Client/CVS.pm  view on Meta::CPAN

    $client->run;

=head1 DESCRIPTION

B<App::KGB::Client::CVS> provides CVS-specific retrieval of
commits and changes for L<App::KGB::Client>.

=head1 CONSTRUCTOR

=head2 B<new> ( { initializers } )

Standard constructor. Accepts inline hash with initial field values.

=head1 FIELDS

App:KGB::Client::CVS defines the following additional fields:

=over

=item B<cvs_root> (B<mandatory>)

Physical path to the CVS root directory.

=item B<author>

The user name of the commit author.

=item B<directory>

Relative (to CVS root) path to the directory this change is in.

As a convention, the first path member is taken as a module.

=back

=head1 METHODS

=over

=item describe_commit

The first time this method is called, it parses STDIN and determines commit
contents, returning an instance of L<App::KGB::Commit> class describing the
commit.

All subsequential invocations return B<undef>.

=back

=cut

require v5.10.0;
use base 'App::KGB::Client';
use App::KGB::Change;
use App::KGB::Commit;
use Carp qw(confess);
__PACKAGE__->mk_accessors(qw( _called author cvs_root directory ));

sub new {
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->_called(0);

    defined( $self->cvs_root )
        or confess "'cvs_root' is mandatory";

    return $self;
}

use Fcntl qw(:flock);

sub describe_commit {
    my ($self) = @_;

    return undef if $self->_called;

    my $merge_file = File::Spec->catfile( $self->cvs_root, 'CVSROOT',
        sprintf( 'kgb-client-%d-%d.tmp', $<, getpgrp() ) );

    open(MERGE, ">>$merge_file") or die "Unable to open $merge_file: $!\n";

    my $first_dir_in_commit = flock( MERGE, LOCK_EX | LOCK_NB );

    my ( $tag, $log, @changes );
    # the first element is module, the rest - directory path
    my ($module, $dir) = $self->directory =~ m{([^/]+)(/.+)?};
    $dir //= '';
    $dir .= '/' if $dir;

    while ( defined( my $line = <> ) ) {
        $tag = $1, next if $line =~ /^\s*Tag: ([a-zA-Z0-9_-]+)/;

        if ( $line =~ /^Added Files:/ ) {
            while ( defined( $line = <> ) and $line =~ /^\s+(.+?)\s?$/ ) {
                my $files = $1;
                push @changes,
                    App::KGB::Change->new(
                    {   action => 'A',
                        path   => "$dir$_",
                    }
                    ) for split( /\s+/, $files );
            }
            redo;
        }
        if ( $line =~ /^Modified Files:/ ) {
            while ( defined( $line = <> ) and $line =~ /^\s+(.+?)\s?$/ ) {
                my $files = $1;
                push @changes,
                    App::KGB::Change->new(
                    {   action => 'M',
                        path   => "$dir$_",
                    }
                    ) for split( /\s+/, $files );
            }
            redo;
        }
        if ( $line =~ /^Removed Files:/ ) {
            while ( defined( $line = <> ) and $line =~ /^\s+(.+?)\s?$/ ) {
                my $files = $1;
                push @changes,
                    App::KGB::Change->new(



( run in 0.861 second using v1.01-cache-2.11-cpan-302cb4679cc )