[Bps-public-commit] r11834 - in Prophet/trunk: . lib/Prophet/Replica lib/Prophet/Resolver t
jesse at bestpractical.com
jesse at bestpractical.com
Tue Apr 22 20:34:04 EDT 2008
Author: jesse
Date: Tue Apr 22 20:34:02 2008
New Revision: 11834
Modified:
Prophet/trunk/ (props changed)
Prophet/trunk/Makefile.PL
Prophet/trunk/lib/Prophet/App.pm
Prophet/trunk/lib/Prophet/CLI.pm
Prophet/trunk/lib/Prophet/Change.pm
Prophet/trunk/lib/Prophet/ConflictingChange.pm
Prophet/trunk/lib/Prophet/ConflictingPropChange.pm
Prophet/trunk/lib/Prophet/Replica.pm
Prophet/trunk/lib/Prophet/Replica/Native.pm
Prophet/trunk/lib/Prophet/Replica/SVN.pm
Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm
Prophet/trunk/lib/Prophet/Resolver/Failed.pm
Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm
Prophet/trunk/lib/Prophet/Test.pm
Prophet/trunk/t/canonicalize.t
Prophet/trunk/t/create.t
Prophet/trunk/t/validate.t
Log:
r29979 at 31b: jesse | 2008-04-22 17:23:49 -0400
* Switched from YAML to JSON
* Switched default replica type from SVN to Native
Modified: Prophet/trunk/Makefile.PL
==============================================================================
--- Prophet/trunk/Makefile.PL (original)
+++ Prophet/trunk/Makefile.PL Tue Apr 22 20:34:02 2008
@@ -4,46 +4,45 @@
name('Prophet');
author('clkao and jesse');
license('DeathandRepudiation');
+
requires('Params::Validate');
requires('List::MoreUtils');
requires('Class::Accessor');
requires('IPC::Run3');
-requires('Test::Exception');
requires('Data::UUID');
requires('Path::Class');
requires('YAML::Syck');
requires('Test::Exception');
-requires('Acme::MetaSyntactic');
requires('UNIVERSAL::require');
requires('Class::Data::Inheritable');
-requires('DateTime::Format::HTTP');
-requires('Devel::Gladiator');
-requires('RT::Client::REST');
-requires('RT::Client::REST::Ticket');
-requires('RT::Client::REST::User');
requires('Term::ReadKey');
-requires('Digest::SHA1');
-requires('LWP::Simple');
+requires('Digest::SHA1'); # Core in 5.10
+requires('LWP::Simple'); # Part of lib-www-perl
requires('URI');
requires('JSON');
requires('Module::Pluggable');
-requires('Test::HTTP::Server::Simple');
-requires('HTTP::Server::Simple');
-requires('Test::WWW::Mechanize');
-requires('HTTP::Server::Simple::CGI');
-requires('SVN::Core'); # SVN::Repos SVN::Fs SVN::Ra SVN::Delta::Editor SVN::Client SVN::Delta
+
features(
+ 'REST Server' => [
+ -default => 1,
+ recommends('HTTP::Server::Simple'), # HTTP::Server::Simple::CGI'
+ recommends('Test::HTTP::Server::Simple'),
+ recommends('Test::WWW::Mechanize'),
+ recommends('HTTP::Server::Simple')
+ ],
+
+
+ 'Subversion replica support' => [
+ -default => 0,
+ recommends( 'SVN::Core') # SVN::Repos SVN::Fs SVN::Ra SVN::Delta::Editor SVN::Client SVN::Delta
+ ],
'Crazy debugging tools' => [
-default => 1,
- recommends => 'Devel::Gladiator'
+ recommends('Acme::MetaSyntactic'),
+ recommends('Devel::Gladiator')
],
- 'Hiveminder sync' => [
- -default => 0,
- requires => 'Net::Jifty',
- requires => 'Jifty',
- ]
);
all_from('lib/Prophet.pm');
-
+auto_install;
WriteAll();
Modified: Prophet/trunk/lib/Prophet/App.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/App.pm (original)
+++ Prophet/trunk/lib/Prophet/App.pm Tue Apr 22 20:34:02 2008
@@ -6,6 +6,9 @@
use Path::Class;
__PACKAGE__->mk_accessors(qw/_resdb_handle/);
+use constant DEFAULT_REPLICA_TYPE => 'prophet';
+
+
sub _handle {
my $self = shift;
$self->{_handle} = shift if (@_);
@@ -31,7 +34,7 @@
my $self = shift;
unless ( $self->_handle() ) {
my $root = $ENV{'PROPHET_REPO'} || dir( $ENV{'HOME'}, '.prophet' );
- my $type = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
+ my $type = $ENV{'PROPHET_REPLICA_TYPE'} || DEFAULT_REPLICA_TYPE;
$self->_handle( Prophet::Replica->new( { url => $type.':file://' . $root } ) );
}
return $self->_handle();
@@ -47,7 +50,7 @@
return ($self->handle->resolution_db_handle) if ($self->handle->resolution_db_handle);
unless ( $self->_resdb_handle ) {
my $root = ( $ENV{'PROPHET_REPO'} || dir( $ENV{'HOME'}, '.prophet' ) ) . "_res";
- my $type = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
+ my $type = $ENV{'PROPHET_REPLICA_TYPE'} || DEFAULT_REPLICA_TYPE;
$self->_resdb_handle( Prophet::Replica->new( { url => $type.':file://' . $root } ) );
}
return $self->_resdb_handle();
Modified: Prophet/trunk/lib/Prophet/CLI.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/CLI.pm (original)
+++ Prophet/trunk/lib/Prophet/CLI.pm Tue Apr 22 20:34:02 2008
@@ -234,8 +234,7 @@
sub do_push {
my $self = shift;
- my $replica_type = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
- my $source_me = Prophet::Replica->new( { url => $replica_type. ":file://" . $self->app_handle->handle->fs_root } );
+ my $source_me = $self->app_handle->handle;
my $other = shift @ARGV;
my $source_other = Prophet::Replica->new( { url => $other } );
my $resdb = $source_me->import_resolutions_from_remote_replica( from => $source_other );
@@ -245,21 +244,16 @@
sub do_export {
my $self = shift;
- my $replica_type = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
- my $source_me = Prophet::Replica->new( { url => $replica_type.":file://" . $self->app_handle->handle->fs_root } );
- my $path = $self->args->{'path'};
- $source_me->export_to( path => $path );
+ $self->app_handle->handle->export_to( path => $self->args->{path} );
}
sub do_pull {
my $self = shift;
- my $replica_type = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
- my $source_me = Prophet::Replica->new( { url => $replica_type. ":file://" . $self->app_handle->handle->fs_root } );
my $other = shift @ARGV;
my $source_other = Prophet::Replica->new( { url => $other } );
- my $resdb = $source_me->import_resolutions_from_remote_replica( from => $source_other );
+ $self->app_handle->handle->import_resolutions_from_remote_replica( from => $source_other );
- $self->_do_merge( $source_other, $source_me );
+ $self->_do_merge( $source_other, $self->app_handle->handle );
}
Modified: Prophet/trunk/lib/Prophet/Change.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Change.pm (original)
+++ Prophet/trunk/lib/Prophet/Change.pm Tue Apr 22 20:34:02 2008
@@ -51,7 +51,7 @@
my ( $class, $conflict ) = @_;
my $self = $class->new(
{ is_resolution => 1,
- resolution_cas => $conflict->cas_key,
+ resolution_cas => $conflict->fingerprint,
change_type => $conflict->change_type,
record_type => $conflict->record_type,
record_uuid => $conflict->record_uuid
Modified: Prophet/trunk/lib/Prophet/ConflictingChange.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ConflictingChange.pm (original)
+++ Prophet/trunk/lib/Prophet/ConflictingChange.pm Tue Apr 22 20:34:02 2008
@@ -1,4 +1,3 @@
-
use warnings;
use strict;
@@ -6,7 +5,8 @@
use Prophet::ConflictingPropChange;
use base qw/Class::Accessor/;
-use Storable 'dclone';
+use JSON qw'to_json';
+use Digest::SHA1 'sha1_hex';
# change_type is one of: add_file add_dir update delete
__PACKAGE__->mk_accessors(qw/record_type record_uuid source_record_exists target_record_exists change_type file_op_conflict/);
@@ -25,33 +25,38 @@
}
-=head2 neutralize
-
-Returns the clone of the changeset, except hte propchanges will have target_value and source_new_value as a sorted "choices" field of arrayref.
-
-=cut
-sub neutralize {
- my $self = shift;
- my $struct = dclone($self);
- for ( @{ $struct->{prop_conflicts} } ) {
- $_->{choices} = [ sort ( delete $_->{source_new_value}, delete $_->{target_value} ) ];
+sub as_hash {
+ my $self = shift;
+ my $struct = {
+ map { $_ => $self->$_() } (
+ qw/record_type record_uuid source_record_exists target_record_exists change_type file_op_conflict/
+ )
+ };
+ for ( @{ $self->prop_conflicts } ) {
+ push @{ $struct->{'prop_conflicts'} }, $_->as_hash;
}
+
return $struct;
}
-=head2 cas_key
+=head2 fingerprint
-returned the key signatured by the content of the conflicting change.
+Returns a fingerprint of the content of this conflicting change
=cut
-use YAML::Syck;
-use Digest::MD5 'md5_hex';
-sub cas_key {
+sub fingerprint {
my $self = shift;
- return md5_hex( YAML::Syck::Dump( $self->neutralize ) );
-}
+ my $struct = $self->as_hash;
+ for ( @{ $struct->{prop_conflicts} } ) {
+ $_->{choices} = [ sort ( delete $_->{source_new_value}, delete $_->{target_value} ) ];
+ }
+
+ return sha1_hex(to_json($struct, {utf8 => 1, canonical => 1}));
+
+
+}
1;
Modified: Prophet/trunk/lib/Prophet/ConflictingPropChange.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ConflictingPropChange.pm (original)
+++ Prophet/trunk/lib/Prophet/ConflictingPropChange.pm Tue Apr 22 20:34:02 2008
@@ -35,4 +35,15 @@
=cut
+sub as_hash {
+ my $self = shift;
+ my $hashref = {};
+
+ for (qw(name source_old_value target_value source_new_value)) {
+ $hashref->{$_} = $self->$_()
+ }
+ return $hashref;
+}
+
+
1;
Modified: Prophet/trunk/lib/Prophet/Replica.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica.pm (original)
+++ Prophet/trunk/lib/Prophet/Replica.pm Tue Apr 22 20:34:02 2008
@@ -1,10 +1,12 @@
use warnings;
use strict;
+
package Prophet::Replica;
use base qw/Class::Accessor/;
use Params::Validate qw(:all);
use UNIVERSAL::require;
+use Data::UUID;
__PACKAGE__->mk_accessors(qw(state_handle resolution_db_handle is_resdb is_state_handle db_uuid url));
Modified: Prophet/trunk/lib/Prophet/Replica/Native.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/Native.pm (original)
+++ Prophet/trunk/lib/Prophet/Replica/Native.pm Tue Apr 22 20:34:02 2008
@@ -3,15 +3,16 @@
package Prophet::Replica::Native;
use base qw/Prophet::Replica/;
+
use Params::Validate qw(:all);
use LWP::Simple ();
-use File::Slurp;
use Path::Class;
-use Digest::SHA1 qw(sha1 sha1_hex);
-use YAML::Syck;
+use Digest::SHA1 qw(sha1_hex);
+use File::Find::Rule;
+use JSON;
+
use Prophet::ChangeSet;
use Prophet::Conflict;
-use File::Find::Rule;
__PACKAGE__->mk_accessors(qw/url _db_uuid _uuid/);
__PACKAGE__->mk_accessors(
@@ -40,15 +41,19 @@
$self->fs_root_parent( $self->url =~ m{^file://(.*)/.*?$} );
$self->_probe_or_create_db();
+# $self->state_handle( Prophet::Replica->new( { url => "prophet:".$self->{url}, is_state_handle =>1 } ) ) unless ( $self->is_state_handle || $self->state_handle);
- # $self->state_handle( Prophet::Replica->new( { url => "prophet:".$self->{url}, is_state_handle =>1 } ) ) unless ( $self->is_state_handle || $self->state_handle);
-
- $self->resolution_db_handle( Prophet::Replica->new( { url => "prophet:".$self->{url}.'/resolutions', is_resdb => 1 } ) )
- unless ( $self->is_resdb || $self->is_state_handle);
+ $self->resolution_db_handle(
+ Prophet::Replica->new(
+ { url => "prophet:" . $self->{url} . '/resolutions',
+ is_resdb => 1
+ }
+ )
+ ) unless ( $self->is_resdb || $self->is_state_handle );
-# warn "I AM ".$ENV{'PROPHET_USER'};
-# warn $self->uuid;
-# warn $self->state_handle->uuid unless ($self->is_state_handle);
+ # warn "I AM ".$ENV{'PROPHET_USER'};
+ # warn $self->uuid;
+ # warn $self->state_handle->uuid unless ($self->is_state_handle);
}
@@ -81,10 +86,13 @@
sub initialize {
my $self = shift;
my %args = validate( @_, { db_uuid => 0 } );
- dir( $self->fs_root, $_ )->mkpath
- for ($self->record_dir, $self->cas_root, $self->record_cas_dir, $self->changeset_cas_dir );
+ dir( $self->fs_root, $_ )->mkpath
+ for (
+ $self->record_dir, $self->cas_root,
+ $self->record_cas_dir, $self->changeset_cas_dir
+ );
- $self->set_db_uuid($args{'db_uuid'} || Data::UUID->new->create_str);
+ $self->set_db_uuid( $args{'db_uuid'} || Data::UUID->new->create_str );
$self->set_latest_sequence_no("0");
$self->set_replica_uuid( Data::UUID->new->create_str );
$self->_write_file(
@@ -93,7 +101,6 @@
);
}
-
sub latest_sequence_no {
my $self = shift;
$self->_read_file('latest-sequence-no');
@@ -110,13 +117,11 @@
sub _increment_sequence_no {
my $self = shift;
- my $seq = $self->latest_sequence_no +1;
+ my $seq = $self->latest_sequence_no + 1;
$self->set_latest_sequence_no($seq);
return $seq;
}
-
-
=head2 uuid
Return the replica SVN repository's UUID
@@ -133,16 +138,16 @@
my $self = shift;
my $uuid = shift;
$self->_write_file(
- path => 'replica-uuid',
+ path => 'replica-uuid',
content => $uuid
);
}
-
sub db_uuid {
my $self = shift;
- $self->_db_uuid( $self->_read_file('database-uuid') ) unless $self->_db_uuid;
+ $self->_db_uuid( $self->_read_file('database-uuid') )
+ unless $self->_db_uuid;
return $self->_db_uuid;
}
@@ -150,15 +155,12 @@
my $self = shift;
my $uuid = shift;
$self->_write_file(
- path => 'database-uuid' ,
+ path => 'database-uuid',
content => $uuid
);
}
-
-
-
=head1 Internals of record handling
=cut
@@ -177,13 +179,13 @@
my $self = shift;
my %args = validate( @_, { type => 1, uuid => 1, props => 1 } );
- for ( keys %{$args{'props'}}) {
- delete $args{'props'}->{$_} if (!defined $args{'props'}->{$_} || $args{'props'}->{$_} eq '');
+ for ( keys %{ $args{'props'} } ) {
+ delete $args{'props'}->{$_}
+ if ( !defined $args{'props'}->{$_} || $args{'props'}->{$_} eq '' );
}
- my $content = YAML::Syck::Dump( $args{'props'} );
my ($cas_key) = $self->_write_to_cas(
- content_ref => \$content,
- cas_dir => $self->record_cas_dir
+ data => $args{props},
+ cas_dir => $self->record_cas_dir
);
$self->_write_record_index_entry(
uuid => $args{uuid},
@@ -200,14 +202,16 @@
type => $args{type}
);
- my $index_path = file($self->fs_root, $idx_filename);
+ my $index_path = file( $self->fs_root, $idx_filename );
$index_path->parent->mkpath;
my $record_index = $index_path->openw;
+
# XXX TODO: skip if the index already has this version of the record;
# XXX TODO FETCH THAT
my $record_last_changed_changeset = 1;
- my $index_row = pack( 'NH40', $record_last_changed_changeset, $args{cas_key} );
+ my $index_row
+ = pack( 'NH40', $record_last_changed_changeset, $args{cas_key} );
print $record_index $index_row || die $!;
close $record_index;
}
@@ -227,13 +231,14 @@
sub _read_serialized_record {
my $self = shift;
my %args = validate( @_, { type => 1, uuid => 1 } );
- my $idx_filename = $self->_record_index_filename( uuid => $args{uuid}, type => $args{type});
-
-
+ my $idx_filename = $self->_record_index_filename(
+ uuid => $args{uuid},
+ type => $args{type}
+ );
+
my $index = $self->_read_file($idx_filename);
return undef unless $index;
-
# XXX TODO THIS CODE IS FUCKING HACKY AND SHOULD BE SHOT;
my $count = length($index) / RECORD_INDEX_SIZE;
@@ -249,7 +254,7 @@
);
# That's the props
- return YAML::Syck::Load( $self->_read_file($casfile) );
+ return from_json( $self->_read_file($casfile), { utf8 => 1} );
}
sub _record_index_filename {
@@ -279,21 +284,21 @@
my $hash_changeset = $changeset->as_hash;
- # XXX TODO: we should not be calculating the changeset's sha1 with the 'replica_uuid' and 'sequence_no' inside it. that makes every replica have a different hash for what should be a unique changeset.
+# XXX TODO: we should not be calculating the changeset's sha1 with the 'replica_uuid' and 'sequence_no' inside it. that makes every replica have a different hash for what should be the samechangeset.
+
+ # These ttwo things should never actually get stored
+ my $seqno = delete $hash_changeset->{'sequence_no'};
+ my $uuid = delete $hash_changeset->{'replica_uuid'};
- my $content = YAML::Syck::Dump($hash_changeset);
my $cas_key = $self->_write_to_cas(
- content_ref => \$content,
- cas_dir => $self->changeset_cas_dir
+ data => $hash_changeset,
+ cas_dir => $self->changeset_cas_dir
);
- # XXX TODO we should only actually be encoding the sha1 of content once
- # and then converting. this is wasteful
-
- my $packed_cas_key = sha1($content);
+ my $packed_cas_key = pack( 'H40', $cas_key );
my $changeset_index_line = pack( 'Na16Na20',
- $changeset->sequence_no,
+ $seqno,
Data::UUID->new->from_string( $changeset->original_source_uuid ),
$changeset->original_sequence_no,
$packed_cas_key );
@@ -324,18 +329,25 @@
my $first_rev = ( $args{'after'} + 1 ) || 1;
my $latest = $self->latest_sequence_no();
my $chgidx = $self->_read_file( $self->changeset_index );
-
+
$self->log("Traversing changesets between $first_rev and $latest");
for my $rev ( $first_rev .. $latest ) {
- my $index_record = substr( $chgidx, ( $rev - 1 ) * CHG_RECORD_SIZE, CHG_RECORD_SIZE );
- my ( $seq, $orig_uuid, $orig_seq, $key ) = unpack( 'Na16NH40', $index_record);
-
+ my $index_record = substr( $chgidx, ( $rev - 1 ) * CHG_RECORD_SIZE,
+ CHG_RECORD_SIZE );
+ my ( $seq, $orig_uuid, $orig_seq, $key )
+ = unpack( 'Na16NH40', $index_record );
$orig_uuid = Data::UUID->new->to_string($orig_uuid);
- $self->log("REV: $rev - seq $seq - originally $orig_seq from ".substr( $orig_uuid,0,6) ." data key $key");
-
+ $self->log( "REV: $rev - seq $seq - originally $orig_seq from "
+ . substr( $orig_uuid, 0, 6 )
+ . " data key $key" );
+
# XXX: deserialize the changeset content from the cas with $key
- my $casfile = file( $self->changeset_cas_dir, substr( $key, 0, 1 ), substr( $key, 1, 1 ), $key);
+ my $casfile = file(
+ $self->changeset_cas_dir,
+ substr( $key, 0, 1 ),
+ substr( $key, 1, 1 ), $key
+ );
my $changeset = $self->_deserialize_changeset(
content => $self->_read_file($casfile),
@@ -347,7 +359,6 @@
}
}
-
sub _deserialize_changeset {
my $self = shift;
my %args = validate(
@@ -358,7 +369,7 @@
sequence_no => 1
}
);
- my $content_struct = YAML::Syck::Load( $args{content} );
+ my $content_struct = from_json( $args{content} , { utf8 => 1 });
my $changeset = Prophet::ChangeSet->new_from_hashref($content_struct);
$changeset->source_uuid( $self->uuid );
@@ -371,20 +382,26 @@
sub _get_changeset_index_handle {
my $self = shift;
- open( my $cs_file, ">>" . file( $self->fs_root, $self->changeset_index ) ) || die $!;
+ open( my $cs_file, ">>" . file( $self->fs_root, $self->changeset_index ) )
+ || die $!;
return $cs_file;
}
-
sub _write_to_cas {
- my $self = shift;
- my %args = validate( @_, { content_ref => 1, cas_dir => 1 } );
- my $content = ${ $args{'content_ref'} };
- my $fingerprint = sha1_hex($content);
- my $content_filename = file( $args{'cas_dir'},
+ my $self = shift;
+ my %args = validate( @_,
+ { content_ref => 0, cas_dir => 1, data => 0 } );
+ my $content;
+ if ( $args{'content_ref'} ) {
+ $content = ${ $args{'content_ref'} };
+ } elsif ( $args{'data'} ) {
+ $content = to_json($args{'data'}, { canonical => 1, pretty=> 0, utf8=>1} );
+ }
+ my $fingerprint = sha1_hex($content);
+ my $content_filename = file(
+ $args{'cas_dir'},
substr( $fingerprint, 0, 1 ),
- substr( $fingerprint, 1, 1 ),
- $fingerprint
+ substr( $fingerprint, 1, 1 ), $fingerprint
);
$self->_write_file( path => $content_filename, content => $content );
@@ -395,14 +412,15 @@
my $self = shift;
my %args = validate( @_, { path => 1, content => 1 } );
- my $file = file($self->fs_root => $args{'path'});
+ my $file = file( $self->fs_root => $args{'path'} );
my $parent = $file->parent;
- unless (-d $parent) {
- $parent->mkpath || die "Failed to create directory ".$file->parent;;
- }
+ unless ( -d $parent ) {
+ $parent->mkpath || die "Failed to create directory " . $file->parent;
+ }
my $fh = $file->openw;
- print $fh scalar($args{'content'}); # can't do "||" as we die if we print 0" || die "Could not write to " . $args{'path'} . " " . $!;
+ print $fh scalar( $args{'content'} )
+ ; # can't do "||" as we die if we print 0" || die "Could not write to " . $args{'path'} . " " . $!;
close $fh || die $!;
}
@@ -416,61 +434,63 @@
my $self = shift;
my ($file) = validate_pos( @_, 1 );
- if ($self->fs_root) {
- my $path = file($self->fs_root, $file);
- if (-f $path ) { return 1}
- elsif (-d $path ) { return 2}
- else { return 0 }
+ if ( $self->fs_root ) {
+ my $path = file( $self->fs_root, $file );
+ if ( -f $path ) { return 1 }
+ elsif ( -d $path ) { return 2 }
+ else { return 0 }
} else {
- return $self->_read_file($file) ? 1 : 0;
+ return $self->_read_file($file) ? 1 : 0;
}
}
sub _read_file {
my $self = shift;
my ($file) = validate_pos( @_, 1 );
- if ($self->fs_root ) {
- if ( $self->_file_exists($file)) {
- return scalar file($self->fs_root => $file)->slurp;
+ if ( $self->fs_root ) {
+ if ( $self->_file_exists($file) ) {
+ return scalar file( $self->fs_root => $file )->slurp;
} else {
return undef;
}
- } else { # http replica
- return LWP::Simple::get( $self->url . "/" . $file );
-}
+ } else { # http replica
+ return LWP::Simple::get( $self->url . "/" . $file );
+ }
}
-
sub begin_edit {
my $self = shift;
- $self->current_edit( Prophet::ChangeSet->new({ source_uuid => $self->uuid }) );
+ $self->current_edit(
+ Prophet::ChangeSet->new( { source_uuid => $self->uuid } ) );
}
-
sub _set_original_source_metadata_for_current_edit {
my $self = shift;
my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
- $self->current_edit->original_source_uuid( $changeset->original_source_uuid );
- $self->current_edit->original_sequence_no( $changeset->original_sequence_no );
+ $self->current_edit->original_source_uuid(
+ $changeset->original_source_uuid );
+ $self->current_edit->original_sequence_no(
+ $changeset->original_sequence_no );
}
-
sub commit_edit {
- my $self = shift;
+ my $self = shift;
my $sequence = $self->_increment_sequence_no;
- $self->current_edit->original_sequence_no($sequence) unless ($self->current_edit->original_sequence_no);
- $self->current_edit->original_source_uuid($self->uuid) unless ($self->current_edit->original_source_uuid);
+ $self->current_edit->original_sequence_no($sequence)
+ unless ( $self->current_edit->original_sequence_no );
+ $self->current_edit->original_source_uuid( $self->uuid )
+ unless ( $self->current_edit->original_source_uuid );
$self->current_edit->sequence_no($sequence);
- $self->_write_changeset_to_index($self->current_edit);
+ $self->_write_changeset_to_index( $self->current_edit );
}
sub _write_changeset_to_index {
- my $self = shift;
+ my $self = shift;
my $changeset = shift;
- my $handle = $self->_get_changeset_index_handle;
- $self->_write_changeset( index_handle => $handle, changeset => $changeset);
- close($handle) || die "Failed to close changeset handle: ".$handle;
+ my $handle = $self->_get_changeset_index_handle;
+ $self->_write_changeset( index_handle => $handle, changeset => $changeset );
+ close($handle) || die "Failed to close changeset handle: " . $handle;
$self->current_edit(undef);
}
@@ -482,9 +502,6 @@
$self->current_edit->is_resolution( $changeset->is_resolution );
}
-
-
-
sub create_record {
my $self = shift;
my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
@@ -492,27 +509,28 @@
my $inside_edit = $self->current_edit ? 1 : 0;
$self->begin_edit() unless ($inside_edit);
-
$self->_write_serialized_record(
type => $args{'type'},
uuid => $args{'uuid'},
props => $args{'props'}
);
- my $change = Prophet::Change->new({
- record_type => $args{'type'},
- record_uuid => $args{'uuid'},
- change_type => 'add_file' });
-
+ my $change = Prophet::Change->new(
+ { record_type => $args{'type'},
+ record_uuid => $args{'uuid'},
+ change_type => 'add_file'
+ }
+ );
foreach my $name ( keys %{ $args{props} } ) {
$change->add_prop_change(
name => $name,
old => undef,
- new => $args{props}->{$name});
+ new => $args{props}->{$name}
+ );
}
- $self->current_edit->add_change(change => $change );
+ $self->current_edit->add_change( change => $change );
$self->commit_edit unless ($inside_edit);
}
@@ -526,26 +544,30 @@
# XXX TODO Write out an entry to the record's index file marking it as a special deleted uuid? - this has lots of ramifications for list, load, exists, create
$self->_delete_record_index( uuid => $args{uuid}, type => $args{type} );
-
- my $change = Prophet::Change->new({
- record_type => $args{'type'},
- record_uuid => $args{'uuid'},
- change_type => 'delete'} );
- $self->current_edit->add_change(change => $change );
- $self->commit_edit() unless ($inside_edit);
+ my $change = Prophet::Change->new(
+ { record_type => $args{'type'},
+ record_uuid => $args{'uuid'},
+ change_type => 'delete'
+ }
+ );
+ $self->current_edit->add_change( change => $change );
+
+ $self->commit_edit() unless ($inside_edit);
return 1;
}
sub set_record_props {
- my $self = shift;
- my %args = validate( @_, { uuid => 1, props => 1, type => 1 } );
+ 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 $old_props = $self->get_record_props( uuid => $args{'uuid'},
- type => $args{'type'} );
+ my $old_props = $self->get_record_props(
+ uuid => $args{'uuid'},
+ type => $args{'type'}
+ );
my %new_props = %$old_props;
foreach my $prop ( %{ $args{props} } ) {
if ( !defined $args{props}->{$prop} ) {
@@ -560,21 +582,23 @@
props => \%new_props
);
- my $change = Prophet::Change->new({
- record_type => $args{'type'},
- record_uuid => $args{'uuid'},
- change_type => 'update_file'} );
-
+ my $change = Prophet::Change->new(
+ { record_type => $args{'type'},
+ record_uuid => $args{'uuid'},
+ change_type => 'update_file'
+ }
+ );
+
foreach my $name ( keys %{ $args{props} } ) {
$change->add_prop_change(
name => $name,
old => $old_props->{$name},
- new => $args{props}->{$name});
+ new => $args{props}->{$name}
+ );
}
- $self->current_edit->add_change(change => $change );
-
+ $self->current_edit->add_change( change => $change );
- $self->commit_edit() unless ($inside_edit);
+ $self->commit_edit() unless ($inside_edit);
}
@@ -615,9 +639,10 @@
sub list_types {
my $self = shift;
+
return [ map { my @path = split( qr'/', $_ ); pop @path }
- File::Find::Rule->mindepth(1)->maxdepth(1)->in( dir( $self->fs_root, $self->record_dir ) )
- ];
+ File::Find::Rule->mindepth(1)->maxdepth(1)
+ ->in( dir( $self->fs_root, $self->record_dir ) ) ];
}
@@ -627,5 +652,4 @@
return $self->_file_exists( $self->_record_type_root( $args{'type'} ) );
}
-
1;
Modified: Prophet/trunk/lib/Prophet/Replica/SVN.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/SVN.pm (original)
+++ Prophet/trunk/lib/Prophet/Replica/SVN.pm Tue Apr 22 20:34:02 2008
@@ -7,7 +7,6 @@
use UNIVERSAL::require;
-use Data::UUID;
Modified: Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm (original)
+++ Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm Tue Apr 22 20:34:02 2008
@@ -3,6 +3,7 @@
package Prophet::Resolver::AlwaysTarget;
use base qw/Prophet::Resolver/;
+use Data::Dumper;
sub run {
my $self = shift;
@@ -15,7 +16,7 @@
} elsif ( $conflicting_change->file_op_conflict eq 'delete_missing_file' ) {
return $resolution;
} elsif ( $conflicting_change->file_op_conflict ) {
- die YAML::Syck::Dump( $conflict, $conflicting_change );
+ die Dumper($conflict,$conflicting_change);
}
for my $prop_change ( @{ $conflicting_change->prop_conflicts } ) {
Modified: Prophet/trunk/lib/Prophet/Resolver/Failed.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/Failed.pm (original)
+++ Prophet/trunk/lib/Prophet/Resolver/Failed.pm Tue Apr 22 20:34:02 2008
@@ -4,14 +4,17 @@
package Prophet::Resolver::Failed;
use base qw/Prophet::Resolver/;
+use Data::Dumper;
+
sub run {
my $self = shift;
my $conflicting_change = shift;
my $conflict = shift;
- use YAML::Syck; die
- " The resolution was not resolved. Sorry dude. (Once Prophet works, you should NEVER see this message)".
- YAML::Syck::Dump($conflicting_change, $conflict);
+ die
+ " The resolution was not resolved. Sorry dude. (Once Prophet works, you should NEVER see this message)"
+ . Dumper($conflict, $conflicting_change);
+
}
1;
Modified: Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm (original)
+++ Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm Tue Apr 22 20:34:02 2008
@@ -4,7 +4,8 @@
package Prophet::Resolver::FromResolutionDB;
use base qw/Prophet::Resolver/;
use Prophet::Change;
-use Digest::MD5 'md5_hex';
+use JSON;
+use Digest::SHA1 'sha1_hex';
sub run {
my $self = shift;
@@ -14,7 +15,8 @@
my $res = Prophet::Collection->new(
handle => $resdb,
- type => '_prophet_resolution-' . $conflicting_change->cas_key
+ # XXX TODO PULL THIS TYPE FROM A CONSTANT
+ type => '_prophet_resolution-' . $conflicting_change->fingerprint
);
$res->matching( sub {1} );
return unless @{ $res->as_array_ref };
@@ -25,7 +27,7 @@
my %answer_count;
for my $answer ( @{ $res->as_array_ref } ) {
- my $key = md5_hex( YAML::Syck::Dump( $answer->get_props ) );
+ my $key = sha1_hex( to_json($answer->get_props, {utf8 => 1, pretty => 1, canonical => 1}));
$answer_map{$key} ||= $answer;
$answer_count{$key}++;
}
Modified: Prophet/trunk/lib/Prophet/Test.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Test.pm (original)
+++ Prophet/trunk/lib/Prophet/Test.pm Tue Apr 22 20:34:02 2008
@@ -16,9 +16,6 @@
use Prophet::CLI;
-use constant DEFAULT_REPLICA_TYPE => 'svn';
-
-
our $REPO_BASE = File::Temp::tempdir();
Test::More->import;
diag( "Replicas can be found in" . $REPO_BASE );
@@ -207,7 +204,7 @@
my $path = repo_path_for($username);
$path =~ s{^|\\}{/}g if IS_WIN32;
- return ($ENV{'PROPHET_REPLICA_TYPE'}|| __PACKAGE__->DEFAULT_REPLICA_TYPE) . ':file://' . $path;
+ return ($ENV{'PROPHET_REPLICA_TYPE'}|| Prophet::App->DEFAULT_REPLICA_TYPE) . ':file://' . $path;
}
sub replica_uuid {
Modified: Prophet/trunk/t/canonicalize.t
==============================================================================
--- Prophet/trunk/t/canonicalize.t (original)
+++ Prophet/trunk/t/canonicalize.t Tue Apr 22 20:34:02 2008
@@ -3,12 +3,15 @@
use Test::More tests => 7;
use File::Temp qw'tempdir';
use lib 't/lib';
-my $SCHEME = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
-use_ok('Prophet::Replica');
-my $REPO = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
-my $cxn = Prophet::Replica->new( {url => "$SCHEME:file://$REPO"} );
-isa_ok( $cxn, 'Prophet::Replica', "Got the cxn" );
+
+
+use_ok('Prophet::CLI');
+$ENV{'PROPHET_REPO'} = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
+my $cli = Prophet::CLI->new();
+my $cxn = $cli->app_handle->handle;
+isa_ok($cxn, 'Prophet::Replica');
+
use_ok('TestApp::Bug');
my $record = TestApp::Bug->new( handle => $cxn );
Modified: Prophet/trunk/t/create.t
==============================================================================
--- Prophet/trunk/t/create.t (original)
+++ Prophet/trunk/t/create.t Tue Apr 22 20:34:02 2008
@@ -4,11 +4,11 @@
use File::Temp qw'tempdir';
-my $SCHEME = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
-use_ok('Prophet::Replica');
-my $REPO = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
-diag($REPO);
-my $cxn = Prophet::Replica->new({ url => "$SCHEME:file://$REPO" });
+use_ok('Prophet::CLI');
+$ENV{'PROPHET_REPO'} = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
+my $cli = Prophet::CLI->new();
+my $cxn = $cli->app_handle->handle;
+
isa_ok( $cxn, 'Prophet::Replica', "Got the cxn" );
use_ok('Prophet::Record');
my $record = Prophet::Record->new( handle => $cxn, type => 'Person' );
Modified: Prophet/trunk/t/validate.t
==============================================================================
--- Prophet/trunk/t/validate.t (original)
+++ Prophet/trunk/t/validate.t Tue Apr 22 20:34:02 2008
@@ -6,11 +6,11 @@
use lib 't/lib';
use Test::Exception;
-my $SCHEME = $ENV{'PROPHET_REPLICA_TYPE'} || 'svn';
-use_ok('Prophet::Replica');
-my $REPO = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
-my $cxn = Prophet::Replica->new( { url => "$SCHEME:file://$REPO" });
+use_ok('Prophet::CLI');
+$ENV{'PROPHET_REPO'} = tempdir( CLEANUP => 0 ) . '/repo-' . $$;
+my $cli = Prophet::CLI->new();
+my $cxn = $cli->app_handle->handle;
isa_ok( $cxn, 'Prophet::Replica', "Got the cxn" );
use_ok('TestApp::Bug');
More information about the Bps-public-commit
mailing list