From b09b9989b43f6b015f0fac9670c1180e97b67972 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Thu, 18 Mar 2010 00:11:52 -0700 Subject: Switched to Module::Build instead of hardcoding paths. --- usr/src/libpiny/Build.PL | 10 ++ usr/src/libpiny/Makefile | 9 -- usr/src/libpiny/Piny.mdwn | 1 - usr/src/libpiny/Piny.pm | 14 --- usr/src/libpiny/Piny/Email.pm | 45 --------- usr/src/libpiny/Piny/Environment.pm | 41 -------- usr/src/libpiny/Piny/Group.pm | 108 -------------------- usr/src/libpiny/Piny/Repo.pm | 169 -------------------------------- usr/src/libpiny/Piny/User.pm | 151 ---------------------------- usr/src/libpiny/debian/changelog | 6 ++ usr/src/libpiny/lib/Piny.pm | 14 +++ usr/src/libpiny/lib/Piny/Email.pm | 45 +++++++++ usr/src/libpiny/lib/Piny/Environment.pm | 41 ++++++++ usr/src/libpiny/lib/Piny/Group.pm | 108 ++++++++++++++++++++ usr/src/libpiny/lib/Piny/Repo.pm | 169 ++++++++++++++++++++++++++++++++ usr/src/libpiny/lib/Piny/User.pm | 151 ++++++++++++++++++++++++++++ 16 files changed, 544 insertions(+), 538 deletions(-) create mode 100644 usr/src/libpiny/Build.PL delete mode 100644 usr/src/libpiny/Makefile delete mode 100644 usr/src/libpiny/Piny.mdwn delete mode 100644 usr/src/libpiny/Piny.pm delete mode 100644 usr/src/libpiny/Piny/Email.pm delete mode 100644 usr/src/libpiny/Piny/Environment.pm delete mode 100644 usr/src/libpiny/Piny/Group.pm delete mode 100644 usr/src/libpiny/Piny/Repo.pm delete mode 100644 usr/src/libpiny/Piny/User.pm create mode 100644 usr/src/libpiny/lib/Piny.pm create mode 100644 usr/src/libpiny/lib/Piny/Email.pm create mode 100644 usr/src/libpiny/lib/Piny/Environment.pm create mode 100644 usr/src/libpiny/lib/Piny/Group.pm create mode 100644 usr/src/libpiny/lib/Piny/Repo.pm create mode 100644 usr/src/libpiny/lib/Piny/User.pm (limited to 'usr') diff --git a/usr/src/libpiny/Build.PL b/usr/src/libpiny/Build.PL new file mode 100644 index 0000000..2a756e7 --- /dev/null +++ b/usr/src/libpiny/Build.PL @@ -0,0 +1,10 @@ +use Module::Build; +Module::Build->new + ( module_name => 'Piny' + , license => 'BSD-3' + , dist_version => '0.2' + , requires => + { 'Moose' => 0 + , 'Email::Valid::Loose' => 0 + } + )->create_build_script( ); diff --git a/usr/src/libpiny/Makefile b/usr/src/libpiny/Makefile deleted file mode 100644 index 578cad8..0000000 --- a/usr/src/libpiny/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -build: - true - -install: - install -o root -g root -m 755 -d $(DESTDIR)/usr/share/perl5/Piny/ - install -o root -g root -m 644 Piny.pm $(DESTDIR)/usr/share/perl5 - install -o root -g root -m 644 Piny/*.pm $(DESTDIR)/usr/share/perl5/Piny - -.PHONY: build install diff --git a/usr/src/libpiny/Piny.mdwn b/usr/src/libpiny/Piny.mdwn deleted file mode 100644 index fb073e3..0000000 --- a/usr/src/libpiny/Piny.mdwn +++ /dev/null @@ -1 +0,0 @@ -[[!map pages="usr/src/libpiny/Piny/* and ! usr/src/libpiny/Piny/*/*"]] diff --git a/usr/src/libpiny/Piny.pm b/usr/src/libpiny/Piny.pm deleted file mode 100644 index 2dc2b84..0000000 --- a/usr/src/libpiny/Piny.pm +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# Licensed under the BSD 3-clause license. - -# This very pointedly does not have a package line. -# That way, you can "use Piny" and import all the Piny packages into your namespace in one fell swoop. -# Of course, you don't get to pass arguments to their import functions anymore. - -use Piny::Email; -use Piny::Environment; -use Piny::Group; -use Piny::Repo; -use Piny::User; - -1; diff --git a/usr/src/libpiny/Piny/Email.pm b/usr/src/libpiny/Piny/Email.pm deleted file mode 100644 index 7ad17d8..0000000 --- a/usr/src/libpiny/Piny/Email.pm +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# Licensed under the BSD 3-clause license. - -package Piny::Email; - -use Moose; -use Moose::Util::TypeConstraints; - -use Email::Valid::Loose; - -# Types - -my $checker = Email::Valid::Loose->new("-fqdn" => 1, "-fudge" => 0, "-local_rules" => 0, "-mxcheck" => 1, "-tldcheck" => 0 ); - -subtype 'EmailAddress' - => as 'Str' - => where { $checker->address( $_ ) } - => message { 'That does not appear to be a valid email address.' } - ; - -# Attributes - -has 'address' => - ( is => 'ro' - , isa => 'EmailAddress' - ); - -# Builder methods - -# If constructed with just one argument, then treat it as an address. -around BUILDARGS => sub { - my ( $orig, $class ) = ( shift, shift ); - - if ( @_ == 1 && ! ref $_[0] ) { - return $class->$orig( address => $_[0] ); - } else { - return $class->$orig( @_ ); - }; -}; - -# Moose boilerplate - -__PACKAGE__->meta->make_immutable; - -1; diff --git a/usr/src/libpiny/Piny/Environment.pm b/usr/src/libpiny/Piny/Environment.pm deleted file mode 100644 index 4430362..0000000 --- a/usr/src/libpiny/Piny/Environment.pm +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# Licensed under the BSD 3-clause license. - -package Piny::Environment; - -use Moose; - -use Piny::User; - -# Attributes - -has 'user' => - ( is => 'ro' - , isa => 'Piny::User' - , lazy_build => 1 - , init_arg => undef - ); - -# Builder methods - -sub _build_user { - my ( $s ) = @_; - - if ( defined $ENV{"SUDO_UID"} ) { - return Piny::User->new( uid => $ENV{"SUDO_UID"} ); - } elsif ( defined $ENV{"SUDO_USER"} ) { - return Piny::User->new( username => $ENV{"SUDO_USER"} ); - } elsif ( defined $ENV{"UID"} ) { - return Piny::User->new( uid => $ENV{"UID"} ); - } elsif ( defined $ENV{"USER"} ) { - return Piny::User->new( username => $ENV{"USERNAME"} ); - } else { - return Piny::User->new( uid => $< ); - }; -}; - -# Moose boilerplate - -__PACKAGE__->meta->make_immutable; - -1; diff --git a/usr/src/libpiny/Piny/Group.pm b/usr/src/libpiny/Piny/Group.pm deleted file mode 100644 index 4b957a7..0000000 --- a/usr/src/libpiny/Piny/Group.pm +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# Licensed under the BSD 3-clause license. - -package Piny::Group; - -use Moose; - -use Piny::User; - -# Attributes - -has 'gid' => - ( is => 'ro' - , isa => 'Int' - , lazy_build => 1 - ); - -has 'groupname' => - ( is => 'ro' - , isa => 'Str' - , lazy_build => 1 - ); - -has 'grent' => - ( is => 'ro' - , isa => 'ArrayRef' - , lazy_build => 1 - , init_arg => undef - ); - -has 'members' => - ( is => 'ro' - , isa => 'ArrayRef[Piny::User]' - , lazy_build => 1 - , init_arg => undef - ); - -# Builder methods - -# If constructed with just one argument, then -# * If that argument is numeric, treat it as a UID. -# * Otherwise, treat it as a username. -around BUILDARGS => sub { - my ( $orig, $class ) = ( shift, shift ); - - if ( @_ == 1 && ! ref $_[0] ) { - if ( $_[0] =~ m/^\d+$/ ) { - return $class->$orig( gid => $_[0] ); - } else { - return $class->$orig( groupname => $_[0] ); - }; - } else { - return $class->$orig( @_ ); - }; -}; - -sub BUILD { - my ( $s ) = @_; - - if ( not ( $s->has_gid( ) or $s->has_groupname( ) ) ) { - die "You must provide either GID or groupname!"; - }; - - if ( $s->has_gid( ) and $s->has_groupname( ) ) { - die "You must not provide both GID and groupname!"; - }; -}; - -sub _build_gid { - my ( $s ) = @_; - - return $s->grent( )->[2]; -}; - -sub _build_groupname { - my ( $s ) = @_; - - return $s->grent( )->[0]; -}; - -sub _build_grent { - my ( $s ) = @_; - - if ( $s->has_gid( ) ) { - my @res = getgrgid( $s->gid( ) ); - die "getgrgid( " . $s->gid( ) . " ) failed: $!" unless @res; - return \@res; - } elsif ( $s->has_groupname( ) ) { - my @res = getgrnam( $s->groupname( ) ); - die "getgrnam( " . $s->groupname( ) . " ) failed: $!" unless @res; - return \@res; - } else { - die "Not enough information provided to lookup group!"; - }; -}; - -sub _build_members { - my ( $s ) = @_; - - return [ ] if ( $s->grent( )->[3] eq "" ); - return [ map { Piny::User->new( username => $_ ) } split( /:/, $s->grent( )->[3] ) ]; -}; - -# Moose boilerplate - -__PACKAGE__->meta->make_immutable; - -1; diff --git a/usr/src/libpiny/Piny/Repo.pm b/usr/src/libpiny/Piny/Repo.pm deleted file mode 100644 index 4783960..0000000 --- a/usr/src/libpiny/Piny/Repo.pm +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# 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; diff --git a/usr/src/libpiny/Piny/User.pm b/usr/src/libpiny/Piny/User.pm deleted file mode 100644 index 53e310b..0000000 --- a/usr/src/libpiny/Piny/User.pm +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright © 2010 Julian Blake Kongslie -# Licensed under the BSD 3-clause license. - -package Piny::User; - -use Moose; - -use Piny::Email; -use Piny::Group; - -# Attributes - -has 'uid' => - ( is => 'ro' - , isa => 'Int' - , lazy_build => 1 - ); - -has 'username' => - ( is => 'ro' - , isa => 'Str' - , lazy_build => 1 - ); - -has 'pwent' => - ( is => 'ro' - , isa => 'ArrayRef' - , lazy_build => 1 - , init_arg => undef - ); - -has 'password_hash' => - ( is => 'ro' - , isa => 'Str' - , lazy_build => 1 - , init_arg => undef - ); - -has 'email' => - ( is => 'ro' - , isa => 'Piny::Email' - , lazy_build => 1 - , init_arg => undef - ); - -has 'groups' => - ( is => 'ro' - , isa => 'ArrayRef[Piny::Group]' - , lazy_build => 1 - , init_arg => undef - ); - -# Builder methods - -# If constructed with just one argument, then -# * If that argument is numeric, treat it as a UID. -# * Otherwise, treat it as a username. -around BUILDARGS => sub { - my ( $orig, $class ) = ( shift, shift ); - - if ( @_ == 1 && ! ref $_[0] ) { - if ( $_[0] =~ m/^\d+$/ ) { - return $class->$orig( uid => $_[0] ); - } else { - return $class->$orig( username => $_[0] ); - }; - } else { - return $class->$orig( @_ ); - }; -}; - -sub BUILD { - my ( $s ) = @_; - - if ( not ( $s->has_uid( ) or $s->has_username( ) ) ) { - die "You must provide either UID or username!"; - }; - - if ( $s->has_uid( ) and $s->has_username( ) ) { - die "You must not provide both UID and username!"; - }; -}; - -sub _build_uid { - my ( $s ) = @_; - - return $s->pwent( )->[2]; -}; - -sub _build_username { - my ( $s ) = @_; - - return $s->pwent( )->[0]; -}; - -sub _build_pwent { - my ( $s ) = @_; - - if ( $s->has_uid( ) ) { - my @res = getpwuid( $s->uid( ) ); - die "getpwuid( " . $s->uid( ) . " ) failed: $!" unless @res; - return \@res; - } elsif ( $s->has_username( ) ) { - my @res = getpwnam( $s->username( ) ); - die "getpwnam( " . $s->username( ) . " ) failed: $!" unless @res; - return \@res; - } else { - die "Not enough information provided to lookup user!"; - }; -}; - -sub _build_password_hash { - my ( $s ) = @_; - - return $s->pwent( )->[1]; -}; - -sub _build_email { - my ( $s ) = @_; - - return Piny::Email->new( address => $s->pwent( )->[6] ); -}; - -sub _build_groups { - my ( $s ) = @_; - - my @res; - my @ent; - - endgrent( ); - - while ( @ent = getgrent( ) ) { - next if ( $ent[3] eq "" ); - foreach my $member ( split( /:/, $ent[3] ) ) { - if ( $member eq $s->username( ) ) { - push @res, Piny::Group->new( gid => $ent[2] ); - last; - }; - }; - }; - - endgrent( ); - - return \@res; -}; - -# Moose boilerplate - -__PACKAGE__->meta->make_immutable; - -1; diff --git a/usr/src/libpiny/debian/changelog b/usr/src/libpiny/debian/changelog index 72b3436..cc1c8ef 100644 --- a/usr/src/libpiny/debian/changelog +++ b/usr/src/libpiny/debian/changelog @@ -1,3 +1,9 @@ +libpiny-perl (0.2-1) unstable; urgency=low + + * Switched to Module::Build because it seems marginally sane. + + -- Julian Blake Kongslie Thu, 18 Mar 2010 00:08:05 -0700 + libpiny-perl (0.1-1) unstable; urgency=low * Initial release. diff --git a/usr/src/libpiny/lib/Piny.pm b/usr/src/libpiny/lib/Piny.pm new file mode 100644 index 0000000..2dc2b84 --- /dev/null +++ b/usr/src/libpiny/lib/Piny.pm @@ -0,0 +1,14 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +# This very pointedly does not have a package line. +# That way, you can "use Piny" and import all the Piny packages into your namespace in one fell swoop. +# Of course, you don't get to pass arguments to their import functions anymore. + +use Piny::Email; +use Piny::Environment; +use Piny::Group; +use Piny::Repo; +use Piny::User; + +1; diff --git a/usr/src/libpiny/lib/Piny/Email.pm b/usr/src/libpiny/lib/Piny/Email.pm new file mode 100644 index 0000000..7ad17d8 --- /dev/null +++ b/usr/src/libpiny/lib/Piny/Email.pm @@ -0,0 +1,45 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +package Piny::Email; + +use Moose; +use Moose::Util::TypeConstraints; + +use Email::Valid::Loose; + +# Types + +my $checker = Email::Valid::Loose->new("-fqdn" => 1, "-fudge" => 0, "-local_rules" => 0, "-mxcheck" => 1, "-tldcheck" => 0 ); + +subtype 'EmailAddress' + => as 'Str' + => where { $checker->address( $_ ) } + => message { 'That does not appear to be a valid email address.' } + ; + +# Attributes + +has 'address' => + ( is => 'ro' + , isa => 'EmailAddress' + ); + +# Builder methods + +# If constructed with just one argument, then treat it as an address. +around BUILDARGS => sub { + my ( $orig, $class ) = ( shift, shift ); + + if ( @_ == 1 && ! ref $_[0] ) { + return $class->$orig( address => $_[0] ); + } else { + return $class->$orig( @_ ); + }; +}; + +# Moose boilerplate + +__PACKAGE__->meta->make_immutable; + +1; diff --git a/usr/src/libpiny/lib/Piny/Environment.pm b/usr/src/libpiny/lib/Piny/Environment.pm new file mode 100644 index 0000000..4430362 --- /dev/null +++ b/usr/src/libpiny/lib/Piny/Environment.pm @@ -0,0 +1,41 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +package Piny::Environment; + +use Moose; + +use Piny::User; + +# Attributes + +has 'user' => + ( is => 'ro' + , isa => 'Piny::User' + , lazy_build => 1 + , init_arg => undef + ); + +# Builder methods + +sub _build_user { + my ( $s ) = @_; + + if ( defined $ENV{"SUDO_UID"} ) { + return Piny::User->new( uid => $ENV{"SUDO_UID"} ); + } elsif ( defined $ENV{"SUDO_USER"} ) { + return Piny::User->new( username => $ENV{"SUDO_USER"} ); + } elsif ( defined $ENV{"UID"} ) { + return Piny::User->new( uid => $ENV{"UID"} ); + } elsif ( defined $ENV{"USER"} ) { + return Piny::User->new( username => $ENV{"USERNAME"} ); + } else { + return Piny::User->new( uid => $< ); + }; +}; + +# Moose boilerplate + +__PACKAGE__->meta->make_immutable; + +1; diff --git a/usr/src/libpiny/lib/Piny/Group.pm b/usr/src/libpiny/lib/Piny/Group.pm new file mode 100644 index 0000000..4b957a7 --- /dev/null +++ b/usr/src/libpiny/lib/Piny/Group.pm @@ -0,0 +1,108 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +package Piny::Group; + +use Moose; + +use Piny::User; + +# Attributes + +has 'gid' => + ( is => 'ro' + , isa => 'Int' + , lazy_build => 1 + ); + +has 'groupname' => + ( is => 'ro' + , isa => 'Str' + , lazy_build => 1 + ); + +has 'grent' => + ( is => 'ro' + , isa => 'ArrayRef' + , lazy_build => 1 + , init_arg => undef + ); + +has 'members' => + ( is => 'ro' + , isa => 'ArrayRef[Piny::User]' + , lazy_build => 1 + , init_arg => undef + ); + +# Builder methods + +# If constructed with just one argument, then +# * If that argument is numeric, treat it as a UID. +# * Otherwise, treat it as a username. +around BUILDARGS => sub { + my ( $orig, $class ) = ( shift, shift ); + + if ( @_ == 1 && ! ref $_[0] ) { + if ( $_[0] =~ m/^\d+$/ ) { + return $class->$orig( gid => $_[0] ); + } else { + return $class->$orig( groupname => $_[0] ); + }; + } else { + return $class->$orig( @_ ); + }; +}; + +sub BUILD { + my ( $s ) = @_; + + if ( not ( $s->has_gid( ) or $s->has_groupname( ) ) ) { + die "You must provide either GID or groupname!"; + }; + + if ( $s->has_gid( ) and $s->has_groupname( ) ) { + die "You must not provide both GID and groupname!"; + }; +}; + +sub _build_gid { + my ( $s ) = @_; + + return $s->grent( )->[2]; +}; + +sub _build_groupname { + my ( $s ) = @_; + + return $s->grent( )->[0]; +}; + +sub _build_grent { + my ( $s ) = @_; + + if ( $s->has_gid( ) ) { + my @res = getgrgid( $s->gid( ) ); + die "getgrgid( " . $s->gid( ) . " ) failed: $!" unless @res; + return \@res; + } elsif ( $s->has_groupname( ) ) { + my @res = getgrnam( $s->groupname( ) ); + die "getgrnam( " . $s->groupname( ) . " ) failed: $!" unless @res; + return \@res; + } else { + die "Not enough information provided to lookup group!"; + }; +}; + +sub _build_members { + my ( $s ) = @_; + + return [ ] if ( $s->grent( )->[3] eq "" ); + return [ map { Piny::User->new( username => $_ ) } split( /:/, $s->grent( )->[3] ) ]; +}; + +# Moose boilerplate + +__PACKAGE__->meta->make_immutable; + +1; 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 +# 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; diff --git a/usr/src/libpiny/lib/Piny/User.pm b/usr/src/libpiny/lib/Piny/User.pm new file mode 100644 index 0000000..53e310b --- /dev/null +++ b/usr/src/libpiny/lib/Piny/User.pm @@ -0,0 +1,151 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +package Piny::User; + +use Moose; + +use Piny::Email; +use Piny::Group; + +# Attributes + +has 'uid' => + ( is => 'ro' + , isa => 'Int' + , lazy_build => 1 + ); + +has 'username' => + ( is => 'ro' + , isa => 'Str' + , lazy_build => 1 + ); + +has 'pwent' => + ( is => 'ro' + , isa => 'ArrayRef' + , lazy_build => 1 + , init_arg => undef + ); + +has 'password_hash' => + ( is => 'ro' + , isa => 'Str' + , lazy_build => 1 + , init_arg => undef + ); + +has 'email' => + ( is => 'ro' + , isa => 'Piny::Email' + , lazy_build => 1 + , init_arg => undef + ); + +has 'groups' => + ( is => 'ro' + , isa => 'ArrayRef[Piny::Group]' + , lazy_build => 1 + , init_arg => undef + ); + +# Builder methods + +# If constructed with just one argument, then +# * If that argument is numeric, treat it as a UID. +# * Otherwise, treat it as a username. +around BUILDARGS => sub { + my ( $orig, $class ) = ( shift, shift ); + + if ( @_ == 1 && ! ref $_[0] ) { + if ( $_[0] =~ m/^\d+$/ ) { + return $class->$orig( uid => $_[0] ); + } else { + return $class->$orig( username => $_[0] ); + }; + } else { + return $class->$orig( @_ ); + }; +}; + +sub BUILD { + my ( $s ) = @_; + + if ( not ( $s->has_uid( ) or $s->has_username( ) ) ) { + die "You must provide either UID or username!"; + }; + + if ( $s->has_uid( ) and $s->has_username( ) ) { + die "You must not provide both UID and username!"; + }; +}; + +sub _build_uid { + my ( $s ) = @_; + + return $s->pwent( )->[2]; +}; + +sub _build_username { + my ( $s ) = @_; + + return $s->pwent( )->[0]; +}; + +sub _build_pwent { + my ( $s ) = @_; + + if ( $s->has_uid( ) ) { + my @res = getpwuid( $s->uid( ) ); + die "getpwuid( " . $s->uid( ) . " ) failed: $!" unless @res; + return \@res; + } elsif ( $s->has_username( ) ) { + my @res = getpwnam( $s->username( ) ); + die "getpwnam( " . $s->username( ) . " ) failed: $!" unless @res; + return \@res; + } else { + die "Not enough information provided to lookup user!"; + }; +}; + +sub _build_password_hash { + my ( $s ) = @_; + + return $s->pwent( )->[1]; +}; + +sub _build_email { + my ( $s ) = @_; + + return Piny::Email->new( address => $s->pwent( )->[6] ); +}; + +sub _build_groups { + my ( $s ) = @_; + + my @res; + my @ent; + + endgrent( ); + + while ( @ent = getgrent( ) ) { + next if ( $ent[3] eq "" ); + foreach my $member ( split( /:/, $ent[3] ) ) { + if ( $member eq $s->username( ) ) { + push @res, Piny::Group->new( gid => $ent[2] ); + last; + }; + }; + }; + + endgrent( ); + + return \@res; +}; + +# Moose boilerplate + +__PACKAGE__->meta->make_immutable; + +1; -- cgit v1.2.3