OSSP CVS Repository

ossp - Check-in [4544]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 4544
Date: 2004-Apr-23 19:58:17 (local)
2004-Apr-23 17:58:17 (UTC)
User:rse
Branch:
Comment: add an abstraction layer between structured revisions and sequential numbers which results in structured revisions to exist only once in the whole internal structure and this way allows us to change a structured revision throughout the whole RCS file content (including all revision references, etc) easily
Tickets:
Inspections:
Files:
ossp-pkg/cvsfusion/RCS.pm      1.6 -> 1.7     90 inserted, 38 deleted

ossp-pkg/cvsfusion/RCS.pm 1.6 -> 1.7

--- RCS.pm       2004/04/23 15:03:27     1.6
+++ RCS.pm       2004/04/23 17:58:17     1.7
@@ -36,7 +36,7 @@
 use IO::File;
 
 @ISA       = qw(Exporter);
-@EXPORT_OK = qw(new destroy DESTROY dump tool load save parse format);
+@EXPORT_OK = qw(new destroy DESTROY dump tool load save parse format revapply trunk2branch);
 
 #   create new object
 sub new ($;$) {
@@ -138,6 +138,30 @@
     return;
 }
 
+#   INTERNAL: structured revision to sequential number mapping
+sub _rev_rev2num ($$) {
+    my ($self, $rev) = @_;
+    foreach my $num (keys(%{$self->{'rcs'}->{'rev'}})) {
+        next if ($num eq '-count');
+        return $num if ($self->{'rcs'}->{'rev'}->{$num} eq $rev);
+    }
+    my $num = sprintf("REV-NUM(%d)", $self->{'rcs'}->{'rev'}->{-count}++);
+    $self->{'rcs'}->{'rev'}->{$num} = $rev;
+    return $num;
+}
+
+#   INTERNAL: sequential number to structured revision mapping
+sub _rev_num2rev ($$) {
+    my ($self, $num) = @_;
+    return $self->{'rcs'}->{'rev'}->{$num};
+}
+
+#   INTERNAL: check whether argument is a valid sequential number
+sub _rev_isnum ($$) {
+    my ($self, $num) = @_;
+    return (($num =~ m|^REV-NUM\(\d+\)$| and defined($self->{'rcs'}->{'rev'}->{$num})) ? 1 : 0);
+}
+
 #   parse a RCS file content into object
 #   (see rcsfile(5) for reference)
 sub parse ($$) {
@@ -147,13 +171,14 @@
     $self->{'rcs'} = {
         'header'    => { -order => [] },
         'delta'     => { -order => [] },
+        'rev'       => { -count => 0  },
     };
 
     #   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_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/(?:\@\@|[^@])*/s;
@@ -163,32 +188,37 @@
     while (1) {
         $rcs =~ s|^\s*||s;
         if ($rcs =~ s/^head\s+($re_rev)\s*;//s) {
-            $self->{'rcs'}->{'header'}->{'head'} = $1;
+            $self->{'rcs'}->{'header'}->{'head'} = $self->_rev_rev2num($1);
             push(@{$self->{'rcs'}->{'header'}->{-order}}, 'head');
         }
         elsif ($rcs =~ s/^branch\s+($re_rev)\s*;//s) {
-            $self->{'rcs'}->{'header'}->{'branch'} = $1;
+            $self->{'rcs'}->{'header'}->{'branch'} = $self->_rev_rev2num($1);
             push(@{$self->{'rcs'}->{'header'}->{-order}}, 'branch');
         }
         elsif ($rcs =~ s/^access((?:\s+$re_id)*)\s*;//s) {
-            $self->{'rcs'}->{'header'}->{'access'} = [ split(/\s+/, $1) ];
+            $self->{'rcs'}->{'header'}->{'access'} = 
+                (defined($1) ? [ split(/\s+/, $1) ] : []);
             push(@{$self->{'rcs'}->{'header'}->{-order}}, 'access');
         }
         elsif ($rcs =~ s/^symbols((?:\s+$re_sym:$re_rev)*)\s*;//s) {
             my $symbols = { -order => [] };
-            map { if (m/^(.+):(.+)$/s) {
-                $symbols->{$1} = $2;
+            if (defined($1)) {
+                map { if (m/^(.+):(.+)$/s) {
+                $symbols->{$1} = $self->_rev_rev2num($2);
                 push(@{$symbols->{-order}}, $1);
-            } } split(/\s+/, $1);
+                } } 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 = { -order => [] };
-            map { if (m/^(.+):(.+)$/s) {
-                $locks->{$1} = $2;
-                push(@{$locks->{-order}}, $1);
-            } } split(/\s+/, $1);
+            if (defined($1)) {
+                map { if (m/^(.+):(.+)$/s) {
+                    $locks->{$1} = $self->_rev_rev2num($2);
+                    push(@{$locks->{-order}}, $1);
+                } } split(/\s+/, $1);
+            }
             $self->{'rcs'}->{'header'}->{'locks'} = $locks;
             push(@{$self->{'rcs'}->{'header'}->{-order}}, 'locks');
         }
@@ -225,7 +255,7 @@
     while (1) {
         $rcs =~ s|^\s*||s;
         if ($rcs =~ s/^($re_rev)//s) {
-            my $rev = $1;
+            my $rev = $self->_rev_rev2num($1);
             $self->{'rcs'}->{'delta'}->{$rev} = {};
             push(@{$self->{'rcs'}->{'delta'}->{-order}}, $rev);
             while (1) {
@@ -240,10 +270,12 @@
                     $self->{'rcs'}->{'delta'}->{$rev}->{'state'} = $1;
                 }
                 elsif ($rcs =~ s/^branches(?:\s+((?:\s*$re_rev)*))?\s*;//s) {
-                    $self->{'rcs'}->{'delta'}->{$rev}->{'branches'} = [ split(/\s+/, $1) ];
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'branches'} =
+                        (defined($1) and $1 ne '' ? [ map { $self->_rev_rev2num($_) } split(/\s+/, $1) ] : []);
                 }
                 elsif ($rcs =~ s/^next(?:\s*($re_rev))?\s*;//s) {
-                    $self->{'rcs'}->{'delta'}->{$rev}->{'next'} = $1;
+                    $self->{'rcs'}->{'delta'}->{$rev}->{'next'} =
+                        (defined($1) and $1 ne '' ? $self->_rev_rev2num($1) : '');
                 }
                 elsif ($rcs =~ m/^desc\s+/s) {
                     last;
@@ -276,9 +308,9 @@
     while (1) {
         $rcs =~ s|^\s*||s;
         if ($rcs =~ s/^($re_rev)//s) {
-            my $rev = $1;
+            my $rev = $self->_rev_rev2num($1);
             if (not defined($self->{'rcs'}->{'delta'}->{$rev})) {
-                croak "deltatext section for unknown revision \"$rev\" found";
+                croak "deltatext section for unknown revision \"".$self->_rev_num2rev($rev)."\" found";
             }
             my $textseen = 0;
             while (1) {
@@ -326,22 +358,22 @@
 sub _revlist ($$) {
     my ($self, $branchfirst) = @_;
     my @revs = ();
-    &nextrev(\@revs, $self->{'rcs'}->{'header'}->{'head'}, $branchfirst);
-    sub nextrev ($$$) {
-        my ($revs, $rev, $branchfirst) = @_;
+    &nextrev($self, \@revs, $self->{'rcs'}->{'header'}->{'head'}, $branchfirst);
+    sub nextrev ($$$$) {
+        my ($self, $revs, $rev, $branchfirst) = @_;
         push(@{$revs}, $rev);
         my $next     = $self->{'rcs'}->{'delta'}->{$rev}->{'next'};
         my $branches = $self->{'rcs'}->{'delta'}->{$rev}->{'branches'};
         if ($branchfirst) {
             foreach my $branch (@{$branches}) {
-                &nextrev($revs, $branch, $branchfirst); 
+                &nextrev($self, $revs, $branch, $branchfirst); 
             }
-            &nextrev($revs, $next, $branchfirst) if (defined($next) and $next ne '');
+            &nextrev($self, $revs, $next, $branchfirst) if (defined($next) and $next ne '');
         }
         else {
-            &nextrev($revs, $next, $branchfirst) if (defined($next) and $next ne '');
+            &nextrev($self, $revs, $next, $branchfirst) if (defined($next) and $next ne '');
             foreach my $branch (@{$branches}) {
-                &nextrev($revs, $branch, $branchfirst); 
+                &nextrev($self, $revs, $branch, $branchfirst); 
             }
         }
         return;
@@ -350,23 +382,30 @@
 }
 
 #   INTERNAL: generate output of a value in RCS syntax and layout
-sub _genvalue ($$) {
-    my ($val, $tag) = @_;
+sub _genvalue ($$$) {
+    my ($self, $val, $tag) = @_;
     my $rcs = '';
     if (ref($val) eq 'ARRAY' and @{$val} > 0) {
         foreach my $v (@{$val}) {
+            $v = $self->_rev_num2rev($v) if ($self->_rev_isnum($v));
             $rcs .= "\n\t$v";
         }
     }
     elsif (ref($val) eq 'HASH' and keys(%{$val}) > 0) {
         if (defined($val->{-order})) {
-            foreach my $v (@{$val->{-order}}) {
-                $rcs .= sprintf("\n\t%s:%s", $v, $val->{$v});
+            foreach my $k (@{$val->{-order}}) {
+                my $v = $val->{$k};
+                $v = $self->_rev_num2rev($v) if ($self->_rev_isnum($v));
+                $k = $self->_rev_num2rev($k) if ($self->_rev_isnum($k));
+                $rcs .= sprintf("\n\t%s:%s", $k, $v);
             }
         }
         else {
-            foreach my $v (keys(%{$val})) {
-                $rcs .= sprintf("\n\t%s:%s", $v, $val->{$v});
+            foreach my $k (keys(%{$val})) {
+                my $v = $val->{$k};
+                $v = $self->_rev_num2rev($v) if ($self->_rev_isnum($v));
+                $k = $self->_rev_num2rev($k) if ($self->_rev_isnum($k));
+                $rcs .= sprintf("\n\t%s:%s", $k, $v);
             }
         }
     }
@@ -375,6 +414,7 @@
             $rcs .= "\t" . &_string_quote($val);
         }
         else {
+            $val = $self->_rev_num2rev($val) if ($self->_rev_isnum($val));
             $rcs .= "\t$val";
         }
     }
@@ -417,29 +457,29 @@
         $tag = $1 if ($header =~ s/([@\-])$//s);
         my $val = $self->{'rcs'}->{'header'}->{$header};
         if (defined($val)) {
-            $rcs .= $header . &_genvalue($val, $tag). ";";
+            $rcs .= $header . $self->_genvalue($val, $tag). ";";
             $rcs .= ($tag eq '-' ? " " : "\n");
         }
     }
     $rcs .= "\n";
 
     #   generate delta section(s)
-    my @revlist = &_revlist($self, 0);
+    my @revlist = $self->_revlist(0);
     foreach my $rev (@revlist) {
         my $delta = $self->{'rcs'}->{'delta'}->{$rev};
         $rcs .= "\n";
-        $rcs .= $rev."\n";
+        $rcs .= $self->_rev_num2rev($rev)."\n";
         $rcs .= "date\t" . $delta->{'date'} . ";\t";
         $rcs .= "author " . $delta->{'author'} . ";\t";
         $rcs .= "state " . $delta->{'state'} . ";\n";
         $rcs .= "branches";
         if (@{$delta->{'branches'}} > 0) {
             foreach my $v (@{$delta->{'branches'}}) {
-                $rcs .= "\n\t$v";
+                $rcs .= "\n\t". $self->_rev_num2rev($v);
             }
         }
         $rcs .= ";\n";
-        $rcs .= "next\t" . $delta->{'next'} . ";\n";
+        $rcs .= "next\t" . (defined($delta->{'next'}) ? $self->_rev_num2rev($delta->{'next'}) : "") . ";\n";
     }
 
     #   generate description section
@@ -447,12 +487,12 @@
     $rcs .= "\n\ndesc\n" . &_string_quote($desc) . "\n";
 
     #   generate deltatext section(s)
-    @revlist = &_revlist($self, 1);
+    @revlist = $self->_revlist(1);
     foreach my $rev (@revlist) {
         my $delta = $self->{'rcs'}->{'delta'}->{$rev};
         $rcs .= "\n";
         $rcs .= "\n";
-        $rcs .= $rev."\n";
+        $rcs .= $self->_rev_num2rev($rev)."\n";
         $rcs .= "log\n" . &_string_quote($delta->{'log'}) . "\n";
         $rcs .= "text\n" . &_string_quote($delta->{'text'}) . "\n";
     }
@@ -460,6 +500,18 @@
     return $rcs;
 }
 
+#   apply a translation function onto all RCS revisions
+sub revapply ($$) {
+    my ($self, $sub) = @_;
+    foreach my $num (keys(%{$self->{'rcs'}->{'rev'}})) {
+        $self->{'rcs'}->{'rev'}->{$num} =
+            &$sub($self->{'rcs'}->{'rev'}->{$num});
+    }
+    return;
+}
+
+1;
+
 __END__
 
 =pod

CVSTrac 2.0.1