Index page fixes.
[catagits/Gitalist.git] / lib / Gitalist / Git / Project.pm
CommitLineData
56b6dbe6 1use MooseX::Declare;
2
3class 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;
941bb5a1 8 use Gitalist::Git::Util;
a8a8f8f9 9 use aliased 'Gitalist::Git::Object';
56b6dbe6 10
4baaeeef 11 our $SHA1RE = qr/[0-9a-fA-F]{40}/;
12
56b6dbe6 13 has name => ( isa => NonEmptySimpleStr,
14 is => 'ro' );
15 has path => ( isa => "Path::Class::Dir",
16 is => 'ro');
17
4ce9e8a0 18 has description => ( isa => 'Str',
56b6dbe6 19 is => 'ro',
20 lazy_build => 1,
21 );
22 has owner => ( isa => NonEmptySimpleStr,
23 is => 'ro',
24 lazy_build => 1,
25 );
26 has last_change => ( isa => 'DateTime',
27 is => 'ro',
28 lazy_build => 1,
29 );
941bb5a1 30 has _util => ( isa => 'Gitalist::Git::Util',
31 is => 'ro',
32 lazy_build => 1,
33 handles => [ 'run_cmd' ],
34 );
56b6dbe6 35
941bb5a1 36 method _build__util {
37 my $util = Gitalist::Git::Util->new(
d9a9b56b 38 gitdir => $self->project_dir($self->path),
941bb5a1 39 );
40 return $util;
41 }
56b6dbe6 42
43 method _build_description {
4ce9e8a0 44 my $description = "";
d9a9b56b 45 eval {
46 $description = $self->path->file('description')->slurp;
47 chomp $description;
48 };
56b6dbe6 49 return $description;
50 }
51
52 method _build_owner {
53 my $owner = (getpwuid $self->path->stat->uid)[6];
54 $owner =~ s/,+$//;
55 return $owner;
56 }
57
58 method _build_last_change {
59 my $last_change;
60 my $output = $self->run_cmd(
61 qw{ for-each-ref --format=%(committer)
62 --sort=-committerdate --count=1 refs/heads
63 });
64 if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
65 my $dt = DateTime->from_epoch(epoch => $epoch);
66 $dt->set_time_zone($tz);
67 $last_change = $dt;
68 }
69 return $last_change;
70 }
71
4baaeeef 72=head2 head_hash
73
74Find the hash of a given head (defaults to HEAD).
75
76=cut
77
78 method head_hash (Str $head?) {
79 my $output = $self->run_cmd(qw/rev-parse --verify/, $head || 'HEAD' );
80 return unless defined $output;
81
82 my($sha1) = $output =~ /^($SHA1RE)$/;
83 return $sha1;
84 }
85
a8a8f8f9 86=head2 list_tree
87
88Return an array of contents for a given tree.
89The tree is specified by sha1, and defaults to HEAD.
90The keys for each item will be:
91
92 mode
93 type
94 object
95 file
96
97=cut
98
99 method list_tree (Str $sha1?) {
100 $sha1 ||= $self->head_hash;
101
102 my $output = $self->run_cmd(qw/ls-tree -z/, $sha1);
103 return unless defined $output;
104
105 my @ret;
106 for my $line (split /\0/, $output) {
107 my ($mode, $type, $object, $file) = split /\s+/, $line, 4;
108 push @ret, Object->new( mode => oct $mode,
109 type => $type,
110 sha1 => $object,
111 file => $file,
50394a3e 112 project => $self,
a8a8f8f9 113 );
114 }
115 return @ret;
116 }
117
118
caba5c95 119 method project_dir {
120 my $dir = $self->path->stringify;
56b6dbe6 121 $dir .= '/.git'
122 if -f dir($dir)->file('.git/HEAD');
123 return $dir;
124 }
125
56b6dbe6 126 # Compatibility
127
caba5c95 128=head2 info
56b6dbe6 129
130Returns a hash containing properties of this project. The keys will
131be:
132
133 name
134 description (empty if .git/description is empty/unnamed)
135 owner
136 last_change
137
138=cut
139
caba5c95 140 method info {
56b6dbe6 141 return {
142 name => $self->name,
143 description => $self->description,
144 owner => $self->owner,
145 last_change => $self->last_change,
146 };
147 };
148
149} # end class