@@ -2,11 +2,13 @@ extern crate hglib;
extern crate tempdir;
use hglib::cmdserver::CommandServer;
+use hglib::connection::ConnectionBackend;
use hglib::Chunk;
use std::env;
use tempdir::TempDir;
-fn run_command(cmdserver: &mut CommandServer, command: Vec<&[u8]>) -> (i32, Vec<u8>, Vec<u8>) {
+fn run_command<B>(cmdserver: &mut CommandServer<B>, command: Vec<&[u8]>)
+ -> (i32, Vec<u8>, Vec<u8>) where B: ConnectionBackend {
let (mut result, mut output, mut error) =
(-1i32, vec![], vec![]);
let run = cmdserver.connection
@@ -20,18 +20,18 @@ use std::io;
use connection::*;
/// Spawns and communicates with a command server process.
-pub struct CommandServer {
+pub struct CommandServer<B> {
/// A handle on the spawned process.
- pub connection: Connection,
+ pub connection: Connection<B>,
/// The list of capabilities the server reported on startup.
pub capabilities: Vec<String>,
/// The character encoding the server reported on startup.
pub encoding: String,
}
-impl CommandServer {
+impl CommandServer<PipeBackend> {
/// Constructs and starts up a command server instance, or returns an error.
- pub fn new() -> io::Result<CommandServer> {
+ pub fn new() -> io::Result<CommandServer<PipeBackend>> {
let mut conn = try!(Connection::new());
let (capabilities, encoding) = match conn.read_hello() {
Ok((caps, enc)) => (caps, enc),
@@ -75,18 +75,28 @@ impl Channel {
}
}
+/// A connection to command server.
+pub trait ConnectionBackend {
+ type R: io::Read;
+ type W: io::Write;
+
+ fn get_reader(&mut self) -> &mut Self::R;
+ fn get_writer(&mut self) -> &mut Self::W;
+ fn close(&mut self) -> io::Result<()>;
+}
+
use Chunk;
/// An iterator over the results of a single Mercurial command.
///
/// Each iteration yields a [`Chunk`](../enum.Chunk.html) with the
/// output data or length of input the server is expecting.
-pub struct CommandRun<'a> {
- connection: &'a mut Connection,
+pub struct CommandRun<'a, B: 'a> {
+ connection: &'a mut Connection<B>,
done: bool,
}
-impl<'a> Iterator for CommandRun<'a> {
+impl<'a, B> Iterator for CommandRun<'a, B> where B: ConnectionBackend {
type Item = io::Result<Chunk>;
fn next(&mut self) -> Option<Self::Item> {
@@ -137,6 +147,11 @@ impl PipeBackend {
.spawn());
Ok(PipeBackend { child: child })
}
+}
+
+impl ConnectionBackend for PipeBackend {
+ type R = ChildStdout;
+ type W = ChildStdin;
// We just unwrap the Option<ChildStd*> because we know that
// we set up the pipe in Connection::new(). We have to call
@@ -166,17 +181,19 @@ impl PipeBackend {
}
/// A handle to a running command server instance.
-pub struct Connection {
- backend: PipeBackend,
+pub struct Connection<B> {
+ backend: B,
}
-impl Connection {
+impl Connection<PipeBackend> {
/// Spawns a new command server process.
- pub fn new() -> io::Result<Connection> {
+ pub fn new() -> io::Result<Connection<PipeBackend>> {
let backend = try!(PipeBackend::spawn());
Ok(Connection { backend: backend })
}
+}
+impl<B> Connection<B> where B: ConnectionBackend {
/// Reads and parses the server hello message. Returns a tuple of
/// ([capabilities], encoding).
///
@@ -276,7 +293,7 @@ impl Connection {
/// Sends the given `command` to Mercurial, returning an iterator
/// over the results.
- pub fn raw_command(&mut self, command: Vec<&[u8]>) -> io::Result<CommandRun> {
+ pub fn raw_command(&mut self, command: Vec<&[u8]>) -> io::Result<CommandRun<B>> {
try!(self._raw_command(command));
Ok(CommandRun {
connection: self,