summaryrefslogtreecommitdiff
path: root/usr/local/sbin/newrepo
diff options
context:
space:
mode:
Diffstat (limited to 'usr/local/sbin/newrepo')
-rwxr-xr-xusr/local/sbin/newrepo226
1 files changed, 226 insertions, 0 deletions
diff --git a/usr/local/sbin/newrepo b/usr/local/sbin/newrepo
new file mode 100755
index 0000000..7988117
--- /dev/null
+++ b/usr/local/sbin/newrepo
@@ -0,0 +1,226 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my( $errorto ) = 'jrayhawk+piny.svcs.cs.pdx.edu@omgwallhack.org'; # Email address to send horrible errors to.
+my( $reponame, $email, @errors, $wikilisttempfile, $cgitrctempfile);
+
+if ( ( ! scalar $ARGV[0] ) or ( scalar $ARGV[1] ) or ( $ARGV[0] !~ /^[a-z0-9][a-z0-9+.-]+$/ ) ) {
+ print( "Usage: newrepo REPONAME\n" );
+ print( " REPONAME must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.).\n" );
+ print( " REPONAME must be at least two characters long and must start with an alphanumeric character.\n" );
+ exit( 1 );
+} else {
+ $reponame = $ARGV[0];
+};
+
+# We want to check to see if
+# 1) $reponame already exists in some form so we don't try to create it, and
+# 2) $reponame is only partially created, in which case we want to email someone who can sanity check and fix it.
+open (PASSWD, '/etc/passwd');
+while(<PASSWD>) {
+ if( $_ =~ /^$ENV{SUDO_USER}:.+?:.+?:.+?:(.+?):/ ) { $email = $1; }; # While we're here, may as well grab the email address.
+ if( $_ =~ /^ikiwiki-$reponame:/ ) { push( @errors, "user ikiwiki-$reponame already exists!\n"); };
+};
+close(PASSWD);
+open (GROUP, '/etc/group');
+while(<GROUP>) {
+ if( $_ =~ /^git-$reponame:/ ) { push( @errors, "group git-$reponame already exists!\n"); };
+};
+close(GROUP);
+if( -d "/srv/git/$reponame.git" ) { push( @errors, "/srv/git/$reponame.git already exists!\n"); };
+if( -d "/srv/ikiwiki/$reponame" ) { push( @errors, "/srv/ikiwiki/$reponame already exists!\n"); };
+if( -d "/srv/www/piny.svcs.cs.pdx.edu/$reponame" ) { push( @errors, "/srv/www/piny.svcs.cs.pdx.edu/$reponame already exists!\n"); };
+if( -d "/srv/www/cgi.piny.svcs.cs.pdx.edu/repos/$reponame" ) { push( @errors, "/srv/www/cgi.piny.svcs.cs.pdx.edu/repos/$reponame already exists!\n"); };
+if( -f "/etc/ikiwiki/piny/$reponame.setup" ) { push( @errors, "/etc/ikiwiki/piny/$reponame.setup already exists!\n"); };
+if( -f "/etc/ikiwiki/wikilist.d/$reponame" ) { push( @errors, "/etc/ikiwiki/wikilist.d/$reponame already exists!\n"); };
+if( -f "/etc/apache2/piny-available/$reponame" ) { push( @errors, "/etc/apache2/piny-available/$reponame already exists!\n"); };
+if( -f "/etc/cgitrc.d/$reponame" ) { push( @errors, "/etc/cgitrc.d/$reponame already exists!\n"); };
+
+if( @errors ) {
+ if( @errors == 10 ) { # Everything's fine, nothing is broken
+ print( "$reponame already exists!\n" );
+ } else { # IT'S ARMAGEDDON
+ open ( MAIL, "|/usr/lib/sendmail -t" );
+ print( MAIL "To: $errorto\n" );
+ print( MAIL "From: newrepo\@piny.svcs.cs.pdx.edu\n" );
+ print( MAIL "Subject: Piny error: $ENV{SUDO_USER} found inconsistent $reponame in the creation process!\n" );
+ print( MAIL "MIME-Version: 1.0\n" );
+ print( MAIL "Content-Type: text/plain; charset=us-ascii\n" );
+ print( MAIL "\n" );
+ print( MAIL "@errors\n" );
+ close( MAIL );
+ print( "$reponame already exists but is in an inconsistent state! The Piny admins probably screwed up; they have been notified and will take a look at it.\n" );
+ };
+ exit( 2 );
+};
+
+
+# CREATE USER/GROUPS
+unless( system( "mkdir /srv/git/$reponame.git" ) == 0 ) { # We need a locking or atomic operation as our first to check against simultaneous execution.
+ print( "I suspect that you are attempting to create the same repo multiple times simultaneously.\n" );
+ exit( 3 );
+};
+system( "/usr/sbin/addgroup --quiet git-$reponame" );
+system( "/usr/sbin/adduser --quiet --system --group --gecos $reponame ikiwiki-$reponame" );
+system( "/usr/sbin/adduser --quiet ikiwiki-$reponame git-$reponame | grep -v 'Adding user'" );
+system( "/usr/sbin/adduser --quiet $ENV{SUDO_USER} git-$reponame | grep -v 'Adding user '" );
+
+# CREATE REPO
+system( "GIT_DIR=/srv/git/$reponame.git /usr/bin/git init --template=/srv/git-template.git --quiet --shared" );
+open ( DESC, ">/srv/git/$reponame.git/description" );
+print( DESC "$reponame owned by $email" );
+close( DESC );
+# ln -f post-receive /srv/git/$reponame.git/hooks/ # turn on e-mail commit notices
+system( "/bin/chown -R $ENV{SUDO_USER}.git-$reponame /srv/git/$reponame.git/" );
+system( "/bin/chown -R ikiwiki-$reponame.ikiwiki-$reponame /srv/git/$reponame.git/hooks/" );
+system( "/bin/touch /srv/git/$reponame.git/git-daemon-export-ok" );
+
+# WRITE IKIWIKI SETUP FILE
+open ( SETUP, ">/etc/ikiwiki/piny/$reponame.setup" );
+print( SETUP
+'#!/usr/bin/perl
+# Configuration file for ikiwiki.
+# Passing this to ikiwiki --setup will make ikiwiki generate wrappers and
+# build the wiki.
+#
+# Remember to re-run ikiwiki --setup any time you edit this file.
+
+use IkiWiki::Setup::Standard {
+ wikiname => \'' . $reponame . '\', # PINY
+ adminemail => \'' . $email . '\', # PINY
+ srcdir => \'/srv/ikiwiki/' . $reponame . '\', # PINY
+ destdir => \'/srv/www/piny.svcs.cs.pdx.edu/' . $reponame . '\', # PINY
+ url => \'http://piny.svcs.cs.pdx.edu/' . $reponame . '\', # PINY
+ cgiurl => \'https://cgi.piny.svcs.cs.pdx.edu/repos/' . $reponame . '/ikiwiki.cgi\', # PINY
+ historyurl => \'https://cgi.piny.svcs.cs.pdx.edu/gitweb.cgi?p=' . $reponame . '.git;a=history;f=[[file]]\', # PINY
+ diffurl => \'https://cgi.piny.svcs.cs.pdx.edu/gitweb.cgi?p=' . $reponame . ';a=blobdiff;f=doc/[[file]];h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_commit]];hpb=[[sha1_parent]]\', # PINY
+
+ templatedir => "/srv/templates",
+ underlaydir => "/etc/ikiwiki/share/underlay",
+
+ rcs => "git",
+ gitorigin_branch => "origin",
+ gitmaster_branch => "master",
+
+ wrappers => [
+ {
+ cgi => 1,
+ wrapper => \'/srv/www/cgi.piny.svcs.cs.pdx.edu/repos/' . $reponame . '/ikiwiki.cgi\', # PINY
+ wrappermode => "06755",
+ wrappergroup => \'git-' . $reponame . '\', # PINY
+ },
+ {
+ wrapper => \'/srv/git/' . $reponame . '.git/hooks/post-update\', # PINY
+ wrappermode => "06755",
+ wrappergroup => \'git-' . $reponame . '\', # PINY
+
+ notify => 0,
+ },
+ ],
+
+ # Generate rss feeds for blogs?
+ rss => 1,
+ # Generate atom feeds for blogs?
+ atom => 0,
+ # Include discussion links on all pages?
+ discussion => 0,
+ # To exclude files matching a regexp from processing. This adds to
+ # the default exclude list.
+ #exclude => qr/*\.wav/,
+ # To change the extension used for generated html files.
+ #htmlext => "htm",
+ # Time format (for strftime)
+ #timeformat => "%c",
+ # Locale to use. Must be a UTF-8 locale.
+ #locale => "en_US.UTF-8",
+ # Only send cookies over SSL connections.
+ sslcookie => 1,
+ # Logging settings:
+ verbose => 0,
+ syslog => 1,
+ # To link to user pages in a subdirectory of the wiki.
+ #userdir => "users",
+ # To create output files named page.html rather than page/index.html.
+ usedirs => 1,
+ # Simple spam prevention: require an account-creation password.
+ #account_creation_password => "example",
+ # Use new "!"-prefixed preprocessor directive syntax
+ prefix_directives => 1,
+ httpauth => 1,
+ # To add plugins, list them here.
+ add_plugins => [qw{sidebar toc meta table tag httpauth attachment rename remove autoindex map teximg version edittemplate}],
+ disable_plugins => [qw{openid passwordauth}],
+ teximg_prefix => \'\\documentclass{scrartcl}
+\\usepackage[version=3]{mhchem}
+\\usepackage{amsmath}
+\\usepackage{amsfonts}
+\\usepackage{amssymb}
+\\pagestyle{empty}
+\\newcommand{\unit}[1]{\\ensuremath{\\, \\mathrm{#1}}}
+\\begin{document}\',
+
+ teximg_dvipng => 1,
+
+ # For use with the tag plugin, make all tags be located under a
+ # base page.
+ tagbase => "tag",
+
+ # For use with the search plugin if your estseek.cgi is located
+ # somewhere else.
+ #estseek => "/usr/lib/estraier/estseek.cgi",
+}');
+close( SETUP );
+open ( WIKILIST, '>>/etc/ikiwiki/wikilist' );
+print( WIKILIST "ikiwiki-$reponame /etc/ikiwiki/piny/$reponame.setup\n" );
+close( WIKILIST );
+
+# WRITE APACHE CONFIG
+open ( APACHE, ">/etc/apache2/piny-available/$reponame" );
+print( APACHE '<Directory /srv/www/cgi.piny.svcs.cs.pdx.edu/repos/' . $reponame . '>
+ AuthPAM_Enabled on
+ AuthGROUP_Enabled on
+ AuthPAM_FallThrough off
+ AuthBasicAuthoritative off
+ AuthType Basic
+ AuthName "User access to ' . $reponame . ' repository needed."
+ Require group git-' . $reponame . '
+</Directory>' );
+close( APACHE );
+link( "/etc/apache2/piny-available/$reponame", "/etc/apache2/piny-enabled/$reponame");
+system( '/etc/init.d/apache2 reload | grep -v "Reloading web server config: apache2."' );
+
+
+# CREATE IKIWIKI WORKING DIR
+system( "/usr/bin/git clone --quiet /srv/git/$reponame /srv/ikiwiki/$reponame" );
+mkdir( "/srv/www/piny.svcs.cs.pdx.edu/$reponame" );
+mkdir( "/srv/www/cgi.piny.svcs.cs.pdx.edu/repos/$reponame" );
+system( "/bin/chown -R ikiwiki-$reponame /srv/ikiwiki/$reponame /srv/www/piny.svcs.cs.pdx.edu/$reponame /srv/www/cgi.piny.svcs.cs.pdx.edu/repos/$reponame" );
+
+open ( WIKILIST, ">/etc/ikiwiki/wikilist.d/$reponame" ); # Maybe someday ikiwiki will support wikilist.d.
+print( WIKILIST "ikiwiki-$reponame /etc/ikiwiki/piny/$reponame.setup\n" ); # In the meantime, we fake it.
+close( WIKILIST );
+$wikilisttempfile = `/bin/mktemp`;
+chomp( $wikilisttempfile );
+system( "/bin/cat /etc/ikiwiki/wikilist.d/* > $wikilisttempfile" );
+chmod ( 0644, $wikilisttempfile );
+system( "/bin/mv $wikilisttempfile /etc/ikiwiki/wikilist" ); # This is marginally racy, but the consequences are probably ignorable.
+
+open ( CGITRC, ">/etc/cgitrc.d/$reponame" ); # Maybe someday cgit will support cgitrc.d.
+print( CGITRC
+"repo.url=$reponame
+repo.path=/srv/git/$reponame.git
+repo.desc=$reponame
+repo.owner=$email
+
+" ); # In the meantime, we fake it.
+close( CGITRC );
+$cgitrctempfile = `/bin/mktemp`;
+chomp( $cgitrctempfile );
+system( "/bin/cat /etc/cgitrc.d/* > $cgitrctempfile" );
+chmod ( 0644, $cgitrctempfile );
+system( "/bin/mv $cgitrctempfile /etc/cgitrepos" ); # This is marginally racy, but the consequences are minor.
+
+# COMPILE
+system( "/usr/bin/sudo -u ikiwiki-$reponame /usr/bin/ikiwiki --setup /etc/ikiwiki/piny/$reponame.setup | grep -v 'successfully generated'" );