[Bps-public-commit] r11014 - in SVN-PropDB: bin lib/Prophet lib/Prophet/Sync/Source lib/Prophet/Sync/Source/SVN t/samples/createt/db
jesse at bestpractical.com
jesse at bestpractical.com
Wed Mar 5 16:56:28 EST 2008
Author: jesse
Date: Wed Mar 5 16:56:26 2008
New Revision: 11014
Added:
SVN-PropDB/lib/Prophet/Change.pm
SVN-PropDB/lib/Prophet/ChangeSet.pm
SVN-PropDB/lib/Prophet/PropChange.pm
Modified:
SVN-PropDB/ (props changed)
SVN-PropDB/bin/merger
SVN-PropDB/bin/svn-replay
SVN-PropDB/lib/Prophet/Handle.pm
SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
SVN-PropDB/lib/Prophet/Sync/Source/SVN/ReplayEditor.pm
SVN-PropDB/notes
SVN-PropDB/t/samples/createt/db/current
Log:
r28131 at 103: jesse | 2008-03-05 16:48:06 -0500
* checkppoint
Modified: SVN-PropDB/bin/merger
==============================================================================
--- SVN-PropDB/bin/merger (original)
+++ SVN-PropDB/bin/merger Wed Mar 5 16:56:26 2008
@@ -5,67 +5,75 @@
my $opts = {};
-GetOptions($opts, 'local=s', 'remote=s');
-
-
-my $local_source = Prophet::MergeSource->new(url => $opts->{'local'});
-my $remote_source = Prophet::MergeSource->new(url => $opts->{'remote'});
-
-
-$local_source->snapshot;
-$remote_source->snapshot;
-
-my @txns_to_integrate = $remote_source->fetch_txns(after => $remote_source->last_txn_seen);
-
+use Getopt::Long;
+GetOptions( $opts, 'target=s', 'source=s' );
+use Prophet::Sync::Source::SVN;
+
+validate_options($opts);
+
+my $target = Prophet::Sync::Source::SVN->new( { url => $opts->{'target'} });
+my $source = Prophet::Sync::Source::SVN->new( {url => $opts->{'source'} });
+
+fatal_error("You appear to be trying to merge two identical replicas. ".
+ "Either you're trying to merge a replica to itself or ".
+ "someone did a bad job cloning your database") if ($target->unique_id eq $source->unique_id);
+
+if ( $target->accepts_changesets ) {
+ my @changesets_to_integrate = $source->fetch_changesets(
+ after => $target->last_changeset_for_source(source => $source->unique_id) );
+
+ for my $changeset (@changesets_to_integrate) {
+ next if ( $target->has_seen_changeset(source => $source->unique_id, changeset => $changeset->unique_id));
+ if ( $target->changeset_will_conflict($changeset) ) {
+ die "Conflicts are hard";
+
+# make a decision about who wins the conflict
+# For parts of the conflict _source_ should win, write out a nullification changeset beforehand,
+# apply the changeset. it will now apply cleanly
+
+# For parts of the conflict _target_ should win,
+# write out a nullification changeset beforehand,
+# - that way, the source update will apply cleanly
+# Then write out the source changeset
+# Then write out a new changeset which reverts the parts of the source changeset which target should win
+ } else {
+ $target->apply_changeset($changeset);
+ }
-for my $txn (@txns_to_integrate) {
- next if ($local_source->has_seen_txn($txn) );
- if ($local_source->txn_will_conflict($txn)) {
- die "Conflicts are hard";
- # make a decision about who wins the conflict
- # For parts of the conflict _remote_ should win, write out a nullification txn beforehand,
- # apply the txn. it will now apply cleanly
-
- # For parts of the conflict _local_ should win,
- # write out a nullification txn beforehand,
- # - that way, the remote update will apply cleanly
- # Then write out the remote txn
- # Then write out a new txn which reverts the parts of the remote txn which local should win
+ $target->record_changeset_for_source(source => $source->unique_id, changeset => $changeset->);
+ }
+} else {
+ fatal_error($target->url." does not accept changesets. Perhaps it's unwritable or something");
- } else {
- $local_source->apply_txn($txn);
- }
}
-if ( $remote_source->accepts_txns ) {
- my @txns_to_send = $local_source->fetch_txns( after =>
- $remote_source->last_txn_received( source => $local_source ) );
-
- for my $txn (@txns_to_send) {
- next if ( $remote_source->has_seen_txn($txn) );
- if ( $remote_source->txn_will_conflict($txn) ) {
- die "Conflicts are hard"
- } else {
- $remote_source->apply_txn($txn);
- }
+sub validate_options {
+ my $opts = shift;
+for (qw(source target)){
+die "You need to specify a --$_ url" unless ($opts->{$_});
+}
+}
- }
+sub fatal_error {
+ my $reason = shift;
+ die $reason."\n";
}
+
package Prophet::MergeSource;
use base 'Class::Accessor';
__PACKAGE__->mk_accessors(qw'url unique_id');
-sub accepts_txns {}
-sub has_seen_txn {}
-sub txn_will_conflict {}
-sub apply_txn {}
-sub fetch_txns {}
-sub last_txn_received {}
+sub accepts_changesets {}
+sub has_seen_changeset {}
+sub changeset_will_conflict {}
+sub apply_changeset {}
+sub fetch_changesets {}
+sub last_changeset_seen {}
=head2 Assumptions about merge sources
@@ -73,28 +81,28 @@
- a source represents a branch
- a branch has had many revisions applied
- revisions we apply to a branch from another branch are always applied UNCHANGED
- - in the event of a conflict, we will apply a "pre-txn" to smooth the application and a "post-txn" if the applied txn doesn't match the desired outcome.
+ - in the event of a conflict, we will apply a "pre-changeset" to smooth the application and a "post-changeset" if the applied changeset doesn't match the desired outcome.
on pull
- we end up applying every single remote txn this peer has seen since the last time we saw this peer, one by one
- we possibly apply another two txns for each txn to smooth the application
+ we end up applying every single source changeset this peer has seen since the last time we saw this peer, one by one
+ we possibly apply another two changesets for each changeset to smooth the application
- we skip any remote txn we've seen from another source before
+ we skip any source changeset we've seen from another source before
on push,
- we publish each txn we've made locally.
- - including "after" fixup txns
- - not including "before" fixup txns.
+ we publish each changeset we've made targetly.
+ - including "after" fixup changesets
+ - not including "before" fixup changesets.
-=head2 assumptions about merge txns
+=head2 assumptions about merge changesets
we can get (and hash):
-original database uuid
@@ -138,11 +146,11 @@
Conflict
- to local c applies a pre-fixup:
+ to target c applies a pre-fixup:
frotz->foo
- to local c applies a at 2:
+ to target c applies a at 2:
foo->baz
- to local c applies a conflict resolution
+ to target c applies a conflict resolution
baz->frotz
@@ -162,7 +170,7 @@
so, what do we push?
options:
fixup to get a to our earliest state unpushed. that's kind of stupid and results in us replaying everthing all the time.
- compute a single large txn from a at HEAD to c at HEAD and apply that?
+ compute a single large changeset from a at HEAD to c at HEAD and apply that?
@@ -173,40 +181,40 @@
there's a new peer I've not seen before. I need to merge in all their changes:
- if a txn comes from a replica at rev lower than our last-seen version for replica, skip it
+ if a changeset comes from a replica at rev lower than our last-seen version for replica, skip it
- for each of their txns, import it, applying fixups as needed
+ for each of their changesets, import it, applying fixups as needed
=head3 push
- get the remote list of all merge tickets.
- find all local revs which remote has never seen.
- - genuine local txns
- - third-party txns that the remote has no merge ticket for
+ get the source list of all merge tickets.
+ find all target revs which source has never seen.
+ - genuine target changesets
+ - third-party changesets that the source has no merge ticket for
- - skip "before" fixup txns
- - include "after" fixup txns, since they're merge resolutions
+ - skip "before" fixup changesets
+ - include "after" fixup changesets, since they're merge resolutions
- iterate over these revs the remote has never seen.
- when the txn applies cleanly, just apply it.
+ iterate over these revs the source has never seen.
+ when the changeset applies cleanly, just apply it.
- when the txn does _not_ apply cleanly,
+ when the changeset does _not_ apply cleanly,
- apply a 'before' fix up transaction
- - apply the original txn
- - apply a merge resolution txn.
+ - apply the original changeset
+ - apply a merge resolution changeset.
- TODO: this doesn't feel quite right
- the resolution should be the same as the equivalent merge resolution transaction on the "pull" variant if it exists.
What info do we have here?
- record uuid
- nearest parent variant
- - local variant
- - remote variant
- - information from the 'future (local head)' about the eventual desired outcome
+ - target variant
+ - source variant
+ - information from the 'future (target head)' about the eventual desired outcome
- audit stage:
- compare local head and remote head. - they should now be identical, since the last transactions we replayed were all local merge fixup txns. (is that true?)
+ compare target head and source head. - they should now be identical, since the last transactions we replayed were all target merge fixup changesets. (is that true?)
=cut
-
+1;
Modified: SVN-PropDB/bin/svn-replay
==============================================================================
--- SVN-PropDB/bin/svn-replay (original)
+++ SVN-PropDB/bin/svn-replay Wed Mar 5 16:56:26 2008
@@ -2,9 +2,8 @@
use strict;
use Prophet::Sync::Source::SVN;
-my $sync = Prophet::Sync::Source::SVN->new();
+my $sync = Prophet::Sync::Source::SVN->new({ url => shift @ARGV} );
-$sync->setup(shift @ARGV);
my @changes = $sync->fetch_changesets();
warn YAML::Dump(\@changes); use YAML;
Added: SVN-PropDB/lib/Prophet/Change.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/Change.pm Wed Mar 5 16:56:26 2008
@@ -0,0 +1,26 @@
+use warnings;
+use strict;
+
+package Prophet::Change;
+use base qw/Class::Accessor/;
+
+use Prophet::PropChange;
+
+use Params::Validate;
+__PACKAGE__->mk_accessors(qw/node_type node_uuid change_type/);
+
+sub add_prop_change {
+ my $self = shift;
+ my %args = validate(@_, { name => 1, old => 0, new => 0 } );
+ my $change = Prophet::PropChange->new();
+ $change->name($args{'name'});
+ $change->old_value($args{'old'});
+ $change->new_value($args{'new'});
+
+ push @{$self->{prop_changes}}, $change;
+
+
+}
+
+
+1;
Added: SVN-PropDB/lib/Prophet/ChangeSet.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/ChangeSet.pm Wed Mar 5 16:56:26 2008
@@ -0,0 +1,20 @@
+use warnings;
+use strict;
+
+package Prophet::ChangeSet;
+use Prophet::Change;
+use Params::Validate;
+
+use base qw/Class::Accessor/;
+
+__PACKAGE__->mk_accessors(qw/change_uuid source_uuid/);
+
+sub add_change {
+ my $self = shift;
+ my %args = validate(@_, { change => 1} );
+ push @{$self->{changes}}, $args{change};
+
+
+}
+
+1;
Modified: SVN-PropDB/lib/Prophet/Handle.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Handle.pm (original)
+++ SVN-PropDB/lib/Prophet/Handle.pm Wed Mar 5 16:56:26 2008
@@ -19,7 +19,7 @@
my $self = {};
bless $self, $class;
my %args = validate( @_, { repository => 1, db_root => 1 } );
- $self->db_root($args{'db_root'});
+ $self->db_root( $args{'db_root'} );
$self->repo_path( $args{'repository'} );
$self->_connect();
@@ -28,42 +28,51 @@
sub current_root {
my $self = shift;
- $self->repo_handle->fs->revision_root ($self->repo_handle->fs->youngest_rev);
+ $self->repo_handle->fs->revision_root(
+ $self->repo_handle->fs->youngest_rev );
}
+sub _connect {
+ my $self = shift;
+ my $repos;
+ eval {
+ $repos = SVN::Repos::open( $self->repo_path );
+
+ };
+
+ if ( $@ && !-d $self->repo_path ) {
+ $repos = SVN::Repos::create( $self->repo_path, undef, undef, undef,
+ undef );
-sub _connect {
- my $self = shift;
- my $repos = SVN::Repos::open( $self->repo_path );
+ }
$self->repo_handle($repos);
- $self->_create_nonexistent_dir($self->db_root);
+ $self->_create_nonexistent_dir( $self->db_root );
}
-
sub _create_nonexistent_dir {
my $self = shift;
- my $dir = shift;
- unless($self->current_root->is_dir($dir) ){
- my $edit = $self->begin_edit;
- $edit->root->make_dir($dir);
- $self->commit_edit($edit);
+ my $dir = shift;
+ unless ( $self->current_root->is_dir($dir) ) {
+ my $edit = $self->begin_edit;
+ $edit->root->make_dir($dir);
+ $self->commit_edit($edit);
}
}
sub begin_edit {
my $self = shift;
- my $fs = $self->repo_handle->fs;
- my $txn = $fs->begin_txn($fs->youngest_rev);
+ my $fs = $self->repo_handle->fs;
+ my $txn = $fs->begin_txn( $fs->youngest_rev );
return $txn;
}
sub commit_edit {
my $self = shift;
- my $txn = shift;
- $txn->change_prop('svn:author',$ENV{'USER'});
+ my $txn = shift;
+ $txn->change_prop( 'svn:author', $ENV{'USER'} );
$txn->commit;
}
@@ -71,68 +80,105 @@
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'}));
+ $self->_create_nonexistent_dir(
+ join( '/', $self->db_root, $args{'type'} ) );
my $edit = $self->begin_edit();
-
- my $file = $self->file_for(uuid => $args{uuid}, type => $args{'type'});
- $edit->root->make_file( $file );
+ my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+ $edit->root->make_file($file);
{
- my $stream = $edit->root->apply_text($file, undef);
- print $stream Dumper($args{'props'});
+ my $stream = $edit->root->apply_text( $file, undef );
+ print $stream Dumper( $args{'props'} );
close $stream;
}
- $self->_set_node_props(uuid => $args{uuid}, props => $args{props}, edit => $edit, type => $args{'type'});
+ $self->_set_node_props(
+ uuid => $args{uuid},
+ props => $args{props},
+ edit => $edit,
+ type => $args{'type'}
+ );
$self->commit_edit($edit);
}
sub _set_node_props {
-my $self = shift;
- my %args = validate(@_, { uuid => 1, props=> 1, edit => 1, type => 1});
- my $file = $self->file_for(uuid => $args{uuid}, type => $args{type});
- foreach my $prop (keys %{$args{'props'}}) {
- $args{edit}->root->change_node_prop($file,$prop, $args{'props'}->{$prop}, undef);
+ my $self = shift;
+ my %args
+ = validate( @_, { uuid => 1, props => 1, edit => 1, type => 1 } );
+ my $file = $self->file_for( uuid => $args{uuid}, type => $args{type} );
+ foreach my $prop ( keys %{ $args{'props'} } ) {
+ $args{edit}
+ ->root->change_node_prop( $file, $prop, $args{'props'}->{$prop},
+ undef );
}
}
sub delete_node {
my $self = shift;
- my %args = validate( @_, { uuid => 1, type => 1} );
+ my %args = validate( @_, { uuid => 1, type => 1 } );
my $edit = $self->begin_edit();
- $edit->root->delete($self->file_for(uuid => $args{uuid}, type => $args{type}));
+ $edit->root->delete(
+ $self->file_for( uuid => $args{uuid}, type => $args{type} ) );
$self->commit_edit($edit);
-
}
sub set_node_props {
my $self = shift;
my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
my $edit = $self->begin_edit();
- my $file = $self->file_for(uuid => $args{uuid}, type => $args{'type'});
- $self->_set_node_props(uuid => $args{uuid}, props => $args{props} ,edit => $edit, type => $args{'type'});
+ my $file = $self->file_for( uuid => $args{uuid}, type => $args{'type'} );
+ $self->_set_node_props(
+ uuid => $args{uuid},
+ props => $args{props},
+ edit => $edit,
+ type => $args{'type'}
+ );
$self->commit_edit($edit);
}
-
-
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'}));
+ return $root->node_proplist(
+ $self->file_for( uuid => $args{'uuid'}, type => $args{'type'} ) );
}
-
-
sub file_for {
-my $self = shift;
- my %args = validate( @_, { uuid => 1, type => 1} );
- my $file = join("/",$self->db_root, $args{'type'}, $args{'uuid'});
+ my $self = shift;
+ my %args = validate( @_, { uuid => 1, type => 1 } );
+ my $file = join( "/", $self->db_root, ,$args{'type'}, $args{'uuid'} );
return $file;
}
+
+my $MERGETICKET_METATYPE = '_merge_tickets';
+sub last_changeset_for_source {
+ my $self = shift;
+ my %args = validate( @_, { source => 1, } );
+
+ my %props = $self->get_node_props(uuid => $args{'source'}, type => $MERGETICKET_METATYPE);
+
+ return $props{'last-rev'};
+
+
+
+}
+
+sub record_changeset_for_source {
+ my $self = shift;
+ my %args = validate( @_, { source => 1, changeset => 1} );
+ my %props = $self->get_node_props(uuid => $args{'source'}, type => $MERGETICKET_METATYPE);
+ unless ($props{'last-rev'}) {
+ $self->create_node( uuid => $args{'source'}, type => $MERGETICKET_METATYPE );
+ }
+ $self->set_node_props(uuid => $args{'source'}, type => $MERGETICKET_METATYPE, props => { 'last-rev' => $args{'changeset'}});
+
+}
+
+
+
1;
Added: SVN-PropDB/lib/Prophet/PropChange.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/PropChange.pm Wed Mar 5 16:56:26 2008
@@ -0,0 +1,9 @@
+use warnings;
+use strict;
+package Prophet::PropChange;
+use base qw/Class::Accessor/;
+
+__PACKAGE__->mk_accessors(qw/name old_value new_value/);
+
+
+1;
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 Wed Mar 5 16:56:26 2008
@@ -2,42 +2,51 @@
use strict;
package Prophet::Sync::Source::SVN;
+use base qw/Class::Accessor/;
+use Params::Validate;
use SVN::Core;
use SVN::Ra;
use SVK;
use SVK::Config;
use SVN::Delta;
-
-use Prophet::Sync::Source::SVN::ReplayEditor;
+use Prophet::Handle;
+use Prophet::Sync::Source::SVN::ReplayEditor;
+use Prophet::ChangeSet;
+__PACKAGE__->mk_accessors(qw/url ra prophet_handle/);
sub new {
- my $class = shift;
- my $self = {};
- bless $self, $class;
+ my $self = shift->SUPER::new(@_);
+ $self->setup();
return $self;
}
-sub ra {
+sub setup {
my $self = shift;
- $self->{'_ra'} = shift if (@_);
- return $self->{'_ra'};
+ my ( $baton, $ref )
+ = SVN::Core::auth_open_helper( SVK::Config->get_auth_providers );
+ my $config = SVK::Config->svnconfig;
+ $self->ra(
+ SVN::Ra->new( url => $self->url, config => $config, auth => $baton )
+ );
+
+ if ( $self->url =~ /^file:\/\/(.*)$/ ) {
+ warn "Connecting to $1";
+ $self->prophet_handle(
+ Prophet::Handle->new(
+ { repository => $1, db_root => '_prophet' }
+ )
+ );
+ }
}
-sub setup{
+sub unique_id {
my $self = shift;
- my $url = shift;
- my ($baton, $ref) = SVN::Core::auth_open_helper(SVK::Config->get_auth_providers);
- my $config = SVK::Config->svnconfig;
- $self->ra( SVN::Ra->new( url => $url , config => $config, auth => $baton));
-
-}
-
-
-
+ return $self->ra->get_uuid;
+}
sub fetch_changesets {
my $self = shift;
@@ -46,19 +55,98 @@
my $handle_replayed_txn = sub {
$last_editor
= Prophet::Sync::Source::SVN::ReplayEditor->new( _debug => 0 );
- $last_editor->ra($self->ra);
+ $last_editor->ra( $self->ra );
return $last_editor;
};
for my $rev ( 1 .. $self->ra->get_latest_revnum ) {
- $Prophet::Sync::Source::SVN::ReplayEditor::CURRENT_REMOTE_REVNO = $rev;
- # This horrible hack is here because I have no idea how to pass custom variables into the editor
+ $Prophet::Sync::Source::SVN::ReplayEditor::CURRENT_REMOTE_REVNO
+ = $rev;
+
+# This horrible hack is here because I have no idea how to pass custom variables into the editor
$self->ra->replay( $rev, 0, 1, $handle_replayed_txn->() );
push @results, $last_editor->dump_deltas;
}
- return \@results;
+
+ # XXX TODO, we should be creating the changesets directly earlier
+ my @changesets;
+ for my $entry (@results) {
+ my $changeset = Prophet::ChangeSet->new(
+ { change_uuid => $entry->{'revision'},
+ source_uuid => $self->unique_id
+ }
+ );
+ for my $path ( keys %{ $entry->{'paths'} } ) {
+ if ( $path =~ qr|^(.+)/(.*?)/(.*?)$| ) {
+ my ( $prefix, $type, $record ) = ( $1, $2, $3 );
+ my $change = Prophet::Change->new(
+ { node_type => $type,
+ node_uuid => $record,
+ change_type => $entry->{'paths'}->{$path}->{'fs'}
+ }
+ );
+ for my $name (
+ keys %{ $entry->{'paths'}->{$path}->{prop_deltas} } )
+ {
+ warn "Changing $name for $change";
+ $change->add_prop_change(
+ name => $name,
+ old =>
+ $entry->{paths}->{$path}->{prop_deltas}->{$name}
+ ->{'old'},
+ new =>
+ $entry->{paths}->{$path}->{prop_deltas}->{$name}
+ ->{'new'},
+ );
+ }
+
+ $changeset->add_change( change => $change );
+ } else {
+ warn "Discarding change to a non-record: $path";
+ warn "Someday, we should be less stupid about this";
+ }
+
+ }
+ warn YAML::Dump($changeset);
+
+ }
+
+ exit;
+ return \@changesets;
+}
+
+sub accepts_changesets {
+ my $self = shift;
+ return 1 if $self->prophet_handle;
+ return undef;
+}
+
+# XXX TODO this is hacky as hell and violates abstraction barriers in the name of doing things over the RA
+sub last_changeset_for_source {
+ my $self = shift;
+ my %args = validate( @_, { source => 1 } );
+ my ( $stream, $pool );
+
+ # XXX HACK
+ my $filename = join( "/",
+ "_prophet", $Prophet::Handle::MERGETICKET_METATYPE,
+ $args{'source'} );
+ my ( $rev_fetched, $props ) = eval {
+ $self->ra->get_file( $filename, $self->ra->get_latest_revnum,
+ $stream, $pool );
+ };
+ return ( $props->{'last-rev'} );
+
+}
+
+sub record_changeset_for_source {
+ my $self = shift;
+ return undef unless ( $self->accepts_changesets );
+ my %args = validate( @_, { source => 1, changeset => 1 } );
+ $self->prophet_handle->record_changeset_for_source(%args);
+
}
1;
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 Wed Mar 5 16:56:26 2008
@@ -38,7 +38,7 @@
sub delete_entry {
my $self = shift;
my ($path, $revision, $parent_baton) = (@_);
- push @{$self->{'paths'}->{ $self->{'dir_stack'}->[-1]->{path} }->{delete_path}}, $path;
+ $self->{'paths'}->{$path}->{fs} = 'delete';
}
sub add_file {
@@ -46,14 +46,14 @@
my ($path, $parent_baton, $copy_path, $copy_revision, $file_pool, $file_baton) = (@_);
$self->{'current_file'} = $path;
$self->{'current_file_base_rev'} = "newly created";
- push @{$self->{'paths'}->{ $self->{'dir_stack'}->[-1]->{path} }->{create_file}}, $path;
+ $self->{'paths'}->{$path}->{fs} = 'add_file';
}
sub add_directory {
my $self = shift;
my ($path, $parent_baton, $copyfrom_path, $copyfrom_revision, $dir_pool, $child_baton) = (@_);
push @{$self->{'dir_stack'}}, { path => $path, base_rev => -1 };
- push @{$self->{'paths'}->{ $self->{'dir_stack'}->[-1]->{path} }->{create_dir}}, $path;
+ $self->{'paths'}->{$path}->{fs} = 'add_dir';
}
sub open_file {
@@ -66,6 +66,7 @@
my ($stream, $pool);
my ($rev_fetched, $prev_props) = $self->ra->get_file($path, $self->{'revision'}-1, $stream,$pool);
+ $self->{'paths'}->{$path}->{fs} = 'update_file';
$self->{'paths'}->{$path}->{prev_properties} = $prev_props;
Modified: SVN-PropDB/notes
==============================================================================
--- SVN-PropDB/notes (original)
+++ SVN-PropDB/notes Wed Mar 5 16:56:26 2008
@@ -26,7 +26,9 @@
Changeset
A changeset contains "old" and "new" versions of a set of database "Records", they can be of any Record Type.
-
+
+Change
+ An entry in a changeset. Contains all the updates to a given record for this changeset
Record
A Record is composed of zero or more Attributes and a universally unique identifier. Each record is categorized into a Record Type.
@@ -225,4 +227,4 @@
Resolution
- When the local Replica
\ No newline at end of file
+ When the local Replica
Modified: SVN-PropDB/t/samples/createt/db/current
==============================================================================
--- SVN-PropDB/t/samples/createt/db/current (original)
+++ SVN-PropDB/t/samples/createt/db/current Wed Mar 5 16:56:26 2008
@@ -1 +1 @@
-11 7 1
+12 8 1
More information about the Bps-public-commit
mailing list