MANIFEST
MANIFEST.bak
*~
+.#*
+*#
--- /dev/null
+use MooseX::Declare;
+
+class Gitalist::Git::Project {
+ # FIXME, use Types::Path::Class and coerce
+ use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
+ use DateTime;
+ use Path::Class;
+
+ has name => ( isa => NonEmptySimpleStr,
+ is => 'ro' );
+ has path => ( isa => "Path::Class::Dir",
+ is => 'ro');
+
+ has description => ( isa => NonEmptySimpleStr,
+ is => 'ro',
+ lazy_build => 1,
+ );
+ has owner => ( isa => NonEmptySimpleStr,
+ is => 'ro',
+ lazy_build => 1,
+ );
+ has last_change => ( isa => 'DateTime',
+ is => 'ro',
+ lazy_build => 1,
+ );
+
+
+ method _build_description {
+ my $description = $self->path->file('description')->slurp;
+ chomp $description;
+ return $description;
+ }
+
+ method _build_owner {
+ my $owner = (getpwuid $self->path->stat->uid)[6];
+ $owner =~ s/,+$//;
+ return $owner;
+ }
+
+ method _build_last_change {
+ my $last_change;
+ my $output = $self->run_cmd(
+ qw{ for-each-ref --format=%(committer)
+ --sort=-committerdate --count=1 refs/heads
+ });
+ if (my ($epoch, $tz) = $output =~ /\s(\d+)\s+([+-]\d+)$/) {
+ my $dt = DateTime->from_epoch(epoch => $epoch);
+ $dt->set_time_zone($tz);
+ $last_change = $dt;
+ }
+ return $last_change;
+ }
+
+
+=head2 run_cmd
+
+Call out to the C<git> binary and return a string consisting of the output.
+
+=cut
+
+ method run_cmd (@args) {
+ unshift @args, ( '--git-dir' => $self->path );
+ 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)';
+
+ my $output = do { local $/ = undef; <$fh> };
+ close $fh;
+
+ return $output;
+ }
+
+ has _git => ( isa => NonEmptySimpleStr, is => 'ro', lazy_build => 1 );
+ use File::Which;
+ method _build__git {
+ my $git = File::Which::which('git');
+
+ if (!$git) {
+ die <<EOR;
+Could not find a git executable.
+Please specify the which git executable to use in gitweb.yml
+EOR
+ }
+
+ return $git;
+ }
+ has _gpp => ( isa => 'Git::PurePerl', is => 'rw', lazy_build => 1 );
+ use Git::PurePerl;
+ method _build__gpp {
+ my $gpp = Git::PurePerl->new(gitdir => $self->path);
+ return $gpp;
+ }
+
+ method project_dir (Path::Class::Dir $project) {
+ my $dir = $project->stringify;
+ $dir .= '/.git'
+ if -f dir($dir)->file('.git/HEAD');
+ return $dir;
+ }
+
+
+ # Compatibility
+
+=head2 project_info
+
+Returns a hash containing properties of this project. The keys will
+be:
+
+ name
+ description (empty if .git/description is empty/unnamed)
+ owner
+ last_change
+
+=cut
+
+ method project_info {
+ return {
+ name => $self->name,
+ description => $self->description,
+ owner => $self->owner,
+ last_change => $self->last_change,
+ };
+ };
+
+} # end class
--- /dev/null
+use MooseX::Declare;
+
+class Gitalist::Git::Repo {
+ use MooseX::Types::Common::String qw/NonEmptySimpleStr/;
+ use Path::Class;
+ use Gitalist::Git::Project;
+ has repo_dir => ( isa => NonEmptySimpleStr,
+ is => 'ro',
+ lazy_build => 1 );
+
+ method _build_repo_dir {
+ return Gitalist->config->{repo_dir};
+ }
+
+=head2 _is_git_repo
+
+Determine whether a given directory (as a L<Path::Class::Dir> object) is a
+C<git> repo.
+
+=cut
+
+ method _is_git_repo ($dir) {
+ 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) {
+ my $dir = blessed($project) && $project->isa('Path::Class::Dir')
+ ? $project->stringify
+ : $self->dir_from_project_name($project);
+
+ $dir .= '/.git'
+ if -f dir($dir)->file('.git/HEAD');
+
+ return $dir;
+ }
+
+=head2 list_projects
+
+For the C<repo_dir> specified in the config return an array of projects where
+each item will contain the contents of L</project_info>.
+
+=cut
+
+ method list_projects {
+ my $base = dir($self->repo_dir);
+ my @ret;
+ my $dh = $base->open || die "Could not open $base";
+ while (my $file = $dh->read) {
+ next if $file =~ /^.{1,2}$/;
+
+ my $obj = $base->subdir($file);
+ next unless -d $obj;
+ next unless $self->_is_git_repo($obj);
+
+ # XXX Leaky abstraction alert!
+ my $is_bare = !-d $obj->subdir('.git');
+
+ my $name = (File::Spec->splitdir($obj))[-1];
+ push @ret, Gitalist::Git::Project->new( name => $name,
+ path => $obj,
+ );
+ #push @ret, {
+ # name => ($name . ( $is_bare ? '' : '/.git' )),
+ # $self->get_project_properties(
+ # $is_bare ? $obj : $obj->subdir('.git')
+ # ),
+ #};
+ }
+
+ 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
--- /dev/null
+use MooseX::Declare;
+
+class Gitalist::Git::Util {
+ has git => ( isa => NonEmptySimpleStr, is => 'ro', lazy_build => 1 );
+ sub _build_git {
+ my $git = File::Which::which('git');
+
+ if (!$git) {
+ die <<EOR;
+Could not find a git executable.
+Please specify the which git executable to use in gitweb.yml
+EOR
+ }
+
+ return $git;
+ }
+
+
+
+
+
+
+
+#
+} # end class
--- /dev/null
+use strict;
+use warnings;
+use FindBin qw/$Bin/;
+use Test::More qw/no_plan/;
+
+use Data::Dumper;
+
+BEGIN { use_ok 'Gitalist::Git::Project' }
+
+use Path::Class;
+my $proj = Gitalist::Git::Project->new(
+ path => dir("$Bin/../lib/repositories/repo1"),
+ name => "repo1",
+);
+isa_ok($proj, 'Gitalist::Git::Project');
+
+like( $proj->_git, qr#/git$#, 'git binary found');
+isa_ok($proj->_gpp, 'Git::PurePerl', 'gpp instance created');
+like($proj->path, qr#/repositories/repo1#, 'repository path is set');
+is($proj->name, qw/repo1/, 'repository name is set');
+is($proj->description, qq/some test repository/, 'repository description loaded');
+isa_ok($proj->last_change, 'DateTime', 'last_change');
+
+
--- /dev/null
+use strict;
+use warnings;
+use FindBin qw/$Bin/;
+use Test::More qw/no_plan/;
+
+use Data::Dumper;
+
+BEGIN { use_ok 'Gitalist::Git::Repo' }
+
+my $repo = Gitalist::Git::Repo->new( repo_dir => "$Bin/../lib/repositories" );
+isa_ok($repo, 'Gitalist::Git::Repo');
+
+is($repo->repo_dir, "$Bin/../lib/repositories", "repo->repo_dir is correct" );
+
+my $project_list = $repo->list_projects;
+warn(Dumper($project_list));
+isa_ok(@$project_list[0], 'Gitalist::Git::Project');