[Bps-public-commit] r13802 - in Prophet/trunk: . lib/Prophet lib/Prophet/Meta lib/Prophet/Replica lib/Prophet/Replica/SVN lib/Prophet/Resolver lib/Prophet/Test t

jesse at bestpractical.com jesse at bestpractical.com
Fri Jul 4 08:50:09 EDT 2008


Author: jesse
Date: Fri Jul  4 08:50:09 2008
New Revision: 13802

Added:
   Prophet/trunk/lib/Prophet/Meta/
   Prophet/trunk/lib/Prophet/Meta/Types.pm
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/ChangeSet.pm
   Prophet/trunk/lib/Prophet/Collection.pm
   Prophet/trunk/lib/Prophet/Config.pm
   Prophet/trunk/lib/Prophet/Conflict.pm
   Prophet/trunk/lib/Prophet/ConflictingChange.pm
   Prophet/trunk/lib/Prophet/ConflictingPropChange.pm
   Prophet/trunk/lib/Prophet/ForeignReplica.pm
   Prophet/trunk/lib/Prophet/PropChange.pm
   Prophet/trunk/lib/Prophet/Record.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/Replica/SVN/ReplayEditor.pm
   Prophet/trunk/lib/Prophet/Replica/SVN/Util.pm
   Prophet/trunk/lib/Prophet/ReplicaExporter.pm
   Prophet/trunk/lib/Prophet/Resolver.pm
   Prophet/trunk/lib/Prophet/Resolver/AlwaysSource.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/Resolver/IdenticalChanges.pm
   Prophet/trunk/lib/Prophet/Resolver/Prompt.pm
   Prophet/trunk/lib/Prophet/Server/REST.pm
   Prophet/trunk/lib/Prophet/Test.pm
   Prophet/trunk/lib/Prophet/Test/Arena.pm
   Prophet/trunk/lib/Prophet/Test/Participant.pm
   Prophet/trunk/t/create.t
   Prophet/trunk/t/export.t
   Prophet/trunk/t/generalized_sync_n_merge.t
   Prophet/trunk/t/real-conflicting-merge.t
   Prophet/trunk/t/simple-conflicting-merge.t
   Prophet/trunk/t/simple-push.t

Log:

* Prophet is now Moose-enabled. (Also, moose-dependent)

