Revs.pm #24

  • //
  • guest/
  • perforce_software/
  • revml/
  • lib/
  • VCP/
  • Revs.pm
  • View
  • Commits
  • Open Download .zip Download (4 KB)
package VCP::Revs ;

=head1 NAME

VCP::Revs - A collection of VCP::Rev objects.

=head1 SYNOPSIS

=head1 DESCRIPTION

Right now, all revs are kept in memory, but we will enable storing them to
disk and recovering them at some point so that we don't gobble huge
tracts of RAM.

=head1 METHODS

=over

=cut

$VERSION = 1 ;

use strict ;

use VCP::Logger qw( BUG );
use VCP::Debug ":debug" ;
use VCP::DB_File::big_records;
use VCP::Rev ;
use VCP::Utils qw( empty );

use fields (
   'REVS_DB',        ## Where the revisions are stored when not needed
   'STORE_LOC',      ## What directory to keep the revisions in
   'PLUGIN_NAME',    ## Which plugin is using us
) ;


=item new

=cut

sub new {
   my $class = CORE::shift ;
   $class = ref $class || $class ;

   my $self ;

   {
      no strict 'refs' ;
      $self = bless [ \%{"$class\::FIELDS"} ], $class ;
   }

   while ( @_ ) {
      my ( $key, $value ) = ( shift, shift );
      $self->{$key} = $value;
   }

   BUG "STORE_LOC not set" if empty $self->{STORE_LOC};

   return $self ;
}


sub revs_db {
   my VCP::Revs $self = shift;

   my $plugin_name = $self->{PLUGIN_NAME};
   $plugin_name = "" unless defined $plugin_name;
   $plugin_name =~ s/::/-/g;
   return $self->{REVS_DB} ||= do {
      my $db = VCP::DB_File::big_records->new(
         StoreLoc  => $self->{STORE_LOC},
         TableName => "$plugin_name-revs",
      );
      $db->delete_db;
      $db->open_db;
      $db;
   };
}


sub DESTROY {
   my VCP::Revs $self = shift;
   if ( $self->{REVS_DB} ) {
      $self->{REVS_DB}->close_db;
      $self->{REVS_DB}->delete_db;
   }
}


=item add

   $revs->add( $rev ) ;
   $revs->add( $rev1, $rev2, ... ) ;

Adds a revision or revisions to the collection.

The ( name, rev_id, branch_id ) tuple must be unique, if a second rev
is C<add()>ed with the same values, an exception is thrown.

=cut

sub added_rev {
   my VCP::Revs $self = CORE::shift ;
   my ( $id ) = @_;
   return $self->revs_db->exists( [ $id ] );
}


sub add {
   my VCP::Revs $self = CORE::shift ;

   Carp::confess "undef passed" if grep ! defined, @_;

   if ( debugging ) {
      debug "queuing ", $_->as_string for @_ ;
   }

   for my $r ( @_ ) {
      my $id = $r->id;

      BUG "can't add same revision twice: '" . $r->as_string
         if $self->added_rev( $id );

      $self->revs_db->set( [ $id ], $r->serialize );
   }
}


=item exists 

   if ( $revs->exists( $id ) ) { ... }

=cut

sub exists {
   my VCP::Revs $self = CORE::shift ;
   return $self->revs_db->exists( [ @_ ] );
}


=item get

   $rev = $revs->get( $id ) ;  ## return the rev with a given ID (or die())

=cut

sub get {
   my VCP::Revs $self = CORE::shift ;

   BUG "can't retrieve all revs at once any more" unless @_;

   my @fields = $self->revs_db->get( [ @_ ] );

   return undef unless @fields;

   return VCP::Rev->deserialize( @fields );
}


=item foreach

   $revs->foreach( sub { ... } );

Apply a subroutine to each revision.

=cut

sub foreach {
   my VCP::Revs $self = shift;

   my ( $sub ) = @_;

   $self->revs_db->foreach_record_do(
      sub {
         my $r = VCP::Rev->deserialize( @_ );
         $sub->( $r );
      }
   );
}


