Refactor somewhat
Tomas Doran [Fri, 6 Nov 2009 03:20:25 +0000 (03:20 +0000)]
Makefile.PL
lib/Gitalist/Git/Object.pm
lib/Gitalist/Git/Project.pm
lib/Gitalist/Git/Repo.pm
lib/Gitalist/Git/Util.pm

index b317781..ee268f1 100644 (file)
@@ -24,12 +24,14 @@ requires 'namespace::autoclean';
 requires 'Config::General'; # This should reflect the config file format you've chosen
                  # See Catalyst::Plugin::ConfigLoader for supported formats
 requires 'MooseX::Types::Common';
+requires 'MooseX::Types::Path::Class';
+requires 'MooseX::Types';
 requires 'File::Find::Rule';
 requires 'File::Stat::ModeString';
-requires 'File::Slurp';
 requires 'DateTime::Format::Mail';
 requires 'IO::Capture::Stdout';
 requires 'File::Which';
+requires 'aliased';
 requires 'CGI';
 requires 'DateTime';
 requires 'Git::PurePerl'; # Note - need the git version in broquaint's fork
index 0c3d82f..1ebe1db 100644 (file)
@@ -1,26 +1,29 @@
 use MooseX::Declare;
+use Moose::Autobox;
 
 class Gitalist::Git::Object {
     use MooseX::Types::Moose qw/Str Int/;
+    use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
     use File::Stat::ModeString qw/mode_to_string/;
     # project and sha1 are required initargs
     has project => ( isa => 'Gitalist::Git::Project',
                      required => 1,
                      is => 'ro',
+                     weak_ref => 1,
                      handles => [ 'run_cmd' ],
                  );
-    has sha1 => ( isa => Str,
+    has sha1 => ( isa => NonEmptySimpleStr,
                required => 1,
                is => 'ro' );
 
-    has $_ => ( isa => Str,
+    has $_ => ( isa => NonEmptySimpleStr,
                   required => 1,
                   is => 'ro',
                   lazy_build => 1 )
         for qw/type modestr size/;
 
     # objects can't determine their mode or filename
-    has file => ( isa => Str,
+    has file => ( isa => NonEmptySimpleStr,
                   required => 0,
                   is => 'ro' );
     has mode => ( isa => Int,
@@ -28,14 +31,12 @@ class Gitalist::Git::Object {
                 default => 0,
                 is => 'ro' );
 
-    method BUILD {
-        $self->$_() for qw/type modestr size/; # Ensure to build early.
-    }
+    method BUILD { $self->$_() for qw/type size modestr/ }
 
-    method _build_type {
-        my $output = $self->run_cmd(qw/cat-file -t/, $self->sha1);
-        chomp($output);
-        return $output;
+    foreach my $key (qw/ type size /) {
+        method "_build_$key" {
+            $self->_cat_file_with_flag(substr($key, 0, 1))->chomp;
+        }
     }
 
     method _build_modestr {
@@ -43,10 +44,8 @@ class Gitalist::Git::Object {
         return $modestr;
     }
 
-    method _build_size {
-        my $output = $self->run_cmd(qw/cat-file -s/, $self->sha1);
-        chomp($output);
-        return $output;
+    method _cat_file_with_flag ($flag) {
+        $self->run_cmd('cat-file', '-' . $flag, $self->{sha1})
     }
 
 =head2 contents
@@ -55,15 +54,13 @@ Return the contents of a given file.
 
 =cut
 
+    # FIXME - Should be an attribute so it gets cached?
     method contents {
         if ( $self->type ne 'blob' ) {
             die "object $self->sha1 is not a file\n"
         }
 
-        my $output = $self->run_cmd(qw/cat-file -p/, $self->sha1);
-        return unless $output;
-
-        return $output;
+        $self->_cat_file_with_flag('p');
     }
 
 } # end class
index e11da8e..cf3ac4c 100644 (file)
@@ -3,9 +3,9 @@ use MooseX::Declare;
 class Gitalist::Git::Project {
     # FIXME, use Types::Path::Class and coerce
     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-    use MooseX::Types::Moose qw/Str Maybe/;
+    use MooseX::Types::Moose qw/Str Maybe Bool/;
     use DateTime;
-    use Path::Class;
+    use MooseX::Types::Path::Class qw/Dir/;
     use Gitalist::Git::Util;
     use aliased 'Gitalist::Git::Object';
 
@@ -13,7 +13,7 @@ class Gitalist::Git::Project {
 
     has name => ( isa => NonEmptySimpleStr,
                   is => 'ro', required => 1 );
-    has path => ( isa => "Path::Class::Dir",
+    has path => ( isa => Dir,
                   is => 'ro', required => 1);
 
     has description => ( isa => Str,
@@ -34,6 +34,31 @@ class Gitalist::Git::Project {
                    handles => [ 'run_cmd' ],
                );
 
+    has project_dir => ( isa => Dir,
+        is => 'ro',
+        lazy => 1,
+        default => sub {
+            my $self = shift;
+            $self->is_bare
+                ? $self->path
+                : $self->path->subdir('.git')
+        },
+    );
+    has is_bare => (
+        isa => Bool,
+        is => 'ro',
+        lazy => 1,
+        default => sub {
+            my $self = shift;
+            -f $self->path->file('.git', 'HEAD')
+                ? 0
+                : -f $self->path->file('HEAD')
+                    ? 1
+                    : confess("Cannot find " . $self->path . "/.git/HEAD or "
+                        . $self->path . "/HEAD");
+        },
+    );
+
     method BUILD {
         $self->$_() for qw/_util last_change owner description/; # Ensure to build early.
     }
@@ -46,21 +71,21 @@ class Gitalist::Git::Project {
 
     method _build__util {
         Gitalist::Git::Util->new(
-            gitdir => $self->_project_dir($self->path),
+            project => $self,
         );
     }
 
     method _build_description {
         my $description = "";
         eval {
-            $description = $self->path->file('description')->slurp;
+            $description = $self->project_dir->file('description')->slurp;
             chomp $description;
         };
         return $description;
     }
 
     method _build_owner {
-        my ($gecos, $name) = (getpwuid $self->path->stat->uid)[6,0];
+        my ($gecos, $name) = (getpwuid $self->project_dir->stat->uid)[6,0];
         $gecos =~ s/,+$//;
         return length($gecos) ? $gecos : $name;
     }
index efddd96..873565a 100644 (file)
@@ -2,11 +2,15 @@ use MooseX::Declare;
 
 class Gitalist::Git::Repo {
     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-    use Path::Class;
+    use MooseX::Types::Path::Class qw/Dir/;
+    use MooseX::Types::Moose qw/ArrayRef/;
     use Gitalist::Git::Project;
-    has repo_dir => ( isa => NonEmptySimpleStr,
-                      is => 'ro',
-                      required => 1 );
+    has repo_dir => (
+        isa => Dir,
+        is => 'ro',
+        required => 1,
+        coerce => 1,
+    );
 
     method project (NonEmptySimpleStr $project) {
         my $pd = $self->dir_from_project_name($project);
@@ -28,18 +32,6 @@ C<git> repo.
         return -f $dir->file('HEAD') || -f $dir->file('.git', 'HEAD');
     }
 
-=head2 project_dir
-
-The directory under which the given project will reside i.e C<.git/..>
-
-=cut
-
-    method project_dir ($project) {
-        -f $project->file('.git', 'HEAD')
-            ? $project->subdir('.git')
-            : $project;
-    }
-
 =head2 list_projects
 
 For the C<repo_dir> specified in the config return an array of projects where
@@ -47,10 +39,16 @@ each item will contain the contents of L</project_info>.
 
 =cut
 
-    method list_projects {
-        my $base = dir($self->repo_dir);
-        my @ret;
+    has projects => (
+        isa => ArrayRef['Gitalist::Git::Project'],
+        reader => 'list_projects',
+        lazy_build => 1,
+    );
+
+    method _build_projects {
+        my $base = $self->repo_dir;
         my $dh = $base->open || die "Could not open $base";
+        my @ret;
         while (my $file = $dh->read) {
             next if $file =~ /^.{1,2}$/;
 
@@ -58,28 +56,12 @@ each item will contain the contents of L</project_info>.
             next unless -d $obj;
             next unless $self->_is_git_repo($obj);
 
-            # FIXME - Is resolving project_dir here sane?
-            #         I think not, just pass $obj down, and
-            #         resolve $project->path and $project->is_bare
-            #         in BUILDARGS
-            push @ret, Gitalist::Git::Project->new( name => $file,
-                                     path => $self->project_dir($obj),
-                                 );
+            push @ret, Gitalist::Git::Project->new(
+                name => $file,
+                path => $obj,
+            );
         }
 
-        return [sort { $a->{name} cmp $b->{name} } @ret];
+        return [sort { $a->name cmp $b->name } @ret];
     }
-
-=head2 dir_from_project_name
-
-Get the corresponding directory of a given project.
-
-=cut
-
-    method dir_from_project_name (Str $project) {
-        return dir($self->repo_dir)->subdir($project);
-    }
-
-
-
 }                               # end class
index d624c4d..af3717c 100644 (file)
@@ -4,7 +4,12 @@ class Gitalist::Git::Util {
     use File::Which;
     use Git::PurePerl;
     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
-    has gitdir => ( isa => 'Path::Class::Dir', is => 'ro', required => 1 );
+    has project => (
+        isa => 'Gitalist::Git::Project',
+        handles => { gitdir => 'project_dir' },
+        is => 'bare', # No accessor
+        weak_ref => 1, # Weak, you have to hold onto me.
+    );
     has _git      => ( isa => NonEmptySimpleStr, is => 'ro', lazy_build => 1 );
     sub _build__git {
         my $git = File::Which::which('git');
@@ -19,16 +24,15 @@ EOR
         return $git;
     }
 
-    has _gpp      => ( isa => 'Git::PurePerl',   is => 'rw', lazy_build => 1 );
-    method _build__gpp {
-        my $gpp = Git::PurePerl->new(gitdir => $self->gitdir);
-        return $gpp;
-    }
+    has _gpp      => (
+        isa => 'Git::PurePerl', is => 'ro', lazy => 1,
+        default => sub { Git::PurePerl->new(gitdir => shift->gitdir) },
+    );
 
     method run_cmd (@args) {
         unshift @args, ( '--git-dir' => $self->gitdir );
         print STDERR 'RUNNING: ', $self->_git, qq[ @args], $/;
-        
+
         open my $fh, '-|', $self->_git, @args
             or die "failed to run git command";
         binmode $fh, ':encoding(UTF-8)';
@@ -38,10 +42,4 @@ EOR
 
         return $output;
     }
-
-
-
-
-
-#
 } # end class