r31160 at 31b (orig r12421):  sartak | 2008-05-17 08:47:12 +0200
 - Create branch moose
 r31163 at 31b (orig r12424):  sartak | 2008-05-17 09:57:02 +0200
  r56125 at onn:  sartak | 2008-05-17 03:13:35 -0400
  Moosify PropChange
 
 r31164 at 31b (orig r12425):  sartak | 2008-05-17 09:57:06 +0200
  r56126 at onn:  sartak | 2008-05-17 03:22:53 -0400
  PropChange->new_value can be undef
 
 r31165 at 31b (orig r12426):  sartak | 2008-05-17 09:57:12 +0200
  r56129 at onn:  sartak | 2008-05-17 03:56:37 -0400
  Include uuid in the delete error message (so it shows up in the test)
 
 r31166 at 31b (orig r12427):  sartak | 2008-05-17 09:57:18 +0200
  r56130 at onn:  sartak | 2008-05-17 03:56:52 -0400
  Dep on MooseX::AttributeHelpers
 
 r31167 at 31b (orig r12428):  sartak | 2008-05-17 10:10:50 +0200
  r56135 at onn:  sartak | 2008-05-17 04:10:46 -0400
  Don't serialize is_empty, it's available by looking at @changes anyway
 
 r31168 at 31b (orig r12429):  sartak | 2008-05-17 10:31:39 +0200
  r56137 at onn:  sartak | 2008-05-17 04:30:18 -0400
  Check whether the changeset is empty rather than scalar @changes (which fails auto_deref)
 
 r31169 at 31b (orig r12430):  sartak | 2008-05-17 11:02:28 +0200
  r56139 at onn:  sartak | 2008-05-17 04:44:54 -0400
  Begin moosifying ChangeSet.. the changes attribute is the snag
 
 r31170 at 31b (orig r12431):  sartak | 2008-05-17 11:02:33 +0200
  r56148 at onn:  sartak | 2008-05-17 05:02:23 -0400
  Turn changes into a very basic attribute, now to see what enhancement breaks it
 
 r31180 at 31b (orig r12441):  sartak | 2008-05-17 11:31:18 +0200
  r56157 at onn:  sartak | 2008-05-17 05:31:05 -0400
  use MooseX::AttributeHelpers and auto_deref for ChangeSet->changes
 
 r31200 at 31b (orig r12458):  sartak | 2008-05-17 11:48:41 +0200
  r56168 at onn:  sartak | 2008-05-17 05:48:35 -0400
  Moosify Prophet::Change
 
 r31201 at 31b (orig r12459):  sartak | 2008-05-17 11:49:17 +0200
  r56186 at onn:  sartak | 2008-05-17 05:49:06 -0400
  Add type constraints to ChangeSet's attributes
 
 r31202 at 31b (orig r12460):  sartak | 2008-05-17 11:53:19 +0200
  r56188 at onn:  sartak | 2008-05-17 05:52:37 -0400
  Change ChangeSet->is_empty to ChangeSet->has_changes so we can use MX::AH's provided method
 
 r31203 at 31b (orig r12461):  sartak | 2008-05-17 12:13:45 +0200
  r56190 at onn:  sartak | 2008-05-17 06:13:04 -0400
  Moosify PropheT::Collection
 
 r31204 at 31b (orig r12462):  sartak | 2008-05-17 12:13:51 +0200
  r56191 at onn:  sartak | 2008-05-17 06:13:34 -0400
  Make use of Collection->items being a smarter attribute
 
 r31205 at 31b (orig r12463):  sartak | 2008-05-17 12:15:09 +0200
  r56194 at onn:  sartak | 2008-05-17 06:15:06 -0400
  empty is deprecated because it's backwards, so use count
 
 r31206 at 31b (orig r12464):  sartak | 2008-05-17 12:26:13 +0200
  r56196 at onn:  sartak | 2008-05-17 06:26:09 -0400
  Moosify Prophet::Conflict
 
 r31207 at 31b (orig r12465):  sartak | 2008-05-17 12:31:27 +0200
  r56198 at onn:  sartak | 2008-05-17 06:31:23 -0400
  Add Prophet::Meta::Types and the ChangeType type
 
 r31208 at 31b (orig r12466):  sartak | 2008-05-17 12:54:02 +0200
  r56200 at onn:  sartak | 2008-05-17 06:53:38 -0400
  Add a FileOpConflict, avoid related undef warnings, and don't pass in an undef file_op_conflict into ConflictingChange's constructor
 
 r31209 at 31b (orig r12467):  sartak | 2008-05-17 12:54:08 +0200
  r56201 at onn:  sartak | 2008-05-17 06:53:48 -0400
  Moosifify ConflictingChange part 1
 
 r31210 at 31b (orig r12468):  sartak | 2008-05-17 13:03:22 +0200
  r56204 at onn:  sartak | 2008-05-17 07:03:11 -0400
  Moosify prop_conflicts
 
 r31211 at 31b (orig r12469):  sartak | 2008-05-17 13:10:56 +0200
  r56206 at onn:  sartak | 2008-05-17 07:10:33 -0400
  Moosify ConflictingPropChange
 
 r31212 at 31b (orig r12470):  sartak | 2008-05-17 13:16:15 +0200
  r56208 at onn:  sartak | 2008-05-17 07:11:43 -0400
  Type constraints for the values on ConflictingPropChange (to match PropChange's)
 
 r31213 at 31b (orig r12471):  sartak | 2008-05-17 13:16:28 +0200
  r56209 at onn:  sartak | 2008-05-17 07:16:11 -0400
  Moosify Prophet::Resolver. Er.
 
 r31214 at 31b (orig r12472):  sartak | 2008-05-17 13:24:00 +0200
  r56212 at onn:  sartak | 2008-05-17 07:23:53 -0400
  Moosify the Prophet::Resolver subclasses
 
 r31215 at 31b (orig r12473):  sartak | 2008-05-17 13:41:31 +0200
  r56214 at onn:  sartak | 2008-05-17 07:41:17 -0400
  Pass a Path::Class::Dir object into ReplicaExporter->new
 
 r31216 at 31b (orig r12474):  sartak | 2008-05-17 13:41:35 +0200
  r56215 at onn:  sartak | 2008-05-17 07:41:26 -0400
  Moosify ReplicaExporter
 
 r31217 at 31b (orig r12475):  sartak | 2008-05-17 13:43:56 +0200
  r56218 at onn:  sartak | 2008-05-17 07:43:52 -0400
  Moosify Prophet::Server::REST
 
 r31218 at 31b (orig r12476):  sartak | 2008-05-17 14:07:20 +0200
  r56220 at onn:  sartak | 2008-05-17 08:04:35 -0400
  Unmoosify Prophet::Server::REST. There's some diamond inheritance going on here and that's tricky enough as it is
 
 r31219 at 31b (orig r12477):  sartak | 2008-05-17 14:07:24 +0200
  r56221 at onn:  sartak | 2008-05-17 08:07:08 -0400
  Moosify Prophet::Record, new dependency on MooseX::ClassAttribute (which fills the same niche as Class::Data::Inheritable)
 
 r31220 at 31b (orig r12478):  sartak | 2008-05-17 14:10:53 +0200
  r56224 at onn:  sartak | 2008-05-17 08:08:52 -0400
  Avoid infinite recursion in the absence of a type. I think.
 
 r31221 at 31b (orig r12479):  sartak | 2008-05-17 14:32:42 +0200
  r56226 at onn:  sartak | 2008-05-17 08:32:31 -0400
  Moosify Prophet::Config
 
 r31222 at 31b (orig r12480):  sartak | 2008-05-17 14:42:26 +0200
  r56228 at onn:  sartak | 2008-05-17 08:42:19 -0400
  Basic moosification of Prophet::Replica and its subclasses
 
 r31225 at 31b (orig r12483):  sartak | 2008-05-17 15:02:12 +0200
  r56230 at onn:  sartak | 2008-05-17 09:02:08 -0400
  Make the replica rebless logic more moosey
 
 r31227 at 31b (orig r12485):  sartak | 2008-05-17 15:04:07 +0200
  r56234 at onn:  sartak | 2008-05-17 09:04:04 -0400
  Remove pointless overriding of new
 
 r31228 at 31b (orig r12486):  sartak | 2008-05-17 15:09:46 +0200
  r56237 at onn:  sartak | 2008-05-17 09:09:43 -0400
  Moosify Prophet::ForeignReplica
 
 r31238 at 31b (orig r12496):  sartak | 2008-05-17 15:18:37 +0200
  r56239 at onn:  sartak | 2008-05-17 09:18:32 -0400
  Add smarts to Conflict->conflicting_changes
 
 r31240 at 31b (orig r12498):  sartak | 2008-05-17 15:25:05 +0200
  r56252 at onn:  sartak | 2008-05-17 09:25:01 -0400
  Run find_or_create_luid right after uuid is set, always
 
 r31241 at 31b (orig r12499):  sartak | 2008-05-17 15:35:17 +0200
  r56254 at onn:  sartak | 2008-05-17 09:30:55 -0400
  Moosify Replica::SVN::Util
 
 r31242 at 31b (orig r12500):  sartak | 2008-05-17 15:35:20 +0200
  r56255 at onn:  sartak | 2008-05-17 09:31:21 -0400
  Remove dependency on Class::Data::Inheritable
 
 r31694 at 31b (orig r12504):  sartak | 2008-05-18 12:06:54 +0200
  r56279 at onn:  sartak | 2008-05-18 06:06:48 -0400
  Moosify Prophet::Test::Arena
 
 r31695 at 31b (orig r12505):  sartak | 2008-05-18 12:12:39 +0200
  r56284 at onn:  sartak | 2008-05-18 06:12:33 -0400
  Moosify Prophet::Test::Participant
 
 r31698 at 31b (orig r12507):  jesse | 2008-05-18 16:53:39 +0200
  r31691 at 31b:  jesse | 2008-05-18 20:44:35 +0800
  * Started to moose the CLI
 
 r31699 at 31b (orig r12508):  jesse | 2008-05-18 16:53:55 +0200
  r31692 at 31b:  jesse | 2008-05-18 21:05:45 +0800
  * Mooseified Prophet::CLI
  * Extracted 'record related' CLI command stuff into a moose role
       Wants review
 
 r31700 at 31b (orig r12509):  jesse | 2008-05-18 16:54:15 +0200
  r31693 at 31b:  jesse | 2008-05-18 22:09:38 +0800
   Kill some extra mooses
 
 r31701 at 31b (orig r12510):  sartak | 2008-05-18 17:13:17 +0200
  r56314 at onn:  sartak | 2008-05-18 11:13:11 -0400
  Use 'handles' for deleting to the cli for args and app_handle
 
 r31710 at 31b (orig r12519):  sartak | 2008-05-18 17:19:34 +0200
  r56316 at onn:  sartak | 2008-05-18 11:19:30 -0400
  Turn args into a Moose attribute
 
 r31711 at 31b (orig r12520):  sartak | 2008-05-18 17:32:11 +0200
  r56326 at onn:  sartak | 2008-05-18 11:32:06 -0400
  AttributeHelpers-ify the args
 
 r31735 at 31b (orig r12528):  sartak | 2008-05-19 15:27:04 +0200
  r56340 at onn:  sartak | 2008-05-19 09:26:44 -0400
  Move some logic out of BUILD and into the attributes
 
 r31736 at 31b (orig r12529):  sartak | 2008-05-19 15:27:20 +0200
  r56341 at onn:  sartak | 2008-05-19 09:26:57 -0400
  Ignore cover_db/
 
 r31737 at 31b (orig r12530):  sartak | 2008-05-19 15:47:21 +0200
  r56350 at onn:  sartak | 2008-05-19 09:42:27 -0400
  Give some kind of output in the merge command
 
 r31738 at 31b (orig r12531):  sartak | 2008-05-19 15:47:26 +0200
  r56351 at onn:  sartak | 2008-05-19 09:47:15 -0400
  Avoid invoking bin/prophet in real-conflicting-merge.t
 
 r31745 at 31b (orig r12533):  sartak | 2008-05-19 16:56:53 +0200
  r56356 at onn:  sartak | 2008-05-19 10:56:42 -0400
  make_immutable and unimport Moose from the CLI classes, and SVN::Util
 
 r39199 at 31b (orig r13798):  jesse | 2008-07-04 12:45:15 +0200
 
 r39201 at 31b (orig r13800):  jesse | 2008-07-04 12:47:16 +0200
  r39154 at 31b:  jesse | 2008-07-04 12:37:38 +0200
  starting to work to pass tests for sd
 


Modified: Prophet/trunk/Makefile.PL
==============================================================================
--- Prophet/trunk/Makefile.PL	(original)
+++ Prophet/trunk/Makefile.PL	Fri Jul  4 08:50:09 2008
@@ -3,7 +3,7 @@
 use inc::Module::Install;
 name('Prophet');
 author('clkao and jesse');
-license('DeathandRepudiation');
+license('Perl');
 
 requires('Params::Validate');
 requires('List::MoreUtils');
@@ -11,10 +11,8 @@
 requires('IPC::Run3');
 requires('Data::UUID');
 requires('Path::Class');
-requires('YAML::Syck');
 requires('Test::Exception');
 requires('UNIVERSAL::require');
-requires('Class::Data::Inheritable');
 requires('Term::ReadKey');
 requires('Digest::SHA1');  # Core in 5.10
 requires('LWP::Simple'); # Part of lib-www-perl
@@ -24,30 +22,37 @@
 requires('File::Find::Rule');
 requires('Proc::InvokeEditor');
 requires('Scalar::Defer');
+requires('Moose'); # Moose::Util::TypeConstraints Moose::Role
+requires('MooseX::AttributeHelpers');
+requires('MooseX::ClassAttribute');
 
 features(
     'REST Server' => [
         -default => 1,
-        recommends('HTTP::Server::Simple'), # HTTP::Server::Simple::CGI
-        recommends('Test::HTTP::Server::Simple'),
-        recommends('Test::WWW::Mechanize' => '1.16'),
-        recommends('HTTP::Server::Simple')
+        'HTTP::Server::Simple', # HTTP::Server::Simple::CGI
+        'Test::HTTP::Server::Simple',
+        'Test::WWW::Mechanize' => '1.16',
+        'HTTP::Server::Simple'
     ],
 
 
     'Subversion replica support' => [
         -default => 0,
-        recommends( 'SVN::Core') # SVN::Repos SVN::Fs SVN::Ra SVN::Delta::Editor SVN::Client SVN::Delta
+         'SVN::Core' # SVN::Repos SVN::Fs SVN::Ra SVN::Delta::Editor SVN::Client SVN::Delta
     ],
     'Maintainer testing tools' => [
         -default   => 1,
-        recommends('Acme::MetaSyntactic'),
-        recommends('Test::POD::Coverage')
+        'Acme::MetaSyntactic',
+        'Test::POD::Coverage'
     ],
-    "Devel::Gladiator support (contact sky at crucially.net if it's not on CPAN)" => [
+    q{Devel::Gladiator support (contact sky at crucially.net if it's not on CPAN)} => [
         -default => 0,
-        recommends('Devel::Gladiator')
+        'Devel::Gladiator'
     ],
+    'Testing' => [
+        -default => 1,
+        'YAML::Syck' => 0
+    ]
 );
 
 all_from('lib/Prophet.pm');

Modified: Prophet/trunk/lib/Prophet/App.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/App.pm	(original)
+++ Prophet/trunk/lib/Prophet/App.pm	Fri Jul  4 08:50:09 2008
@@ -1,10 +1,42 @@
-use warnings;
-use strict;
-
 package Prophet::App;
-use base qw/Class::Accessor/;
+use Moose;
 use Path::Class;
-__PACKAGE__->mk_accessors(qw/_resdb_handle _config/);
+
+has handle => (
+    is      => 'rw',
+    isa     => 'Prophet::Replica',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        my $root = $ENV{'PROPHET_REPO'} || dir($ENV{'HOME'}, '.prophet');
+        my $type = $self->default_replica_type;
+        return Prophet::Replica->new({ url => $type.':file://' . $root });
+    },
+);
+
+has resdb_handle => (
+    is      => 'rw',
+    isa     => 'Prophet::Replica',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        return $self->handle->resolution_db_handle
+            if $self->handle->resolution_db_handle;
+        my $root = ($ENV{'PROPHET_REPO'} || dir($ENV{'HOME'}, '.prophet')) . "_res";
+        my $type = $self->default_replica_type;
+        return Prophet::Replica->new({ url => $type.':file://' . $root });
+    },
+);
+
+has _config => (
+    is      => 'rw',
+    isa     => 'Prophet::Config',
+    lazy    => 1,
+    default => sub {
+        Prophet::Config->require;
+        return Prophet::Config->new;
+    },
+);
 
 use constant DEFAULT_REPLICA_TYPE => 'prophet';
 
@@ -14,73 +46,27 @@
 
 =cut
 
-sub _handle {
+sub BUILD {
     my $self = shift;
-    $self->{_handle} = shift if (@_);
-    return $self->{_handle};
-}
-
-sub new {
-    my $self = shift->SUPER::new(@_);
-   
     $self->_load_replica_types();
-
-    # Initialize our handle and resolution db handle
-    $self->handle;
-    $self->resdb_handle;
-
-    return $self;
 }
 
 sub _load_replica_types {
     my $self = shift;
-        my $replica_class = ref($self)."::Replica";
-        my $except = $replica_class."::(.*)::";
-        Module::Pluggable->import( search_path => $replica_class, sub_name => 'app_replica_types', require => 0, except => qr/$except/);
-        for my $package ( $self->app_replica_types) {
-            $package->require;
+    my $replica_class = blessed($self)."::Replica";
+    my $except = $replica_class."::(.*)::";
+    Module::Pluggable->import( search_path => $replica_class, sub_name => 'app_replica_types', require => 0, except => qr/$except/);
+    for my $package ( $self->app_replica_types) {
+        $package->require;
         Prophet::Replica->register_replica_scheme(scheme => $package->scheme, class => $package) 
-        }
     }
-
-sub default_replica_type {
-    my $self = shift;
-     return $ENV{'PROPHET_REPLICA_TYPE'} || DEFAULT_REPLICA_TYPE;
-
 }
 
-=head2 handle
-
-
-=cut
-
-sub handle {
-    my $self = shift;
-    unless ( $self->_handle() ) {
-        my $root = $ENV{'PROPHET_REPO'} || dir( $ENV{'HOME'}, '.prophet' );
-        my $type = $self->default_replica_type;
-        $self->_handle( Prophet::Replica->new( { url => $type.':file://' . $root } ) );
-    }
-    return $self->_handle();
-}
-
-=head2 resdb_handle
-
-=cut
-
-sub resdb_handle {
+sub default_replica_type {
     my $self = shift;
-   
-    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 = $self->default_replica_type;
-        $self->_resdb_handle( Prophet::Replica->new( { url => $type.':file://' . $root } ) );
-    }
-    return $self->_resdb_handle();
+    return $ENV{'PROPHET_REPLICA_TYPE'} || DEFAULT_REPLICA_TYPE;
 }
 
-
 sub require_module {
     my $self = shift;
     my $class = shift;
@@ -107,11 +93,6 @@
 sub config {
     my $self = shift;
 
-    unless ($self->_config) {
-        require Prophet::Config;
-        $self->_config(Prophet::Config->new);
-    }
-
     return $self->_config if @_ == 0;
 
     my $key = shift;
@@ -121,4 +102,7 @@
     return $self->_config->set($key => $value);
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/CLI.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/CLI.pm	(original)
+++ Prophet/trunk/lib/Prophet/CLI.pm	Fri Jul  4 08:50:09 2008
@@ -1,26 +1,62 @@
-use warnings;
-use strict;
-
 package Prophet::CLI;
-use base qw/Class::Accessor/;
-__PACKAGE__->mk_accessors(
-    qw/app_class record_class type uuid app_handle primary_commands/);
+use Moose;
+use MooseX::ClassAttribute;
+
+has app_class => (
+        is => 'rw',
+        isa => 'Str', # 'Prophet::App',
+        default => 'Prophet::App'
+);
+
+has record_class => (
+        is => 'rw',
+        isa => 'Str',# 'Prophet::Record',
+        default => 'Prophet::Record'
+);
+
+has app_handle => (
+        is => 'rw',
+        isa => 'Prophet::App',
+        lazy => 1,
+        default => sub { $_[0]->app_class->require; $_[0]->app_class->new() }
+);
+
+
+
+has uuid => (   # this is the uuid set by the user from the commandline
+    is => 'rw',
+    isa => 'Str'
+    );
+
+has type => (   # this is the type set by the user from the commandline
+    is => 'rw',
+    isa => 'Str'
+    );
+
+
+has primary_commands => ( # the commadns the user executes from the commandline
+    is => 'rw',
+    isa => 'ArrayRef'
+    );
+
+has args => (
+    metaclass  => 'Collection::Hash',
+    is         => 'rw',
+    isa        => 'HashRef',
+    default    => sub { {} },
+    provides   => {
+        set    => 'set_arg',
+        get    => 'arg',
+        exists => 'has_arg',
+        delete => 'delete_arg',
+    },
+);
 
 use Prophet;
 use Prophet::Record;
 use Prophet::Collection;
 use Prophet::Replica;
 
-sub new {
-    my $class = shift;
-    my $self  = $class->SUPER::new(@_);
-    $self->record_class('Prophet::Record') unless $self->record_class;
-
-    $self->app_class || $self->app_class('Prophet::App');
-    $self->app_class->require();    # unless exists $INC{$app_class_path};
-    $self->app_handle( $self->app_class->new );
-    return $self;
-}
 
 =head2 _record_cmd
 
@@ -43,32 +79,31 @@
 
     my @commands = map { exists $CMD_MAP{$_} ? $CMD_MAP{$_} : $_ } @{ $self->primary_commands };
 
-
-
     my @possible_classes;
-    
+
     my @to_try = @commands;
 
-    while( @to_try ) {
-        my $cmd = $self->app_class . "::CLI::Command::" . join( '::', map {ucfirst lc $_} @to_try ) ;    # App::SD::CLI::Command::Ticket::Comment::List
+    while (@to_try) {
+        my $cmd = $self->app_class . "::CLI::Command::" . join( '::', map { ucfirst lc $_ } @to_try );    # App::SD::CLI::Command::Ticket::Comment::List
         push @possible_classes, $cmd;
-        shift @to_try; # throw away that top-level "Ticket" option 
+        shift @to_try;                                                                                    # throw away that top-level "Ticket" option
     }
 
-   my @extreme_fallback_commands = (     $self->app_class . "::CLI::Command::" . ucfirst(lc( $commands[-1] )),    # App::SD::CLI::Command::List
-        "Prophet::CLI::Command::" . ucfirst( lc $commands[-1] ),    # Prophet::CLI::Command::List
+    my @extreme_fallback_commands = (
+        $self->app_class . "::CLI::Command::" . ucfirst( lc( $commands[-1] ) ),                           # App::SD::CLI::Command::List
+        "Prophet::CLI::Command::" . ucfirst( lc $commands[-1] ),                                          # Prophet::CLI::Command::List
         $self->app_class . "::CLI::Command::NotFound",
         "Prophet::CLI::Command::NotFound"
     );
 
     my $class;
 
-    for my $try (@possible_classes, @extreme_fallback_commands) {
+    for my $try ( @possible_classes, @extreme_fallback_commands ) {
         $class = $self->_try_to_load_cmd_class($try);
         last if $class;
     }
 
-    die "I don't know how to parse '" . join(" ", @{$self->primary_commands}) ."'. Are you sure that's a valid command?" unless ($class);
+    die "I don't know how to parse '" . join( " ", @{ $self->primary_commands } ) . "'. Are you sure that's a valid command?" unless ($class);
 
     my $command_obj = $class->new(
         {   cli      => $self,
@@ -84,8 +119,11 @@
     my $self = shift;
     my $class = shift;
     Prophet::App->require_module($class);
+    warn "trying out " .$class;
+    no strict 'refs';
+    warn join(',', @{$class.'::ISA'});
     return $class if ( $class->isa('Prophet::CLI::Command') );
-
+    warn "aw. not it";
     return undef;
 }
 
@@ -111,7 +149,7 @@
 
         ($name,$val)= split(/=/,$name,2) if ($name =~/=/);
         $name =~ s/^--//;
-        $self->{'args'}->{$name} =  ($val || shift @ARGV);
+        $self->set_arg($name => ($val || shift @ARGV));
     }
 
 }
@@ -125,26 +163,26 @@
 sub set_type_and_uuid {
     my $self = shift;
 
-    if (my $id = delete $self->{args}->{id}) {
+    if (my $id = $self->delete_arg('id')) {
         if ($id =~ /^(\d+)$/) { 
-        $self->{args}->{luid} = $id;
+        $self->set_arg(luid => $id);
         } else { 
-        $self->{args}->{uuid} = $id;
+        $self->set_arg(uuid => $id);
 
         }
 
     }
 
-    if ( my $uuid = delete $self->{args}->{uuid} ) {
+    if ( my $uuid = $self->delete_arg('uuid')) {
         $self->uuid($uuid);
     }
-    elsif ( my $luid = delete $self->{args}->{luid} ) {
+    elsif ( my $luid = $self->delete_arg('luid')) {
         my $uuid = $self->app_handle->handle->find_uuid_by_luid(luid => $luid);
         die "I have no UUID mapped to the local id '$luid'\n" if !defined($uuid);
         $self->uuid($uuid);
     }
-    if ( $self->{args}->{type} ) {
-        $self->type( delete $self->{args}->{'type'} );
+    if ( my $type = $self->delete_arg('type') ) {
+        $self->type($type);
     } elsif($self->primary_commands->[-2]) {
         $self->type($self->primary_commands->[-2]); 
     }
@@ -158,12 +196,6 @@
 
 =cut
 
-sub args {
-    my $self = shift;
-    $self->{'args'} = shift if $_[0];
-    return $self->{'args'};
-}
-
 sub run_one_command {
     my $self = shift;
     $self->parse_args();
@@ -192,20 +224,29 @@
     return $ret;
 }
 
-package Prophet::CLI::Command;
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
-use base qw/Class::Accessor/;
+package Prophet::CLI::RecordCommand;
+use Moose::Role;
 
-__PACKAGE__->mk_accessors(qw/cli record_class command type uuid/);
+has type => (
+    is => 'rw',
+    isa => 'Str',
+    required => 0
+);
 
-# XXX type, uuid are only for record commands
+has uuid => (
+    is => 'rw',
+    isa => 'Str',
+    required => 0
+);
 
-sub fatal_error {
-    my $self   = shift;
-    my $reason = shift;
-    die $reason . "\n";
+has record_class => (
+    is => 'rw',
+    isa => 'Prophet::Record',
+);
 
-}
 
 sub _get_record {
     my $self = shift;
@@ -232,14 +273,26 @@
     return 'Prophet::Record';
 }
 
-sub args {
-    shift->cli->args(@_);
-}
+no Moose::Role;
+
+package Prophet::CLI::Command;
+use Moose;
+
+has cli => (
+    is => 'rw',
+    isa => 'Prophet::CLI',
+    weak_ref => 1,
+    handles => [qw/args set_arg arg has_arg delete_arg app_handle/],
+);
+
+sub fatal_error {
+    my $self   = shift;
+    my $reason = shift;
+    die $reason . "\n";
 
-sub app_handle {
-    shift->cli->app_handle;
 }
 
+
 =head2 edit_text [text] -> text
 
 Filters the given text through the user's C<$EDITOR> using
@@ -291,8 +344,8 @@
     my $arg  = shift || 'edit';
 
     my $edit_hash;
-    if (exists $self->args->{$arg}) {
-        delete $self->args->{$arg};
+    if ($self->has_arg($arg)) {
+        $self->delete_arg($arg);
         $edit_hash = 1;
     }
 
@@ -311,14 +364,22 @@
     return \%args;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Create;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
+with 'Prophet::CLI::RecordCommand';
+has +uuid => ( required => 0);
 
 sub run {
     my $self   = shift;
     my $record = $self->_get_record;
-
-    $record->create( props => $self->edit_args );
+    my ($val, $msg) = $record->create( props => $self->edit_args );
+    if (!$val) { 
+        warn $msg ."\n";
+    }
     if (!$record->uuid) {
         warn "Failed to create " . $record->record_type . "\n";
         return;
@@ -328,9 +389,14 @@
 
 }
 
-package Prophet::CLI::Command::Search;
-use base qw/Prophet::CLI::Command/;
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
+package Prophet::CLI::Command::Search;
+use Moose;
+extends 'Prophet::CLI::Command';
+with 'Prophet::CLI::RecordCommand';
+has +uuid => ( required => 0);
 
 sub get_collection_object {
     my $self = shift;
@@ -348,7 +414,7 @@
 sub get_search_callback {
     my $self = shift;
 
-    if ( my $regex = $self->args->{regex} ) {
+    if ( my $regex = $self->arg('regex') ) {
             return sub {
                 my $item  = shift;
                 my $props = $item->get_props;
@@ -366,7 +432,7 @@
     my $search_cb = $self->get_search_callback();
     $records->matching($search_cb);
 
-    for ( sort { $a->uuid cmp $b->uuid } @{ $records->as_array_ref } ) {
+    for ( sort { $a->uuid cmp $b->uuid } $records->items ) {
         if ( $_->summary_props ) {
             print $_->format_summary . "\n";
         } else {
@@ -376,14 +442,19 @@
     }
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Update;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
+with 'Prophet::CLI::RecordCommand';
 
 sub edit_record {
     my $self   = shift;
     my $record = shift;
 
-    if (exists $self->args->{edit}) {
+    if ($self->has_arg('edit')) {
         my $props = $record->get_props;
         return $self->edit_hash($props);
     }
@@ -410,15 +481,19 @@
     }
 }
 
-package Prophet::CLI::Command::Delete;
-use base qw/Prophet::CLI::Command/;
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
+package Prophet::CLI::Command::Delete;
+use Moose;
+extends 'Prophet::CLI::Command';
+with 'Prophet::CLI::RecordCommand';
 sub run {
     my $self = shift;
 
     my $record = $self->_get_record;
     $record->load( uuid => $self->uuid )
-        || $self->fatal_error("I couldn't find that record");
+        || $self->fatal_error("I couldn't find the record " . $self->uuid);
     if ( $record->delete ) {
         print $record->type . " " . $record->uuid . " deleted.\n";
     } else {
@@ -427,8 +502,14 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Show;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
+with 'Prophet::CLI::RecordCommand';
+
 
 sub run {
     my $self = shift;
@@ -446,21 +527,25 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Merge;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
 
 sub run {
 
     my $self = shift;
 
-    my $opts = $self->args();
-
-    my $source = Prophet::Replica->new( { url => $opts->{'from'} } );
-    my $target = Prophet::Replica->new( { url => $opts->{'to'} } );
+    my $source = Prophet::Replica->new( { url => $self->arg('from') } );
+    my $target = Prophet::Replica->new( { url => $self->arg('to') } );
 
     $target->import_resolutions_from_remote_replica( from => $source );
 
     $self->_do_merge( $source, $target );
+
+    print "Merge complete.\n";
 }
 
 sub _do_merge {
@@ -472,9 +557,7 @@
                 . "someone did a bad job cloning your database" );
     }
 
-    my $opts = $self->args();
-
-    $opts->{'prefer'} ||= 'none';
+    my $prefer = $self->arg('prefer') || 'none';
 
     if ( !$target->can_write_changesets ) {
         $self->fatal_error( $target->url
@@ -487,20 +570,25 @@
         resdb => $self->app_handle->resdb_handle,
         $ENV{'PROPHET_RESOLVER'}
         ? ( resolver_class => 'Prophet::Resolver::' . $ENV{'PROPHET_RESOLVER'} )
-        : ( (   $opts->{'prefer'} eq 'to'
+        : ( (   $prefer eq 'to'
                 ? ( resolver_class => 'Prophet::Resolver::AlwaysTarget' )
                 : ()
             ),
-            (   $opts->{'prefer'} eq 'from'
+            (   $prefer eq 'from'
                 ? ( resolver_class => 'Prophet::Resolver::AlwaysSource' )
                 : ()
             )
         )
     );
+
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Push;
-use base qw/Prophet::CLI::Command::Merge/;
+use Moose;
+extends 'Prophet::CLI::Command::Merge';
 
 sub run {
     my $self = shift;
@@ -514,17 +602,25 @@
     $self->_do_merge( $source_me, $source_other );
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Export;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
 
 sub run {
     my $self = shift;
 
-    $self->app_handle->handle->export_to( path => $self->args->{path} );
+    $self->app_handle->handle->export_to( path => $self->arg('path') );
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Pull;
-use base qw/Prophet::CLI::Command::Merge/;
+use Moose;
+extends 'Prophet::CLI::Command::Merge';
 
 sub run {
 
@@ -538,28 +634,36 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::Server;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
 
 sub run {
 
     my $self = shift;
 
-    my $opts = $self->args();
     require Prophet::Server::REST;
-    my $server = Prophet::Server::REST->new( $opts->{'port'} || 8080 );
+    my $server = Prophet::Server::REST->new( $self->arg('port') || 8080 );
     $server->prophet_handle( $self->app_handle->handle );
     $server->run;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 package Prophet::CLI::Command::NotFound;
-use base qw/Prophet::CLI::Command/;
+use Moose;
+extends 'Prophet::CLI::Command';
 
 sub run {
     my $self = shift;
-    $self->fatal_error( "The command you ran, '"
-            . ($self->command || '')
-            . "', could not be found. Perhaps running '$0 help' would help?" );
+    $self->fatal_error( "The command you ran could not be found. Perhaps running '$0 help' would help?" );
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Change.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Change.pm	(original)
+++ Prophet/trunk/lib/Prophet/Change.pm	Fri Jul  4 08:50:09 2008
@@ -1,12 +1,46 @@
-use warnings;
-use strict;
-
 package Prophet::Change;
-use base qw/Class::Accessor/;
-
+use Moose;
+use Prophet::Meta::Types;
+use MooseX::AttributeHelpers;
 use Prophet::PropChange;
 use Params::Validate;
-__PACKAGE__->mk_accessors(qw/record_type record_uuid change_type resolution_cas/);
+
+has record_type => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has record_uuid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has change_type => (
+    is  => 'rw',
+    isa => 'Prophet::Type::ChangeType',
+);
+
+has resolution_cas => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has is_resolution => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has prop_changes => (
+    metaclass  => 'Collection::Array',
+    is         => 'rw',
+    isa        => 'ArrayRef[Prophet::PropChange]',
+    auto_deref => 1,
+    default    => sub { [] },
+    provides   => {
+        count => 'has_prop_changes',
+        push  => '_add_prop_change',
+    },
+);
 
 =head1 NAME
 
@@ -28,8 +62,7 @@
 
 =head2 change_type
 
-One of create_file, add_dir, update_file, delete
-XXX TODO is it create_file or add_file?
+One of add_file, add_dir, update_file, delete
 
 =head2 prop_changes [\@PROPCHANGES]
 
@@ -37,12 +70,6 @@
 
 =cut
 
-sub prop_changes {
-    my $self = shift;
-    $self->{prop_changes} = shift if @_;
-    return @{ $self->{prop_changes} || [] };
-}
-
 =head2 new_from_conflict( $conflict )
 
 =cut
@@ -71,13 +98,12 @@
 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;
-
+    my $change = Prophet::PropChange->new(
+        name      => $args{'name'},
+        old_value => $args{'old'},
+        new_value => $args{'new'},
+    );
+    $self->_add_prop_change($change);
 }
 
 sub as_hash {
@@ -111,4 +137,7 @@
     return $self;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/ChangeSet.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ChangeSet.pm	(original)
+++ Prophet/trunk/lib/Prophet/ChangeSet.pm	Fri Jul  4 08:50:09 2008
@@ -1,8 +1,50 @@
-use warnings;
-use strict;
-
 package Prophet::ChangeSet;
-use base qw/Class::Accessor/;
+use Moose;
+use MooseX::AttributeHelpers;
+use Prophet::Change;
+use Params::Validate;
+
+has source_uuid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has sequence_no => (
+    is  => 'rw',
+    isa => 'Maybe[Int]',
+);
+
+has original_source_uuid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has original_sequence_no => (
+    is  => 'rw',
+    isa => 'Maybe[Int]',
+);
+
+has is_nullification => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has is_resolution => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has changes => (
+    metaclass  => 'Collection::Array',
+    is         => 'rw',
+    isa        => 'ArrayRef[Prophet::Change]',
+    auto_deref => 1,
+    default    => sub { [] },
+    provides   => {
+        push   => '_add_change',
+        count  => 'has_changes',
+    },
+);
 
 =head1 NAME
 
@@ -14,16 +56,10 @@
 
 =cut
 
-use Prophet::Change;
-use Params::Validate;
-
 =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.
@@ -65,7 +101,7 @@
 sub add_change {
     my $self = shift;
     my %args = validate( @_, { change => { isa => 'Prophet::Change' } } );
-    push @{ $self->{changes} }, $args{change};
+    $self->_add_change($args{change});
 
 }
 
@@ -75,27 +111,14 @@
 
 =cut
 
-sub changes {
-    my $self = shift;
-    if (@_) {
-        $self->{'changes'} = shift;
-    }
-    return @{ $self->{'changes'} || [] };
-}
-
-=head2 is_empty
+=head2 has_changes
 
-Returns true if this changeset has no changes
+Returns true if this changeset has any changes
 
 =cut
 
-sub is_empty {
-    my $self = shift;
-    return $self->changes ? 0 : 1;
-}
-
 our @SERIALIZE_PROPS
-    = (qw(sequence_no source_uuid original_source_uuid original_sequence_no is_nullification is_resolution is_empty));
+    = (qw(sequence_no source_uuid original_source_uuid original_sequence_no is_nullification is_resolution));
 
 sub as_hash {
     my $self = shift;
@@ -119,4 +142,7 @@
     return $self;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Collection.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Collection.pm	(original)
+++ Prophet/trunk/lib/Prophet/Collection.pm	Fri Jul  4 08:50:09 2008
@@ -1,15 +1,37 @@
-use warnings;
-use strict;
-
 package Prophet::Collection;
+use Moose;
+use MooseX::AttributeHelpers;
 use Params::Validate;
-use base qw/Class::Accessor/;
-
-use overload '@{}' => \&as_array_ref, fallback => 1;
+use Prophet::Record;
 
-__PACKAGE__->mk_accessors(qw'handle type');
+use overload '@{}' => sub { shift->items }, fallback => 1;
 use constant record_class => 'Prophet::Record';
-use Prophet::Record;
+
+has handle => (
+    is  => 'rw',
+    isa => 'Prophet::Replica',
+);
+
+has type => (
+    is      => 'rw',
+    isa     => 'Str',
+    default => sub {
+        my $self = shift;
+        $self->record_class->record_type;
+    },
+);
+
+has items => (
+    metaclass  => 'Collection::Array',
+    is         => 'rw',
+    isa        => 'ArrayRef[Prophet::Record]',
+    default    => sub { [] },
+    auto_deref => 1,
+    provides   => {
+        push   => 'add_item',
+        count  => 'count',
+    },
+);
 
 =head1 NAME
 
@@ -31,17 +53,6 @@
 
 =cut
 
-sub new {
-    my $class = shift;
-    my $self  = {};
-    bless $self, $class;
-    my $args = ref( $_[0] ) ? $_[0] : {@_};
-    $args->{type} ||= $class->record_class->record_type;
-    my %args = validate( @{ [%$args] }, { handle => 1, type => 1 } );
-    $self->$_( $args{$_} ) for ( keys %args );
-    return $self;
-}
-
 =head2 matching $CODEREF
 
 Find all L<Prophet::Record>s of this collection's C<type> where $CODEREF returns true.
@@ -60,12 +71,12 @@
     my $records = $self->handle->list_records( type => $self->type );
 
     # run coderef against each item;
-    # if it matches, add it to _items
+    # if it matches, add it to items
     foreach my $key (@$records) {
         my $record = $self->record_class->new( { handle => $self->handle, type => $self->type } );
         $record->load( uuid => $key );
         if ( $coderef->($record) ) {
-            push @{ $self->{_items} }, $record;
+            $self->add_item($record);
         }
 
     }
@@ -74,16 +85,7 @@
 
 }
 
-=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} || [];
-
-}
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
 1;

Modified: Prophet/trunk/lib/Prophet/Config.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Config.pm	(original)
+++ Prophet/trunk/lib/Prophet/Config.pm	Fri Jul  4 08:50:09 2008
@@ -1,10 +1,65 @@
-use warnings;
-use strict;
-
 package Prophet::Config;
-
+use Moose;
+use MooseX::AttributeHelpers;
 use Path::Class;
 
+has config => (
+    metaclass => 'Collection::Hash',
+    is        => 'rw',
+    isa       => 'HashRef',
+    lazy      => 1,
+    default   => sub { shift->load_config_files },
+    provides  => {
+        get   => 'get',
+        set   => 'set',
+    },
+);
+
+sub prophet_config_file { dir($ENV{HOME}, ".prophetrc") }
+sub app_config_file { dir($ENV{PROPHET_REPO}, "prophetrc") }
+
+my $singleton;
+around new => sub {
+    return $singleton if $singleton;
+    my $orig = shift;
+    return $singleton = $orig->(@_);
+};
+
+sub load_config_files {
+    my $self = shift;
+    my @config = @_;
+    @config = grep { -f $_ } $self->prophet_config_file, $self->app_config_file
+        if !@config;
+
+    my $config = {};
+
+    for my $file (@config) {
+        $self->load_config_file($file, $config);
+    }
+
+    return $config;
+}
+
+sub load_config_file {
+    my $self   = shift;
+    my $file   = shift;
+    my $config = shift || {};
+
+    for my $line ($file->slurp) {
+        s/\#.*//; # strip comments
+        if ($line =~ /^([^:]+):\s*(.*)$/) {
+            $config->{$1} = $2;
+        }
+    }
+}
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
+
+__END__
+
 =head1 NAME
 
 Prophet::Config
@@ -29,93 +84,31 @@
 
 =cut
 
-my $singleton;
-sub new {
-    my $class = shift;
-    return $singleton if $singleton;
-
-    my $self = $singleton = bless {}, $class;
-    $self->load_config_files;
-    return $self;
-}
-
 =head2 prophet_config_file
 
 The file which controls configuration for all Prophet apps. C<$HOME/.prophetc>.
 
-=cut
-
-sub prophet_config_file { dir($ENV{HOME}, ".prophetrc") }
-
 =head2 app_config_file
 
 The file which controls configuration for this application.
 C<$PROPHET_REPO/prophetrc>.
 
-=cut
-
-sub app_config_file { dir($ENV{PROPHET_REPO}, "prophetrc") }
-
 =head2 load_config_files [files]
 
 Loads the given config files. If no files are passed in, it will use the
 default of L</prophet_config_file> and L</app_config_file>.
 
-=cut
-
-sub load_config_files {
-    my $self = shift;
-    my @config = @_;
-    @config = ($self->prophet_config_file, $self->app_config_file) if !@config;
-
-    for my $file (@config) {
-        $self->load_config_file($file);
-    }
-}
-
 =head2 load_config_file file
 
 Loads the given config file.
 
-=cut
-
-sub load_config_file {
-    my $self = shift;
-    my $file = shift;
-
-    for my $line ($file->slurp) {
-        s/\#.*//; # strip comments
-        if ($line =~ /^([^:]+):\s*(.*)$/) {
-            $self->{$1} = $2;
-        }
-    }
-}
-
 =head2 get
 
 Gets a specific config setting.
 
-=cut
-
-sub get {
-    my $self = shift;
-    my $key  = shift;
-
-    return $self->{$key};
-}
-
 =head2 set
 
 Sets a specific config setting.
 
 =cut
 
-sub set {
-    my $self  = shift;
-    my $key   = shift;
-    my $value = shift;
-
-    return $self->{$key} = $value;
-}
-1;
-

Modified: Prophet/trunk/lib/Prophet/Conflict.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Conflict.pm	(original)
+++ Prophet/trunk/lib/Prophet/Conflict.pm	Fri Jul  4 08:50:09 2008
@@ -1,15 +1,52 @@
-
-use warnings;
-use strict;
-
 package Prophet::Conflict;
+use Moose;
+use MooseX::AttributeHelpers;
 use Params::Validate;
-use base qw/Class::Accessor/;
 use Prophet::ConflictingPropChange;
 use Prophet::ConflictingChange;
 
-__PACKAGE__->mk_accessors(
-    qw/prophet_handle resolvers changeset nullification_changeset resolution_changeset autoresolved/);
+has prophet_handle => (
+    is  => 'rw',
+    isa => 'Prophet::Replica',
+);
+
+has resolvers => (
+    is         => 'rw',
+    isa        => 'ArrayRef[CodeRef]',
+    default    => sub { [] },
+    auto_deref => 1,
+);
+
+has changeset => (
+    is  => 'rw',
+    isa => 'Prophet::ChangeSet',
+);
+
+has nullification_changeset => (
+    is  => 'rw',
+    isa => 'Prophet::ChangeSet',
+);
+
+has resolution_changeset => (
+    is  => 'rw',
+    isa => 'Prophet::ChangeSet',
+);
+
+has autoresolved => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has conflicting_changes => (
+    metaclass => 'Collection::Array',
+    is        => 'ro',
+    isa       => 'ArrayRef[Prophet::ConflictingChange]',
+    default   => sub { [] },
+    provides  => {
+        count => 'has_conflicting_changes',
+        push  => 'add_conflicting_change',
+    },
+);
 
 =head2 analyze_changeset Prophet::ChangeSet
 
@@ -25,7 +62,7 @@
     #my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
 
     $self->generate_changeset_conflicts();
-    return unless ( @{ $self->conflicting_changes } );
+    return unless $self->has_conflicting_changes;
 
     $self->generate_nullification_changeset;
 
@@ -42,14 +79,14 @@
     my @resolvers = (
         sub { Prophet::Resolver::IdenticalChanges->new->run(@_); },
         $resdb ? sub { Prophet::Resolver::FromResolutionDB->new->run(@_) } : (),
-        @{ $self->resolvers || [] },
+        $self->resolvers,
         sub { Prophet::Resolver::Failed->new->run(@_) },
     );
     my $resolutions = Prophet::ChangeSet->new( { is_resolution => 1 } );
     for my $conflicting_change ( @{ $self->conflicting_changes } ) {
         for (@resolvers) {
             if ( my $resolution = $_->( $conflicting_change, $self, $resdb ) ) {
-                $resolutions->add_change( change => $resolution ) if $resolution->prop_changes;
+                $resolutions->add_change( change => $resolution ) if $resolution->has_prop_changes;
                 last;
             }
         }
@@ -69,7 +106,7 @@
     my $self = shift;
     for my $change ( $self->changeset->changes ) {
         if ( my $change_conflicts = $self->_generate_change_conflicts($change) ) {
-            push @{ $self->conflicting_changes }, $change_conflicts;
+            $self->add_conflicting_change($change_conflicts);
         }
     }
 }
@@ -83,7 +120,7 @@
 sub _generate_change_conflicts {
     my $self = shift;
     my ($change) = validate_pos( @_, { isa => "Prophet::Change" } );
-    my $file_op_conflict = '';
+    my $file_op_conflict;
 
     my $file_exists = $self->prophet_handle->record_exists( uuid => $change->record_uuid, type => $change->record_type );
 
@@ -105,7 +142,7 @@
             record_uuid          => $change->record_uuid,
             target_record_exists => $file_exists,
             change_type        => $change->change_type,
-            file_op_conflict   => $file_op_conflict
+            $file_op_conflict ? (file_op_conflict   => $file_op_conflict) : (),
         }
     );
 
@@ -113,10 +150,10 @@
         my $current_state
             = $self->prophet_handle->get_record_props( uuid => $change->record_uuid, type => $change->record_type );
 
-        push @{ $change_conflict->prop_conflicts }, $self->_generate_prop_change_conflicts( $change, $current_state );
+        $change_conflict->add_prop_conflict($self->_generate_prop_change_conflicts( $change, $current_state ));
     }
 
-    return ( @{ $change_conflict->prop_conflicts } || $file_op_conflict ) ? $change_conflict : undef;
+    return ( $change_conflict->has_prop_conflicts || $file_op_conflict ) ? $change_conflict : undef;
 }
 
 =head2 _generate_prop_change_conflicts Prophet::Change %hash_of_current_properties
@@ -155,19 +192,6 @@
     return @prop_conflicts;
 }
 
-=head2 conflicting_changes 
-
-Returns a referencew to an array of conflicting changes for this conflict
-
-
-=cut
-
-sub conflicting_changes {
-    my $self = shift;
-    $self->{'conflicting_changes'} ||= [];
-    return $self->{'conflicting_changes'};
-}
-
 =head2 generate_nullification_changeset
 
 In order to record a changeset which might not apply cleanly to the
@@ -188,13 +212,14 @@
         my $nullify_conflict
             = Prophet::Change->new( { record_type => $conflict->record_type, record_uuid => $conflict->record_uuid } );
 
-        if ( $conflict->file_op_conflict eq "delete_missing_file" ) {
+        my $file_op_conflict = $conflict->file_op_conflict || '';
+        if ( $file_op_conflict eq "delete_missing_file" ) {
             $nullify_conflict->change_type('add_file');
-        } elsif ( $conflict->file_op_conflict eq "update_missing_file" ) {
+        } elsif ( $file_op_conflict eq "update_missing_file" ) {
             $nullify_conflict->change_type('add_file');
-        } elsif ( $conflict->file_op_conflict eq "create_existing_file" ) {
+        } elsif ( $file_op_conflict eq "create_existing_file" ) {
             $nullify_conflict->change_type('delete');
-        } elsif ( $conflict->file_op_conflict ) {
+        } elsif ( $file_op_conflict ) {
             die "We don't know how to deal with a conflict of type " . $conflict->file_op_conflict;
         } else {
             $nullify_conflict->change_type('update_file');
@@ -214,5 +239,8 @@
     $self->nullification_changeset($nullification);
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;
 

Modified: Prophet/trunk/lib/Prophet/ConflictingChange.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ConflictingChange.pm	(original)
+++ Prophet/trunk/lib/Prophet/ConflictingChange.pm	Fri Jul  4 08:50:09 2008
@@ -1,30 +1,51 @@
-use warnings;
-use strict;
-
 package Prophet::ConflictingChange;
+use Moose;
+use MooseX::AttributeHelpers;
+use Prophet::Meta::Types;
 use Prophet::ConflictingPropChange;
-
-use base qw/Class::Accessor/;
-use JSON qw'to_json';
+use JSON '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/);
-
-=head2 prop_conflicts
-
-Returns a reference to an array of Prophet::ConflictingPropChange objects
-
-=cut
-
-sub prop_conflicts {
-    my $self = shift;
-
-    $self->{'prop_conflicts'} ||= [];
-    return $self->{prop_conflicts};
-
-}
-
+has record_type => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has record_uuid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has source_record_exists => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has target_record_exists => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has change_type => (
+    is  => 'rw',
+    isa => 'Prophet::Type::ChangeType',
+);
+
+has file_op_conflict => (
+    is  => 'rw',
+    isa => 'Prophet::Type::FileOpConflict',
+);
+
+has prop_conflicts => (
+    metaclass => 'Collection::Array',
+    is        => 'rw',
+    isa       => 'ArrayRef',
+    default   => sub { [] },
+    provides  => {
+        push  => 'add_prop_conflict',
+        count => 'has_prop_conflicts',
+    },
+);
 
 sub as_hash {
     my $self = shift;
@@ -56,7 +77,9 @@
     }
 
     return  sha1_hex(to_json($struct, {utf8 => 1, canonical => 1}));
+}
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
-}
 1;

Modified: Prophet/trunk/lib/Prophet/ConflictingPropChange.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ConflictingPropChange.pm	(original)
+++ Prophet/trunk/lib/Prophet/ConflictingPropChange.pm	Fri Jul  4 08:50:09 2008
@@ -1,11 +1,25 @@
-
-use warnings;
-use strict;
-
 package Prophet::ConflictingPropChange;
-use base qw/Class::Accessor/;
+use Moose;
 
-__PACKAGE__->mk_accessors(qw/name source_old_value target_value source_new_value/);
+has name => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has source_old_value => (
+    is  => 'rw',
+    isa => 'Maybe[Str]',
+);
+
+has target_value => (
+    is  => 'rw',
+    isa => 'Maybe[Str]',
+);
+
+has source_new_value => (
+    is  => 'rw',
+    isa => 'Maybe[Str]',
+);
 
 =head1 NAME
 
@@ -39,11 +53,13 @@
     my $self = shift;
     my $hashref = {};
 
-    for  (qw(name source_old_value target_value source_new_value)) {
-         $hashref->{$_} = $self->$_()
+    for ($self->meta->get_attribute_list) {
+         $hashref->{$_} = $self->$_
     }
     return $hashref;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
 1;

Modified: Prophet/trunk/lib/Prophet/ForeignReplica.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ForeignReplica.pm	(original)
+++ Prophet/trunk/lib/Prophet/ForeignReplica.pm	Fri Jul  4 08:50:09 2008
@@ -1,9 +1,7 @@
-use warnings;
-use strict;
-
 package Prophet::ForeignReplica;
-use base qw/Prophet::Replica/;
+use Moose;
 use Params::Validate qw(:all);
+extends 'Prophet::Replica';
 
 =head1 NAME
 
@@ -13,7 +11,7 @@
 
 =cut
 
-sub setup {
+sub BUILD {
     my $self = shift;
     my $cli  = Prophet::CLI->new();
 
@@ -88,4 +86,7 @@
         'prophet-uuid' )->(@_);
 }
 
+no Moose;
+__PACKAGE__->meta->make_immutable;
+
 1;

Added: Prophet/trunk/lib/Prophet/Meta/Types.pm
==============================================================================
--- (empty file)
+++ Prophet/trunk/lib/Prophet/Meta/Types.pm	Fri Jul  4 08:50:09 2008
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+
+package Prophet::Meta::Types;
+use Moose::Util::TypeConstraints;
+
+enum 'Prophet::Type::ChangeType' => qw/add_file add_dir update_file delete/;
+enum 'Prophet::Type::FileOpConflict' => qw/delete_missing_file update_missing_file create_existing_file create_existing_dir/;
+
+1;
+
+__END__
+
+=head1 NAME
+
+Prophet::Meta::Types - extra types for Prophet
+
+=head1 TYPES
+
+=head2 Prophet::Type::ChangeType
+
+A single change type: add_file, add_dir, update_file, delete.
+
+=cut
+

Modified: Prophet/trunk/lib/Prophet/PropChange.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/PropChange.pm	(original)
+++ Prophet/trunk/lib/Prophet/PropChange.pm	Fri Jul  4 08:50:09 2008
@@ -1,10 +1,20 @@
-use warnings;
-use strict;
-
 package Prophet::PropChange;
-use base qw/Class::Accessor/;
+use Moose;
 
-__PACKAGE__->mk_accessors(qw/name old_value new_value/);
+has name => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has old_value => (
+    is  => 'rw',
+    isa => 'Maybe[Str]',
+);
+
+has new_value => (
+    is  => 'rw',
+    isa => 'Maybe[Str]',
+);
 
 =head1 NAME
 
@@ -31,4 +41,7 @@
 
 =cut
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Record.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Record.pm	(original)
+++ Prophet/trunk/lib/Prophet/Record.pm	Fri Jul  4 08:50:09 2008
@@ -1,7 +1,12 @@
-use warnings;
-use strict;
-
 package Prophet::Record;
+use Moose;
+use MooseX::ClassAttribute;
+use Params::Validate;
+use Data::UUID;
+use List::MoreUtils qw/uniq/;
+use Prophet::App; # for require_module. Kinda hacky
+
+use constant collection_class => 'Prophet::Collection';
 
 =head1 NAME
 
@@ -13,24 +18,55 @@
 
 =cut
 
-use base qw'Class::Accessor Class::Data::Inheritable';
-
-__PACKAGE__->mk_accessors(qw'handle uuid luid type');
-__PACKAGE__->mk_classdata( REFERENCES => {} );
-__PACKAGE__->mk_classdata( PROPERTIES => {} );
+has handle => (
+    is       => 'rw',
+    required => 1,
+);
+
+has type => (
+    is        => 'rw',
+    isa       => 'Str',
+    required  => 1,
+    predicate => 'has_type',
+    default   => sub {
+        my $self = shift;
+        $self->record_type;
+    },
+);
+
+has uuid => (
+    is      => 'rw',
+    isa     => 'Str',
+    trigger => sub {
+        my $self = shift;
+        $self->find_or_create_luid;
+    },
+);
+
+has luid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+class_has REFERENCES => (
+    is      => 'rw',
+    isa     => 'HashRef',
+    default => sub { {} },
+);
+
+class_has PROPERTIES => (
+    is      => 'rw',
+    isa     => 'HashRef',
+    default => sub { {} },
+);
 
 sub declared_props {
     return sort keys %{ $_[0]->PROPERTIES };
 }
 
-use Params::Validate;
-use Data::UUID;
-use List::MoreUtils qw/uniq/;
-use Prophet::App;    # for require_module. Kinda hacky
-
 my $UUIDGEN = Data::UUID->new();
 
-use constant collection_class => 'Prophet::Collection';
+sub record_type { $_[0]->has_type ? $_[0]->type : undef }
 
 =head1 METHODS
 
@@ -40,18 +76,6 @@
 
 =cut
 
-sub new {
-    my $class = shift;
-    my $self  = bless {}, $class;
-    my $args  = ref( $_[0] ) ? $_[0] : {@_};
-    $args->{type} ||= $class->record_type;
-    my %args = validate( @{ [%$args] }, { handle => 1, type => 1 } );
-    $self->$_( $args{$_} ) for keys(%args);
-    return $self;
-}
-
-sub record_type { $_[0]->type }
-
 =head2 register_reference
 
 =cut
@@ -120,12 +144,10 @@
     my $self = shift;
     my %args = validate( @_, { props => 1 } );
     my $uuid = $UUIDGEN->create_str;
-
     $self->canonicalize_props( $args{'props'} );
     $self->validate_props( $args{'props'} ) or return undef;
 
     $self->uuid($uuid);
-    $self->find_or_create_luid();
 
     $self->handle->create_record(
         props => $args{'props'},
@@ -167,7 +189,6 @@
         $self->uuid( $self->handle->find_uuid_by_luid( luid => $args{luid} ) );
     } else {
         $self->uuid( $args{uuid} );
-        $self->find_or_create_luid();
     }
 
     return $self->handle->record_exists(
@@ -343,4 +364,8 @@
     return $luid;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+no MooseX::ClassAttribute;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Replica.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica.pm	(original)
+++ Prophet/trunk/lib/Prophet/Replica.pm	Fri Jul  4 08:50:09 2008
@@ -1,16 +1,39 @@
-use warnings;
-use strict;
-
-
 package Prophet::Replica;
-use base qw/Class::Accessor/;
+use Moose;
 use Params::Validate qw(:all);
 use UNIVERSAL::require;
 use Data::UUID;
 use Path::Class;
 
-
-__PACKAGE__->mk_accessors(qw(state_handle resolution_db_handle is_resdb is_state_handle db_uuid url));
+has state_handle => (
+    is  => 'rw',
+    isa => 'Prophet::Replica',
+);
+
+has resolution_db_handle => (
+    is  => 'rw',
+    isa => 'Prophet::Replica',
+);
+
+has is_resdb => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has is_state_handle => (
+    is  => 'rw',
+    isa => 'Bool',
+);
+
+has db_uuid => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has url => (
+    is  => 'rw',
+    isa => 'Str',
+);
 
 use constant state_db_uuid => 'state';
 use Module::Pluggable search_path => 'Prophet::Replica', sub_name => 'core_replica_types', require => 0, except => qr/Prophet::Replica::(.*)::/;
@@ -35,7 +58,7 @@
 
 =head1 METHODS
 
-=head2 new
+=head2 BUILD
 
 Instantiates a new replica
 
@@ -43,12 +66,22 @@
 
 sub _unimplemented { my $self = shift; die ref($self). " does not implement ". shift; }
 
-sub new {
-    my $self = shift->SUPER::new(@_);
-    $self->_rebless_to_replica_type(@_);
-    $self->setup();
-    return $self;
-}
+around new => sub {
+    my $orig  = shift;
+    my $class = shift;
+    my %args  = @_ == 1 ? %{ $_[0] } : @_;
+
+    my ($new_class, $scheme, $url) = $class->_url_to_replica_class($args{url});
+
+    if (!$new_class) {
+        $class->log_fatal("$scheme isn't a replica type I know how to handle. (The Replica URL given was $args{url})");
+    }
+
+    return $orig->($class, %args, url => $args{url}) if $class eq $new_class;
+
+    $new_class->require;
+    return $new_class->new(%args);
+};
 
 =head2 register_replica_scheme { class=> Some::Perl::Class, scheme => 'scheme:' }
 
@@ -65,23 +98,19 @@
 
 
 }
-=head2 _rebless_to_replica_type
 
-Reblesses this replica into the right sort of replica for whatever kind of replica $self->url points to
+=head2 _url_to_replica_class
 
+Returns the replica class for the given url.
 
 =cut
-sub _rebless_to_replica_type {
+
+sub _url_to_replica_class {
     my $self = shift;
+    my $url  = shift;
 
-    my ($scheme, $real_url) = split(/:/,$self->url,2);
-    $self->url($real_url);
-    if ( my $class = $Prophet::Replica::REPLICA_TYPE_MAP->{$scheme}) {
-    $class->require or die $@;
-    return bless $self, $class;
-    } else {
-        $self->log_fatal( "$scheme isn't a replica type I know how to handle. (The Replica URL given was ".$self->url.")");
-    }
+    my ($scheme, $real_url) = split /:/, $url;
+    return ($Prophet::Replica::REPLICA_TYPE_MAP->{$scheme}, $scheme, $real_url);
 }
 
 sub import_changesets {
@@ -176,7 +205,7 @@
     return if ($changeset->is_nullification);
 
     $self->remove_redundant_data($changeset);    #Things we have already seen
-    return if ($changeset->is_empty);
+    return unless $changeset->has_changes;
 
 
 
@@ -322,7 +351,7 @@
 
     $conflict->analyze_changeset();
 
-    return undef unless @{ $conflict->conflicting_changes };
+    return undef unless $conflict->has_conflicting_changes;
 
     return $conflict;
 
@@ -461,7 +490,7 @@
     my %args = validate( @_, { path => 1, } );
     Prophet::ReplicaExporter->require();
 
-    my $exporter = Prophet::ReplicaExporter->new({target_path => $args{'path'}, source_replica => $self});
+    my $exporter = Prophet::ReplicaExporter->new({target_path => dir($args{'path'}), source_replica => $self});
     $exporter->export();
 }
 
@@ -659,7 +688,7 @@
         # Otherwise, record them locally
     my $res_handle =  $self->resolution_db_handle || $self;
 
-    return unless $changeset->changes;
+    return unless $changeset->has_changes;
 
     $self->begin_edit();
     $self->record_changes($changeset);
@@ -917,5 +946,8 @@
     Carp::confess(@_);
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;
 

Modified: Prophet/trunk/lib/Prophet/Replica/Native.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/Native.pm	(original)
+++ Prophet/trunk/lib/Prophet/Replica/Native.pm	Fri Jul  4 08:50:09 2008
@@ -1,9 +1,6 @@
-use warnings;
-use strict;
-
 package Prophet::Replica::Native;
-use base qw/Prophet::Replica/;
-
+use Moose;
+extends 'Prophet::Replica';
 use Params::Validate qw(:all);
 use LWP::Simple ();
 use Path::Class;
@@ -14,11 +11,65 @@
 use Prophet::ChangeSet;
 use Prophet::Conflict;
 
-__PACKAGE__->mk_accessors(qw/url _db_uuid _uuid/);
-__PACKAGE__->mk_accessors(
-    qw(fs_root_parent fs_root target_replica cas_root record_cas_dir changeset_cas_dir record_dir current_edit)
+has _db_uuid => (
+    is => 'rw',
+);
+
+has _uuid => (
+    is => 'rw',
+);
+
+has fs_root_parent => (
+    is      => 'rw',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        $self->fs_root_parent($self->url =~ m{^file://(.*)/.*?$});
+    },
+);
+
+has fs_root => (
+    is      => 'rw',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        $self->fs_root($self->url =~ m{^file://(.*)$});
+    },
+);
+
+has target_replica => (
+    is => 'rw',
+);
+
+has current_edit => (
+    is => 'rw',
+);
+
+has '+resolution_db_handle' => (
+    isa     => 'Prophet::Replica | Undef',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        return if $self->is_resdb || $self->is_state_handle;
+        return Prophet::Replica->new({
+            url      => "prophet:" . $self->url . '/resolutions',
+            is_resdb => 1,
+        })
+    },
 );
 
+#has '+state_handle' => (
+#    isa     => 'Prophet::Replica | Undef',
+#    lazy    => 1,
+#    default => sub {
+#        return if $self->is_state_handle;
+#        return Prophet::Replica->new({
+#            url             => "prophet:" . $self->url,
+#            is_state_handle => 1
+#        });
+#    },
+#);
+
 use constant scheme            => 'prophet';
 use constant cas_root          => 'cas';
 use constant record_cas_dir    => dir( __PACKAGE__->cas_root => 'records' );
@@ -26,30 +77,19 @@
 use constant record_dir        => 'records';
 use constant changeset_index   => 'changesets.idx';
 
-=head2 setup
+=head2 BUILD
 
 Open a connection to the SVN source identified by C<$self->url>.
 
 =cut
 
-sub setup {
+sub BUILD {
     my $self = shift;
     $self->{url}
         =~ s/^prophet://;  # url-based constructor in ::replica should do better
     $self->{url} =~ s{/$}{};
-    $self->fs_root( $self->url        =~ m{^file://(.*)$} );
-    $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->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;
@@ -653,4 +693,7 @@
     return $self->_file_exists( $self->_record_type_root( $args{'type'} ) );
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Replica/SVN.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/SVN.pm	(original)
+++ Prophet/trunk/lib/Prophet/Replica/SVN.pm	Fri Jul  4 08:50:09 2008
@@ -1,21 +1,41 @@
-use warnings;
-use strict;
-
 package Prophet::Replica::SVN;
-use base qw/Prophet::Replica/;
+use Moose;
+extends 'Prophet::Replica';
 use Params::Validate qw(:all);
 use UNIVERSAL::require;
- 
-
-
-
 
 # require rather than use to make them late-binding
 use Prophet::ChangeSet;
 use Prophet::Conflict;
 
-__PACKAGE__->mk_accessors(qw/url ra fs_root repo_handle current_edit _pool/);
-
+has ra => (
+    is      => 'rw',
+    isa     => 'SVN::Ra',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        require Prophet::Replica::SVN::Util;
+        my ( $baton, $ref ) = SVN::Core::auth_open_helper( Prophet::Replica::SVN::Util->get_auth_providers );
+        my $config = Prophet::Replica::SVN::Util->svnconfig;
+        return SVN::Ra->new(url => $self->url, config => $config, auth => $baton, pool => $self->_pool);
+    },
+);
+
+has fs_root => (
+    is => 'rw',
+);
+
+has repo_handle => (
+    is => 'rw',
+);
+
+has current_edit => (
+    is => 'rw',
+);
+
+has _pool => (
+    is => 'rw',
+);
 
 use constant scheme => 'svn';
 
@@ -26,14 +46,6 @@
 
 =cut
 
-sub _get_ra {
-    my $self = shift;
-    require Prophet::Replica::SVN::Util;
-    my ( $baton, $ref ) = SVN::Core::auth_open_helper( Prophet::Replica::SVN::Util->get_auth_providers );
-    my $config = Prophet::Replica::SVN::Util->svnconfig;
-    return SVN::Ra->new( url => $self->url, config => $config, auth => $baton, pool => $self->_pool );
-}
-
 sub setup {
     my $self = shift;
    require SVN::Core; require SVN::Ra; require SVN::Delta; require SVN::Repos; require SVN::Fs;
@@ -43,10 +55,6 @@
         #$self->state_handle( $self->prophet_handle ); XXX DO THIS RIGHT
     }
 
-
-    
-    $self->ra( $self->_get_ra );
-    
     if ( $self->is_resdb ) {
 
         # XXX: should probably just point to self
@@ -124,7 +132,6 @@
 
     require Prophet::Replica::SVN::ReplayEditor;
     my $editor = Prophet::Replica::SVN::ReplayEditor->new( _debug => 0 );
-    $editor->ra( $self->_get_ra );
     my $pool = SVN::Pool->new_default;
 
     # This horrible hack is here because I have no idea how to pass custom variables into the editor
@@ -477,5 +484,8 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;
 

Modified: Prophet/trunk/lib/Prophet/Replica/SVN/ReplayEditor.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/SVN/ReplayEditor.pm	(original)
+++ Prophet/trunk/lib/Prophet/Replica/SVN/ReplayEditor.pm	Fri Jul  4 08:50:09 2008
@@ -29,11 +29,6 @@
 
 =cut
 
-sub new {
-    my $self = shift->SUPER::new(@_);
-    return $self;
-}
-
 =head2 ra [$RA]
 
 Gets or sets the Subversion RA object.

Modified: Prophet/trunk/lib/Prophet/Replica/SVN/Util.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Replica/SVN/Util.pm	(original)
+++ Prophet/trunk/lib/Prophet/Replica/SVN/Util.pm	Fri Jul  4 08:50:09 2008
@@ -1,8 +1,11 @@
-use warnings;
-use strict;
-
 # XXX CARGO CULTED FROM SVK::Util;
 package Prophet::Replica::SVN::Util;
+use Moose;
+use MooseX::ClassAttribute;
+
+use SVN::Client;
+
+my $pool = SVN::Pool->new;
 
 =head1 NAME
 
@@ -14,16 +17,25 @@
 
 =cut
 
-use base 'Class::Data::Inheritable';
-
-__PACKAGE__->mk_classdata('_svnconfig');
-__PACKAGE__->mk_classdata('auth_providers');
+class_has svnconfig => (
+    is      => 'rw',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        return undef if $ENV{PROPHET_NO_SVN_CONFIG};
+
+        SVN::Core::config_ensure(undef);
+        return $self->_svnconfig( SVN::Core::config_get_config( undef, $pool ) );
+    },
+);
 
 # XXX: this is 1.3 api. use SVN::Auth::* for 1.4 and we don't have to load ::Client anymore
 # (well, fix svn perl bindings to wrap the prompt functions correctly first.
-use SVN::Client;
-__PACKAGE__->auth_providers(
-    sub {
+
+class_has auth_providers => (
+    is      => 'rw',
+    lazy    => 1,
+    default => sub { sub {
         my $keychain = SVN::_Core->can('svn_auth_get_keychain_simple_provider');
         my $win32    = SVN::_Core->can('svn_auth_get_windows_simple_provider');
         [   $keychain ? $keychain : (),
@@ -37,10 +49,9 @@
             SVN::Client::get_ssl_client_cert_pw_prompt_provider( \&_ssl_client_cert_pw_prompt, 2 ),
             SVN::Client::get_username_prompt_provider( \&_username_prompt, 2 ),
         ];
-    }
+    }},
 );
 
-my $pool = SVN::Pool->new;
 
 =head2 svnconfig
 
@@ -48,16 +59,6 @@
 
 =cut
 
-sub svnconfig {
-    my $class = shift;
-    return $class->_svnconfig if $class->_svnconfig;
-
-    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
@@ -190,4 +191,7 @@
     return $password;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/ReplicaExporter.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/ReplicaExporter.pm	(original)
+++ Prophet/trunk/lib/Prophet/ReplicaExporter.pm	Fri Jul  4 08:50:09 2008
@@ -1,13 +1,32 @@
-use warnings;
-use strict;
-
 package Prophet::ReplicaExporter;
-use base qw/Class::Accessor/;
+use Moose;
 use Params::Validate qw(:all);
 use Path::Class;
 use UNIVERSAL::require;
 
-__PACKAGE__->mk_accessors(qw( source_replica target_path target_replica));
+has source_replica => (
+    is  => 'rw',
+    isa => 'Prophet::Replica',
+);
+
+has target_path => (
+    is        => 'rw',
+    isa       => 'Path::Class::Dir',
+    predicate => 'has_target_path',
+);
+
+has target_replica => (
+    is      => 'rw',
+    isa     => 'Prophet::Replica',
+    lazy    => 1,
+    default => sub {
+        my $self = shift;
+        confess "No target_path specified." unless $self->has_target_path;
+        my $replica = Prophet::Replica->new({url => "prophet:file://" . $self->target_path});
+        $replica->initialize;
+        return $replica;
+    },
+);
 
 =head1 NAME
 
@@ -156,12 +175,6 @@
 sub export {
     my $self = shift;
 
-    $self->target_replica(
-        Prophet::Replica->new(
-            { url => "prophet:file://" . $self->target_path }
-        )
-    );
-    $self->target_replica->initialize();
     $self->_init_export_metadata();
     $self->export_records( type => $_ )
         for ( @{ $self->source_replica->list_types } );
@@ -214,4 +227,7 @@
     close($cs_file);
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Resolver.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver.pm	Fri Jul  4 08:50:09 2008
@@ -1,13 +1,8 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver;
+use Moose;
 
-sub new {
-    my $class = shift;
-    my $self = bless {}, $class;
-    return $self;
-}
+__PACKAGE__->meta->make_immutable;
+no Moose;
 
 1;
 

Modified: Prophet/trunk/lib/Prophet/Resolver/AlwaysSource.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/AlwaysSource.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/AlwaysSource.pm	Fri Jul  4 08:50:09 2008
@@ -1,9 +1,7 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::AlwaysSource;
-use base qw/Prophet::Resolver/;
+use Moose;
 use Prophet::Change;
+extends 'Prophet::Resolver';
 
 sub run {
     my $self               = shift;
@@ -14,4 +12,7 @@
     return $resolution;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/AlwaysTarget.pm	Fri Jul  4 08:50:09 2008
@@ -1,21 +1,20 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::AlwaysTarget;
-use base qw/Prophet::Resolver/;
+use Moose;
 use Data::Dumper;
+extends 'Prophet::Resolver';
 
 sub run {
     my $self               = shift;
     my $conflicting_change = shift;
     my $conflict           = shift;
     my $resolution         = Prophet::Change->new_from_conflict($conflicting_change);
-    if ( $conflicting_change->file_op_conflict eq 'update_missing_file' ) {
+    my $file_op_conflict = $conflicting_change->file_op_conflict || '';
+    if ( $file_op_conflict eq 'update_missing_file' ) {
         $resolution->change_type('delete');
         return $resolution;
-    } elsif ( $conflicting_change->file_op_conflict eq 'delete_missing_file' ) {
+    } elsif ( $file_op_conflict eq 'delete_missing_file' ) {
         return $resolution;
-    } elsif ( $conflicting_change->file_op_conflict ) {
+    } elsif ( $file_op_conflict ) {
         die Dumper($conflict,$conflicting_change);
     }
 
@@ -29,5 +28,8 @@
     return $resolution;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;
 

Modified: Prophet/trunk/lib/Prophet/Resolver/Failed.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/Failed.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/Failed.pm	Fri Jul  4 08:50:09 2008
@@ -1,10 +1,7 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::Failed;
-use base qw/Prophet::Resolver/;
-
+use Moose;
 use Data::Dumper;
+extends 'Prophet::Resolver';
 
 sub run {
     my $self               = shift;
@@ -17,4 +14,7 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/FromResolutionDB.pm	Fri Jul  4 08:50:09 2008
@@ -1,11 +1,9 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::FromResolutionDB;
-use base qw/Prophet::Resolver/;
+use Moose;
 use Prophet::Change;
 use JSON;
 use Digest::SHA1 'sha1_hex';
+extends 'Prophet::Resolver';
 
 sub run {
     my $self               = shift;
@@ -19,14 +17,12 @@
         type   => '_prophet_resolution-' . $conflicting_change->fingerprint
     );
     $res->matching( sub {1} );
-    return unless @{ $res->as_array_ref };
-
-    #    return unless scalar @{ $res->as_array_ref };
+    return unless $res->count;
 
     my %answer_map;
     my %answer_count;
 
-    for my $answer ( @{ $res->as_array_ref } ) {
+    for my $answer ($res->items) {
         my $key = sha1_hex( to_json($answer->get_props, {utf8 => 1, pretty => 1, canonical => 1}));
         $answer_map{$key} ||= $answer;
         $answer_count{$key}++;
@@ -44,7 +40,9 @@
         );
     }
     return $resolution;
-
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Resolver/IdenticalChanges.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/IdenticalChanges.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/IdenticalChanges.pm	Fri Jul  4 08:50:09 2008
@@ -1,10 +1,8 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::IdenticalChanges;
-use base qw/Prophet::Resolver/;
+use Moose;
 use Params::Validate qw(:all);
 use Prophet::Change;
+extends 'Prophet::Resolver';
 
 =head2 attempt_automatic_conflict_resolution
 
@@ -56,4 +54,7 @@
 
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Resolver/Prompt.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Resolver/Prompt.pm	(original)
+++ Prophet/trunk/lib/Prophet/Resolver/Prompt.pm	Fri Jul  4 08:50:09 2008
@@ -1,8 +1,6 @@
-use warnings;
-use strict;
-
 package Prophet::Resolver::Prompt;
-use base qw/Prophet::Resolver/;
+use Moose;
+extends 'Prophet::Resolver';
 
 sub run {
     my $self               = shift;
@@ -50,5 +48,8 @@
     return $resolution;
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;
 

Modified: Prophet/trunk/lib/Prophet/Server/REST.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Server/REST.pm	(original)
+++ Prophet/trunk/lib/Prophet/Server/REST.pm	Fri Jul  4 08:50:09 2008
@@ -1,14 +1,11 @@
-use warnings;
-use strict;
-
 package Prophet::Server::REST;
-use base qw/HTTP::Server::Simple::CGI/;
 use Params::Validate qw/:all/;
 use JSON;
+use base 'HTTP::Server::Simple::CGI';
 
 sub prophet_handle {
     my $self = shift;
-    $self->{'_prophet_handle'} = shift if (@_);
+    $self->{'_prophet_handle'} = shift if @_;
     return $self->{'_prophet_handle'};
 }
 

Modified: Prophet/trunk/lib/Prophet/Test.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Test.pm	(original)
+++ Prophet/trunk/lib/Prophet/Test.pm	Fri Jul  4 08:50:09 2008
@@ -50,7 +50,7 @@
 
 {
     no warnings 'redefine';
-
+    require Test::More;
     sub Test::More::diag {    # bad bad bad # convenient convenient convenient
         Test::More->builder->diag(@_) if ( $Test::Harness::Verbose || $ENV{'TEST_VERBOSE'} );
     }
@@ -253,7 +253,7 @@
     my $cli     = Prophet::CLI->new();
     my $tickets = Prophet::Collection->new( handle => $cli->app_handle->handle, type => $Prophet::Replica::MERGETICKET_METATYPE );
     $tickets->matching( sub {1} );
-    return { map { $_->uuid => $_->prop('last-changeset') } @{ $tickets->as_array_ref } };
+    return { map { $_->uuid => $_->prop('last-changeset') } $tickets->items };
 
 }
 

Modified: Prophet/trunk/lib/Prophet/Test/Arena.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Test/Arena.pm	(original)
+++ Prophet/trunk/lib/Prophet/Test/Arena.pm	Fri Jul  4 08:50:09 2008
@@ -1,9 +1,28 @@
-use warnings;
-use strict;
-
 package Prophet::Test::Arena;
-use base qw/Class::Accessor/;
-__PACKAGE__->mk_accessors(qw/chickens record_callback history/);
+use Moose;
+use MooseX::AttributeHelpers;
+
+has chickens => (
+    is         => 'rw',
+    isa        => 'ArrayRef[Prophet::Test::Participant]',
+    default    => sub { [] },
+    auto_deref => 1,
+);
+
+has record_callback => (
+    is  => 'rw',
+    isa => 'CodeRef',
+);
+
+has history => (
+    metaclass => 'Collection::Array',
+    is        => 'rw',
+    isa       => 'ArrayRef[ArrayRef]',
+    default   => sub { [] },
+    provides  => {
+        push => 'add_history',
+    },
+);
 
 use Prophet::Test::Participant;
 use Acme::MetaSyntactic;
@@ -25,7 +44,7 @@
             });
     }
     
-    $self->chickens(@chickens);
+    $self->chickens(\@chickens);
 }
 
 sub run_from_yaml {
@@ -63,7 +82,7 @@
 
     for ( @{ $data->{recipe} } ) {
         my ( $name, $action, $args ) = @$_;
-        my ($chicken) = grep { $_->name eq $name } @{ $arena->chickens };
+        my ($chicken) = grep { $_->name eq $name } $arena->chickens;
         if ( $args->{record} ) {
             $args->{record} = $record_map->{ $args->{record} };
         }
@@ -96,7 +115,7 @@
     my $step_name = shift || undef;
     my $step_display = defined($step_name) ? $step_name : "(undef)";
 
-    for my $chicken ( @{ $self->chickens } ) {
+    for my $chicken ($self->chickens) {
 
         diag(" as ".$chicken->name. ": $step_display");
         # walk the arena, noting the type of each value
@@ -111,7 +130,7 @@
 sub dump_state {
     my $self = shift;
     my %state;
-    for my $chicken ( @{ $self->chickens } ) {
+    for my $chicken ($self->chickens) {
         $state{ $chicken->name } = as_user( $chicken->name, sub { $chicken->dump_state } );
     }
     return \%state;
@@ -124,8 +143,8 @@
 
     diag("now syncing all pairs");
 
-    my @chickens_a = shuffle @{ $self->chickens };
-    my @chickens_b = shuffle @{ $self->chickens };
+    my @chickens_a = shuffle $self->chickens;
+    my @chickens_b = shuffle $self->chickens;
 
     foreach my $a (@chickens_a) {
         foreach my $b (@chickens_b) {
@@ -151,7 +170,10 @@
         if $self->record_callback;
 
     # XXX: move to some kind of recorder class and make use of callback
-    push @{ $self->{history} ||= [] }, [ $name, $action, $stored ];
+    $self->add_history([$name, $action, $stored]);
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/lib/Prophet/Test/Participant.pm
==============================================================================
--- Prophet/trunk/lib/Prophet/Test/Participant.pm	(original)
+++ Prophet/trunk/lib/Prophet/Test/Participant.pm	Fri Jul  4 08:50:09 2008
@@ -1,22 +1,19 @@
-use warnings;
-use strict;
-
 package Prophet::Test::Participant;
-use base qw/Class::Accessor/;
-__PACKAGE__->mk_accessors(qw/name arena/);
+use Moose;
 use Prophet::Test;
-use Scalar::Util qw/weaken/;
-
-sub new {
 
-    my $self = shift->SUPER::new(@_);
-    $self->_setup();
-    weaken( $self->{'arena'} );
+has name => (
+    is  => 'rw',
+    isa => 'Str',
+);
+
+has arena => (
+    is       => 'rw',
+    isa      => 'Prophet::Test::Arena',
+    weak_ref => 1,
+);
 
-    return $self;
-}
-
-sub _setup {
+sub BUILD {
     my $self = shift;
     as_user( $self->name, sub { call_func_ok( [qw(search --type Bug --regex .)] ) } );
 
@@ -116,7 +113,7 @@
     my $self = shift;
     my $args = shift;
 
-    my $from = $args->{from} ||= ( shuffle( grep { $_->name ne $self->name } @{ $self->arena->chickens } ) )[0]->name;
+    my $from = $args->{from} ||= ( shuffle( grep { $_->name ne $self->name } $self->arena->chickens ) )[0]->name;
 
     $self->record_action( 'sync_from_peer', $args );
 
@@ -148,9 +145,9 @@
     $resolutions->matching( sub {1} );
     $merges->matching( sub      {1} );
 
-    %{ $state->{records} }       = map { $_->uuid => $_->get_props } @{ $records->as_array_ref };
-    %{ $state->{merges} }      = map { $_->uuid => $_->get_props } @{ $merges->as_array_ref };
-    %{ $state->{resolutions} } = map { $_->uuid => $_->get_props } @{ $resolutions->as_array_ref };
+    %{ $state->{records} }       = map { $_->uuid => $_->get_props } $records->items;
+    %{ $state->{merges} }      = map { $_->uuid => $_->get_props } $merges->items;
+    %{ $state->{resolutions} } = map { $_->uuid => $_->get_props } $resolutions->items;
 
     return $state;
 
@@ -199,4 +196,7 @@
     return ( $ret, $str, undef );
 }
 
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
 1;

Modified: Prophet/trunk/t/create.t
==============================================================================
--- Prophet/trunk/t/create.t	(original)
+++ Prophet/trunk/t/create.t	Fri Jul  4 08:50:09 2008
@@ -29,18 +29,16 @@
 
 my $people = Prophet::Collection->new( handle => $cxn, type => 'Person' );
 $people->matching( sub { ( shift->prop('species') || '' ) ne 'cat' } );
-is( $#{ $people->as_array_ref }, 1 );
-my @people = @$people;
-is_deeply( [ sort map { $_->prop('name') } @people ], [qw(Jesse Kaia)] );
+is( $people->count, 2 );
+is_deeply( [ sort map { $_->prop('name') } @$people ], [qw(Jesse Kaia)] );
 
 my $cats = Prophet::Collection->new( handle => $cxn, type => 'Person' );
 $cats->matching( sub { ( shift->prop('species') || '' ) eq 'cat' } );
-is( $#{ $cats->as_array_ref }, 1 );
-my @cats = @{ $cats->as_array_ref };
-for (@cats) {
+is( $cats->count , 2 );
+for (@$cats) {
     is( $_->prop('age'), "0.7" );
 }
-is_deeply( [ sort map { $_->prop('name') } @cats ], [qw(Mao Mei)] );
+is_deeply( [ sort map { $_->prop('name') } @$cats ], [qw(Mao Mei)] );
 
 my $cat = Prophet::Record->new( handle => $cxn, type => 'Person' );
 $cat->load( uuid => $mao );
@@ -49,16 +47,16 @@
 $cat2->load( uuid => $mei );
 $cat2->set_prop( name => 'age', value => '0.8' );
 
-is( $#{ $cats->as_array_ref }, 1 );
-for (@cats) {
+is( $cats->count, 2 );
+for (@$cats) {
     is( $_->prop('age'), "0.8" );
 }
 
-for (@cats) {
+for (@$cats) {
     ok( $_->delete );
 }
 
 my $records = Prophet::Collection->new( type => 'Person', handle => $cxn );
 $records->matching( sub {1} );
-is( $#{ $records->as_array_ref }, 1 );
+is( $records->count, 2 );
 1;

Modified: Prophet/trunk/t/export.t
==============================================================================
--- Prophet/trunk/t/export.t	(original)
+++ Prophet/trunk/t/export.t	Fri Jul  4 08:50:09 2008
@@ -63,7 +63,7 @@
     use_ok('Prophet::Replica::Native');
     diag("Checking changesets in $path");
     my $changesets =  Prophet::Replica->new( { url => 'prophet:file://' . $path } )->fetch_changesets( after => 0 );
-    my @changesets = grep {!$_->is_empty} @$changesets;
+    my @changesets = grep {$_->has_changes} @$changesets;
     is( $#changesets, 2, "We found a total of 3 changesets" );
     # XXX: compare the changeset structure
     is( lc( $changesets->[-1]->{source_uuid} ), lc( $changesets->[-1]->{original_source_uuid} ) );

Modified: Prophet/trunk/t/generalized_sync_n_merge.t
==============================================================================
--- Prophet/trunk/t/generalized_sync_n_merge.t	(original)
+++ Prophet/trunk/t/generalized_sync_n_merge.t	Fri Jul  4 08:50:09 2008
@@ -36,18 +36,18 @@
 ok( !$err, "There was no error ($err)" );
 my $Test = Test::Builder->new;
 if ( grep { !$_ } $Test->summary ) {
-    my $fname = join( '', sort map { substr( $_->name, 0, 1 ) } @{ $arena->chickens } ) . '.yml';
+    my $fname = join( '', sort map { substr( $_->name, 0, 1 ) } $arena->chickens ) . '.yml';
     diag "test failed... dumping recipe to $fname";
     YAML::Syck::DumpFile(
         $fname,
-        {   chickens => [ map { $_->name } @{ $arena->chickens } ],
+        {   chickens => [ map { $_->name } $arena->chickens ],
             recipe   => $arena->{history}
         }
     );
 }
 
 exit;
-for ( @{ $arena->chickens } ) {
+for ( $arena->chickens ) {
     warn $_->name;
     as_user(
         $_->name,
@@ -61,7 +61,7 @@
             );
             $records->matching( sub {1} );
             use Data::Dumper;
-            for ( @{ $records->as_array_ref } ) {
+            for ($records->items) {
                 warn $_->uuid . ' : ' . Dumper( $_->get_props );
             }
         }

Modified: Prophet/trunk/t/real-conflicting-merge.t
==============================================================================
--- Prophet/trunk/t/real-conflicting-merge.t	(original)
+++ Prophet/trunk/t/real-conflicting-merge.t	Fri Jul  4 08:50:09 2008
@@ -7,8 +7,8 @@
 use Prophet::Test tests => 19;
 
 as_alice {
-    run_ok( 'prophet', [qw(create --type Bug --status new --from alice )], "Created a record as alice" );
-    run_output_matches( 'prophet', [qw(search --type Bug --regex .)], [qr/new/], " Found our record" );
+    like(run_command(qw(create --type Bug --status new --from alice)), qr/Created Bug/, "Created a record as alice");
+    like(run_command(qw(search --type Bug --regex .)), qr/new/, "Found our record");
 };
 
 diag('Bob syncs from alice');
@@ -17,18 +17,18 @@
 
 as_bob {
 
-    run_ok( 'prophet', [qw(create --type Dummy --ignore yes)], "Created a dummy record" );
-
-    run_ok( 'prophet', [ 'merge', '--to', repo_uri_for('bob'), '--from', repo_uri_for('alice') ], "Sync ran ok!" );
+    like(run_command(qw(create --type Dummy --ignore yes)), qr/Created Dummy/);
+    like(run_command('merge', '--to', repo_uri_for('bob'), '--from', repo_uri_for('alice')), qr/Merge complete/, "Sync ran ok!");
 
     # check our local replicas
-    my ( $ret, $out, $err ) = run_script( 'prophet', [qw(search --type Bug --regex .)] );
-    like( $out, qr/new/, "We have the one record from alice" );
+    my $out = run_command(qw(search --type Bug --regex .));
+    like($out, qr/new/, "We have the one record from alice" );
     if ( $out =~ /^(.*?)\s./ ) {
         $record_id = $1;
     }
 
-    run_ok( 'prophet', [ 'update', '--type', 'Bug', '--uuid', $record_id, '--status' => 'stalled' ] );
+    like(run_command( 'update', '--type', 'Bug', '--uuid', $record_id, '--status' => 'stalled'), qr/Bug .* updated/);
+
     run_output_matches(
         'prophet',
         [ 'show', '--type',            'Bug',             '--uuid', $record_id ],
@@ -40,7 +40,8 @@
 };
 
 as_alice {
-    run_ok( 'prophet', [ 'update', '--type', 'Bug', '--uuid', $record_id, '--status' => 'open' ] );
+    like(run_command('update', '--type', 'Bug', '--uuid', $record_id, '--status' => 'open' ), qr/Bug .* updated/);
+
     run_output_matches(
         'prophet',
         [ 'show', '--type',            'Bug',          '--uuid', $record_id ],
@@ -164,7 +165,6 @@
                         }
                     }
                 },
-                is_empty             => 0,
                 is_nullification     => 1,
                 is_resolution        => undef,
                 sequence_no          => ( replica_last_rev() - 2 ),
@@ -172,7 +172,7 @@
                 source_uuid          => replica_uuid(),
                 original_source_uuid => replica_uuid(),
             },
-            {   is_empty             => 0,
+            {
                 is_nullification     => undef,
                 is_resolution        => undef,
                 sequence_no          => ( replica_last_rev() - 1 ),
@@ -205,7 +205,7 @@
                 }
             },
 
-            {   is_empty             => 0,
+            {
                 is_nullification     => undef,
                 is_resolution        => 1,
                 sequence_no          => replica_last_rev(),

Modified: Prophet/trunk/t/simple-conflicting-merge.t
==============================================================================
--- Prophet/trunk/t/simple-conflicting-merge.t	(original)
+++ Prophet/trunk/t/simple-conflicting-merge.t	Fri Jul  4 08:50:09 2008
@@ -105,7 +105,6 @@
         $null_as_hash,
         {
 
-            is_empty             => 0,
             is_nullification     => 1,
             is_resolution        => undef,
             original_sequence_no => undef,
@@ -143,7 +142,7 @@
     $from_alice_as_hash->{$_} = undef for qw(sequence_no source_uuid);
     is_deeply(
         $from_alice_as_hash,
-        {   is_empty             => 0,
+        {
             is_nullification     => undef,
             is_resolution        => undef,
             source_uuid          => undef,

Modified: Prophet/trunk/t/simple-push.t
==============================================================================
--- Prophet/trunk/t/simple-push.t	(original)
+++ Prophet/trunk/t/simple-push.t	Fri Jul  4 08:50:09 2008
@@ -45,7 +45,7 @@
 };
 
 is_deeply(
-    [ map { $_->as_hash } grep { !$_->is_empty}  @$changesets ],
+    [ map { $_->as_hash } grep { $_->has_changes }  @$changesets ],
     [ 
         {   'sequence_no'          => 3,
             'original_sequence_no' => 3,
@@ -69,7 +69,6 @@
                 }
             },
             'is_nullification' => undef,
-            'is_empty'         => 0
         }
     ]
 );
@@ -97,7 +96,7 @@
 
 $changesets = $bob->new_changesets_for($alice);
 
-my @changes = map { $_->as_hash } grep {!$_->is_empty} @$changesets;
+my @changes = map { $_->as_hash } grep { $_->has_changes } @$changesets;
 
 is_deeply(
     \@changes,
@@ -123,7 +122,6 @@
                 }
             },
             'is_nullification' => undef,
-            'is_empty'         => 0
         }
     ]
 );



More information about the Bps-public-commit mailing list