summaryrefslogtreecommitdiff
path: root/usr/src/libpiny/lib/Piny/Repo.pm
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/libpiny/lib/Piny/Repo.pm')
-rw-r--r--usr/src/libpiny/lib/Piny/Repo.pm169
1 files changed, 169 insertions, 0 deletions
diff --git a/usr/src/libpiny/lib/Piny/Repo.pm b/usr/src/libpiny/lib/Piny/Repo.pm
new file mode 100644
index 0000000..4783960
--- /dev/null
+++ b/usr/src/libpiny/lib/Piny/Repo.pm
@@ -0,0 +1,169 @@
+# Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
+# Licensed under the BSD 3-clause license.
+
+package Piny::Repo;
+
+use Moose;
+
+use File::Find qw( find );
+
+use Piny::User;
+
+# Attributes
+
+has 'name' =>
+ ( is => 'rw'
+ , isa => 'Str'
+ , trigger => \&_rename_repo
+ , required => 1
+ );
+
+has 'path' =>
+ ( is => 'ro'
+ , isa => 'Str'
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+has 'description' =>
+ ( is => 'rw'
+ , isa => 'Str'
+ , trigger => \&_set_description
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+has 'repostat' =>
+ ( is => 'ro'
+ , isa => 'ArrayRef'
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+has 'owner' =>
+ ( is => 'rw'
+ , isa => 'Piny::User'
+ , trigger => \&_change_owner
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+has 'globally_readable' =>
+ ( is => 'ro'
+ , isa => 'Bool'
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+has 'globally_writable' =>
+ ( is => 'ro'
+ , isa => 'Bool'
+ , lazy_build => 1
+ , init_arg => undef
+ );
+
+# Triggers
+
+sub _rename_repo {
+ my ( $s, $new_name, $old_name ) = @_;
+
+ return unless defined $old_name;
+
+ my $olddir = "/srv/git/$old_name.git";
+ my $newdir = "/srv/git/$new_name.git";
+
+ rename( $olddir, $newdir ) or die "Couldn't rename $olddir to $newdir: $!";
+
+ $s->clear_path( );
+};
+
+sub _set_description {
+ my ( $s, $new_description, $old_description ) = @_;
+
+ return unless defined $old_description;
+
+ open( my $fd, ">", $s->path( ) . "/description" ) or die "Unable to open " . $s->path( ) . "/description for writing: $!";
+ print $fd $new_description;
+ close( $fd ) or die "Error when closing " . $s->path( ) . "/description: $!";
+};
+
+sub _change_owner {
+ my ( $s, $new_owner, $old_owner ) = @_;
+
+ return unless defined $old_owner;
+
+ find( { wanted => sub { chown( $new_owner->uid( ), -1, $_ ) or die "Couldn't chown $_: $!"; }, no_chdir => 1 }, $s->path( ) );
+};
+
+# Builder methods
+
+# If constructed with just one argument, then treat it as a repo name.
+around BUILDARGS => sub {
+ my ( $orig, $class ) = ( shift, shift );
+
+ if ( @_ == 1 && ! ref $_[0] ) {
+ return $class->$orig( name => $_[0] );
+ } else {
+ return $class->$orig( @_ );
+ };
+};
+
+sub _build_path {
+ my ( $s ) = @_;
+
+ my $dir = "/srv/git/" . $s->name( ) . ".git";
+
+ if ( -d $dir ) {
+ return $dir;
+ } else {
+ die "Expected repo $dir does not exist!";
+ };
+};
+
+sub _build_description {
+ my ( $s ) = @_;
+
+ open( my $d, "<", $s->path( ) . "/description" ) or die "Unable to open " . $s->path( ) . "/description: $!";
+ my $desc;
+ {
+ local $/ = undef;
+ $desc = <$d>;
+ };
+ close( $d );
+
+ return $desc;
+};
+
+sub _build_repostat {
+ my ( $s ) = @_;
+
+ my @res = stat( $s->path( ) );
+ die "stat( " . $s->path( ) . " ) failed: $!" unless @res;
+ return \@res;
+};
+
+sub _build_owner {
+ my ( $s ) = @_;
+
+ my ( $uid ) = $s->repostat( )->[4];
+
+ return Piny::User->new( uid => $uid );
+};
+
+sub _build_globally_readable {
+ my ( $s ) = @_;
+
+ return ( $s->repostat( )->[2] & 0444 ) == 0444;
+};
+
+sub _build_globally_writable {
+ my ( $s ) = @_;
+
+ return ( $s->repostat( )->[2] & 0111 ) == 0111;
+};
+
+# Moose boilerplate
+
+__PACKAGE__->meta->make_immutable;
+
+1;