[Bps-public-commit] r11265 - in SVN-PropDB: . lib/Prophet lib/Prophet/Sync/Source/SVN

jesse at bestpractical.com jesse at bestpractical.com
Sat Mar 29 21:27:23 EDT 2008


Author: jesse
Date: Sat Mar 29 21:27:22 2008
New Revision: 11265

Modified:
   SVN-PropDB/   (props changed)
   SVN-PropDB/Makefile.PL
   SVN-PropDB/lib/Prophet/ChangeSet.pm
   SVN-PropDB/lib/Prophet/Collection.pm
   SVN-PropDB/lib/Prophet/ConflictingPropChange.pm
   SVN-PropDB/lib/Prophet/HistoryEntry.pm
   SVN-PropDB/lib/Prophet/Record.pm
   SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
   SVN-PropDB/lib/Prophet/Sync/Source/SVN/ReplayEditor.pm
   SVN-PropDB/lib/Prophet/Sync/Source/SVN/Util.pm

Log:
 r28786 at 70-5-172-195:  jesse | 2008-03-29 15:27:10 -1000
 * lots of POD coverage


Modified: SVN-PropDB/Makefile.PL
==============================================================================
--- SVN-PropDB/Makefile.PL	(original)
+++ SVN-PropDB/Makefile.PL	Sat Mar 29 21:27:22 2008
@@ -4,6 +4,7 @@
 requires('Params::Validate');
 requires('Class::Accessor');
 requires('Data::UUID');
+requires('Path::Class');
 requires('SVN::Core'); # SVN::Repos SVN::Fs SVN::Ra SVN::Delta::Editor SVN::Client SVN::Delta
 all_from('lib/Prophet.pm');
 

Modified: SVN-PropDB/lib/Prophet/ChangeSet.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/ChangeSet.pm	(original)
+++ SVN-PropDB/lib/Prophet/ChangeSet.pm	Sat Mar 29 21:27:22 2008
@@ -2,13 +2,65 @@
 use strict;
 
 package Prophet::ChangeSet;
+use base qw/Class::Accessor/;
+
+=head1 NAME
+
+Prophet::ChangeSet
+
+=head1 DESCRIPTION
+
+This class represents a single, atomic Prophet database update. It tracks some metadata about the changeset it self and contains a list of L<Prophet::Change> entries which describe the actual records created, updated and deleted.
+
+=cut
+
 use Prophet::Change;
 use Params::Validate;
 
-use base qw/Class::Accessor/;
+=head1 METHODS
+
+=cut
 
 __PACKAGE__->mk_accessors(qw/sequence_no source_uuid original_source_uuid original_sequence_no is_nullification is_resolution/);
 
+=head2 new
+
+Instantiate a new, empty L<Prophet::ChangeSet> object.
+
+=cut
+
+=head2 sequence_no
+
+The changeset's sequence number (In subversion terms, revision #) on the replica sending us the changeset
+
+=head2 source_uuid
+
+The uuid of the replica sending us the change
+
+=head2 original_source_uuid
+
+The uuid of the replica where the change was authored
+
+=head2 original_sequence_no
+
+The changeset's sequence number (In subversion terms, revision #) on the replica where the change was originally created
+
+=head2 is_nullification
+
+Currently unused
+
+=head2 is_resolution
+
+Currently unused
+
+=cut
+
+=head2 add_change { change => L<Prophet::Change> }
+
+Add a new change, L<$args{'change'}> to this changeset.
+
+=cut
+
 sub add_change {
     my $self = shift;
     my %args = validate( @_, { change => { isa => 'Prophet::Change'} } );
@@ -16,6 +68,12 @@
 
 }
 
