office-gobmx/solenv/bin/modules/Cvs.pm
Jens-Heiner Rechtien 22c7f3f170 initial import
2000-09-20 13:43:26 +00:00

235 lines
4.9 KiB
Perl

#
# Cvs.pm - package for manipulating CVS archives
#
# $Id: Cvs.pm,v 1.1.1.1 2000-09-20 14:43:11 hr Exp $
package Cvs;
use strict;
##### ctor ####
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = {};
$self->{NAME} = undef;
$self->{HEAD} = undef;
$self->{FLAGS} = undef;
if ($^O eq "MSWin32" || $^O eq "os2" ) {
$self->{CVS_BINARY} = "_cvs.exe";
} else {
$self->{CVS_BINARY} = "cvs.clt";
}
$self->{REV_DATA} = {};
$self->{REV_SORTED} = [];
$self->{REV_TAGS} = {};
$self->{TAGS} = {};
$self->{"_PARSED"} = undef;
$self->{"_SORTED"} = undef;
$self->{"_TAGGED"} = undef;
bless ($self, $class);
return $self;
}
#### methods to access per object data ####
sub name {
my $self = shift;
if ( @_ ) {
$self->{name} = shift;
}
return $self->{name};
}
sub cvs_binary {
my $self = shift;
if ( @_ ) {
$self->{CVS_BINARY} = shift;
}
return $self->{CVS_BINARY};
}
sub get_data_by_rev {
my $self = shift;
$self->parse_log();
return $self->{REV_DATA};
}
sub get_sorted_revs {
my $self = shift;
if ( $self->{"_SORTED"} ) {
return $self->{REV_TAGS};
}
$self->parse_log();
sub by_rev {
# comparison function for sorting
my (@field_a, @field_b, $min_field, $i);
@field_a = split /\./, $a;
@field_b = split /\./, $b;
$min_field = ($#field_a > $#field_b) ? $#field_b : $#field_a;
for ($i = 0; $i <= $min_field; $i++)
{
if ( ($field_a[$i] < $field_b[$i]) ) {
return -1;
}
if ( ($field_a[$i] > $field_b[$i]) ) {
return 1;
}
}
if ( $#field_a == $#field_b ) {
return 0;
}
# eg. 1.70 sorts before 1.70.1.0
($#field_a < $#field_b) ? return -1 : return 1;
}
@{$self->{REV_SORTED}} = sort by_rev (keys %{$self->{REV_DATA}});
$self->{"_SORTED"} = 1;
return $self->{REV_SORTED};
}
sub get_tags_by_rev {
my $self = shift;
my ($tag, $rev);
if ( $self->{"_TAGGED"} ) {
return $self->{REV_TAGS};
}
$self->parse_log();
foreach $tag (keys %{$self->{TAGS}}) {
$rev = $self->{TAGS}->{$tag};
push (@{$self->{REV_TAGS}->{$rev}}, $tag);
}
$self->{"_TAGGED"} = 1;
return $self->{REV_TAGS};
}
sub get_flags {
my $self = shift;
$self->parse_log();
return $self->{FLAGS};
}
sub get_tags {
my $self = shift;
$self->parse_log();
return $self->{TAGS};
}
sub get_head {
my $self = shift;
$self->parse_log();
return $self->{HEAD};
}
#### methods to manipulate archive ####
sub delete_rev {
my $self = shift;
my $rev = shift;
my $file = $self->name;
my $out;
if ($^O eq "MSWin32") {
open (CVSDELETE,
"$self->{CVS_BINARY} admin -o$rev $file 2>nul |");
} elsif ( $^O eq "os2" ) {
open (CVSDELETE,
"$self->{CVS_BINARY} admin -o$rev $file 2>nul |");
} else {
open (CVSDELETE,
"$self->{CVS_BINARY} admin -o$rev $file 2>/dev/null |");
}
while(<CVSDELETE>) {
/deleting revision $rev/ && return 1;
}
close(CVSDELETE);
return 0;
}
#### private methods ####
sub parse_log {
my $self = shift;
if ( $self->{"_PARSED"} ) {
return;
}
my $file = $self->name;
my $in_revisions = 0;
my $in_tags = 0;
my $rev_data = {};
my ($rev, $date, $author, $state, $comment, @branches);
open(CVSLOG, "$self->{CVS_BINARY} log $file |");
while( <CVSLOG> ) {
chomp;
if ( $in_revisions ) {
/revision\s((\d|\.)+)$/o && do { $rev = $1; next; };
/^date:\s(\S+\s\S+);\s+author:\s(\S+);\s+state:\s(\S+);/
&& do { $date = $1; $author = $2; $state = $3; next; };
/^branches:((\s+(\d|\.)+;)+)$/o && do {
my $line;
$line = $1;
$line =~ s/\s//go;
@branches = split(/;/, $line);
next;
};
(/^----------------------------$/o || /^=============================================================================$/o)
&& do {
$rev_data = {
DATE => $date,
AUTHOR => $author,
STATE => $state,
COMMENT => $comment,
BRANCHES => [ @branches ]
};
$self->{REV_DATA}->{$rev} = $rev_data;
$comment = undef;
@branches = ();
next;
};
$comment .= $_ . "\n" ;
} elsif ( $in_tags ) {
/^keyword\ssubstitution:/o
&& do { $self->{FLAGS} = $'; $in_tags--; next; };
/^\t(\w+):\s((\d|\.)+)$/o
&& do { $self->{TAGS}->{$1} = $2; next; };
} else {
/^----------------------------$/o
&& do { $in_revisions++; next; };
/^symbolic\snames:$/o && do { $in_tags++; next; };
/^head:\s((\d|\.)+)$/o && do { $self->{HEAD} = $1; next; };
}
}
close(CVSLOG);
$self->{"_PARSED"} = 1;
}
####
1; # needed by "use" or "require"