From 0e5be768a7128745bd1f4a6a3904eb67a131e719 Mon Sep 17 00:00:00 2001
From: Julian Blake Kongslie <jblake@omgwallhack.org>
Date: Mon, 11 Oct 2010 21:53:06 -0700
Subject: Making libpiny saner

This is a rewrite of libpiny to make much better use of Moose, and have a
cleaner overall architecture.

Signed-off-by: Julian Blake Kongslie <jblake@omgwallhack.org>
---
 usr/src/libpiny/debian/control           |   2 +-
 usr/src/libpiny/lib/Piny/Config.pm       | 175 ++++++++++++++++++-------------
 usr/src/libpiny/lib/Piny/Email.pm        |   4 +
 usr/src/libpiny/lib/Piny/Environment.pm  |   6 +-
 usr/src/libpiny/lib/Piny/Group.pm        |   4 +
 usr/src/libpiny/lib/Piny/Repo.pm         |  39 +++----
 usr/src/libpiny/lib/Piny/User.pm         |   4 +
 usr/src/libpiny/lib/Piny/User/IkiWiki.pm |   4 +
 usr/src/pinyadmin/bin/lsaccess           |   2 +-
 usr/src/pinyadmin/bin/lsrepo             |   2 -
 usr/src/pinyadmin/bin/pinyconfig         |  18 ++++
 usr/src/pinyadmin/sbin/addaccess         |   2 +-
 usr/src/pinyadmin/sbin/rmaccess          |   2 +-
 usr/src/pinyadmin/sbin/rmrepo            |   2 +-
 14 files changed, 163 insertions(+), 103 deletions(-)
 create mode 100755 usr/src/pinyadmin/bin/pinyconfig

diff --git a/usr/src/libpiny/debian/control b/usr/src/libpiny/debian/control
index 04f501e..cebce96 100644
--- a/usr/src/libpiny/debian/control
+++ b/usr/src/libpiny/debian/control
@@ -7,7 +7,7 @@ Standards-version: 3.8.4
 
 Package: libpiny-perl
 Architecture: all
-Depends: ${perl:Depends}, ${misc:Depends}, libconfig-tiny-perl, libemail-valid-loose-perl, libmoose-perl, libmoosex-singleton-perl, libyaml-tiny-perl
+Depends: ${perl:Depends}, ${misc:Depends}, libconfig-simple-perl, libemail-valid-loose-perl, libmoose-perl, libmoosex-singleton-perl, libyaml-tiny-perl
 Description: Perl interface for the piny infrastructure
  This is a set of modules for accomplishing administrative tasks in the piny.be
  infrastructure.
diff --git a/usr/src/libpiny/lib/Piny/Config.pm b/usr/src/libpiny/lib/Piny/Config.pm
index ecc6d89..6cca2f6 100644
--- a/usr/src/libpiny/lib/Piny/Config.pm
+++ b/usr/src/libpiny/lib/Piny/Config.pm
@@ -1,119 +1,154 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::Config;
 
-use MooseX::Singleton;
+use Moose;
+use MooseX::StrictConstructor;
 
-use YAML::Tiny qw( );
+use Carp;
+use Config::Simple qw( );
 
 # Attributes
 
-has '_conf' =>
-  ( is          => 'ro'
-  , isa         => 'HashRef[Str]'
-  , lazy_build  => 1
-  , init_arg    => undef
-  );
-
-has 'ikiwiki_destdir' =>
+has 'confpath' =>
   ( is          => 'ro'
   , isa         => 'Str'
-  , lazy_build  => 1
-  , init_arg    => undef
+  , predicate   => 'has_confpath'
   );
 
-has 'ikiwiki_srcdir' =>
-  ( is          => 'ro'
-  , isa         => 'Str'
-  , lazy_build  => 1
-  , init_arg    => undef
-  );
-
-has 'ikiwiki_url' =>
-  ( is          => 'ro'
-  , isa         => 'Str'
-  , lazy_build  => 1
-  , init_arg    => undef
-  );
-
-has 'ikiwiki_secure_url' =>
-  ( is          => 'ro'
-  , isa         => 'Str'
-  , lazy_build  => 1
-  , init_arg    => undef
-  );
-
-has 'ikiwiki_secure_path' =>
+has '_conf' =>
   ( is          => 'ro'
-  , isa         => 'Str'
+  , isa         => 'HashRef[Str]'
   , lazy_build  => 1
   , init_arg    => undef
   );
 
 # Builder methods
 