+=head2 changes
+
+Return an array of all the changes in the current changeset.
+
+=cut
+
 sub changes {
     my $self = shift;
     return @{ $self->{'changes'} || [] };

Modified: SVN-PropDB/lib/Prophet/Collection.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Collection.pm	(original)
+++ SVN-PropDB/lib/Prophet/Collection.pm	Sat Mar 29 21:27:22 2008
@@ -7,6 +7,25 @@
 __PACKAGE__->mk_accessors(qw'handle type');
 use Prophet::Record;
 
+=head1 NAME
+
+Prophet::Collection
+
+=head1 DESCRIPTION
+
+This class allows the programmer to search for L<Prophet::Record>
+objects matching certain criteria and to operate on those records
+as a collection.
+
+=head1 METHODS
+
+
+=head2 new { handle => L<Prophet::Handle>, type => $TYPE }
+
+Instantiate a new, empty L<Prophet::Collection> object to find items of type C<$TYPE>
+
+
+=cut
 
 sub new {
     my $class = shift;
@@ -17,6 +36,11 @@
     return $self;
 }
 
+=head2 matching $CODEREF
+
+Find all L<Prophet::Record>s of this collection's C<type> where $CODEREF returns true.
+
+=cut
 
 sub matching {
     my $self = shift;
@@ -41,6 +65,13 @@
 
 }
 
+=head2 as_array_ref
+
+Return the set of L<Prophet::Record>s we've found as an array reference or return an empty array ref if none were found.
+
+=cut
+
+
 sub as_array_ref {
     my $self = shift;
     return $self->{_items}||[];

Modified: SVN-PropDB/lib/Prophet/ConflictingPropChange.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/ConflictingPropChange.pm	(original)
+++ SVN-PropDB/lib/Prophet/ConflictingPropChange.pm	Sat Mar 29 21:27:22 2008
@@ -6,4 +6,32 @@
 
 __PACKAGE__->mk_accessors(qw/name source_old_value target_value source_new_value/);
 
+=head1 NAME
+
+Prophet::ConflictingPropChange
+
+=head1 DESCRIPTION
+
+Objects of this class describe a case when the a property change can not be cleanly applied to a replica because the old value for the property locally did not match the "begin state" of the change being applied.
+
+=head1 METHODS
+
+=head2 name
+
+The property name for the conflict in question
+
+=head2 source_old_value
+
+The inital (old) state from the change being merged in
+
+=head2 source_new_value
+
+The final (new) state of the property from the change being merged in.
+
+=head2 target_value
+
+The current target-replica value of the property being merged.
+
+=cut
+
 1;

Modified: SVN-PropDB/lib/Prophet/HistoryEntry.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/HistoryEntry.pm	(original)
+++ SVN-PropDB/lib/Prophet/HistoryEntry.pm	Sat Mar 29 21:27:22 2008
@@ -6,9 +6,28 @@
 use base qw/Class::Accessor/;
 use Params::Validate;
 
+=head1 NAME
+
+Prophet::HistoryEntry
+
+=head1 DESCRIPTION
+
+This class represents an indivdual, local change in the history of a L<Prophet::Replica>.
+In the future, this class's representation should be merged with the code we're using for L<Prophet::Sync>
+
+
+=cut
 
 __PACKAGE__->mk_accessors(qw/handle rev date author msg action props prop_changes copy_from copy_from_rev/);
 
+=head1 METHODS
+
+=head2 new { handle => L<Prophet::Handle> }
+
+Create a new, empty history entry. 
+
+
+=cut
 
 sub new {
    my $class = shift;
@@ -22,4 +41,46 @@
    return $self;
 
 }
+
+=head2 rev
+
+The local revision number for this history entry
+
+=head2 date
+
+The date this history entry was recorded. in RFC2445 format
+
+=head2 author
+
+The original author of this commit. Right now, this is a nice, forgable text string. It should likely become an email address or a replica UUID
+
+=head2 msg
+
+The commit message associated with the update
+
+=head2 action
+
+Was a node created, updated or deleted?
+
+XXX TODO FILL IN VALID VALUES
+
+
+=head2 props
+
+The current value of the record's properties after this update?
+
+=head2 prop_changes
+
+NEEDS DESCRIPTION
+
+=head2 copy_from
+
+unused
+
+=head2 copy_from_rev
+
+unused
+
+=cut
+
 1;

Modified: SVN-PropDB/lib/Prophet/Record.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Record.pm	(original)
+++ SVN-PropDB/lib/Prophet/Record.pm	Sat Mar 29 21:27:22 2008
@@ -1,13 +1,37 @@
-
 use warnings;
 use strict;
+
 package Prophet::Record;
-use Params::Validate;
-use Prophet::HistoryEntry;
+
+=head1 NAME
+
+Prophet::Record
+
+=head1 DESCRIPTION
+
+This class represents a base class for any record in a Prophet database
+
+=cut
+
+
 use base qw'Class::Accessor';
+
 __PACKAGE__->mk_accessors(qw'handle props uuid type');
+
+use Params::Validate;
+use Prophet::HistoryEntry;
+
 my $UUIDGEN = Data::UUID->new();
 
+=head1 METHODS
+
+=head2 new  { handle => Prophet::Handle, type => $type }
+
+Instantiates a new, empty L<Prophet::Record/> of type $type.
+
+=cut
+
+
 sub new {
     my $class = shift;
     my $self = {};
@@ -17,6 +41,17 @@
     return $self;
 }
 
+=head2 create { props => { %hash_of_kv_pairs } }
+
+Creates a new Prophet database record in your database. Sets the record's properties to the keys and values passed in.
+
+Automatically canonicalizes and then validates the props.
+
+Upon successful creation, returns the new record's C<uuid>.
+In case of failure, returns undef.
+
+=cut
+
 sub create {
     my $self = shift;
     my %args = validate(@_, {  props => 1});
@@ -35,7 +70,11 @@
 }
 
 
+=head2 load { uuid => $UUID }
 
+Loads a Prophet record off disk by its uuid.
+
+=cut
 
 
 sub load {
@@ -45,6 +84,15 @@
 
 }
 
+
+=head2 set_prop { name => $name, value => $value }
+
+Updates the current record to set an individual property called C<$name> to C<$value>
+
+This is a convenience method around L</set_props>.
+
+=cut
+
 sub set_prop {
     my $self = shift;
 
@@ -53,6 +101,17 @@
     $self->set_props(props => $props);
 }
 
+=head2 set_props { props => { key1 => val1, key2 => val2} }
+
+Updates the current record to set all the keys contained in the C<props> parameter to their associated values.
+Automatically canonicalizes and validates the props in question.
+
+In case of failure, returns false.
+
+On success, returns ____
+
+=cut
+
 
 sub set_props {
     my $self = shift;
@@ -64,19 +123,37 @@
 }
 
 
+=head2 get_props
+
+Returns a hash of this record's properties as currently set in the database.
 
+=cut
 
 sub get_props {
     my $self = shift;
     return $self->handle->get_node_props(uuid => $self->uuid, type => $self->type);
 }
 
+=head2 prop $name
+
+Returns the current value of the property C<$name> for this record. 
+(This is a convenience method wrapped around L</get_props>.
+
+=cut
+
 sub prop {
     my $self = shift;
     my $prop = shift;
     return $self->get_props->{$prop};
 }
 
+=head2 delete_prop { name => $name }
+
+Deletes the current value for the property $name. 
+
+TODO: how is this different than setting it to an empty value?
+
+=cut
 
 sub delete_prop {
     my $self = shift;
@@ -84,6 +161,12 @@
     $self->handle->delete_node_prop(uuid => $self->uuid, name => $args{'name'});
 }
 
+=head2 delete
+
+Deletes this record from the database. (Note that it does _not_ purge historical versions of the record)
+
+=cut
+
 sub delete {
     my $self = shift;
     $self->handle->delete_node(type => $self->type, uuid => $self->uuid);
@@ -118,12 +201,23 @@
     return 1;
 }
 
+=head2 storage_node
+
+Returns the path of this node within the Prophet repository. (Really, it delegates this to L<Prophet::Handle/file_for>.
+
+=cut
+
 sub storage_node {
     my $self = shift;
     return $self->handle->file_for(type => $self->type, uuid => $self->uuid);
 }
 
 
+=head2 history
+
+Returns an array of L<Prophet::HistoryEntry> objects ordered from oldest to newest. It is important to note that Prophet's merge algorithms guarantee that _local_ record history will never be reordered but that different replicas will often have different history orderings based on when replicas were merged or synced.
+
+=cut
 
 sub history {
     my $self       = shift;

Modified: SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm	(original)
+++ SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm	Sat Mar 29 21:27:22 2008
@@ -16,6 +16,14 @@
 
 __PACKAGE__->mk_accessors(qw/url ra prophet_handle/);
 
+=head2 setup
+
+Open a connection to the SVN source identified by C<$self->url>.
+
+XXX TODO, make the _prophet/ directory in the replica configurable
+
+=cut
+
 sub setup {
     my $self = shift;
     my ( $baton, $ref ) = SVN::Core::auth_open_helper( Prophet::Sync::Source::SVN::Util->get_auth_providers );
@@ -28,6 +36,12 @@
 
 }
 
+=head2 uuid
+
+Return the replica SVN repository's UUID
+
+=cut
+
 sub uuid {
     my $self = shift;
     return $self->ra->get_uuid;
@@ -188,6 +202,14 @@
 
 }
 
+=head2 integrate_changeset L<Prophet::ChangeSet>
+
+If there are conflicts, generate a nullification change, figure out a conflict resolution and apply the nullification, original change and resolution all at once (as three separate changes).
+
+If there are no conflicts, just apply the change.
+
+
+=cut
 
 sub integrate_changeset {
     my $self = shift;
@@ -211,6 +233,12 @@
 
 # XXX TODO this is hacky as hell and violates abstraction barriers in the name of doing things over the RA
 
+=head2 last_changeset_from_source $SOURCE_UUID
+
+Returns the last changeset id seen from the source identified by $SOURCE_UUID
+
+=cut
+
 sub last_changeset_from_source {
     my $self = shift;
     # XXX TODO should htis be an object rather than a uuid?

Modified: SVN-PropDB/lib/Prophet/Sync/Source/SVN/ReplayEditor.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source/SVN/ReplayEditor.pm	(original)
+++ SVN-PropDB/lib/Prophet/Sync/Source/SVN/ReplayEditor.pm	Sat Mar 29 21:27:22 2008
@@ -5,13 +5,40 @@
 use base qw/SVN::Delta::Editor/;
 our $CURRENT_REMOTE_REVNO;
 
+=head1 NAME
+
+Prophet::Sync::Source::SVN::ReplayEditor
+
+=head1 DESCRIPTION
+
+This class encapsulates a Subversion "replay" editor.  Prophet's
+Subversion synchronization client (L<Prophet::Sync::Source::SVN>)
+uses it to turn a set of subversion
+deltas into a set of L<Prophet::ChangeSet> objects.
+
+
+=head1 METHODS
+
+=cut
+
+=head2 new
+
+Instantiates a new subversion "editor" to track a single remote revision
+
+
+=cut
+
 sub new {
     my $self = shift->SUPER::new(@_);
     $self->{'revision'} = $CURRENT_REMOTE_REVNO;
     return $self;
 }
 
+=head2 ra [$RA]
+
+Gets or sets the Subversion RA object.
 
+=cut
 
 sub ra {
     my $self = shift;
@@ -20,6 +47,12 @@
 
 }
 
+=head2 open_root  ($edit_baton, $base_rev, $dir_pool, $root_baton)
+
+Called by subversion at the beginning of any edit. We only care about the base_rev
+
+=cut
+
 
 sub open_root {
     my $self = shift;
@@ -27,18 +60,37 @@
     $self->{'base_rev'} = $base_rev;
 }
 
+=head2 open_directory($path, $parent_baton, $base_rev, $dir_pool, $child_baton) 
+
+Called by the subversion RA layer each time SVN descends into a new directory within an open edit.
+Pushes the directory onto the internal L</dir_stack>
+
+=cut
 
 sub open_directory { 
     my $self = shift;
     my ($path, $parent_baton, $base_rev, $dir_pool, $child_baton) = (@_);
     push @{$self->{'dir_stack'}}, { path => $path, base_rev => $base_rev};
 }
+
+=head2 delete_entry ($path, $revision, $parent_baton)
+
+Called for any file/directory deleted within this edit.
+
+=cut
+
 sub delete_entry { 
     my $self = shift;
     my ($path, $revision, $parent_baton) = (@_);
     $self->{'paths'}->{$path}->{fs} = 'delete';
 }
 
+=head2 add_file ($path, $parent_baton, $copy_path, $copy_revision, $file_pool, $file_baton) 
+
+Called whenever a file is added within an edit.
+
+=cut
+
 sub add_file { 
     my $self = shift;
     my ($path, $parent_baton, $copy_path, $copy_revision, $file_pool, $file_baton) = (@_);
@@ -47,6 +99,13 @@
     $self->{'paths'}->{$path}->{fs} = 'add_file';
 }
 
+=head2 add_file ($path, $parent_baton, $copy_path, $copy_revision, $dir_pool, $child_baton) 
+
+Called whenever a directory is added within an edit.
+
+=cut
+
+
 sub add_directory {
     my $self = shift;
     my ($path, $parent_baton, $copyfrom_path, $copyfrom_revision, $dir_pool, $child_baton) = (@_);
@@ -54,6 +113,16 @@
     $self->{'paths'}->{$path}->{fs} = 'add_dir';
 }
 
+
+
+=head2 open_file  ($path, $parent_baton, $base_rev, $file_pool, $file_baton) 
+
+Called whenever a file is opened for writing within the current
+edit. This routine sets the context of future content or property
+changes.
+
+=cut
+
 sub open_file {
     my $self = shift;
     my ($path, $parent_baton, $base_rev, $file_pool, $file_baton) = (@_);
@@ -69,6 +138,12 @@
 }
 
 
+=head2 close_file ($file_baton, $text_checksum,$pool)
+
+Called when all edits to a file are complete. This routine ends the 'current file' context
+
+=cut
+
 
 sub close_file {
     my $self = shift;
@@ -78,10 +153,16 @@
 
 }
 
-sub absent_file {
-    my $self = shift;
-    my ($file_baton, $text_checksum, $pool) = (@_);
-}
+#sub absent_file {
+#    my $self = shift;
+#    my ($file_baton, $text_checksum, $pool) = (@_);
+#}
+
+=head2 close_directory ($dir_baton, $pool)
+
+Called by Subversion to indicate that all edits inside a directory have been completed
+
+=cut
 
 sub close_directory {
     my $self = shift;
@@ -89,10 +170,20 @@
     pop @{$self->{dir_stack}};
 }
 
-sub absent_directory {
-    my $self = shift;
-    my ($path, $parent_baton, $pool) = (@_);
-}
+#sub absent_directory {
+#    my $self = shift;
+#    my ($path, $parent_baton, $pool) = (@_);
+#}
+
+
+=head2 change_file_prop ($baton, $name, $value,$pool)
+
+Called by Subversion when a file property changes. All Subversion
+tells us is that 'the current node's property called $name has
+changed to $value'. This routine roots around and builds a delta
+from the previous value to the new value.
+
+=cut
 
 sub change_file_prop {
     my $self = shift;
@@ -104,6 +195,16 @@
     };
 }
 
+=head2 change_file_prop ($baton, $name, $value,$pool)
+
+Called by Subversion when a directory property changes. All Subversion
+tells us is that 'the current node's property called $name has
+changed to $value'. This routine roots around and builds a delta
+from the previous value to the new value.
+
+=cut
+
+
 sub change_dir_prop {
     my $self = shift;
     my ($dir_baton, $name, $value, $pool) = (@_);
@@ -115,10 +216,25 @@
 }
 
 
-sub close_edit {
-    my $self = shift;
-    my ($edit_baton, $pool) = (@_); 
-}
+
+#sub close_edit {
+#    my $self = shift;
+#    my ($edit_baton, $pool) = (@_); 
+#}
+
+
+=head2 dump_deltas
+
+Returns a data structure describiing the revision and all the changes made to it:
+
+ { revision => 1234,
+   paths => { 'foo' => { ... } 
+            }
+   }
+
+        
+
+=cut
 
 
 sub dump_deltas{

Modified: SVN-PropDB/lib/Prophet/Sync/Source/SVN/Util.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source/SVN/Util.pm	(original)
+++ SVN-PropDB/lib/Prophet/Sync/Source/SVN/Util.pm	Sat Mar 29 21:27:22 2008
@@ -4,6 +4,16 @@
 # XXX CARGO CULTED FROM SVK::Util;
 package Prophet::Sync::Source::SVN::Util;
 
+=head1 NAME
+
+Prophet::Sync::Source::SVN
+
+=head1 DESCRIPTION
+
+A library of utility functions for Subversion repository authentication. Ripped from SVK
+
+=cut
+
 use base 'Class::Data::Inheritable';
 
 __PACKAGE__->mk_classdata('_svnconfig');
@@ -39,17 +49,31 @@
 
 my $pool = SVN::Pool->new;
 
+
+=head2 svnconfig
+
+Returns a handle to the user's Subversion configuration.
+
+=cut
+
 sub svnconfig {
     my $class = shift;
     return $class->_svnconfig if $class->_svnconfig;
 
-    return undef if $ENV{SVKNOSVNCONFIG};
+    return undef if $ENV{PROPHET_NO_SVN_CONFIG};
 
     SVN::Core::config_ensure(undef);
     return $class->_svnconfig( SVN::Core::config_get_config(undef, $pool) );
 }
 
+=head2 get_auth_providers
+
+Returns an array of Subversion authentication providers
+
 # Note: Use a proper default pool when calling get_auth_providers
+
+=cut
+
 sub get_auth_providers {
     my $class = shift;
     return $class->auth_providers->();



More information about the Bps-public-commit mailing list