Introduce Gitalist::Git::Tag.
Zachary Stevens [Sun, 27 Jun 2010 22:28:13 +0000 (23:28 +0100)]
Encapsulates a git tag.
Repository->tags is now an ArrayRef of these.

lib/Gitalist/Git/Repository.pm
lib/Gitalist/Git/Tag.pm [new file with mode: 0644]
t/02git_Repository.t
t/02git_tag.t [new file with mode: 0644]

index 5259eb8..328e10a 100644 (file)
@@ -16,6 +16,7 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
     use Gitalist::Git::Object::Commit;
     use Gitalist::Git::Object::Tag;
     use Gitalist::Git::Head;
+    use Gitalist::Git::Tag;
 
     our $SHA1RE = qr/[0-9a-fA-F]{40}/;
 
@@ -63,7 +64,7 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
     has heads => ( isa => ArrayRef['Gitalist::Git::Head'],
                    is => 'ro',
                    lazy_build => 1);
-    has tags => ( isa => ArrayRef[HashRef],
+    has tags => ( isa => ArrayRef['Gitalist::Git::Tag'],
                    is => 'ro',
                    lazy_build => 1);
     has references => ( isa => HashRef[ArrayRef[Str]],
@@ -251,21 +252,8 @@ class Gitalist::Git::Repository with Gitalist::Git::HasUtils {
         );
         my @ret;
         for my $line (@revlines) {
-            my($refinfo, $creatorinfo) = split /\0/, $line;
-            my($rev, $type, $name, $refid, $reftype, $title) = split(' ', $refinfo, 6);
-            my($creator, $epoch, $tz) = ($creatorinfo =~ /^(.*) ([0-9]+) (.*)$/);
-            $name =~ s!^refs/tags/!!;
-
-            push @ret, { sha1 => $rev, name => $name };
-
-            #FIXME: That isn't the time I'm looking for..
-            if($epoch and $tz) {
-                my $dt = DateTime->from_epoch(epoch => $epoch);
-                $dt->set_time_zone($tz);
-                $ret[-1]->{last_change} = $dt;
-            }
+            push @ret, Gitalist::Git::Tag->new($line);
         }
-
         return \@ret;
     }
 
diff --git a/lib/Gitalist/Git/Tag.pm b/lib/Gitalist/Git/Tag.pm
new file mode 100644 (file)
index 0000000..be53088
--- /dev/null
@@ -0,0 +1,79 @@
+package Gitalist::Git::Tag;
+use Moose;
+use namespace::autoclean;
+
+use Gitalist::Git::Types qw/SHA1/;
+use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
+use MooseX::Types::Moose qw/Maybe Str/;
+use MooseX::Types::DateTime;
+use DateTime;
+
+has sha1        => ( isa      => SHA1,
+                     is       => 'ro',
+                     required => 1,
+                 );
+has name        => ( isa      => NonEmptySimpleStr,
+                     is       => 'ro',
+                     required => 1,
+                 );
+
+has type        => ( isa      => NonEmptySimpleStr,
+                     is       => 'ro',
+                     required => 1,
+                 );
+
+has ref_sha1    => ( isa      => Maybe[SHA1],
+                     is       => 'ro',
+                     required => 0,
+                 );
+has ref_type    => ( isa      => Maybe[NonEmptySimpleStr],
+                     is       => 'ro',
+                     required => 0,
+                 );
+has committer   => ( isa      => NonEmptySimpleStr,
+                     is       => 'ro',
+                     required => 1,
+                 );
+has last_change => ( isa      => 'DateTime',
+                     is       => 'ro',
+                     required => 1,
+                     coerce   => 1,
+);
+
+around BUILDARGS => sub {
+    my $orig = shift;
+    my $class = shift;
+
+    if ( @_ == 1 && ! ref $_[0] ) {
+        my $line = $_[0];
+        # expects $line to match the output from
+        # --format=%(objectname) %(objecttype) %(refname) %(*objectname) %(*objecttype) %(subject)%00%(creator)
+        my ($sha1, $type, $name, $ref_sha1, $ref_type, $rest) = split / /, $line, 6;
+        $name =~ s!^refs/tags/!!;
+
+        unless ($ref_sha1) {
+            ($ref_sha1, $ref_type) = (undef, undef);
+        }
+        my ($subject, $commitinfo) = split /\0/, $rest, 2;
+        my ($committer, $epoch, $tz) =
+            $commitinfo =~ /(.*)\s(\d+)\s+([+-]\d+)$/;
+        my $dt = DateTime->from_epoch(
+            epoch => $epoch,
+            time_zone => $tz,
+        );
+
+        return $class->$orig(
+            sha1 => $sha1,
+            name => $name,
+            type => $type,
+            committer => $committer,
+            last_change => $dt,
+            ref_sha1 => $ref_sha1,
+            ref_type => $ref_type,
+        );
+    } else {
+        return $class->$orig(@_);
+    }
+};
+
+1;
index 0ac8294..d12fd14 100644 (file)
@@ -56,6 +56,8 @@ is($proj->head_hash, '36c6c6708b8360d7023e8a1649c45bcf9b3bd818', 'head_hash for
 is($proj->head_hash('refs/heads/master'), '36c6c6708b8360d7023e8a1649c45bcf9b3bd818', 'head_hash for refs/heads/master is correct');
 is($proj->head_hash('rafs/head/mister'), undef, 'head_hash for rafs/head/mister is undef');
 
+ok(scalar @{$proj->tags} == 1, '->tags list has one element');
+
 # Return an ::Object from a sha1
 my $obj1 = $proj->get_object('729a7c3f6ba5453b42d16a43692205f67fb23bc1');
 isa_ok($obj1, 'Gitalist::Git::Object::Tree');
diff --git a/t/02git_tag.t b/t/02git_tag.t
new file mode 100644 (file)
index 0000000..3647cb1
--- /dev/null
@@ -0,0 +1,29 @@
+use strict;
+use warnings;
+use Test::More qw/no_plan/;
+use Test::Exception;
+use Data::Dumper;
+
+BEGIN { use_ok 'Gitalist::Git::Tag' }
+
+# Create an instance from for-each-ref output
+my $revline="36c6c6708b8360d7023e8a1649c45bcf9b3bd818 commit refs/tags/0.01   add dir1/file2\0Florian Ragwitz <rafl\@debian.org> 1173210275 +0100";
+#my $revline="a92fb1c9282f7319099ce7f783c8be7d5360f6e3\0refs/heads/model-cleanup\0Zachary Stevens <zts\@cryptocracy.com> 1277601094 +0100";
+my $instance = Gitalist::Git::Tag->new($revline);
+isa_ok($instance, 'Gitalist::Git::Tag');
+
+# Create an instance, passing last_change as a DateTime
+use DateTime;
+my $timespec = [1173210275, '+0100'];
+my $dt = DateTime->from_epoch(
+    epoch => @$timespec[0],
+    time_zone => @$timespec[1],
+);
+my $head = Gitalist::Git::Tag->new(
+    sha1 => '36c6c6708b8360d7023e8a1649c45bcf9b3bd818',
+    name => '0.01',
+    type => 'commit',
+    committer => 'Florian Ragwitz <rafl@debian.org>',
+    last_change => $dt,
+);
+isa_ok($head, 'Gitalist::Git::Tag');