-sub _build__conf {
-  my ( $s ) = @_;
+# If constructed with just one argument, then treat it as a config path.
+around BUILDARGS => sub {
+  my ( $orig, $class ) = ( shift, shift );
 
-  if ( -e "/etc/piny.conf" ) {
-    my $yaml = YAML::Tiny->new;
-    return $yaml->read( "/etc/piny.conf" )->[0];
+  if ( @_ == 1 && ! ref $_[0] ) {
+    return $class->$orig( confpath => $_[0] );
   } else {
-    return { };
+    return $class->$orig( @_ );
   };
 };
 
-sub _build_ikiwiki_destdir {
+sub _build__conf {
   my ( $s ) = @_;
 
-  if ( exists $s->_conf->{"ikiwiki_destdir"} ) {
-    return $s->_conf->{"ikiwiki_destdir"};
+  my $conf;
+
+  if ( $s->has_confpath and -e $s->confpath ) {
+    $conf = Config::Simple->new( $s->confpath )->vars;
   } else {
-    return "/srv/www/piny.be/";
+    $conf = { };
   };
-};
 
-sub _build_ikiwiki_srcdir {
-  my ( $s ) = @_;
+  if ( -e "/etc/piny-default.conf" ) {
+
+    my $default = Config::Simple->new( "/etc/piny-default.conf" )->vars;
+
+    foreach my $key ( keys %$default ) {
+      if ( not exists $conf->{$key} ) {
+        $conf->{$key} = $default->{$key};
+      };
+    };
 
-  if ( exists $s->_conf->{"ikiwiki_srcdir"} ) {
-    return $s->_conf->{"ikiwiki_srcdir"};
-  } else {
-    return "/srv/ikiwiki/";
   };
-};
 
-sub _build_ikiwiki_url {
-  my ( $s ) = @_;
+  if ( -e "/etc/piny-override.conf" ) {
+
+    my $override = Config::Simple->new( "/etc/piny-override.conf" )->vars;
+
+    foreach my $key ( keys %$override ) {
+      $conf->{$key} = $override->{$key};
+    };
 
-  if ( exists $s->_conf->{"ikiwiki_url"} ) {
-    return $s->_conf->{"ikiwiki_url"};
-  } else {
-    return "http://piny.be/";
   };
+
+  return $conf;
 };
 
-sub _build_ikiwiki_secure_url {
+# Save the config
+
+sub save {
   my ( $s ) = @_;
 
-  if ( exists $s->_conf->{"ikiwiki_secure_url"} ) {
-    return $s->_conf->{"ikiwiki_secure_url"};
-  } else {
-    return "https://secure.piny.be/";
+  if ( not $s->has_confpath ) {
+    croak "Can't save a Piny::Config if the confpath is not set!";
+  };
+
+  my $cs = Config::Simple->new( syntax => "ini" );
+
+  foreach my $key ( keys %{$s->_conf} ) {
+    $cs->param( $key, $s->_conf->{$key} );
   };
+
+  $cs->write( $s->confpath );
 };
 
-sub _build_ikiwiki_secure_path {
-  my ( $s ) = @_;
+# Tweakable helper
+
+sub tweakable {
+  my ( $attr, $default ) = @_;
+
+  my $attrname = $attr;
+  $attrname =~ s/_/./g;
+
+  has $attr =>
+    ( is          => 'rw'
+    , isa         => 'Str'
+    , lazy_build  => 1
+    , trigger     => sub {
+                      my ( $s, $old, $new ) = @_;
+
+                      $s->_conf->{$attrname} = $new;
+
+                      if ( $s->has_confpath ) {
+                        $s->save;
+                        $s->clear__conf;
+                      } else {
+                        carp "Attribute $attrname modification ignored!";
+                        $s->clear__conf;
+                        my $clearer = "clear_$attr";
+                        $s->$clearer;
+                      };
+                    }
+    );
+
+  my $builder = sub {
+    my ( $s ) = @_;
+
+    if ( exists $s->_conf->{$attrname} ) {
+      return $s->_conf->{$attrname};
+    } else {
+      return $default;
+    };
+  };
 
-  if ( exists $s->_conf->{"ikiwiki_secure_path"} ) {
-    return $s->_conf->{"ikiwiki_secure_path"};
-  } else {
-    return "/srv/www/secure.piny.be/";
+  {
+    no strict "refs";
+
+    *{"_build_" . $attr} = $builder;
   };
 };
 
+# The tweakables
+
+tweakable "piny_ikiwiki_destdir"        => "/srv/www/piny.be/";
+tweakable "piny_ikiwiki_srcdir"         => "/srv/ikiwiki/";
+tweakable "piny_ikiwiki_url"            => "http://piny.be/";
+tweakable "piny_ikiwiki_secure_url"     => "https://secure.piny.be/";
+tweakable "piny_ikiwiki_secure_path"    => "/srv/www/secure.piny.be/";
+tweakable "receive_denyNonFastforwards" => "true";
+
 # Moose boilerplate
 
 __PACKAGE__->meta->make_immutable;
diff --git a/usr/src/libpiny/lib/Piny/Email.pm b/usr/src/libpiny/lib/Piny/Email.pm
index 7ad17d8..baa56f0 100644
--- a/usr/src/libpiny/lib/Piny/Email.pm
+++ b/usr/src/libpiny/lib/Piny/Email.pm
@@ -1,10 +1,14 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::Email;
 
 use Moose;
 use Moose::Util::TypeConstraints;
+use MooseX::StrictConstructor;
 
 use Email::Valid::Loose;
 
diff --git a/usr/src/libpiny/lib/Piny/Environment.pm b/usr/src/libpiny/lib/Piny/Environment.pm
index 6cd3532..06416b8 100644
--- a/usr/src/libpiny/lib/Piny/Environment.pm
+++ b/usr/src/libpiny/lib/Piny/Environment.pm
@@ -1,9 +1,13 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::Environment;
 
 use MooseX::Singleton;
+use MooseX::StrictConstructor;
 
 use Piny::User;
 
@@ -36,6 +40,6 @@ sub _build_user {
 
 # Moose boilerplate
 
-__PACKAGE__->meta->make_immutable;
+__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
 
 1;
diff --git a/usr/src/libpiny/lib/Piny/Group.pm b/usr/src/libpiny/lib/Piny/Group.pm
index ac064da..86a6d95 100644
--- a/usr/src/libpiny/lib/Piny/Group.pm
+++ b/usr/src/libpiny/lib/Piny/Group.pm
@@ -1,9 +1,13 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::Group;
 
 use Moose;
+use MooseX::StrictConstructor;
 
 use Piny::User;
 
diff --git a/usr/src/libpiny/lib/Piny/Repo.pm b/usr/src/libpiny/lib/Piny/Repo.pm
index de8501b..31b7a70 100644
--- a/usr/src/libpiny/lib/Piny/Repo.pm
+++ b/usr/src/libpiny/lib/Piny/Repo.pm
@@ -1,12 +1,15 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::Repo;
 
 use Moose;
 use Moose::Util::TypeConstraints;
+use MooseX::StrictConstructor;
 
-use Config::Tiny qw( );
 use File::Find qw( find );
 use File::Temp qw( );
 use IO::Dir qw( );
@@ -165,7 +168,7 @@ has 'apache_config' =>
 
 has 'config' =>
   ( is          => 'ro'
-  , isa         => 'HashRef[Str]'
+  , isa         => 'Piny::Config'
   , lazy_build  => 1
   , init_arg    => undef
   );
@@ -313,7 +316,7 @@ sub all_repos {
 sub create {
   my ( $class, $name, $description ) = @_;
 
-  my $user = Piny::Environment->new->user;
+  my $user = Piny::Environment->instance->user;
 
   find_type_constraint( "Reponame" )->assert_valid( $name );
   find_type_constraint( "SimpleText" )->assert_valid( $description );
@@ -511,39 +514,31 @@ sub _build_ikiwiki_setup {
 sub _build_ikiwiki_destdir {
   my ( $s ) = @_;
 
-  return Piny::Config->instance->ikiwiki_destdir . $s->name;
+  return $s->config->piny_ikiwiki_destdir . $s->name;
 };
 
 sub _build_ikiwiki_srcdir {
   my ( $s ) = @_;
 
-  return Piny::Config->instance->ikiwiki_srcdir . $s->name;
+  return $s->config->piny_ikiwiki_srcdir . $s->name;
 };
 
 sub _build_ikiwiki_url {
   my ( $s ) = @_;
 
-  if ( defined $s->config->{"http_url"} ) {
-    return $s->config->{"http_url"} . $s->name;
-  } else {
-    return Piny::Config->instance->ikiwiki_url . $s->name;
-  };
+  return $s->config->piny_ikiwiki_url . $s->name;
 };
 
 sub _build_ikiwiki_cgiurl {
   my ( $s ) = @_;
 
-  if ( defined $s->config->{"https_url"} ) {
-    return $s->config->{"https_url"} . "repos/" . $s->name . "/ikiwiki.cgi";
-  } else {
-    return Piny::Config->instance->ikiwiki_secure_url . "repos/" . $s->name . "/ikiwiki.cgi";
-  };
+  return $s->config->piny_ikiwiki_secure_url . "repos/" . $s->name . "/ikiwiki.cgi";
 };
 
 sub _build_secure_path {
   my ( $s ) = @_;
 
-  return Piny::Config->instance->ikiwiki_secure_path . "repos/" . $s->name;
+  return $s->config->piny_ikiwiki_secure_path . "repos/" . $s->name;
 };
 
 sub _build_ikiwiki_cgipath {
@@ -558,7 +553,7 @@ sub _build_ikiwiki_historyurl {
   if ( defined $s->config->{"https_url"} ) {
     return $s->config->{"https_url"} . "cgit/" . $s->name . "/log/[[file]]";
   } else {
-    return Piny::Config->instance->ikiwiki_secure_url . "cgit/" . $s->name . "/log/[[file]]";
+    return $s->config->piny_ikiwiki_secure_url . "cgit/" . $s->name . "/log/[[file]]";
   };
 };
 
@@ -568,7 +563,7 @@ sub _build_ikiwiki_diffurl {
   if ( defined $s->config->{"https_url"} ) {
     return $s->config->{"https_url"} . "cgit/" . $s->name . "/diff/?id=[[sha1_commit]]";
   } else {
-    return Piny::Config->instance->ikiwiki_secure_url . "cgit/" . $s->name . "/diff/?id=[[sha1_commit]]";
+    return $s->config->piny_ikiwiki_secure_url . "cgit/" . $s->name . "/diff/?id=[[sha1_commit]]";
   };
 };
 
@@ -581,13 +576,7 @@ sub _build_apache_config {
 sub _build_config {
   my ( $s ) = @_;
 
-  my $c = Config::Tiny->read( $s->path . "/config" );
-
-  if ( defined $c and defined $c->{"piny"}) {
-    return $c->{"piny"};
-  } else {
-    return { };
-  };
+  return Piny::Config->new( confpath => $s->path . "/config" );
 };
 
 # Moose boilerplate
diff --git a/usr/src/libpiny/lib/Piny/User.pm b/usr/src/libpiny/lib/Piny/User.pm
index 91d6b5b..20ef4f1 100644
--- a/usr/src/libpiny/lib/Piny/User.pm
+++ b/usr/src/libpiny/lib/Piny/User.pm
@@ -1,10 +1,14 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::User;
 
 use Moose;
 use Moose::Util::TypeConstraints;
+use MooseX::StrictConstructor;
 
 use Piny::Email;
 use Piny::Group;
diff --git a/usr/src/libpiny/lib/Piny/User/IkiWiki.pm b/usr/src/libpiny/lib/Piny/User/IkiWiki.pm
index b522ad8..8585e90 100644
--- a/usr/src/libpiny/lib/Piny/User/IkiWiki.pm
+++ b/usr/src/libpiny/lib/Piny/User/IkiWiki.pm
@@ -1,10 +1,14 @@
 # Copyright © 2010 Julian Blake Kongslie <jblake@omgwallhack.org>
 # Licensed under the BSD 3-clause license.
 
+use strict;
+use warnings;
+
 package Piny::User::IkiWiki;
 
 use Moose;
 use Moose::Util::TypeConstraints;
+use MooseX::StrictConstructor;
 
 use Piny::User;
 
diff --git a/usr/src/pinyadmin/bin/lsaccess b/usr/src/pinyadmin/bin/lsaccess
index b55900c..ce41fc4 100755
--- a/usr/src/pinyadmin/bin/lsaccess
+++ b/usr/src/pinyadmin/bin/lsaccess
@@ -5,7 +5,7 @@ use warnings;
 
 use Piny;
 
-my $env = Piny::Environment->new( );
+my $env = Piny::Environment->instance( );
 
 my ( $reponame ) = @ARGV;
 
diff --git a/usr/src/pinyadmin/bin/lsrepo b/usr/src/pinyadmin/bin/lsrepo
index 1587654..2d88eb5 100755
--- a/usr/src/pinyadmin/bin/lsrepo
+++ b/usr/src/pinyadmin/bin/lsrepo
@@ -5,8 +5,6 @@ use warnings;
 
 use Piny;
 
-my $env = Piny::Environment->new( );
-
 foreach my $repo ( Piny::Repo->all_repos( ) ) {
   print $repo->name . "\n";
 };
diff --git a/usr/src/pinyadmin/bin/pinyconfig b/usr/src/pinyadmin/bin/pinyconfig
new file mode 100755
index 0000000..ec8e80a
--- /dev/null
+++ b/usr/src/pinyadmin/bin/pinyconfig
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Piny;
+
+my ( $reponame, $attr, $value ) = @ARGV;
+
+$attr =~ s/\./_/g;
+
+my $repo = Piny::Repo->new( $reponame );
+
+if ( defined $value ) {
+  $repo->config->$attr( $value );
+};
+
+print "$attr = " . $repo->config->$attr . "\n";
diff --git a/usr/src/pinyadmin/sbin/addaccess b/usr/src/pinyadmin/sbin/addaccess
index 8d0cef9..e351114 100755
--- a/usr/src/pinyadmin/sbin/addaccess
+++ b/usr/src/pinyadmin/sbin/addaccess
@@ -5,7 +5,7 @@ use warnings;
 
 use Piny;
 
-my $env = Piny::Environment->new( );
+my $env = Piny::Environment->instance( );
 
 my ( $reponame, @users ) = @ARGV;
 
diff --git a/usr/src/pinyadmin/sbin/rmaccess b/usr/src/pinyadmin/sbin/rmaccess
index f84fba0..d6c22a9 100755
--- a/usr/src/pinyadmin/sbin/rmaccess
+++ b/usr/src/pinyadmin/sbin/rmaccess
@@ -5,7 +5,7 @@ use warnings;
 
 use Piny;
 
-my $env = Piny::Environment->new( );
+my $env = Piny::Environment->instance( );
 
 my ( $reponame, @users ) = @ARGV;
 
diff --git a/usr/src/pinyadmin/sbin/rmrepo b/usr/src/pinyadmin/sbin/rmrepo
index 8b26feb..e12a067 100755
--- a/usr/src/pinyadmin/sbin/rmrepo
+++ b/usr/src/pinyadmin/sbin/rmrepo
@@ -5,7 +5,7 @@ use warnings;
 
 use Piny;
 
-my $env = Piny::Environment->new;
+my $env = Piny::Environment->instance( );
 
 foreach my $reponame ( @ARGV ) {
 
-- 
cgit v1.2.3