# # # add_dir "lib" # # add_file "gen-wrapper.sh" # content [ad68a7b129ceb422f657c385defb7767c5a442f1] # # add_file "ikiwiki.setup" # content [e99a350d67c8b001d0e2fa4f616d0741cec665af] # # add_file "lib/Monotone.pm" # content [0667003b1e698fb8aef9b113a3d1e9bf274153c3] # # patch ".mtn-ignore" # from [aad1393f844ff4b703574393f26cddd53e9abe42] # to [1228c188f67e36b632257017afef76eadddf0181] # # patch "build.sh" # from [c5894d7d641c1654ad916d3aaf0e302f954061f9] # to [f6a93db53ff5933b740a72c00fa9153b81a64e5e] # ============================================================ --- .mtn-ignore aad1393f844ff4b703574393f26cddd53e9abe42 +++ .mtn-ignore 1228c188f67e36b632257017afef76eadddf0181 @@ -1,2 +1,6 @@ ^wiki/\.ikiwiki +^wiki/recentchanges +cgi-bin compiled +keys +database.mtn ============================================================ --- build.sh c5894d7d641c1654ad916d3aaf0e302f954061f9 +++ build.sh f6a93db53ff5933b740a72c00fa9153b81a64e5e @@ -7,22 +7,17 @@ HISTORY_URL="http://code.monotone.ca/p/m WIKI_URL="http://wiki.monotone.ca" PULL_URL="mtn://code.monotone.ca/monotone-web?$BRANCH" HISTORY_URL="http://code.monotone.ca/p/monotone-web/source/changes/h:$BRANCH/" -MTN_CALL="/opt/local/bin/mtn -q --confdir ." ### end configuration +alias mtn="mtn -q --confdir ." + if [ -e _MTN ]; then echo "> pulling and merging changes" - $MTN_CALL pull "$PULL_URL" - $MTN_CALL merge -b "$BRANCH" - $MTN_CALL update -r "h:$BRANCH" + mtn pull "$PULL_URL" + mtn merge -b "$BRANCH" + mtn update -r "h:$BRANCH" fi echo "> rebuilding wiki" -rm -rf compiled -ikiwiki --wikiname monotone --plugin rawhtml --plugin goodstuff \ - --plugin graphviz --plugin table --plugin search \ - --url $WIKI_URL --cgiurl $WIKI_URL/ikiwiki.cgi --underlaydir underlay \ - --historyurl $HISTORY_URL --no-usedirs --rebuild \ - wiki compiled - +ikiwiki --setup ikiwiki.setup --rebuild echo "done" ============================================================ --- /dev/null +++ gen-wrapper.sh ad68a7b129ceb422f657c385defb7767c5a442f1 @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +echo "> generating ikiwiki wrapper" +ikiwiki --setup ikiwiki.setup --cgi 1 --wrappermode 06755 \ + --wrapper cgi-bin/ikiwiki.cgi +echo "done" ============================================================ --- /dev/null +++ ikiwiki.setup e99a350d67c8b001d0e2fa4f616d0741cec665af @@ -0,0 +1,103 @@ +#!/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 Cwd; +use IkiWiki::Setup::Standard { + wikiname => "monotone", + adminuser => ['address@hidden', ], + adminemail => 'address@hidden', + + # Be sure to customise these.. + srcdir => getcwd . "/wiki", + destdir => getcwd . "/compiled", + + url => "http://wiki.monotone.ca/", + cgiurl => "http://wiki.monotone.ca/cgi-bin/ikiwiki.cgi", + underlaydir => getcwd . "/underlay", + + # Monotone stuff + rcs => "monotone", + mtnkey => "address@hidden", + # IDF doesn't support these yet (see http://projects.ceondo.com/p/indefero/issues/550) + #historyurl => "http://code.monotone.ca/p/monotone-web/source/history/h:net.venge.monotone.web.ikiwiki/[[file]]", + #diffurl => "http://code.monotone.ca/p/monotone-web/source/diff/[[r1]]/[[r2]]/[[file]]", + # Set if you want the wiki to sync on update and commit. + #mtnsync => 0, + # The path to your workspace (defaults to the srcdir itself) + # e.g. use if your srcdir is a subdirectory of the workspace. + mtnrootdir => getcwd, + + # Default to generating rss feeds for pages with feeds? + #rss => 1, + # Default to generating atom feeds for pages with feeds? + #atom => 1, + # Allow generating feeds even if not generated by default? + #allowrss => 1, + #allowatom => 1, + # Urls to ping with XML-RPC when rss feeds are updated + #pingurl => [qw{http://rpc.technorati.com/rpc/ping}], + # 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 => 1, + syslog => 0, + # 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", + # Uncomment to force ikiwiki to run with a particular umask. + #umask => 022, + # Default settings for the recentchanges page. + #recentchangespage => "recentchanges", + #recentchangesnum => 100, + # Use new '!'-prefixed preprocessor directive syntax + prefix_directives => 0, + # Attempt to make hardlinks to source files instead of copying them. + # Useful if the wiki contains large media files. + hardlink => 1, + + # To add plugins, list them here. + # (Plugins to be considered: search wikitext fortune rst + add_plugins => [qw{goodstuff tag rawhtml graphviz sidebar map table search}], + # If you want to disable any of the default plugins, list them here. + #disable_plugins => [qw{inline htmlscrubber passwordauth openid}], + disable_plugins => [qw{anonok lockedit opendiscussion}], + + # To add a directory to the perl search path, use this. + libdir => getcwd . "/lib", + + # 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", + + # For use with the openid plugin, to give an url to a page users + # can use to signup for an OpenID. + #openidsignup => "http://myopenid.com/", + + # For use with the mirrorlist plugin, a list of mirrors. + #mirrorlist => { + # mirror1 => "http://hostname1", + # mirror2 => "http://hostname2/mirror", + #}, +} ============================================================ --- /dev/null +++ lib/Monotone.pm 0667003b1e698fb8aef9b113a3d1e9bf274153c3 @@ -0,0 +1,200 @@ +# This is a simple Perl module to start a monotone automate sub-process and then pass commands to it. +# Written by Will Uther, but I'm not a PERL hacker and I'm hoping someone will come along and fix it +# to make it right. + +package Monotone; + +use warnings; +use strict; +use FileHandle; +use IPC::Open2; + +require Exporter; +our @ISA = qw(Exporter); +our %EXPORT_TAGS = ( 'all' => [ qw() ] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +our @EXPORT = qw( ); + +our $VERSION = '0.03'; + +#constructor +sub new { + my $class = shift; + my $self = { + In => undef, + Out => undef, + PID => undef, + CmdNum => undef, + }; + bless ($self, $class); + return $self; +} + +sub open ($$) { + my ( $self, $db, $workspace ) = @_; + local (*READ, *WRITE); + die("Monotone automate session already running!") if (defined($self->{PID}) && $self->{PID}); + if (defined($db) && defined($workspace)) { + $self->{PID} = open2(\*READ, \*WRITE, "mtn --db=$db --root=$workspace automate stdio" ); + } elsif (defined($workspace)) { + $self->{PID} = open2(\*READ, \*WRITE, "mtn --root=$workspace automate stdio" ); + } else { + $self->{PID} = open2(\*READ, \*WRITE, "mtn automate stdio" ); + } + die("Unable to start mtn automate stdio session") if (!(defined($self->{PID}) && $self->{PID})); + $self->{In} = *READ; + $self->{Out} = *WRITE; + $self->{CmdNum} = 0; + + # my ($out, $err) = $self->call("interface_version"); + # die("Wrong monotone interface version: $out") if ($out != 5.0 || $err ne ""); +} + +sub open_args ($) { + my $self=shift; + local (*READ, *WRITE); + die("Monotone automate session already running!") if (defined($self->{PID}) && $self->{PID}); + my $cmd = "mtn automate stdio"; + while (my $arg=shift) { + $cmd = $cmd." $arg"; + } + $self->{PID} = open2(\*READ, \*WRITE, $cmd ); + die("Unable to start mtn automate stdio session") if (!(defined($self->{PID}) && $self->{PID})); + $self->{In} = *READ; + $self->{Out} = *WRITE; + $self->{CmdNum} = 0; + + # my ($out, $err) = $self->call("interface_version"); + # die("Wrong monotone interface version: $out") if ($out != 5.0 || $err ne ""); +} + +sub setOpts { + my $self = shift; + + die("mtn automate stdio session not running") if !defined($self->{PID}); + my $numargs = @_; + die("No arguments in Monotone->setOpts() call!?!") if ($numargs == 0); + die("Uneven number of arguments to Monotone->setOpts()!") if ($numargs-2*int($numargs/2) == 1); + + my $read = $self->{In}; + my $write = $self->{Out}; + + print $write "o"; + + foreach my $arg (@_) { + my $arglen = length $arg; + print $write $arglen; + print $write ":"; + print $write $arg; + } + print $write "e"; +} + +sub call { + my $self = shift; + + die("mtn automate stdio session not running") if !defined($self->{PID}); + die("No arguments in Monotone->call() call!?!") if (@_ == 0); + + my $read = $self->{In}; + my $write = $self->{Out}; + + print $write "l"; + + foreach my $arg (@_) { + my $arglen = length $arg; + print $write $arglen; + print $write ":"; + print $write $arg; + } + print $write "e"; + + my @ret = ("", ""); + my $stream = ""; + my %input = ( + "m" => "", + "e" => "", + "w" => "", + "p" => "", + "t" => "", + "l" => "" + ); + my $last; + + do { + my $numString = ""; + my $ch; + my $firstchar = 1; + while (($ch = getc($read)) ne ':' && ! eof $read) { + if (($ch lt '0' || $ch gt '9') && $firstchar) { + # Read through headers + do { + while (($ch = getc($read)) ne "\n" && ! eof $read) { + } + } while (($ch = getc($read)) ne "\n" && ! eof $read); + $firstchar = 0; + } else { + $numString = $numString . $ch; + } + } + die("Got wrong command number from monotone: ". $numString . ".") if ($numString != $self->{CmdNum}); + $stream = getc($read); + die("Parser confused.") if ($stream ne 'm' + && $stream ne 'e' && $stream ne 'w' + && $stream ne 'p' && $stream ne 't' + && $stream ne 'l'); + die("Parser confused.") if (getc($read) ne ':'); + $numString = ""; + while (($ch = getc($read)) ne ':' && ! eof $read) { + $numString = $numString . $ch; + } + while ($numString > 0 && ! eof $read) { + $input{$stream} = $input{$stream} . getc($read); + $numString--; + } + } while ($stream ne 'l' && ! eof $read); + + die("Parser confused.") if ($stream ne 'l'); + + if ($input{l} eq '1') { + die("Syntax error in Monotone stdio"); + } elsif ($input{l} eq '2') { + $ret[1] = $ret[1] . $input{e}; + } elsif ($input{l} eq '0') { + $ret[0] = $ret[0] . $input{m}; + } + + $self->{CmdNum} += 1; + return @ret; +} + +sub close { + my $self = shift; + + close $self->{Out} if defined($self->{Out}); + $self->{Out} = undef; + close $self->{In} if defined($self->{In}); + $self->{In} = undef; + waitpid($self->{PID}, 0) if defined($self->{PID}); + $self->{PID} = undef; +} + +# print "starting tests\n"; +# +# my $test = Monotone->new(); +# $test->open("/Users/willu/src/monotone/mt.db","/Users/willu/src/monotone/monotone-source"); +# +# my @revs = $test->call("get_base_revision_id"); +# print "got revisions: " . $revs[0] . "\n"; +# +# my $rev = $revs[0]; +# chomp $rev; # remove the trailing \n that monotone leaves there. +# +# my @certs = $test->call("certs", $rev); +# my $cert = $certs[0]; +# +# print "Got certs:\n" . $cert . "\n"; +# +# $test->close(); +# +# print "done\n";