[Bps-public-commit] r11539 - in SVN-PropDB: . doc lib/Prophet/Handle

jesse at bestpractical.com jesse at bestpractical.com
Sat Apr 5 17:29:22 EDT 2008


Author: jesse
Date: Sat Apr  5 17:28:42 2008
New Revision: 11539

Added:
   SVN-PropDB/lib/Prophet/Handle/
   SVN-PropDB/lib/Prophet/Handle/SVN.pm
Modified:
   SVN-PropDB/   (props changed)
   SVN-PropDB/doc/todo
   SVN-PropDB/lib/Prophet/Handle.pm
   SVN-PropDB/lib/Prophet/Record.pm

Log:
 r29238 at 31b:  jesse | 2008-04-05 11:28:03 -1000
 * Extracting out Handle::SVN methods


Modified: SVN-PropDB/doc/todo
==============================================================================
--- SVN-PropDB/doc/todo	(original)
+++ SVN-PropDB/doc/todo	Sat Apr  5 17:28:42 2008
@@ -1,84 +1,77 @@
 Todo Saturday
 
     - get a state_db exposed within the ::ForeignReplica driver
-    - replace app::cache with state dbs 
+    - replace app::cache with state dbs
+    
+      - multiple Prophet::Handle can point to the same repo_handle but with different db_root
+      - repo_handle should be the actual storage layer
+        - current use of repo_handle
+          - prophet::record: get_logs/youngest_rev/reivision_root/node_proplist
+          - prophet::handle: revision_root, current_edit
+          - prophet::test : youngest_rev
+          - move {begin,end}_edit, node* methods into repo handler (Prophet::Handle::SVN) ?
+                record_resolution & other friends belong higher level than actual storage, ditto for record_changeset,
+                node* and edit* functions are needed from the storage layer
+                rebless is probbly good for now, i will work on the callers that creates proper handles.
+    
+                - what if we move them to ..no. moving them to ::Replica::SVN is wrong.
+                
+                - Should I start on that and make Handle->new() rebless to handle::svn new for now?         
+                
+  
+  
+    
     - implement a simple Prophet::Replica::Hiveminder for "personal tasks only"
     - write tests for RT-prophet-prophet-RT sync
     
     - lunch
     
     - implement uuids for prophet databases
-       - (use the uuid as a prefix for the db root?)    
-    - design/implement basic non-svn sync protocol
-
-    - sketch out RT scrips replacement
-
-    - dinner
-
-Saturday done
-
-    - extract the reusable bits of Prophet::Replica::RT to
-            Prophet::ForeignReplica
+       - (use the uuid as a prefix for the db root?)  
+        - each replica should know the uuid of the database it is a replica of
+        - merging between replicas with different uuids should require a 'force' argument of some kind.
+
+    - push to a remote prophet
+        - bundle all changesets newer than that which we know the other party hasn't seen up as a serialized structure (FeedSync? Storable ;)?)
+        - send them to remote to "pull from textfile
+        - also need to send along all merge tickets we have
+                 
+        - design/implement basic non-svn sync protocol
 
+    - refactor Source::integrate_changeset to get the merge ticket and let the source(dst) decide how to record them, rather than having handle do the job
 
 
 
+    - sketch out RT scrips replacement
 
------------------
+    - dinner
 
 
-- prophet databases need uuids.
-    - each replica should know the uuid of the database it is a replica of
-    - merging between replicas with different uuids should require a 'force' argument of some kind.
 
-- refactor Source::integrate_changeset to get the merge ticket and let the source(dst) decide how to record them, rather than having handle does the job
-- also need to send along all merge tickets we have
 
+Saturday done
 
-- validation on bug tracker fields
-	- severity
+    - extract the reusable bits of Prophet::Replica::RT to
+            Prophet::ForeignReplica
 
-- ability to add comments to a bug (visible history entries)
-    - maybe long-prop edits
 
