From d809044c2f00d7f8358dc8013c4e6639760aba67 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Wed, 7 Jul 2010 15:44:46 -0700 Subject: Revising newrepo to use libpiny. --- usr/src/libpiny/lib/Piny.pm | 1 + usr/src/libpiny/lib/Piny/Email.pm | 2 + usr/src/libpiny/lib/Piny/Repo.pm | 127 ++++++++++++++++++++++++++----- usr/src/libpiny/lib/Piny/User.pm | 4 +- usr/src/libpiny/lib/Piny/User/IkiWiki.pm | 33 ++++++++ 5 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 usr/src/libpiny/lib/Piny/User/IkiWiki.pm (limited to 'usr/src/libpiny/lib') diff --git a/usr/src/libpiny/lib/Piny.pm b/usr/src/libpiny/lib/Piny.pm index 2dc2b84..2ed139b 100644 --- a/usr/src/libpiny/lib/Piny.pm +++ b/usr/src/libpiny/lib/Piny.pm @@ -10,5 +10,6 @@ use Piny::Environment; use Piny::Group; use Piny::Repo; use Piny::User; +use Piny::User::IkiWiki; 1; diff --git a/usr/src/libpiny/lib/Piny/Email.pm b/usr/src/libpiny/lib/Piny/Email.pm index 7ad17d8..e031c34 100644 --- a/usr/src/libpiny/lib/Piny/Email.pm +++ b/usr/src/libpiny/lib/Piny/Email.pm @@ -18,6 +18,8 @@ subtype 'EmailAddress' => message { 'That does not appear to be a valid email address.' } ; +Moose::Util::TypeConstraints::export_type_constraints_as_functions; + # Attributes has 'address' => diff --git a/usr/src/libpiny/lib/Piny/Repo.pm b/usr/src/libpiny/lib/Piny/Repo.pm index 5ad7007..48690c4 100644 --- a/usr/src/libpiny/lib/Piny/Repo.pm +++ b/usr/src/libpiny/lib/Piny/Repo.pm @@ -7,11 +7,15 @@ use Moose; use Moose::Util::TypeConstraints; use File::Find qw( find ); +use File::Temp qw( ); +use IO::Dir qw( ); use IkiWiki::FakeSetup qw( readSetup writeSetup ); +use Piny::Environment; use Piny::Group; use Piny::User; +use Piny::User::IkiWiki; # Types @@ -27,6 +31,8 @@ subtype 'SimpleText' => message { 'That description is not in the correct format for a piny repo.' } ; +Moose::Util::TypeConstraints::export_type_constraints_as_functions; + # Attributes has 'name' => @@ -239,6 +245,103 @@ sub all_repos { return @ret; }; +sub create { + my ( $class, $name, $description ) = @_; + + my $user = Piny::Environment->new->user; + + Reponame->assert_valid( $name ); + SimpleText->assert_valid( $description ); + + my $repo = $class->new( "name" => $name ); + + mkdir( $repo->path ) or die "The repo $name appears to already exist! ($!)"; + + system( "/usr/sbin/adduser", "--quiet", "--system", "--group", "--gecos", $name, "ikiwiki-$name" ) and die "Could not create ikiwiki user!"; + + my $ikiuser = Piny::User::IkiWiki->new( "name" => "ikiwiki-$name" ); + + system( "/usr/sbin/addgroup", "--quiet", "git-$name" ) and die "Could not create repo group!"; + + my $group = Piny::Group->new( "name" => "git-$name" ); + + system( "/usr/sbin/adduser", "--quiet", $user->name, $group->name ) and die "Could not add you to the repo group!"; + system( "/usr/sbin/adduser", "--quiet", $ikiuser->name, $group->name ) and die "Could not add ikiwiki user to the repo group!"; + + $ENV{"GIT_DIR"} = $repo->path; + system( "/usr/bin/git", "init", "--template=/srv/git-template.git", "--quiet", "--shared" ) and die "Could not initialize git repo!"; + delete $ENV{"GIT_DIR"}; + + $repo->set_description( $description ); + + open( TOUCH, ">", $repo->path . "/git-daemon-export-ok" ) or die "Could not touch git-daemon-export-ok for repo: $!"; + close( TOUCH ); + + system( "/bin/chown", "-R", $user->name . "." . $group->name, $repo->path ) and die "Could not change ownership of git repo!"; + system( "/bin/chown", "-R", $ikiuser->name . "." . $ikiuser->name, $repo->path . "/hooks" ) and die "Could not change ownership of git hooks!"; + + open( SETUP, ">", "/etc/ikiwiki/piny/" . $repo->name . ".setup" ) or die "Could not open new ikiwiki setup file: $!"; + print SETUP $repo->ikiwiki_setup; + close( SETUP ) or die "Could not close new ikiwiki setup file: $!"; + + open( APACHE, ">", "/etc/apache2/piny-available/" . $repo->name ) or die "Could not open new apache config: $!"; + print APACHE $repo->apache_config; + close( APACHE ) or die "Could not close new apache config: $!"; + + symlink( "/etc/apache2/piny-available/" . $repo->name, "/etc/apache2/piny-enabled/" . $repo->name ) or die "Could not symlink apache config: $!"; + + system( "/etc/init.d/apache2", "reload" ) and die "Could not reload apache config!"; + + system( "/usr/bin/git", "clone", "--quiet", $repo->path, $repo->ikiwiki_srcdir ) and die "Could not clone repo to ikiwiki srcdir!"; + + mkdir( $repo->ikiwiki_destdir ) or die "Could not create ikiwiki destdir: $!"; + mkdir( $repo->secure_path ) or die "Could not create secure dir: $!"; + + system( "/bin/chown", "-R", $ikiuser->name . "." . $ikiuser->name, $repo->ikiwiki_srcdir, $repo->ikiwiki_destdir, $repo->secure_path ) and die "Could not change ownership of ikiwiki directories!"; + + open( WIKILIST, ">", "/etc/ikiwiki/wikilist.d/" . $repo->name ) or die "Could not create wikilist.d file: $!"; + print WIKILIST $ikiuser->name . " /etc/ikiwiki/piny/" . $repo->name . ".setup\n"; + close( WIKILIST ) or die "Could not close wikilist.d file: $!"; + + my $temp = File::Temp->new( ) or die "Could not create temporary file: $!"; + $temp->unlink_on_destroy( 0 ); + + my $dh = IO::Dir->new( "/etc/ikiwiki/wikilist.d" ) or die "Could not open wikilist.d directory: $!"; + while ( defined ( my $entry = $dh->read ) ) { + next if ( $entry =~ /^\./ ); + open( FILE, "<", "/etc/ikiwiki/wikilist.d/" . $entry ) or die "Could not open wikilist.d entry $entry: $!"; + print $temp ; + close( FILE ) or die "Could not close wikilist.d entry $entry: $!"; + }; + + $temp->close or die "Could not close new wikilist: $!"; + + rename( $temp->filename, "/etc/ikiwiki/wikilist" ) or die "Could not rename over old wikilist: $!"; + + open( CGITLIST, ">", "/etc/cgitrc.d/" . $repo->name ) or die "Could not create cgitrc.d file: $!"; + print CGITLIST "repo.url=" . $repo->name . "\nrepo.path=" . $repo->path . "\nrepo.desc=" . $repo->description . "\nrepo.owner=" . $repo->owner->email . "\n\n"; + close( CGITLIST ) or die "Could not close cgitrc.d file: $!"; + + $temp = File::Temp->new( ) or die "Could not create temporary file: $!"; + $temp->unlink_on_destroy( 0 ); + + $dh = IO::Dir->new( "/etc/cgitrc.d" ) or die "Could not open cgitrc.d directory: $!"; + while ( defined ( my $entry = $dh->read ) ) { + next if ( $entry =! /^\./ ); + open( FILE, "<", "/etc/cgitrc.d/" . $entry ) or die "Could not open cgitrc.d entry $entry: $!"; + print $temp ; + close( FILE ) or die "Could not close cgitrc.d entry $entry: $!"; + }; + + $temp->close or die "Could not close new cgitrc: $!"; + + rename( $temp->filename, "/etc/cgitrepos" ) or die "Could not rename over old cgitrc: $!"; + + system( "/usr/bin/sudo", "-u", $ikiuser->name, "/usr/bin/ikiwiki", "--setup", "/etc/ikiwiki/piny/" . $repo->name . ".setup" ) and die "Could not do initial compile of ikiwiki!"; + + return $repo; +}; + # Builder methods # If constructed with just one argument, then treat it as a repo name. @@ -261,13 +364,7 @@ sub _build_group { 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!"; - }; + return "/srv/git/" . $s->name . ".git"; }; sub _build_description { @@ -345,25 +442,13 @@ sub _build_ikiwiki_setup { sub _build_ikiwiki_destdir { my ( $s ) = @_; - my $dir = "/srv/www/piny.be/" . $s->name; - - if ( -d $dir ) { - return $dir; - } else { - die "Expected destdir $dir does not exist!"; - }; + return "/srv/www/piny.be/" . $s->name; }; sub _build_ikiwiki_srcdir { my ( $s ) = @_; - my $dir = "/srv/ikiwiki/" . $s->name; - - if ( -d $dir ) { - return $dir; - } else { - die "Expected srcdir $dir does not exist!"; - }; + return "/srv/ikiwiki/" . $s->name; }; sub _build_ikiwiki_url { diff --git a/usr/src/libpiny/lib/Piny/User.pm b/usr/src/libpiny/lib/Piny/User.pm index 173b592..fb9a20f 100644 --- a/usr/src/libpiny/lib/Piny/User.pm +++ b/usr/src/libpiny/lib/Piny/User.pm @@ -13,10 +13,12 @@ use Piny::Group; subtype 'Username' => as 'Str' - => where { $_ =~ /^(?!(git|ikiwiki)-)[[a-zA-Z][a-zA-Z0-9_.-]*$/ } + => where { $_ =~ /^(?!(git|ikiwiki)-)[a-zA-Z][a-zA-Z0-9_.-]*$/ } => message { 'That username is not in the correct format for a piny user.' } ; +Moose::Util::TypeConstraints::export_type_constraints_as_functions; + # Attributes has 'uid' => diff --git a/usr/src/libpiny/lib/Piny/User/IkiWiki.pm b/usr/src/libpiny/lib/Piny/User/IkiWiki.pm new file mode 100644 index 0000000..b522ad8 --- /dev/null +++ b/usr/src/libpiny/lib/Piny/User/IkiWiki.pm @@ -0,0 +1,33 @@ +# Copyright © 2010 Julian Blake Kongslie +# Licensed under the BSD 3-clause license. + +package Piny::User::IkiWiki; + +use Moose; +use Moose::Util::TypeConstraints; + +use Piny::User; + +extends "Piny::User"; + +# Types + +subtype 'IkiWikiUsername' + => as 'Str' + => where { $_ =~ /^ikiwiki-[a-zA-Z][a-zA-Z0-9_.-]*$/ } + => message { 'That username is not in the correct format for an ikiwiki user.' } + ; + +# Attributes + +has 'name' => + ( is => 'ro' + , isa => 'IkiWikiUsername' + , lazy_build => 1 + ); + +# Moose boilerplate + +__PACKAGE__->meta->make_immutable; + +1; -- cgit v1.2.3