OSSP CVS Repository

ossp - Difference in ossp-pkg/cvsfusion/RCS.pm versions 1.1 and 1.2
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/cvsfusion/RCS.pm 1.1 -> 1.2

--- RCS.pm       2004/04/22 06:56:28     1.1
+++ RCS.pm       2004/04/23 09:23:38     1.2
@@ -32,6 +32,8 @@
 
 require 5;
 require Exporter;
+use Carp;
+use IO::File;
 
 @ISA       = qw(Exporter);
 @EXPORT_OK = qw(new destroy DESTROY dump);
@@ -42,8 +44,12 @@
     my $self = {};
     bless ($self, $class);
 
-    $self->{'prog-rcs'}  = "";
-    $self->{'prog-diff'} = "";
+    $self->{'tool'} = {
+        'rcs'  => 'rcs',
+        'co'   => 'co',
+        'diff' => 'diff',
+    };
+    $self->{'rcs'} = {};
 
     return $self;
 }
@@ -75,6 +81,238 @@
     return $dump;
 }
 
+sub tool ($;$) {
+    my $self = shift;
+    my ($tool, $path) = @_;
+    my $old = $self->{'tool'}->{$tool};
+    if (not defined($old)) {
+        croak "tool \"$tool\" not known";
+    }
+    if (defined($path)) {
+        $self->{'tool'}->{$tool} = $path;
+    }
+    return $old;
+}
+
+sub load ($$) {
+    my $self = shift;
+    my ($file) = @_;
+
+    #   read RCS file into buffer
+    my $io = new IO::File "<$file"
+        or croak "RCS file \"$file\": cannot open for reading";
+    my $rcs = '';
+    $rcs .= $_ while (<$io>);
+    $io->close;
+
+    #   clear RCS structure
+    $self->{'rcs'} = {
+        'header'    => { -order => [] },
+        'delta'     => { -order => [] },
+    };
+
+    #   pre-generate reusable regular expressions
+    my $re_num     = qr/[\d.]+/;
+    my $re_rev     = qr/\d+(?:\.\d+)*/;
+    my $re_special = qr/[$,.:;@]/;
+    my $re_idchar  = qr/[^$,.:;@]/;
+    my $re_id      = qr/(?:${re_num})?${re_idchar}+(?:${re_idchar}|${re_num})*/;
+    my $re_sym     = qr/\d?${re_idchar}+(?:${re_idchar}|\d)*/;
+    my $re_str     = qr/(?:@@|[^@])*/;
+    my $re_date    = qr/\d{4}\.\d{2}\.\d{2}\.\d{2}\.\d{2}\.\d{2}/;
+
+    #   parse header section
+    while (1) {
+        $rcs =~ s|^\s*||s;
+        if ($rcs =~ s/^head\s+($re_rev)\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'head'} = $1;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'head');
+        }
+        elsif ($rcs =~ s/^branch\s+($re_rev)\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'branch'} = $1;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'branch');
+        }
+        elsif ($rcs =~ s/^access((?:\s+$re_id)*)\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'access'} = [ split(/\s+/, $1) ];
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'access');
+        }
+        elsif ($rcs =~ s/^symbols((?:\s+$re_sym:$re_rev)*)\s*;//s) {
+            my $symbols = {};
+            map { $symbols->{$1} = $2 if (m/^(.+):(.+)$/s); } split(/\s+/, $1);
+            $self->{'rcs'}->{'header'}->{'symbols'} = $symbols;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'symbols');
+        }
+        elsif ($rcs =~ s/^locks((?:\s+$re_id:$re_rev)*)\s*;//s) {
+            my $locks = {};
+            map { $locks->{$1} = $2 if (m/^(.+):(.+)$/); } split(/\s+/, $1);
+            $self->{'rcs'}->{'header'}->{'locks'} = $locks;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'locks');
+        }
+        elsif ($rcs =~ s/^strict\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'strict'} = "";
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'strict');
+        }
+        elsif ($rcs =~ s/^comment\s+\@($re_str)\@\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'comment'} = $1;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'comment');
+        }
+        elsif ($rcs =~ s/^expand\s+\@($re_str)\@\s*;//s) {
+            $self->{'rcs'}->{'header'}->{'expand'} = $1;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, 'expand');
+        }
+        elsif ($rcs =~ s/^([a-z]+)(\s*[^;]*);//s) {
+            $self->{'rcs'}->{'header'}->{$1} = $2;
+            push(@{$self->{'rcs'}->{'header'}->{-order}}, $1);
+        }
+        else {
+            last;
+        }
+    }
+
+    #   parse delta section(s)
+    while (1) {
+        $rcs =~ s|^\s*||s;
+        if ($rcs =~ s/^($re_rev)//s) {
+            my $rev = $1;
+            $self->{'rcs'}->{'delta'}->{$rev} = {};
+            push(@{$self->{'rcs'}->{'delta'}->{-order}}, $rev);
+            while (1) {
+                $rcs =~ s|^\s*||s;
+                if ($rcs =~ s/^date\s+($re_date)\s*;//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'date'} = $1;
+                }
+                elsif ($rcs =~ s/^author\s+($re_id)\s*;//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'author'} = $1;
+                }
+                elsif ($rcs =~ s/^state(?:\s*($re_id))?\s*;//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'state'} = $1;
+                }
+                elsif ($rcs =~ s/^branches(?:\s+((?:\s*$re_rev)*))?\s*;//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'branches'} = [ split(/\s+/, $1) ];
+                }
+                elsif ($rcs =~ s/^next(?:\s*($re_rev))?\s*;//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'next'} = $1;
+                }
+                elsif ($rcs =~ m/^desc\s+/s) {
+                    last;
+                }
+                elsif ($rcs =~ s/^([a-z]+)(\s*[^;]*);//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{$1} = $2;
+                }
+                else {
+                    last;
+                }
+            }
+        }
+        else {
+            last;
+        }
+    }
+
+    #   parse description section
+    $rcs =~ s|^\s*||s;
+    if ($rcs =~ s/^desc\s+\@($re_str)\@\s*//s) {
+        $self->{'rcs'}->{'header'}->{'desc'} = $1;
+        push(@{$self->{'rcs'}->{'header'}->{-order}}, 'desc');
+    }
+
+    #  parse deltatext section(s)
+    while (1) {
+        $rcs =~ s|^\s*||s;
+        if ($rcs =~ s/^($re_rev)//s) {
+            my $rev = $1;
+            if (not defined($self->{'rcs'}->{'delta'}->{$rev})) {
+                croak "deltatext section for unknown revision \"$rev\" found";
+            }
+            my $textseen = 0;
+            while (1) {
+                $rcs =~ s|^\s*||s;
+                if ($rcs =~ s/^log\s+\@($re_str)\@\s*//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'log'} = $1;
+                }
+                elsif ($rcs =~ s/^text\s+\@($re_str)\@\s*//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'text'} = $1;
+                    $textseen = 1;
+                }
+                elsif ($textseen == 0 and $rcs =~ s/^([a-z]+)(\s*[^;]*);//s) {
+                    $self->{'rcs'}->{'delta'}->{$rev}->{$1} = $2;
+                }
+                else {
+                    last;
+                }
+            }
+        }
+        else {
+            last;
+        }
+    }
+    return;
+}
+
+sub save ($$) {
+    my $self = shift;
+    my ($file) = @_;
+    my $rcs = '';
+
+    #   define known keywords
+    my @kw_header    = (qw(head branch access symbols locks- strict comment@ expand@));
+    my @kw_delta     = (qw(date author state branches next));
+    my @kw_desc      = (qw(desc));
+    my @kw_deltatext = (qw(log text));
+
+    #   generate header section
+    foreach my $header (@kw_header) {
+        my $tag = '';
+        $tag = $1 if ($header =~ s/([@\-])$//s);
+        my $val = $self->{'rcs'}->{'header'}->{$header};
+        if (defined($val)) {
+            $rcs .= $header;
+            if (ref($val) eq 'ARRAY') {
+                if (@{$val} > 0) {
+                    foreach my $v (@{$val}) {
+                        $rcs .= "\n\t$v";
+                    }
+                }
+            }
+            elsif (ref($val) eq 'HASH') {
+                if (keys(%{$val}) > 0) {
+                    foreach my $v (keys(%{$val})) {
+                        $rcs .= sprintf("\n\t%s:%s", $v, $val->{$v});
+                    }
+                }
+            }
+            else {
+                if ($val ne '') {
+                    if ($tag eq '@') {
+                        $val =~ s|\@|\@\@|sg;
+                        $rcs .= "\t\@$val\@";
+                    }
+                    else {
+                        $rcs .= "\t$val";
+                    }
+                }
+            }
+            $rcs .= ";";
+            $rcs .= ($tag eq '-' ? " " : "\n");
+        }
+    }
+    $rcs .= "\n";
+
+    #   generate delta section(s)
+    foreach my $rev (@{$self->{'rcs'}->{'delta'}->{-order}}) {
+        my $delta = $self->{'rcs'}->{'delta'}->{$rev};
+        $rcs .= $rev."\n";
+    }
+
+    #   write new RCS file for disk
+    my $io = new IO::File ">$file"
+        or croak "RCS file \"$file\": cannot open for writing";
+    $io->print($rcs);
+    $io->close;
+
+    return;
+}
+
 __END__
 
 =pod

CVSTrac 2.0.1