~ubuntu-branches/ubuntu/vivid/muse-el/vivid

« back to all changes in this revision

Viewing changes to contrib/ikiwiki/IkiWiki/Plugin/test.pl

  • Committer: Bazaar Package Importer
  • Author(s): Bhavani Shankar
  • Date: 2010-10-16 09:53:48 UTC
  • mfrom: (1.1.6 upstream) (4.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20101016095348-fu6k0inu5uownt09
Tags: 3.20-2ubuntu1
* Merge from debian unstable. Remaining changes:
  - Keep the GFDL manual:
    + Modified debian/rules to build the manual
    + Added copyright info about the manual in debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
use warnings;
 
3
use strict;
 
4
 
 
5
use IO::Select qw();
 
6
use IO::Socket::INET qw();
 
7
 
 
8
my %config = (
 
9
    muse_emacs => '/usr/local/bin/emacs',
 
10
    muse_init => '/stuff/proj/personal-site/ikiwiki/muse-init.el',
 
11
    muse_shared_secret => 'foo',
 
12
);
 
13
 
 
14
my %MUSE_SERVER = ( host => 'localhost' );
 
15
 
 
16
main();
 
17
exit 0;
 
18
 
 
19
# Determine the emacs binary to use
 
20
sub locate_emacs {
 
21
    my $err = sub {
 
22
        die "Unable to find your emacs binary.\n",
 
23
          "  Set muse_emacs config to the right value.\n";
 
24
    };
 
25
    if ( $config{muse_emacs} ) {
 
26
        ( -x $config{muse_emacs} ) ? return $config{muse_emacs} : $err->();
 
27
    }
 
28
    else {
 
29
        my $emacs = `which emacs`;
 
30
        chomp $emacs;
 
31
        ( $emacs ) ? return $emacs : $err->();
 
32
    }
 
33
}
 
34
 
 
35
# Initialize connection to the Muse IPC server
 
36
sub start_muse_server {
 
37
    my $secret = $config{muse_shared_secret};
 
38
    my $init_port = $config{muse_init_port} || 0;
 
39
    my $ipc_port = $config{muse_ipc_port};
 
40
 
 
41
    # Perform sanity checks
 
42
    $config{muse_init} or die "Error: muse_init config option not defined.\n";
 
43
 
 
44
    # Start initialization server
 
45
    my $pserver = IO::Socket::INET->new(
 
46
        Proto => 'tcp',
 
47
        LocalAddr => 'localhost',
 
48
        LocalPort => $init_port,
 
49
        Listen => IO::Socket::INET::SOMAXCONN,
 
50
    ) or die "Error: Cannot begin initialization for the Muse IPC server.\n";
 
51
    $pserver->autoflush(1);
 
52
    $init_port = $pserver->sockport();
 
53
    my $select = IO::Select->new($pserver);
 
54
 
 
55
    # Start Emacs
 
56
    defined(my $pid = fork()) or die "Error: Unable to fork.\n";
 
57
    if ( $pid ) {
 
58
        $MUSE_SERVER{pid} = $pid;
 
59
    }
 
60
    else {
 
61
        exec locate_emacs(),
 
62
          qw( -q --no-site-file -batch -l ), $config{muse_init},
 
63
          qw( --eval ), "(muse-ikiwiki-start-server \"$init_port\"" .
 
64
          ( $ipc_port ? " \"$ipc_port\"" : '' ) . ")";
 
65
        die "Error: Unable to exec emacs.\n";
 
66
    }
 
67
 
 
68
    my $emacs_port = undef;
 
69
 
 
70
  SERVER:
 
71
    # Respond to clients
 
72
    while ( my @ready = $select->can_read() ) {
 
73
        for my $client (@ready) {
 
74
            if ($client == $pserver) {
 
75
                my $new = $pserver->accept();
 
76
                $select->add($new);
 
77
                next;
 
78
            }
 
79
            my $line = <$client>;
 
80
            chomp $line if defined $line;
 
81
            if ( defined $line && $line =~ m/^begin (.+)$/s &&
 
82
                   $1 eq $secret ) {
 
83
                print $client "ok\n";
 
84
                $line = <$client>;
 
85
                chomp $line if defined $line;
 
86
                if ( defined $line && $line =~ m/^port (.+)$/s ) {
 
87
                    $emacs_port = $1;
 
88
                }
 
89
                else {
 
90
                    print STDERR <<EOF;
 
91
Error: Invalid response while initializing Muse IPC server.
 
92
EOF
 
93
                }
 
94
                last SERVER;
 
95
            }
 
96
            print $client "nok\n" if $line;
 
97
            $select->remove($client);
 
98
            $client->close();
 
99
        }
 
100
    }
 
101
    $pserver->close();
 
102
 
 
103
    if ( $emacs_port ) {
 
104
        $MUSE_SERVER{port} = $emacs_port;
 
105
    }
 
106
    else {
 
107
        kill_muse_server();
 
108
    }
 
109
}
 
110
 
 
111
sub stop_muse_server {
 
112
    my ( $sock ) = @_;
 
113
 
 
114
    if ( $MUSE_SERVER{pid} ) {
 
115
        # Give Muse 3 seconds to stop, presuming that it has already
 
116
        # been sent the "done" command via stop_muse_server.
 
117
        local $SIG{ALRM} = sub {
 
118
            kill 9, $MUSE_SERVER{pid};
 
119
            die "Timeout";
 
120
        };
 
121
        eval {
 
122
            alarm 3;
 
123
            print $sock "done\n";
 
124
            $sock->close();
 
125
            waitpid($MUSE_SERVER{pid}, 0);
 
126
            alarm 0;
 
127
        };
 
128
        delete $MUSE_SERVER{pid};
 
129
    }
 
130
    else {
 
131
        print $sock "done\n";
 
132
        $sock->close();
 
133
    }
 
134
}
 
135
 
 
136
sub kill_muse_server {
 
137
    my @msgs = @_;
 
138
 
 
139
    kill 9, $MUSE_SERVER{pid} if $MUSE_SERVER{pid};
 
140
    die @msgs if @msgs;
 
141
}
 
142
 
 
143
sub ipc_expect_ok {
 
144
    my ( $sock, $err_msg ) = @_;
 
145
    $err_msg = "Error: Command did not succeed on Muse IPC server.\n";
 
146
 
 
147
    my $line = <$sock>;
 
148
    chomp $line;
 
149
    if ( $line ne 'ok' ) {
 
150
        $sock->close();
 
151
        kill_muse_server $err_msg;
 
152
    }
 
153
}
 
154
 
 
155
sub ipc_connect {
 
156
    my $secret = $config{muse_shared_secret};
 
157
    my $host = $MUSE_SERVER{host};
 
158
    my $port = $MUSE_SERVER{port};
 
159
    $host && $port
 
160
      or kill_muse_server "Error: No Muse IPC server is active.\n";
 
161
 
 
162
    # Start client connection
 
163
    my $sock = IO::Socket::INET->new(
 
164
        Proto => 'tcp',
 
165
        PeerAddr => $host,
 
166
        PeerPort => $port,
 
167
    ) or kill_muse_server "Error: Cannot connect to the Muse IPC server.\n";
 
168
    $sock->autoflush(1);
 
169
 
 
170
    # Authenticate
 
171
    print $sock "begin $secret\n";
 
172
    ipc_expect_ok $sock,
 
173
      "Error: Could not authenticate to the Muse IPC server.\n";
 
174
 
 
175
    return $sock;
 
176
}
 
177
 
 
178
sub test_name {
 
179
    my ( $sock ) = @_;
 
180
 
 
181
    print $sock "name foobar\n";
 
182
    ipc_expect_ok $sock,
 
183
      "Error: Could not set name of page on Muse IPC server.\n";
 
184
}
 
185
 
 
186
sub test_title {
 
187
    my ( $sock ) = @_;
 
188
 
 
189
    print $sock "title quux\n";
 
190
    ipc_expect_ok $sock,
 
191
      "Error: Could not set title of page on Muse IPC server.\n";
 
192
}
 
193
 
 
194
sub main {
 
195
    print "Starting Muse server ...\n";
 
196
    start_muse_server();
 
197
 
 
198
    print "Got port $MUSE_SERVER{port}.\n";
 
199
    my $sock = ipc_connect();
 
200
    test_name($sock);
 
201
    test_title($sock);
 
202
 
 
203
    print "Shutting down ...\n";
 
204
    stop_muse_server($sock);
 
205
    print "Done shutting down.\n";
 
206
}