Move nuts and bolts of git access out of the Project class.
[catagits/Gitalist.git] / lib / Gitalist / Git / Project.pm
1 use MooseX::Declare;
2
3 class Gitalist::Git::Project {
4     # FIXME, use Types::Path::Class and coerce
5     use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
6     use DateTime;
7     use Path::Class;
8     use Gitalist::Git::Util;
9
10     has name => ( isa => NonEmptySimpleStr,
11                   is => 'ro' );
12     has path => ( isa => "Path::Class::Dir",
13                   is => 'ro');
14
15     has description => ( isa => NonEmptySimpleStr,
16                          is => 'ro',
17                          lazy_build => 1,
18                      );
19     has owner => ( isa => NonEmptySimpleStr,
20                    is => 'ro',
21                    lazy_build => 1,
22                );
23     has last_change => ( isa => 'DateTime',
24                          is => 'ro',
25                          lazy_build => 1,
26                      );
27     has _util => ( isa => 'Gitalist::Git::Util',
28                    is => 'ro',
29                    lazy_build => 1,
30                    handles => [ 'run_cmd' ],
31                );
32
33     method _build__util {
34         my $util = Gitalist::Git::Util->new(
35             gitdir => $self->path,
36         );
37         return $util;
38     }
39     
40     method _build_description {
41         my $description = $self->path->file('description')->slurp;
42         chomp $description;
43         return $description;
44     }
45
46     method _build_owner {
47         my $owner = (getpwuid $self->path->stat->uid)[6];
48         $owner =~ s/,+$//;
49         return $owner;
50     }
51     
52     method _build_last_change {
53         my $last_change;
54         my $output = $self->run_cmd(
55             qw{ for-each-ref --format=%(committer)
56                 --sort=-committerdate --count=1 refs/heads
57           });
58         if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
59             my $dt = DateTime->from_epoch(epoch => $epoch);
60             $dt->set_time_zone($tz);
61             $last_change = $dt;
62         }
63         return $last_change;
64     }
65
66     method project_dir (Path::Class::Dir $project) {
67         my $dir = $project->stringify;
68         $dir .= '/.git'
69             if -f dir($dir)->file('.git/HEAD');
70         return $dir;
71     }
72
73     # Compatibility
74
75 =head2 project_info
76
77 Returns a hash containing properties of this project. The keys will
78 be:
79
80         name
81         description (empty if .git/description is empty/unnamed)
82         owner
83         last_change
84
85 =cut
86
87     method project_info {
88         return {
89             name => $self->name,
90             description => $self->description,
91             owner => $self->owner,
92             last_change => $self->last_change,
93         };
94     };
95     
96 } # end class