-- push to a remote prophet
-            
-    - bundle all changesets newer than that which we know the other party hasn't seen up as a serialized structure (FeedSync? Storable ;)?)
-    - send them to remote to "pull from textfile
-
-- pull from a remote RT by url and query
-    - be able to tell RT to only give us history entries newer than the $DATE of RT history entry with ID #1234 (which is the sequence number we used for the merge ticket from the remote RT).
-
-    - massage this crap into a sequence of prophet changesets
-    - apply.
-    - rt id & record uuid bidirectional mapping how?
-        - uuid as a link?
-        - get rt to store uuid on all tickets at create time?
-            - jesse thinks rt should do this anyway
-
-- issues:
-    - how do we validate RT queues?
-    - how do we deal with RT rejecting a commit because the committer doesn't have acls?
-    - how do we map random remote sd users to rt users?
-    
 
-- push to a remote RT
-    - get the remote RT to give us its merge tickets ?!
-    - for every txn RT hasn't seen, send the txn to remote.
-    - if it's a record-create, we need to do some clever mapping.
-        "find an RT ticket with the uuid $UUID"
-        map that back to local
+Todo after saturday:
 
+- validation on bug tracker fields	- severity
 - Replace this todo list with a svb database
 - elegant support for large attachments
 - RESTy web server API to let third-parties build non-perl apps against a Prophet Depot
-
 - define a value for a property that is a reference to another record or set of records
 
 
 
 Archive:
 
+- ability to add comments to a bug (visible history entries)
+    - maybe long-prop edits
+
+
 
 - when committing any change:
     - record the original depot uuid and change sequence_no as revprops

Modified: SVN-PropDB/lib/Prophet/Handle.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Handle.pm	(original)
+++ SVN-PropDB/lib/Prophet/Handle.pm	Sat Apr  5 17:28:42 2008
@@ -7,12 +7,8 @@
 use Data::Dumper;
 use Data::UUID;
 
-use SVN::Core;
-use SVN::Repos;
-use SVN::Fs;
+our $DEBUG = 0;
 
-our $DEBUG = '0';
-__PACKAGE__->mk_accessors(qw(repo_path repo_handle current_edit _pool));
 
 use constant db_root => '_prophet';
 
@@ -24,83 +20,10 @@
 
 sub new {
     my $class = shift;
-    my $self  = {};
-    bless $self, $class;
-    my %args = validate( @_, { repository => 1, db_root => 0 } );
-    $self->repo_path( $args{'repository'} );
-    $self->_connect();
-    $self->_pool( SVN::Pool->new );
-
-    return $self;
-}
-
-=head2 current_root
-
-Returns a handle to the svn filesystem's HEAD
-
-=cut
-
-sub current_root {
-    my $self = shift;
-    $self->repo_handle->fs->revision_root( $self->repo_handle->fs->youngest_rev );
+    use Prophet::Handle::SVN;
+    return Prophet::Handle::SVN->new(@_);
 }
 
-sub _connect {
-    my $self = shift;
-    my $repos = eval { SVN::Repos::open( $self->repo_path ); };
-
-    # If we couldn't open the repository handle, we should create it
-    if ( $@ && !-d $self->repo_path ) {
-        $repos = SVN::Repos::create( $self->repo_path, undef, undef, undef, undef, $self->_pool );
-    }
-
-    $self->repo_handle($repos);
-    $self->_create_nonexistent_dir( $self->db_root );
-}
-
-sub _create_nonexistent_dir {
-    my $self = shift;
-    my $dir  = shift;
-    my $pool = SVN::Pool->new_default;
-    my $root = $self->current_edit ? $self->current_edit->root : $self->current_root;
-
-    unless ( $root->is_dir($dir) ) {
-        my $inside_edit = $self->current_edit ? 1 : 0;
-        $self->begin_edit() unless ($inside_edit);
-        $self->current_edit->root->make_dir($dir);
-        $self->commit_edit() unless ($inside_edit);
-    }
-}
-
-=head2 begin_edit
-
-Starts a new transaction within the replica's backend database. Sets L</current_edit> to that edit object.
-
-Returns $self->current_edit.
-
-=cut
-
-sub begin_edit {
-    my $self = shift;
-    my $fs   = $self->repo_handle->fs;
-    $self->current_edit( $fs->begin_txn( $fs->youngest_rev ) );
-    return $self->current_edit;
-}
-
-=head2 commit_edit
-
-Finalizes L</current_edit> and sets the 'svn:author' change-prop to the current user.
-
-=cut
-
-sub commit_edit {
-    my $self = shift;
-    my $txn  = shift;
-    $self->current_edit->change_prop( 'svn:author', ( $ENV{'PROPHET_USER'} || $ENV{'USER'} ) );
-    $self->current_edit->commit;
-    $self->current_edit(undef);
-
-}
 
 =head2 integrate_changeset L<Prophet::ChangeSet>
 
