# 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 $last;
do {
my $numString = "";
my $ch;
while (($ch = getc($read)) ne ':' && ! eof $read) {
$numString = $numString . $ch;
}
die("Got wrong command number from monotone: ". $numString . ".") if ($numString != $self->{CmdNum});
my $err = getc($read);
die("Parser confused.") if ($err ne '0' && $err ne '1' && $err ne '2');
die("Parser confused.") if (getc($read) ne ':');
$last = getc($read);
die("Parser confused.") if ($last ne 'l' && $last ne 'm');
die("Parser confused.") if (getc($read) ne ':');
$numString = "";
while (($ch = getc($read)) ne ':' && ! eof $read) {
$numString = $numString . $ch;
}
my $input = "";
while ($numString > 0 && ! eof $read) {
$input = $input . getc($read);
$numString--;
}
if ($err eq '1') {
die("Syntax error in Monotone stdio");
} elsif ($err eq '2') {
$ret[1] = $ret[1] . $input;
} elsif ($err eq '0') {
$ret[0] = $ret[0] . $input;
}
} while ($last eq 'm' && ! eof $read);
die("Parser confused.") if ($last ne 'l');
$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";
syntax highlighted by Code2HTML, v. 0.9.1