First cut at reintroducing object serialization.
Dan Brook [Fri, 6 May 2011 22:27:28 +0000 (23:27 +0100)]
This is very much based on the work t0m did in his json branch (which
was merged into swann to become swann-with-json). The nicely broken up
Git objects created more replicated code than I like but it seems to work
which is enough for now. Next up is the rest of the objects and then onto
a shiny new REST interface.

Makefile.PL
lib/Gitalist/Git/CollectionOfRepositories.pm
lib/Gitalist/Git/HasUtils.pm
lib/Gitalist/Git/Head.pm
lib/Gitalist/Git/Repository.pm
lib/Gitalist/Git/Serializable.pm [new file with mode: 0644]
lib/Gitalist/Git/Tag.pm
lib/Gitalist/Git/Types.pm
t/02git_Repository.t

index ad2134c..def336c 100644 (file)
@@ -78,9 +78,11 @@ requires 'Config::General';
 requires 'Moose';
 requires 'Moose::Autobox';
 requires 'MooseX::Declare' => '0.32';
+requires 'MooseX::Storage';
+requires 'MooseX::Types';
 requires 'MooseX::Types::Common';
 requires 'MooseX::Types::Path::Class';
-requires 'MooseX::Types';
+requires 'MooseX::Types::ISO8601';
 requires 'namespace::autoclean';
 
 requires 'Git::PurePerl' => '0.47';
index 116b409..4d8fd32 100644 (file)
@@ -1,6 +1,6 @@
 use MooseX::Declare;
 
-role Gitalist::Git::CollectionOfRepositories {
+role Gitalist::Git::CollectionOfRepositories with Gitalist::Git::Serializable {
     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
     use MooseX::Types::Moose qw/ArrayRef/;
     use Moose::Autobox;
index 7d133ac..e57f1c1 100644 (file)
@@ -21,6 +21,7 @@ role Gitalist::Git::HasUtils {
             get_gpp_object
             gpp
         /],
+        traits => ['DoNotSerialize']
     );
     method _build_util { confess(shift() . " cannot build _util") }
 }
index 9301a31..53f689f 100644 (file)
@@ -1,11 +1,15 @@
 package Gitalist::Git::Head;
+
 use Moose;
 use namespace::autoclean;
 
-use Gitalist::Git::Types qw/SHA1/;
+with 'Gitalist::Git::Serializable';
+
 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-use MooseX::Types::DateTime;