@@ -220,182 +143,13 @@
     } else {
         Carp::confess( " I have never heard of the change type: " . $change->change_type );
     }
-    my $changed = $self->current_edit->root->paths_changed;
-
-}
-
-=head2 create_node { type => $TYPE, uuid => $uuid, props => { key-value pairs }}
-
-Create a new record of type C<$type> with uuid C<$uuid>  within the current replica.
-
-Sets the record's properties to the key-value hash passed in as the C<props> argument.
-
-If called from within an edit, it uses the current edit. Otherwise it manufactures and finalizes one of its own.
-
-=cut
-
-sub create_node {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
-
-    $self->_create_nonexistent_dir( join( '/', $self->db_root, $args{'type'} ) );
-
-    my $inside_edit = $self->current_edit ? 1 : 0;
-    $self->begin_edit() unless ($inside_edit);
-
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
-    $self->current_edit->root->make_file($file);
-    {
-        my $stream = $self->current_edit->root->apply_text( $file, undef );
-
-        # print $stream Dumper( $args{'props'} );
-        close $stream;
-    }
-    $self->_set_node_props(
-        uuid  => $args{uuid},
-        props => $args{props},
-        type  => $args{'type'}
-    );
-    $self->commit_edit() unless ($inside_edit);
-
-}
-
-sub _set_node_props {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
-
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{type} );
-    foreach my $prop ( keys %{ $args{'props'} } ) {
-        eval { $self->current_edit->root->change_node_prop( $file, $prop, $args{'props'}->{$prop}, undef ) };
-        Carp::confess($@) if ($@);
-    }
-}
-
-=head2 delete_node {uuid => $uuid, type => $type }
-
-Deletes the node C<$uuid> of type C<$type> from the current replica. 
-
-Manufactures its own new edit if C<$self->current_edit> is undefined.
-
-=cut
-
-sub delete_node {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, type => 1 } );
-
-    my $inside_edit = $self->current_edit ? 1 : 0;
-    $self->begin_edit() unless ($inside_edit);
-
-    $self->current_edit->root->delete( $self->file_for( uuid => $args{uuid}, type => $args{type} ) );
-    $self->commit_edit() unless ($inside_edit);
-    return 1;
+    
 }
 
