Start conversion to new model
[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
18 has description => ( isa => NonEmptySimpleStr,
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(
38 gitdir => $self->path,
39 );
40 return $util;
41 }
56b6dbe6 42
43 method _build_description {
44 my $description = $self->path->file('description')->slurp;
45 chomp $description;
46 return $description;
47 }
48
49 method _build_owner {
50 my $owner = (getpwuid $self->path->stat->uid)[6];
51 $owner =~ s/,+$//;
52 return $owner;
53 }
54
55 method _build_last_change {
56 my $last_change;
57 my $output = $self->run_cmd(
58 qw{ for-each-ref --format=%(committer)
59 --sort=-committerdate --count=1 refs/heads
60 });
61 if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
62 my $dt = DateTime->from_epoch(epoch => $epoch);
63 $dt->set_time_zone($tz);
64 $last_change = $dt;
65 }
66 return $last_change;
67 }
68
4baaeeef 69=head2 head_hash
70
71Find the hash of a given head (defaults to HEAD).
72
73=cut
74
75 method head_hash (Str $head?) {
76 my $output = $self->run_cmd(qw/rev-parse --verify/, $head || 'HEAD' );
77 return unless defined $output;
78
79 my($sha1) = $output =~ /^($SHA1RE)$/;
80 return $sha1;
81 }
82
a8a8f8f9 83=head2 list_tree
84
85Return an array of contents for a given tree.
86The tree is specified by sha1, and defaults to HEAD.
87The keys for each item will be:
88
89 mode
90 type
91 object
92 file
93
94=cut
95
96 method list_tree (Str $sha1?) {
97 $sha1 ||= $self->head_hash;
98
99 my $output = $self->run_cmd(qw/ls-tree -z/, $sha1);
100 return unless defined $output;
101
102 my @ret;
103 for my $line (split /\0/, $output) {
104 my ($mode, $type, $object, $file) = split /\s+/, $line, 4;
105 push @ret, Object->new( mode => oct $mode,
106 type => $type,
107 sha1 => $object,
108 file => $file,
50394a3e 109 project => $self,
a8a8f8f9 110 );
111 }
112 return @ret;
113 }
114
115
caba5c95 116 method project_dir {
117 my $dir = $self->path->stringify;
56b6dbe6 118 $dir .= '/.git'
119 if -f dir($dir)->file('.git/HEAD');
120 return $dir;
121 }
122
56b6dbe6 123 # Compatibility
124
caba5c95 125=head2 info
56b6dbe6 126
127Returns a hash containing properties of this project. The keys will
128be:
129
130 name
131 description (empty if .git/description is empty/unnamed)
132 owner
133 last_change
134
135=cut
136
caba5c95 137 method info {
56b6dbe6 138 return {
139 name => $self->name,
140 description => $self->description,
141 owner => $self->owner,
142 last_change => $self->last_change,
143 };
144 };
145
146} # end class