-use DateTime;
+use MooseX::Types::Moose          qw/Maybe/;
+use Gitalist::Git::Types          qw/SHA1 DateTime/;
+
+use aliased 'DateTime' => 'DT';
 
 has sha1        => ( isa      => SHA1,
                      is       => 'ro',
@@ -19,10 +23,9 @@ has committer   => ( isa      => NonEmptySimpleStr,
                      is       => 'ro',
                      required => 1,
                  );
-has last_change => ( isa      => 'DateTime',
+has last_change => ( isa      => Maybe[DateTime],
                      is       => 'ro',
                      required => 1,
-                     coerce   => 1,
 );
 
 around BUILDARGS => sub {
@@ -38,7 +41,7 @@ around BUILDARGS => sub {
 
         my ($committer, $epoch, $tz) =
             $commitinfo =~ /(.*)\s(\d+)\s+([+-]\d+)$/;
-        my $dt = DateTime->from_epoch(
+        my $dt = DT->from_epoch(
             epoch => $epoch,
             time_zone => $tz,
         );
index 2977c59..602126b 100644 (file)
@@ -1,16 +1,18 @@
 use MooseX::Declare;
 
-class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
-    # FIXME, use Types::Path::Class and coerce
+class Gitalist::Git::Repository with (Gitalist::Git::HasUtils, Gitalist::Git::Serializable) {
+    use MooseX::Storage::Meta::Attribute::Trait::DoNotSerialize;
+
     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-    use MooseX::Types::Path::Class qw/Dir/;
-    use MooseX::Types::Moose qw/Str Maybe Bool HashRef ArrayRef/;
-    use Gitalist::Git::Types qw/SHA1/;
+    use MooseX::Types::Moose          qw/Str Maybe Bool HashRef ArrayRef/;
+    use Gitalist::Git::Types          qw/SHA1 DateTime Dir/;
+
     use Moose::Autobox;
+    use aliased 'DateTime' => 'DT';
     use List::MoreUtils qw/any zip/;
-    use DateTime;
-    use Encode qw/decode/;
-    use I18N::Langinfo qw/langinfo CODESET/;
+    use Encode          qw/decode/;
+    use I18N::Langinfo  qw/langinfo CODESET/;
+
     use Gitalist::Git::Object::Blob;
     use Gitalist::Git::Object::Tree;
     use Gitalist::Git::Object::Commit;
@@ -41,7 +43,8 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
                   is => 'ro', required => 1 );
 
     has path => ( isa => Dir,
-                  is => 'ro', required => 1);
+                  is => 'ro', required => 1,
+                  traits => ['DoNotSerialize'] );
 
     has description => ( isa => Str,
                          is => 'ro',
@@ -53,7 +56,7 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
                    lazy_build => 1,
                );
 
-    has last_change => ( isa => Maybe['DateTime'],
+    has last_change => ( isa => Maybe[DateTime],
                          is => 'ro',
                          lazy_build => 1,
                      );
@@ -233,7 +236,7 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
                 --sort=-committerdate --count=1 refs/heads
           });
         if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
-            my $dt = DateTime->from_epoch(epoch => $epoch);
+            my $dt = DT->from_epoch(epoch => $epoch);
             $dt->set_time_zone($tz);
             $last_change = $dt;
         }
diff --git a/lib/Gitalist/Git/Serializable.pm b/lib/Gitalist/Git/Serializable.pm
new file mode 100644 (file)
index 0000000..f0a6e7f
--- /dev/null
@@ -0,0 +1,8 @@
+package Gitalist::Git::Serializable;
+
+use Moose::Role;
+use MooseX::Storage;
+
+with Storage( traits => ['OnlyWhenBuilt'] );
+
+1;
index a0a8ea6..da14daf 100644 (file)
@@ -1,12 +1,15 @@
 package Gitalist::Git::Tag;
+
 use Moose;
 use namespace::autoclean;
 
-use Gitalist::Git::Types qw/SHA1/;
+with 'Gitalist::Git::Serializable';
+
 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-use MooseX::Types::Moose qw/Maybe Str/;
-use MooseX::Types::DateTime;
-use DateTime;
+use MooseX::Types::Moose          qw/Maybe/;
+use Gitalist::Git::Types          qw/SHA1 DateTime/;
+
+use aliased 'DateTime' => 'DT';
 
 has sha1        => ( isa      => SHA1,
                      is       => 'ro',
@@ -34,10 +37,9 @@ has committer   => ( isa      => NonEmptySimpleStr,
                      is       => 'ro',
                      required => 1,
                  );
-has last_change => ( isa      => 'DateTime',
+has last_change => ( isa      => Maybe[DateTime],
                      is       => 'ro',
                      required => 1,
-                     coerce   => 1,
 );
 
 around BUILDARGS => sub {
@@ -57,7 +59,7 @@ around BUILDARGS => sub {
         my ($subject, $commitinfo) = split /\0/, $rest, 2;
         my ($committer, $epoch, $tz) =
             $commitinfo =~ /(.*)\s(\d+)\s+([+-]\d+)$/;
-        my $dt = DateTime->from_epoch(
+        my $dt = DT->from_epoch(
             epoch => $epoch,
             time_zone => $tz,
         );
index af12bbc..3b5d103 100644 (file)
@@ -1,8 +1,16 @@
 package Gitalist::Git::Types;
 
 use MooseX::Types
-    -declare => [qw/SHA1/];
+     -declare => [qw/
+         SHA1
+         DateTime
+         Dir
+     /];
 
+use MooseX::Types::Path::Class;
+use MooseX::Types::ISO8601 qw/ISO8601DateTimeStr/;
+use MooseX::Types::DateTime ();
+use MooseX::Storage::Engine ();
 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
 
 subtype SHA1,
@@ -14,4 +22,34 @@ coerce SHA1,
     from NonEmptySimpleStr,
     via { 1 };
 
+subtype DateTime,
+    as 'MooseX::Types::DateTime::DateTime',
+    where { 1 };
+
+MooseX::Storage::Engine->add_custom_type_handler(
+    DateTime,
+        expand   => sub {
+            my $val = shift;
+            Carp::confess("Not implemented");
+        },
+        collapse => sub {
+            to_ISO8601DateTimeStr(shift);
+        },
+);
+
+subtype Dir,
+    as 'MooseX::Types::Path::Class::Dir',
+    where { 1 };
+
+MooseX::Storage::Engine->add_custom_type_handler(
+    Dir,
+        expand   => sub {
+            my $val = shift;
+            Carp::confess("Not implemented");
+        },
+        collapse => sub {
+            shift() . '';
+        },
+);
+
 1;
index d12fd14..ba86a79 100644 (file)
@@ -83,3 +83,46 @@ my $owner = $proj->owner;
 is_flagged_utf8($owner, "Owner name is flagged as utf8");
 is_sane_utf8($owner, "Owner name is not double-encoded");
 is($owner, decode_utf8("T\x{c3}\x{a9}st"),  "Owner name is correct");
+
+is_deeply $proj->pack,  {
+    __CLASS__   => 'Gitalist::Git::Repository',
+    description => 'some test repository',
+    heads       => [
+        {
+            __CLASS__   => 'Gitalist::Git::Head',
+            committer   => 'Zachary Stevens <zts@cryptocracy.com>',
+            last_change => '2009-11-12T19:00:34Z',
+            name        => 'branch1',
+            sha1        => '0710a7c8ee11c73e8098d08f9384c2a839c65e4e'
+        },
+        {
+            __CLASS__   => 'Gitalist::Git::Head',
+            committer   => 'Florian Ragwitz <rafl@debian.org>',
+            last_change => '2007-03-06T20:44:35Z',
+            name        => 'master',
+            sha1        => '36c6c6708b8360d7023e8a1649c45bcf9b3bd818'
+        }
+    ],
+    is_bare     => 1,
+    last_change => '2009-11-12T19:00:34Z',
+    name        => 'repo1',
+    owner       => "T\351st",
+    references  => {
+        "36c6c6708b8360d7023e8a1649c45bcf9b3bd818" => [
+            'heads/master',
+            'tags/0.01'
+        ],
+        "0710a7c8ee11c73e8098d08f9384c2a839c65e4e" => [ 'heads/branch1' ]
+    },
+    tags        => [ {
+        __CLASS__
+             => 'Gitalist::Git::Tag',
+        committer
+             => 'Florian Ragwitz <rafl@debian.org>',
+        last_change
+             => '2007-03-06T20:44:35Z',
+        name    => 0.01,
+        sha1    => '36c6c6708b8360d7023e8a1649c45bcf9b3bd818',
+        type    => 'commit'
+    } ]
+}, 'Serialized correctly';