3 class Gitalist::Git::Project {
4 # FIXME, use Types::Path::Class and coerce
5 use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
6 use MooseX::Types::Moose qw/Str Maybe/;
9 use Gitalist::Git::Util;
10 use aliased 'Gitalist::Git::Object';
12 our $SHA1RE = qr/[0-9a-fA-F]{40}/;
14 has name => ( isa => NonEmptySimpleStr,
15 is => 'ro', required => 1 );
16 has path => ( isa => "Path::Class::Dir",
17 is => 'ro', required => 1);
19 has description => ( isa => Str,
23 has owner => ( isa => NonEmptySimpleStr,
27 has last_change => ( isa => Maybe['DateTime'],
31 has _util => ( isa => 'Gitalist::Git::Util',
34 handles => [ 'run_cmd' ],
38 $self->$_() for qw/_util last_change owner description/; # Ensure to build early.
42 Gitalist::Git::Util->new(
43 gitdir => $self->path,
47 method _build_description {
50 $description = $self->path->file('description')->slurp;
57 my ($gecos, $name) = (getpwuid $self->path->stat->uid)[6,0];
59 return length($gecos) ? $gecos : $name;
62 method _build_last_change {
64 my $output = $self->run_cmd(
65 qw{ for-each-ref --format=%(committer)
66 --sort=-committerdate --count=1 refs/heads
68 if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
69 my $dt = DateTime->from_epoch(epoch => $epoch);
70 $dt->set_time_zone($tz);
78 Find the hash of a given head (defaults to HEAD).
82 method head_hash (Str $head?) {
83 my $output = $self->run_cmd(qw/rev-parse --verify/, $head || 'HEAD' );
84 return unless defined $output;
86 my($sha1) = $output =~ /^($SHA1RE)$/;
92 Return an array of contents for a given tree.
93 The tree is specified by sha1, and defaults to HEAD.
94 The keys for each item will be:
103 method list_tree (Str $sha1?) {
104 $sha1 ||= $self->head_hash;
106 my $output = $self->run_cmd(qw/ls-tree -z/, $sha1);
107 return unless defined $output;
110 for my $line (split /\0/, $output) {
111 my ($mode, $type, $object, $file) = split /\s+/, $line, 4;
112 push @ret, Object->new( mode => oct $mode,
122 use Gitalist::Git::Object;
123 method get_object (Str $sha1) {
124 return Gitalist::Git::Object->new(
130 # Should be in ::Object
131 method get_object_mode_string (Gitalist::Git::Object $object) {
132 return unless $object && $object->{mode};
133 return $object->{modestr};
136 method get_object_type ($object) {
137 chomp(my $output = $self->run_cmd(qw/cat-file -t/, $object));
138 return unless $output;
143 method cat_file ($object) {
144 my $type = $self->get_object_type($object);
145 die "object `$object' is not a file\n"
146 if (!defined $type || $type ne 'blob');
148 my $output = $self->run_cmd(qw/cat-file -p/, $object);
149 return unless $output;
154 method hash_by_path ($base, $path?, $type?) {
158 my $output = $self->run_cmd('ls-tree', $base, '--', $path)
160 my($line) = $output ? split(/\n/, $output) : ();
162 #'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa panic.c'
163 $line =~ m/^([0-9]+) (.+) ($SHA1RE)\t/;
164 return defined $type && $type ne $2
175 Returns a hash containing properties of this project. The keys will
179 description (empty if .git/description is empty/unnamed)
188 description => $self->description,
189 owner => $self->owner,
190 last_change => $self->last_change,