=back

=head1 SUBCLASSING

This class uses the fields pragma, so you'll need to use base and 
possibly fields in any subclasses.

=head1 COPYRIGHT

Copyright 2000, Perforce Software, Inc.  All Rights Reserved.

This module and the VCP package are licensed according to the terms given in
the file LICENSE accompanying this distribution, a copy of which is included in
L<vcp>.

=head1 AUTHOR

Barrie Slaymaker <barries@slaysys.com>

=cut

1
# Change User Description Committed
#27 4508 Barrie Slaymaker - VCP::Revs::exists() removed
#26 4021 Barrie Slaymaker - Remove all phashes and all base & fields pragmas
- Work around SWASHGET error
#25 4012 Barrie Slaymaker - Remove dependance on pseudohashes (deprecated Perl feature)
#24 3970 Barrie Slaymaker - VCP::Source handles rev queing, uses disk to reduce RAM
- Lots of other fixes
#23 3805 Barrie Slaymaker - VCP::Revs::fetch_files() removed
#22 3804 Barrie Slaymaker - Refactored to prepare way for reducing memory footprint
#21 3742 Barrie Slaymaker - VCP::Source::vss correctly links the first rev of a file
  to the the delete action its deleted predecessor.
#20 3155 Barrie Slaymaker Convert to logging using VCP::Logger to reduce stdout/err spew.
       Simplify & speed up debugging quite a bit.
       Provide more verbose information in logs.
       Print to STDERR progress reports to keep users from wondering
       what's going on.
       Breaks test; halfway through upgrading run3() to an inline
       function for speed and for VCP specific features.
#19 3140 Barrie Slaymaker Remove deprecated function
#18 3133 Barrie Slaymaker Make destinations call back to sources to check out files to
       simplify the architecture (is_metadata_only() no longer needed)
       and make it more optimizable (checkouts can be batched).
#17 3131 Barrie Slaymaker Double the speed of the RCS file parser.
       Deprecate VCP::Revs::shift() in favor of remove_all().
#16 2975 Barrie Slaymaker Deal with CVS' propensity to have multiple branch tags
       on the same version.
#15 2232 Barrie Slaymaker Major memory and sort speed enhancements.
#14 2059 Barrie Slaymaker Support for branching in p4->p4 added
#13 2026 Barrie Slaymaker VCP::8::cvs now supoprt branching
#12 2017 Barrie Slaymaker Interim checkin of id=/base_version_id for revml: and
       branch_diagram:
#11 2015 Barrie Slaymaker submit changes
#10 1855 Barrie Slaymaker Major VSS checkin.
 Works on Win32
#9 1809 Barrie Slaymaker VCP::Patch should ignore lineends
#8 1055 Barrie Slaymaker add sorting, revamp test suite, misc cleanup.
 Dest/revml is
not portable off my system yet (need to release ...::Diff)
#7 687 Barrie Slaymaker remove -f, tweak deduce_rev_root
#6 628 Barrie Slaymaker Cleaned up POD in bin/vcp, added BSD-style license.
#5 608 Barrie Slaymaker Lots of changes to get vcp to install better, now up to 0.066.
Many thanks to Matthew Attaway for testing & suggestions.
#4 480 Barrie Slaymaker 0.06 Wed Dec 20 23:19:15 EST 2000
   - bin/vcp: Added --versions, which loads all modules and checks them
     for a $VERSION and print the results out.  This should help with
     diagnosing out-of-sync modules.
   - Added $VERSION vars to a few modules :-).  Forgot to increment any
     $VERSION strings.
   - VCP::Dest::cvs: The directory "deeply" was not being `cvs add`ed on
     paths like "a/deeply/nested/file", assuming "deeply" had no files
     in it.
   - VCP::Dest::revml: fixed a bug that was causing files with a lot of
     linefeeds to be emitted in base64 instead of deltaed.  This means
     most text files.
   - Various minor cleanups of diagnostics and error messages, including
     exposing "Can't locate Foo.pm" when a VCP::Source or VCP::Dest
     module depends on a module that's not installed, as reported by
     Jeff Anton.