-=head2 set_node_props { uuid => $uuid, type => $type, props => {hash of kv pairs }}
-
-
-Updates the record of type C<$type> with uuid C<$uuid> to set each property defined by the props hash. It does NOT alter any property not defined by the props hash.
-
-Manufactures its own current edit if none exists.
-
-=cut
-
-sub set_node_props {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
 
-    my $inside_edit = $self->current_edit ? 1 : 0;
-    $self->begin_edit() unless ($inside_edit);
 
-    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
-    $self->_set_node_props(
-        uuid  => $args{uuid},
-        props => $args{props},
-        type  => $args{'type'}
-    );
-    $self->commit_edit() unless ($inside_edit);
-
-}
-
-=head2 uuid 
-
-Returns the uuid of the repilica
-
-=cut
-
-sub uuid {
-    my $self = shift;
-    return $self->repo_handle->fs->get_uuid;
-}
-
-=head2 get_node_props {uuid => $uuid, type => $type, root => $root }
-
-Returns a hashref of all properties for the record of type $type with uuid C<$uuid>.
-
-'root' is an optional argument which you can use to pass in an alternate historical version of the replica to inspect.  Code to look at the immediately previous version of a record might look like:
-
-    $handle->get_node_props(
-        type => $record->type,
-        uuid => $record->uuid,
-        root => $self->repo_handle->fs->revision_root( $self->repo_handle->fs->youngest_rev - 1 )
-    );
 
 
-=cut
-
-sub get_node_props {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
-    my $root = $args{'root'} || $self->current_root;
-    return $root->node_proplist( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
-}
-
-=head2 file_for { uuid => $UUID, type => $type }
-
-Returns a file path within the repository (starting from the root)
-
-=cut
-
-sub file_for {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, type => 1 } );
-    Carp::cluck unless $args{uuid};
-    my $file = join( "/", $self->directory_for_type( type => $args{'type'} ), $args{'uuid'} );
-    return $file;
-
-}
-
-sub directory_for_type {
-    my $self = shift;
-    my %args = validate( @_, { type => 1 } );
-    Carp::cluck unless defined $args{type};
-    return join( "/", $self->db_root, $args{'type'} );
-
-}
-
-=head2 node_exists {uuid => $uuid, type => $type, root => $root }
-
-Returns true if the node in question exists. False otherwise
-
-=cut
-
-sub node_exists {
-    my $self = shift;
-    my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
-
-    my $root = $args{'root'} || $self->current_root;
-    return $root->check_path( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
-
-}
-
-sub type_exists {
-    my $self = shift;
-    my %args = validate( @_, { type => 1, root => undef } );
-
-    my $root = $args{'root'} || $self->current_root;
-    return $root->check_path( $self->directory_for_type( type => $args{'type'}, ) );
-
-}
 
 our $MERGETICKET_METATYPE = '_merge_tickets';
 

Added: SVN-PropDB/lib/Prophet/Handle/SVN.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/Handle/SVN.pm	Sat Apr  5 17:28:42 2008
@@ -0,0 +1,291 @@
+use warnings;
+use strict;
+
+package Prophet::Handle::SVN;
+use base qw/Prophet::Handle/;
+
+use SVN::Core;
+use SVN::Repos;
+use SVN::Fs;
+
+our $DEBUG = '0';
+use Params::Validate qw(:all);
+
+__PACKAGE__->mk_accessors(qw(repo_path repo_handle current_edit _pool));
+
+
+
+sub new {
+    my $class = shift;
+    my $self  = {};
+    bless $self, $class;
+    
+    my %args = validate( @_, { repository => 1, db_root => 0 } );
+    $self->repo_path( $args{'repository'} );
+    $self->_connect();
+    $self->_pool( SVN::Pool->new );
+    return $self;
+}
+
+
+=head2 uuid 
+
+Returns the uuid of the repilica
+
+=cut
+
+sub uuid {
+    my $self = shift;
+    return $self->repo_handle->fs->get_uuid;
+}
+
+
+
+=head2 current_root
+
+Returns a handle to the svn filesystem's HEAD
+
+=cut
+
+sub current_root {
+    my $self = shift;
+    $self->repo_handle->fs->revision_root( $self->repo_handle->fs->youngest_rev );
+}
+
+sub _connect {
+    my $self = shift;
+    my $repos = eval { SVN::Repos::open( $self->repo_path ); };
+
+    # If we couldn't open the repository handle, we should create it
+    if ( $@ && !-d $self->repo_path ) {
+        $repos = SVN::Repos::create( $self->repo_path, undef, undef, undef, undef, $self->_pool );
+    }
+
+    $self->repo_handle($repos);
+    $self->_create_nonexistent_dir( $self->db_root );
+}
+
+sub _create_nonexistent_dir {
+    my $self = shift;
+    my $dir  = shift;
+    my $pool = SVN::Pool->new_default;
+    my $root = $self->current_edit ? $self->current_edit->root : $self->current_root;
+
+    unless ( $root->is_dir($dir) ) {
+        my $inside_edit = $self->current_edit ? 1 : 0;
+        $self->begin_edit() unless ($inside_edit);
+        $self->current_edit->root->make_dir($dir);
+        $self->commit_edit() unless ($inside_edit);
+    }
+}
+
+=head2 begin_edit
+
+Starts a new transaction within the replica's backend database. Sets L</current_edit> to that edit object.
+
+Returns $self->current_edit.
+
+=cut
+
+sub begin_edit {
+    my $self = shift;
+    my $fs   = $self->repo_handle->fs;
+    $self->current_edit( $fs->begin_txn( $fs->youngest_rev ) );
+    return $self->current_edit;
+}
+
+=head2 commit_edit
+
+Finalizes L</current_edit> and sets the 'svn:author' change-prop to the current user.
+
+=cut
+
+sub commit_edit {
+    my $self = shift;
+    my $txn  = shift;
+    $self->current_edit->change_prop( 'svn:author', ( $ENV{'PROPHET_USER'} || $ENV{'USER'} ) );
+    $self->current_edit->commit;
+    $self->current_edit(undef);
+
+}
+
+
+
+=head2 create_node { type => $TYPE, uuid => $uuid, props => { key-value pairs }}
+
+Create a new record of type C<$type> with uuid C<$uuid>  within the current replica.
+
+Sets the record's properties to the key-value hash passed in as the C<props> argument.
+
+If called from within an edit, it uses the current edit. Otherwise it manufactures and finalizes one of its own.
+
+=cut
+
+sub create_node {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
+
+    $self->_create_nonexistent_dir( join( '/', $self->db_root, $args{'type'} ) );
+
+    my $inside_edit = $self->current_edit ? 1 : 0;
+    $self->begin_edit() unless ($inside_edit);
+
+    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+    $self->current_edit->root->make_file($file);
+    {
+        my $stream = $self->current_edit->root->apply_text( $file, undef );
+
+        # print $stream Dumper( $args{'props'} );
+        close $stream;
+    }
+    $self->_set_node_props(
+        uuid  => $args{uuid},
+        props => $args{props},
+        type  => $args{'type'}
+    );
+    $self->commit_edit() unless ($inside_edit);
+
+}
+
+sub _set_node_props {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
+
+    my $file = $self->file_for( uuid => $args{uuid}, type => $args{type} );
+    foreach my $prop ( keys %{ $args{'props'} } ) {
+        eval { $self->current_edit->root->change_node_prop( $file, $prop, $args{'props'}->{$prop}, undef ) };
+        Carp::confess($@) if ($@);
+    }
+}
+
+=head2 delete_node {uuid => $uuid, type => $type }
+
+Deletes the node C<$uuid> of type C<$type> from the current replica. 
+
+Manufactures its own new edit if C<$self->current_edit> is undefined.
+
+=cut
+
+sub delete_node {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, type => 1 } );
+
+    my $inside_edit = $self->current_edit ? 1 : 0;
+    $self->begin_edit() unless ($inside_edit);
+
+    $self->current_edit->root->delete( $self->file_for( uuid => $args{uuid}, type => $args{type} ) );
+    $self->commit_edit() unless ($inside_edit);
+    return 1;
+}
+
+=head2 set_node_props { uuid => $uuid, type => $type, props => {hash of kv pairs }}
+
+
+Updates the record of type C<$type> with uuid C<$uuid> to set each property defined by the props hash. It does NOT alter any property not defined by the props hash.
+
+Manufactures its own current edit if none exists.
+
+=cut
+
+sub set_node_props {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
+
+    my $inside_edit = $self->current_edit ? 1 : 0;
+    $self->begin_edit() unless ($inside_edit);
+
+    my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+    $self->_set_node_props(
+        uuid  => $args{uuid},
+        props => $args{props},
+        type  => $args{'type'}
+    );
+    $self->commit_edit() unless ($inside_edit);
+
+}
+
+
+
+=head2 get_node_props {uuid => $uuid, type => $type, root => $root }
+
+Returns a hashref of all properties for the record of type $type with uuid C<$uuid>.
+
+'root' is an optional argument which you can use to pass in an alternate historical version of the replica to inspect.  Code to look at the immediately previous version of a record might look like:
+
+    $handle->get_node_props(
+        type => $record->type,
+        uuid => $record->uuid,
+        root => $self->repo_handle->fs->revision_root( $self->repo_handle->fs->youngest_rev - 1 )
+    );
+
+
+=cut
+
+sub get_node_props {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
+    my $root = $args{'root'} || $self->current_root;
+    return $root->node_proplist( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
+}
+
+
+
+
+
+
+=head2 file_for { uuid => $UUID, type => $type }
+
+Returns a file path within the repository (starting from the root)
+
+=cut
+
+sub file_for {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, type => 1 } );
+    Carp::cluck unless $args{uuid};
+    my $file = join( "/", $self->directory_for_type( type => $args{'type'} ), $args{'uuid'} );
+    return $file;
+
+}
+
+sub directory_for_type {
+    my $self = shift;
+    my %args = validate( @_, { type => 1 } );
+    Carp::cluck unless defined $args{type};
+    return join( "/", $self->db_root, $args{'type'} );
+
+}
+
+
+
+=head2 node_exists {uuid => $uuid, type => $type, root => $root }
+
+Returns true if the node in question exists. False otherwise
+
+=cut
+
+sub node_exists {
+    my $self = shift;
+    my %args = validate( @_, { uuid => 1, type => 1, root => undef } );
+
+    my $root = $args{'root'} || $self->current_root;
+    return $root->check_path( $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
+
+}
+
+sub type_exists {
+    my $self = shift;
+    my %args = validate( @_, { type => 1, root => undef } );
+
+    my $root = $args{'root'} || $self->current_root;
+    return $root->check_path( $self->directory_for_type( type => $args{'type'}, ) );
+
+}
+
+
+
+1;
+
+
+
+

Modified: SVN-PropDB/lib/Prophet/Record.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Record.pm	(original)
+++ SVN-PropDB/lib/Prophet/Record.pm	Sat Apr  5 17:28:42 2008
@@ -250,88 +250,6 @@
     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;
-    my $oldest_rev = 0;
-    my @history;
-    $self->handle->repo_handle->get_logs(
-        [ $self->storage_node ],
-        $self->handle->repo_handle->fs->youngest_rev,
-        $oldest_rev, 1, 0, sub { $self->_history_entry_callback( \@history, @_ ) }
-    );
-    $self->_compute_history_deltas( \@history );
-    return \@history;
-}
-
-sub _history_entry_callback {
-    my $self = shift;
-    my ( $accumulator, $paths, $rev, $author, $date, $msg ) = @_;
-    my @nodes = keys %$paths;
-    die "We should only have one node!" unless ( $#nodes == 0 );
-
-    my $node = $paths->{ $nodes[0] };
-    my $data = Prophet::HistoryEntry->new( handle => $self->handle );
-
-    $data->rev($rev);
-    $data->author($author);
-    $data->date($date);
-    $data->msg($msg);
-    $data->action( $node->action() );
-    $data->copy_from( $node->copyfrom_path() );
-    $data->copy_from_rev( $node->copyfrom_rev() );
-    $data->props( $self->handle->repo_handle->fs()->revision_root($rev)->node_proplist( $nodes[0] ) );
-
-    push @$accumulator, $data;
-}
-
-sub _compute_history_deltas {
-    my $self    = shift;
-    my $log_ref = shift;
-    @$log_ref = reverse @$log_ref;
-    my $last_props = {};
-    for my $i ( 0 .. $#{$log_ref} ) {
-
-        my $props = $log_ref->[$i]->props;
-
-        for my $key ( keys %$props ) {
-
-            if ( !exists $last_props->{$key} ) {
-                $log_ref->[$i]->prop_changes->{$key}->{'add'} = $props->{$key};
-            } elsif ( $last_props->{$key} ne $props->{$key} ) {
-                $log_ref->[$i]->prop_changes->{$key}->{'add'} = $props->{$key};
-                $log_ref->[$i]->prop_changes->{$key}->{'del'} = $last_props->{$key};
-            }
-        }
-        foreach my $key ( keys %$last_props ) {
-            if ( !exists $props->{$key} ) {
-                $log_ref->[$i]->prop_changes->{$key}->{'del'} = $last_props->{$key};
-            }
-        }
-
-        $last_props = $props;
-    }
-
-    return $log_ref;
-
-}
-
 =head2 format_summary
 
 returns a formated string that is the summary for the record.



More information about the Bps-public-commit mailing list