#3 478 Barrie Slaymaker 0.05 Mon Dec 18 07:27:53 EST 2000
   - Use `p4 labels //...@label` command as per Rober Cowham's suggestion, with
     the '-s' flag recommended by Christopher Siewald and
     Amaury.FORGEOTDARC@atsm.fr.  Though it's actually something like

       vcp: running /usr/bin/p4 -u safari -c safari -p localhost:5666 -s files
       //.../NtLkly //...@compiler_a3 //.../NtLkly //...@compiler_may3

     and so //on //for 50 parameters to get the speed up.  I use the
     //.../NtLkly "file" as //a separator between the lists of files in various
     //revisions.  Hope nobody has any files named that :-).  What I should do
     is choose a random label that doesn't occur in the labels list, I guess.
   - VCP::Source::revml and VCP::Dest::revml are now binary, control code, and
     "hibit ASCII" (I know, that's an oxymoron) clean.  The <comment>, <delta>,
     and <content> elements now escape anything other than tab, line feed,
     space, or printable chars (32 <= c <= ASCII 126) using a tag like '<char
     code="0x09">'.  The test suite tests all this.  Filenames should also
     be escaped this way, but I didn't get to that.
   - The decision whether to do deltas or encode the content in base64 is now
     based on how many characters would need to be escaped.
   - We now depend on the users' diff program to have a "-a" option to force it
     to diff even if the files look binary to it.  I need to use Diff.pm and
     adapt it for use on binary data.
   - VCP::Dest::cvs now makes sure that no two consecutive revisions of the
     same file have the same mod_time.  VCP::Source::p4 got so fast at pulling
     revisions from the repositories the test suite sets up that CVS was not
     noticing that files had changed.
   - VCP::Plugin now allows you to set a list of acceptable result codes, since
     we now use p4 in ways that make it return non-zero result codes.
   - VCP::Revs now croaks if you try to add two entries of the same VCP::Rev
     (ie matching filename and rev_id).
   - The <type> tag is now limited to "text" or "binary", and is meant to
     pass that level of info between foreign repositories.
   - The <p4_info> on each file now carries the one line p4 description of
     the file so that p4->p4 transferes can pick out the more detailed
     info.  VCP::Source::p4, VCP::Dest::p4 do this.
   - VCP::{Source,Dest}::{p4,cvs} now set binaryness on added files properly,
     I think.  For p4->p4, the native p4 type is preserved.  For CVS sources,
     seeing the keyword substitution flag 'o' or 'b' implies binaryness, for
     p4, seeing a filetype like qr/u?x?binary/ or qr/x?tempobj/ or "resource"
     implies binaryness (to non-p4 destinations).  NOTE: Seeing a 'o' or 'b'
     in a CVS source only ends up setting the 'b' option on the destination.
     That should be ok for most uses, but we can make it smarter for cvs->cvs
     transfers if need be.
#2 468 Barrie Slaymaker - VCP::Dest::p4 now does change number aggregation based on the
  comment field changing or whenever a new revision of a file with
  unsubmitted changes shows up on the input stream.  Since revisions of
  files are normally sorted in time order, this should work in a number
  of cases.  I'm sure we'll need to generalize it, perhaps with a time
  thresholding function.
- t/90cvs.t now tests cvs->p4 replication.
- VCP::Dest::p4 now doesn't try to `p4 submit` when no changes are
  pending.
- VCP::Rev now prevents the same label from being applied twice to
  a revision.  This was occuring because the "r_1"-style label that
  gets added to a target revision by VCP::Dest::p4 could duplicate
  a label "r_1" that happened to already be on a revision.
- Added t/00rev.t, the beginnings of a test suite for VCP::Rev.
- Tweaked bin/gentrevml to comment revisions with their change number
  instead of using a unique comment for every revision for non-p4
  t/test-*-in-0.revml files.  This was necessary to test cvs->p4
  functionality.
#1 467 Barrie Slaymaker Version 0.01, initial checkin in perforce public depot.