<commit_before>//! Our main CLI tool.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![deny(warnings)]

#[macro_use]
extern crate conductor;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{self, Write};
use std::path::Path;
use std::process;

use conductor::command_runner::OsCommandRunner;
use conductor::cmd::*;
use conductor::Error;

/// Our version number, set by Cargo at compile time.
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

/// Our help string.
const USAGE: &'static str = "
conductor: Manage large, multi-pod docker-compose apps

Usage:
  conductor [options] new <name>
  conductor [options] build
  conductor [options] pull
  conductor [options] up [<pods>..]
  conductor [options] stop
  conductor [options] run <pod>
  conductor [options] exec [exec options] <pod> <service> <command> [--] [<args>..]
  conductor [options] shell [exec options] <pod> <service>
  conductor [options] test <pod> <service>
  conductor [options] repo list
  conductor [options] repo clone <repo>
  conductor [options] generate list
  conductor [options] generate <generator>
  conductor [options] export <dir>
  conductor (--help | --version)

Commands:
  new               Create a directory containing a new sample project
  build             Build images for the containers associated with this project
  pull              Pull Docker images used by project
  up                Run project
  stop              Stop all containers associated with project
  run               Run a specific pod as a one-shot task
  exec              Run a command inside a container
  shell             Run an interactive shell inside a running container
  test              Run the tests associated with a service, if any
  repo list         List all git repository aliases and URLs
  repo clone        Clone a git repository using its short alias and mount it
                    into the containers that use it
  generate list     List all available generators
  generate          Run the specified generator
  export            Export to the named directory as flattened *.yml files

Arguments:
  <dir>             The name of a directory
  <name>            The name of the project directory to create
  <pod>, <pods>     The name of a pod specified in `pods/`
  <repo>            Short alias for a repo (see `repo list`)
  <service>         The name of a service in a pod
  <generator>       The name of a generator

Exec options:
  -d                Run command detached in background
  --privileged      Run a command with elevated privileges
  --user <user>     User as which to run a command
  -T                Do not allocate a TTY when running a command

General options:
  -h, --help        Show this message
  --version         Show the version of conductor
  -p, --project-name <project_name>
                    The name of this project.  Defaults to the current
                    directory name.
  --override=<override>
                    Use overrides from the specified subdirectory of
                    `pods/overrides` [default: development]
  --default-tags=<tag_file>
                    A list of tagged image names, one per line, to
                    be used as defaults for images

Run conductor in a directory containing a `pods` subdirectory.  For more
information, see https://github.com/faradayio/conductor.
";

/// Our parsed command-line arguments.  See [docopt.rs][] for an
/// explanation of how this works.
///
/// [docopt.rs]: https://github.com/docopt/docopt.rs
#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)] // Allow uppercase options without warnings.
struct Args {
    cmd_build: bool,
    cmd_pull: bool,
    cmd_up: bool,
    cmd_stop: bool,
    cmd_run: bool,
    cmd_exec: bool,
    cmd_shell: bool,
    cmd_test: bool,
    cmd_repo: bool,
    cmd_list: bool,
    cmd_clone: bool,
    cmd_new: bool,
    cmd_generate: bool,
    cmd_export: bool,

    arg_args: Option<Vec<String>>,
    arg_command: Option<String>,
    arg_dir: Option<String>,
    arg_generator: Option<String>,
    arg_name: Option<String>,
    arg_pod: Option<String>,
    arg_pods: Vec<String>,
    arg_repo: Option<String>,
    arg_service: Option<String>,

    // Exec options.
    flag_d: bool,
    flag_privileged: bool,
    flag_user: Option<String>,
    flag_T: bool,

    // General options.
    flag_version: bool,
    flag_default_tags: Option<String>,
    flag_override: String,
    flag_project_name: Option<String>,
}

impl Args {
    /// Extract `exec::Options` from our command-line arguments.
    fn to_exec_options(&self) -> conductor::exec::Options {
        conductor::exec::Options {
            detached: self.flag_d,
            privileged: self.flag_privileged,
            user: self.flag_user.clone(),
            allocate_tty: !self.flag_T,
            ..Default::default()
        }
    }

    /// Extract `exec::Target` from our command-line arguments.
    fn to_exec_target<'a>(&'a self,
                          project: &'a conductor::Project,
                          ovr: &'a conductor::Override)
                          -> Result<Option<conductor::exec::Target<'a>>, Error> {
        match (&self.arg_pod, &self.arg_service) {
            (&Some(ref pod), &Some(ref service)) => {
                Ok(Some(try!(conductor::exec::Target::new(project,
                                                          ovr,
                                                          pod,
                                                          service))))
            }
            _ => Ok(None),
        }
    }

    /// Extract `exec::Command` from our command-line arguments.
    fn to_exec_command(&self) -> Option<conductor::exec::Command> {
        // We have an `Option<Vec<String>>` and we want a `&[String]`,
        // so do a little munging.
        let args = self.arg_args
            .as_ref()
            .map_or(&[] as &[_], |v| (v as &[_]));
        if let Some(ref command) = self.arg_command {
            Some(conductor::exec::Command::new(command).with_args(args))
        } else {
            None
        }
    }
}

/// The function which does the real work.  Unlike `main`, we have a return
/// type of `Result` and may therefore use `try!` to handle errors.
fn run(args: &Args) -> Result<(), Error> {

    if args.cmd_new {
        try!(conductor::Project::generate_new(&try!(env::current_dir()),
                                              args.arg_name.as_ref().unwrap()));
        return Ok(());
    }

    let mut proj = try!(conductor::Project::from_current_dir());
    if let Some(ref project_name) = args.flag_project_name {
        proj.set_name(project_name);
    }
    if let Some(ref default_tags_path) = args.flag_default_tags {
        let file = try!(fs::File::open(default_tags_path));
        proj.set_default_tags(try!(conductor::DefaultTags::read(file)));
    }
    let ovr = try!(proj.ovr(&args.flag_override)
        .ok_or_else(|| err!("override {} is not defined", &args.flag_override)));
    try!(proj.output(ovr));
    let runner = OsCommandRunner::new();

    if args.cmd_pull {
        try!(proj.pull(&runner, &ovr));
    } else if args.cmd_build {
        try!(proj.build(&runner, &ovr));
    } else if args.cmd_up {
        if args.arg_pods.is_empty() {
            try!(proj.up_all(&runner, &ovr));
        } else {
            let pods: Vec<&str> = args.arg_pods
                .iter()
                .map(|p| &p[..])
                .collect();
            try!(proj.up(&runner, &ovr, &pods));
        }
    } else if args.cmd_stop {
        try!(proj.stop(&runner, &ovr));
    } else if args.cmd_run {
        try!(proj.run(&runner, &ovr, args.arg_pod.as_ref().unwrap()));
    } else if args.cmd_exec {
        let target = try!(args.to_exec_target(&proj, &ovr)).unwrap();
        let opts = args.to_exec_options();
        let cmd = args.to_exec_command().unwrap();
        try!(proj.exec(&runner, &target, &cmd, &opts));
    } else if args.cmd_shell {
        let target = try!(args.to_exec_target(&proj, &ovr)).unwrap();
        let opts = args.to_exec_options();
        try!(proj.shell(&runner, &target, &opts));
    } else if args.cmd_test {
        let test_ovr = try!(proj.ovr("test")
            .ok_or_else(|| conductor::err("override test is required to run tests")));
        let target = try!(args.to_exec_target(&proj, &test_ovr)).unwrap();
        try!(proj.test(&runner, &target));
    } else if args.cmd_repo && args.cmd_list {
        try!(proj.repo_list(&runner));
    } else if args.cmd_repo && args.cmd_clone {
        try!(proj.repo_clone(&runner, args.arg_repo.as_ref().unwrap()));
        // Regenerate our output now that we've cloned.
        try!(proj.output(ovr));
    } else if args.cmd_generate && args.cmd_list {
        try!(proj.generate_list())
    } else if args.cmd_generate {
        try!(proj.generate(&args.arg_generator.as_ref().unwrap()))
    } else if args.cmd_export {
        try!(proj.export(&ovr, &Path::new(args.arg_dir.as_ref().unwrap())));
    } else {
        // The above cases should be exhaustive.
        unreachable!()
    }

    Ok(())
}

/// Our main entry point.
fn main() {
    // Initialize logging with some custom options, mostly so we can see
    // our own warnings.
    let mut builder = env_logger::LogBuilder::new();
    builder.filter(Some("docker_compose"), log::LogLevelFilter::Warn);
    builder.filter(Some("conductor"), log::LogLevelFilter::Warn);
    if let Ok(config) = env::var("RUST_LOG") {
        builder.parse(&config);
    }
    builder.init().unwrap();

    // Parse our args using docopt.rs.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    debug!("Arguments: {:?}", &args);

    // Display our version if we were asked to do so.
    if args.flag_version {
        println!("conductor {}", VERSION);
        process::exit(0);
    }

    // Defer all our real work to `run`, and handle any errors.  This is a
    // standard Rust pattern to make error-handling in `main` nicer.
    if let Err(ref err) = run(&args) {
        // We use `unwrap` here to turn I/O errors into application panics.
        // If we can't print a message to stderr without an I/O error,
        // the situation is hopeless.
        write!(io::stderr(), "Error: {}\n", err).unwrap();
        process::exit(1);
    }
}
<commit_msg>Implement --all-versions flag to print docker, etc., versions<commit_after>//! Our main CLI tool.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![deny(warnings)]

#[macro_use]
extern crate conductor;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use docopt::Docopt;
use std::env;
use std::fs;
use std::io::{self, Write};
use std::path::Path;
use std::process;

use conductor::command_runner::{Command, CommandRunner, OsCommandRunner};
use conductor::cmd::*;
use conductor::Error;

/// Our version number, set by Cargo at compile time.
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

/// Our help string.
const USAGE: &'static str = "
conductor: Manage large, multi-pod docker-compose apps

Usage:
  conductor [options] new <name>
  conductor [options] build
  conductor [options] pull
  conductor [options] up [<pods>..]
  conductor [options] stop
  conductor [options] run <pod>
  conductor [options] exec [exec options] <pod> <service> <command> [--] [<args>..]
  conductor [options] shell [exec options] <pod> <service>
  conductor [options] test <pod> <service>
  conductor [options] repo list
  conductor [options] repo clone <repo>
  conductor [options] generate list
  conductor [options] generate <generator>
  conductor [options] export <dir>
  conductor (--help | --version | --all-versions)

Commands:
  new               Create a directory containing a new sample project
  build             Build images for the containers associated with this project
  pull              Pull Docker images used by project
  up                Run project
  stop              Stop all containers associated with project
  run               Run a specific pod as a one-shot task
  exec              Run a command inside a container
  shell             Run an interactive shell inside a running container
  test              Run the tests associated with a service, if any
  repo list         List all git repository aliases and URLs
  repo clone        Clone a git repository using its short alias and mount it
                    into the containers that use it
  generate list     List all available generators
  generate          Run the specified generator
  export            Export to the named directory as flattened *.yml files

Arguments:
  <dir>             The name of a directory
  <name>            The name of the project directory to create
  <pod>, <pods>     The name of a pod specified in `pods/`
  <repo>            Short alias for a repo (see `repo list`)
  <service>         The name of a service in a pod
  <generator>       The name of a generator

Exec options:
  -d                Run command detached in background
  --privileged      Run a command with elevated privileges
  --user <user>     User as which to run a command
  -T                Do not allocate a TTY when running a command

General options:
  -h, --help        Show this message
  --version         Show the version of conductor
  --all-versions    Show the version of conductor and supporting tools
  -p, --project-name <project_name>
                    The name of this project.  Defaults to the current
                    directory name.
  --override=<override>
                    Use overrides from the specified subdirectory of
                    `pods/overrides` [default: development]
  --default-tags=<tag_file>
                    A list of tagged image names, one per line, to
                    be used as defaults for images

Run conductor in a directory containing a `pods` subdirectory.  For more
information, see https://github.com/faradayio/conductor.
";

/// Our parsed command-line arguments.  See [docopt.rs][] for an
/// explanation of how this works.
///
/// [docopt.rs]: https://github.com/docopt/docopt.rs
#[derive(Debug, RustcDecodable)]
#[allow(non_snake_case)] // Allow uppercase options without warnings.
struct Args {
    cmd_build: bool,
    cmd_pull: bool,
    cmd_up: bool,
    cmd_stop: bool,
    cmd_run: bool,
    cmd_exec: bool,
    cmd_shell: bool,
    cmd_test: bool,
    cmd_repo: bool,
    cmd_list: bool,
    cmd_clone: bool,
    cmd_new: bool,
    cmd_generate: bool,
    cmd_export: bool,

    arg_args: Option<Vec<String>>,
    arg_command: Option<String>,
    arg_dir: Option<String>,
    arg_generator: Option<String>,
    arg_name: Option<String>,
    arg_pod: Option<String>,
    arg_pods: Vec<String>,
    arg_repo: Option<String>,
    arg_service: Option<String>,

    // Exec options.
    flag_d: bool,
    flag_privileged: bool,
    flag_user: Option<String>,
    flag_T: bool,

    // General options.
    flag_version: bool,
    flag_all_versions: bool,
    flag_default_tags: Option<String>,
    flag_override: String,
    flag_project_name: Option<String>,
}

impl Args {
    /// Extract `exec::Options` from our command-line arguments.
    fn to_exec_options(&self) -> conductor::exec::Options {
        conductor::exec::Options {
            detached: self.flag_d,
            privileged: self.flag_privileged,
            user: self.flag_user.clone(),
            allocate_tty: !self.flag_T,
            ..Default::default()
        }
    }

    /// Extract `exec::Target` from our command-line arguments.
    fn to_exec_target<'a>(&'a self,
                          project: &'a conductor::Project,
                          ovr: &'a conductor::Override)
                          -> Result<Option<conductor::exec::Target<'a>>, Error> {
        match (&self.arg_pod, &self.arg_service) {
            (&Some(ref pod), &Some(ref service)) => {
                Ok(Some(try!(conductor::exec::Target::new(project,
                                                          ovr,
                                                          pod,
                                                          service))))
            }
            _ => Ok(None),
        }
    }

    /// Extract `exec::Command` from our command-line arguments.
    fn to_exec_command(&self) -> Option<conductor::exec::Command> {
        // We have an `Option<Vec<String>>` and we want a `&[String]`,
        // so do a little munging.
        let args = self.arg_args
            .as_ref()
            .map_or(&[] as &[_], |v| (v as &[_]));
        if let Some(ref command) = self.arg_command {
            Some(conductor::exec::Command::new(command).with_args(args))
        } else {
            None
        }
    }
}

/// The function which does the real work.  Unlike `main`, we have a return
/// type of `Result` and may therefore use `try!` to handle errors.
fn run(args: &Args) -> Result<(), Error> {

    // Handle any flags or arguments we can handle without a project
    // directory.
    if args.flag_all_versions {
        try!(all_versions());
        return Ok(());
    } else if args.flag_version {
        version();
        return Ok(());
    } else if args.cmd_new {
        try!(conductor::Project::generate_new(&try!(env::current_dir()),
                                              args.arg_name.as_ref().unwrap()));
        return Ok(());
    }

    let mut proj = try!(conductor::Project::from_current_dir());
    if let Some(ref project_name) = args.flag_project_name {
        proj.set_name(project_name);
    }
    if let Some(ref default_tags_path) = args.flag_default_tags {
        let file = try!(fs::File::open(default_tags_path));
        proj.set_default_tags(try!(conductor::DefaultTags::read(file)));
    }
    let ovr = try!(proj.ovr(&args.flag_override)
        .ok_or_else(|| err!("override {} is not defined", &args.flag_override)));
    try!(proj.output(ovr));
    let runner = OsCommandRunner::new();

    if args.cmd_pull {
        try!(proj.pull(&runner, &ovr));
    } else if args.cmd_build {
        try!(proj.build(&runner, &ovr));
    } else if args.cmd_up {
        if args.arg_pods.is_empty() {
            try!(proj.up_all(&runner, &ovr));
        } else {
            let pods: Vec<&str> = args.arg_pods
                .iter()
                .map(|p| &p[..])
                .collect();
            try!(proj.up(&runner, &ovr, &pods));
        }
    } else if args.cmd_stop {
        try!(proj.stop(&runner, &ovr));
    } else if args.cmd_run {
        try!(proj.run(&runner, &ovr, args.arg_pod.as_ref().unwrap()));
    } else if args.cmd_exec {
        let target = try!(args.to_exec_target(&proj, &ovr)).unwrap();
        let opts = args.to_exec_options();
        let cmd = args.to_exec_command().unwrap();
        try!(proj.exec(&runner, &target, &cmd, &opts));
    } else if args.cmd_shell {
        let target = try!(args.to_exec_target(&proj, &ovr)).unwrap();
        let opts = args.to_exec_options();
        try!(proj.shell(&runner, &target, &opts));
    } else if args.cmd_test {
        let test_ovr = try!(proj.ovr("test")
            .ok_or_else(|| conductor::err("override test is required to run tests")));
        let target = try!(args.to_exec_target(&proj, &test_ovr)).unwrap();
        try!(proj.test(&runner, &target));
    } else if args.cmd_repo && args.cmd_list {
        try!(proj.repo_list(&runner));
    } else if args.cmd_repo && args.cmd_clone {
        try!(proj.repo_clone(&runner, args.arg_repo.as_ref().unwrap()));
        // Regenerate our output now that we've cloned.
        try!(proj.output(ovr));
    } else if args.cmd_generate && args.cmd_list {
        try!(proj.generate_list())
    } else if args.cmd_generate {
        try!(proj.generate(&args.arg_generator.as_ref().unwrap()))
    } else if args.cmd_export {
        try!(proj.export(&ovr, &Path::new(args.arg_dir.as_ref().unwrap())));
    } else {
        // The above cases should be exhaustive.
        unreachable!()
    }

    Ok(())
}

/// Print the version of this executable.
fn version() {
    println!("conductor {}", VERSION);
}

/// Print the version of this executable and also the versions of several
/// tools we use.
fn all_versions() -> Result<(), Error> {
    version();

    let runner = OsCommandRunner::new();
    for tool in &["docker", "docker-compose", "git"] {
        let status = try!(runner.build(tool)
            .arg("--version")
            .status());
        if !status.success() {
            return Err(err!("Could not run {} (is it installed?)", tool));
        }
    }
    Ok(())
}

/// Our main entry point.
fn main() {
    // Initialize logging with some custom options, mostly so we can see
    // our own warnings.
    let mut builder = env_logger::LogBuilder::new();
    builder.filter(Some("docker_compose"), log::LogLevelFilter::Warn);
    builder.filter(Some("conductor"), log::LogLevelFilter::Warn);
    if let Ok(config) = env::var("RUST_LOG") {
        builder.parse(&config);
    }
    builder.init().unwrap();

    // Parse our args using docopt.rs.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    debug!("Arguments: {:?}", &args);

    // Defer all our real work to `run`, and handle any errors.  This is a
    // standard Rust pattern to make error-handling in `main` nicer.
    if let Err(ref err) = run(&args) {
        // We use `unwrap` here to turn I/O errors into application panics.
        // If we can't print a message to stderr without an I/O error,
        // the situation is hopeless.
        write!(io::stderr(), "Error: {}\n", err).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>//
//	main.rs
//	SweetEngine
//
//	Copyright (c) 2015 Infinite
//	Licensed under the terms of the Apache License, v2
//

//----------------------------------------------------------------

//	Feature gates
#![feature(std_misc)]
#![feature(plugin)]
#![feature(core)]
#![feature(io)]

//	Imports
#[plugin] extern crate glium_macros;
#[macro_use] extern crate glium;
extern crate glutin;

//	Global namespace pollution ;P
use std::old_io::timer;
use std::time::Duration;
use glium::{DisplayBuild, Surface};

//----------------------------------------------------------------

//	Our vertex struct
#[vertex_format]
#[derive(Copy)]
struct Vertex
{
	position: [f32; 2],
	color: [f32; 3],
}

//----------------------------------------------------------------

fn main()
{
	let display = glutin::WindowBuilder::new()
		.with_vsync()
		.with_gl_version((4, 1))
		.with_dimensions(960, 540)
		.with_title(format!("SweetWindow"))
		.build_glium().unwrap();

	let vertex_buffer = {
		glium::VertexBuffer::new(&display,
			vec!
			[
				Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
				Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
				Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
			]
		)
	};

	let index_buffer = glium::IndexBuffer::new(&display,
		glium::index_buffer::TrianglesList(vec![0u16, 1, 2]));

	let program = glium::Program::from_source(&display,
		"#version 410
		 uniform mat4 matrix;

		 in vec2 position;
		 in vec3 color;

		 out vec3 vColor;

		 void main()
		 {
		 	gl_Position = vec4(position, 0.0, 1.0) * matrix;
		 	vColor = color;
		 }",

		"#version 410
		 in vec3 vColor;

		 out vec4 fragColor;

		 void main()
		 {
		 	fragColor = vec4(vColor, 1.0);
		 }", None).unwrap();

	'main: loop
	{
		let uniforms = uniform!
		{
			matrix:
			[
				[1.0, 0.0, 0.0, 0.0],
				[0.0, 1.0, 0.0, 0.0],
				[0.0, 0.0, 1.0, 0.0],
				[0.0, 0.0, 0.0, 1.0f32]
			]
		};

		let mut target = display.draw();
		target.clear_color(0.0, 0.0, 0.0, 0.0);
		target.draw(&vertex_buffer, &index_buffer, &program, &uniforms,
			&std::default::Default::default());
		target.finish();

		timer::sleep(Duration::milliseconds(10));

		for event in display.poll_events()
		{
			match event
			{
				glutin::Event::KeyboardInput(_, _,
					Some(glutin::VirtualKeyCode::Q)) => break 'main,
				_ => ()
			}
		}
	}
}

//----------------------------------------------------------------
<commit_msg>more minor changes<commit_after>//
//	main.rs
//	SweetEngine
//
//	Copyright (c) 2015 Infinite
//	Licensed under the terms of the Apache License, v2
//

//----------------------------------------------------------------

//	Feature gates
#![feature(std_misc, plugin, io)]

//	Imports
#![plugin(glium_macros)]
#[macro_use] extern crate glium;
extern crate glutin;

//	Global namespace pollution ;P
use std::old_io::timer;
use std::time::Duration;
use glium::{DisplayBuild, Surface};

//----------------------------------------------------------------

//	Our vertex struct
#[vertex_format]
#[derive(Copy)]
struct Vertex
{
	position: [f32; 2],
	color: [f32; 3],
}

//----------------------------------------------------------------

fn main()
{
	let display = glutin::WindowBuilder::new()
		.with_vsync()
		.with_gl_version((4, 1))
		.with_dimensions(960, 540)
		.with_title(format!("SweetWindow"))
		.build_glium().unwrap();

	let vertex_buffer = {
		glium::VertexBuffer::new(&display,
			vec!
			[
				Vertex { position: [-0.5, -0.5], color: [0.0, 1.0, 0.0] },
				Vertex { position: [ 0.0,  0.5], color: [0.0, 0.0, 1.0] },
				Vertex { position: [ 0.5, -0.5], color: [1.0, 0.0, 0.0] },
			]
		)
	};

	let index_buffer = glium::IndexBuffer::new(&display,
		glium::index_buffer::TrianglesList(vec![0u16, 1, 2]));

	let program = glium::Program::from_source(&display,
		"#version 410
		 uniform mat4 matrix;

		 in vec2 position;
		 in vec3 color;

		 out vec3 vColor;

		 void main()
		 {
		 	gl_Position = vec4(position, 0.0, 1.0) * matrix;
		 	vColor = color;
		 }",

		"#version 410
		 in vec3 vColor;

		 out vec4 fragColor;

		 void main()
		 {
		 	fragColor = vec4(vColor, 1.0);
		 }", None).unwrap();

	'main: loop
	{
		let uniforms = uniform!
		{
			matrix:
			[
				[1.0, 0.0, 0.0, 0.0],
				[0.0, 1.0, 0.0, 0.0],
				[0.0, 0.0, 1.0, 0.0],
				[0.0, 0.0, 0.0, 1.0f32]
			]
		};

		let mut target = display.draw();
		target.clear_color(0.0, 0.0, 0.0, 0.0);
		target.draw(&vertex_buffer, &index_buffer, &program, &uniforms,
			&std::default::Default::default());
		target.finish();

		timer::sleep(Duration::milliseconds(10));

		for event in display.poll_events()
		{
			match event
			{
				glutin::Event::KeyboardInput(_, _,
					Some(glutin::VirtualKeyCode::Q)) => break 'main,
				_ => ()
			}
		}
	}
}

//----------------------------------------------------------------
<|endoftext|>


<commit_before>extern crate regex;
use regex::Regex;

use std::io::{self, BufReader};
use std::io::BufRead;
use std::fs::File;
extern crate time;
use time::Tm;
use time::strptime;
use time::Duration;

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct Request {
    id: i32,
    time: Tm,
    url: String,
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct Response {
    id: i32,
    time: Tm,
    mime_type: String,
    response_time: Duration,
}

fn open_logfile(path: &str) -> Result<Vec<Request>, io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();

    for line in f.lines() {
        let r = try!(parse_request_line(line.unwrap()));
        println!("{:?}", r);
        requests.push(r)
    }

    Ok(requests)
}

pub fn parse_request_line(log_line: String) -> Result<Request, io::Error> {
    let parts: Vec<&str> = log_line.split(" ").collect();

    let id = parts[2];
    let url = parts[5];

    Ok(Request {
        id: id[1..id.len()-1].parse().unwrap(),
        time: strptime(parts[0], "%d/%b/%Y:%H:%M:%S").unwrap(),
        url: url.to_string()
    })
}

pub fn parse_response_line(log_line: String) -> Result<Response, io::Error> {
    let parts: Vec<&str> = log_line.split(" ").collect();

    let id = parts[2];
    let response_time = parts[parts.len()-1];
    let mime_type = parts[5];

    Ok(Response {
        id: id[1..id.len()-1].parse().unwrap(),
        time: strptime(parts[0], "%d/%b/%Y:%H:%M:%S").unwrap(),
        response_time: Duration::milliseconds(response_time[0..response_time.len()-2].parse().unwrap()),
        mime_type: mime_type.to_string()
    })
}

fn main() {
    let requests = open_logfile("src/test/simple-1.log");

    match requests {
        Ok(requests) => println!("So many: {}", requests.len()),
        Err(e) => println!("Could not parse, error {}", e),
    }
}

#[cfg(test)]
mod tests {
	use super::*;
    extern crate time;
    use time::strptime;
    use::time::Duration;

    #[test]
    fn test_parse_request_line() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1".to_string();

        let expected = Request {
            id: 2,
            time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            url: "/content/some/other.html".to_string()
        };

        let result = parse_request_line(line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line() {
        let line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let expected = Response {
            id: 2,
            time: strptime("08/Apr/2016:09:58:48 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            mime_type: "text/html".to_string(),
            response_time: Duration::milliseconds(10),
        };

        let result = parse_response_line(line);

        assert_eq!(result.unwrap(), expected)
    }
}
<commit_msg>Parse both line types<commit_after>extern crate regex;
use regex::Regex;

use std::io::{self, BufReader};
use std::io::BufRead;
use std::fs::File;
extern crate time;
use time::Tm;
use time::strptime;
use time::Duration;

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub enum HttpStatus {
    Continue,
    SwitchingProtocols,
    Processing,
    OK,
    Created,
    Accepted,
    NonAuthoritativeInformation,
    NoContent,
    ResetContent,
    PartialContent,
    MultiStatus,
    AlreadyReported,
    IMUsed,
    MultipleChoices,
    MovedPermanently,
    Found,
    SeeOther,
    NotModified,
    UseProxy,
    TemporaryRedirect,
    PermanentRedirect,
    BadRequest,
    Unauthorized,
    PaymentRequired,
    Forbidden,
    NotFound,
    MethodNotAllowed,
    NotAcceptable,
    ProxyAuthenticationRequired,
    RequestTimeout,
    Conflict,
    Gone,
    LengthRequired,
    PreconditionFailed,
    PayloadTooLarge,
    URITooLong,
    UnsupportedMediaType,
    RangeNotSatisfiable,
    ExpectationFailed,
    ImaTeapot,
    MisdirectedRequest,
    UnprocessableEntity,
    Locked,
    FailedDependency,
    UpgradeRequired,
    PreconditionRequired,
    TooManyRequests,
    RequestHeaderFieldsTooLarge,
    UnavailableForLegalReasons,
    InternalServerError,
    NotImplemented,
    BadGateway,
    ServiceUnavailable,
    GatewayTimeout,
    HTTPVersionNotSupported,
    VariantAlsoNegotiates,
    InsufficientStorage,
    LoopDetected,
    NotExtended,
    NetworkAuthenticationRequired,
    Unregistered,
}

impl HttpStatus {
    fn from_code(code: i32) -> HttpStatus {
        match code {
            100 => HttpStatus::Continue,
            101 => HttpStatus::SwitchingProtocols,
            102 => HttpStatus::Processing,
            200 => HttpStatus::OK,
            201 => HttpStatus::Created,
            202 => HttpStatus::Accepted,
            203 => HttpStatus::NonAuthoritativeInformation,
            204 => HttpStatus::NoContent,
            205 => HttpStatus::ResetContent,
            206 => HttpStatus::PartialContent,
            207 => HttpStatus::MultiStatus,
            208 => HttpStatus::AlreadyReported,
            226 => HttpStatus::IMUsed,
            300 => HttpStatus::MultipleChoices,
            301 => HttpStatus::MovedPermanently,
            302 => HttpStatus::Found,
            303 => HttpStatus::SeeOther,
            304 => HttpStatus::NotModified,
            305 => HttpStatus::UseProxy,
            307 => HttpStatus::TemporaryRedirect,
            308 => HttpStatus::PermanentRedirect,
            400 => HttpStatus::BadRequest,
            401 => HttpStatus::Unauthorized,
            402 => HttpStatus::PaymentRequired,
            403 => HttpStatus::Forbidden,
            404 => HttpStatus::NotFound,
            405 => HttpStatus::MethodNotAllowed,
            406 => HttpStatus::NotAcceptable,
            407 => HttpStatus::ProxyAuthenticationRequired,
            408 => HttpStatus::RequestTimeout,
            409 => HttpStatus::Conflict,
            410 => HttpStatus::Gone,
            411 => HttpStatus::LengthRequired,
            412 => HttpStatus::PreconditionFailed,
            413 => HttpStatus::PayloadTooLarge,
            414 => HttpStatus::URITooLong,
            415 => HttpStatus::UnsupportedMediaType,
            416 => HttpStatus::RangeNotSatisfiable,
            417 => HttpStatus::ExpectationFailed,
            418 => HttpStatus::ImaTeapot,
            421 => HttpStatus::MisdirectedRequest,
            422 => HttpStatus::UnprocessableEntity,
            423 => HttpStatus::Locked,
            424 => HttpStatus::FailedDependency,
            426 => HttpStatus::UpgradeRequired,
            428 => HttpStatus::PreconditionRequired,
            429 => HttpStatus::TooManyRequests,
            431 => HttpStatus::RequestHeaderFieldsTooLarge,
            451 => HttpStatus::UnavailableForLegalReasons,
            500 => HttpStatus::InternalServerError,
            501 => HttpStatus::NotImplemented,
            502 => HttpStatus::BadGateway,
            503 => HttpStatus::ServiceUnavailable,
            504 => HttpStatus::GatewayTimeout,
            505 => HttpStatus::HTTPVersionNotSupported,
            506 => HttpStatus::VariantAlsoNegotiates,
            507 => HttpStatus::InsufficientStorage,
            508 => HttpStatus::LoopDetected,
            510 => HttpStatus::NotExtended,
            511 => HttpStatus::NetworkAuthenticationRequired,
            _ => HttpStatus::Unregistered,
        }
    }
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct Request {
    id: i32,
    time: Tm,
    url: String,
}

#[derive(Eq, PartialEq)]
#[derive(Debug)]
pub struct Response {
    id: i32,
    time: Tm,
    mime_type: String,
    response_time: Duration,
    http_status: HttpStatus,
}

pub fn open_logfile(path: &str) -> Result<(Vec<Request>,Vec<Response>), io::Error> {
    let f = try!(File::open(path));

    let f = BufReader::new(f);

    let mut requests: Vec<Request> = Vec::new();
    let mut responses: Vec<Response> = Vec::new();

    for line in f.lines() {
        let line_value = &line.unwrap();

        if line_value.contains("->") {
            let r = try!(parse_request_line(&line_value));
            println!("{:#?}", r);
            requests.push(r)
        }

        if line_value.contains("<-") {
            let r = try!(parse_response_line(&line_value));
            println!("{:#?}", r);
            responses.push(r)
        }

    }

    Ok((requests, responses))
}

pub fn parse_request_line(log_line: &String) -> Result<Request, io::Error> {
    let parts: Vec<&str> = log_line.split(" ").collect();

    let id = parts[2];
    let url = parts[5];

    Ok(Request {
        id: id[1..id.len()-1].parse().unwrap(),
        time: strptime(parts[0], "%d/%b/%Y:%H:%M:%S").unwrap(),
        url: url.to_string()
    })
}

pub fn parse_response_line(log_line: &String) -> Result<Response, io::Error> {
    let parts: Vec<&str> = log_line.split(" ").collect();

    let id = parts[2];
    let response_time = parts[parts.len()-1];
    let mime_type = parts[5];
    let status_code = parts[4];

    Ok(Response {
        id: id[1..id.len()-1].parse().unwrap(),
        time: strptime(parts[0], "%d/%b/%Y:%H:%M:%S").unwrap(),
        response_time: Duration::milliseconds(response_time[0..response_time.len()-2].parse().unwrap()),
        mime_type: mime_type.to_string(),
        http_status: HttpStatus::from_code(status_code.parse().unwrap()),
    })
}

fn main() {
    let lines = open_logfile("src/test/simple-1.log");
    let (requests, responses) = lines.unwrap();
    println!("So many requests: {}", requests.len());
    println!("So many responses: {}", responses.len());
}

#[cfg(test)]
mod tests {
	use super::*;
    extern crate time;
    use time::strptime;
    use::time::Duration;

    #[test]
    fn test_parse_request_line() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1".to_string();

        let expected = Request {
            id: 2,
            time: strptime("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            url: "/content/some/other.html".to_string()
        };

        let result = parse_request_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line() {
        let line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let expected = Response {
            id: 2,
            time: strptime("08/Apr/2016:09:58:48 +0200", "%d/%b/%Y:%H:%M:%S").unwrap(),
            mime_type: "text/html".to_string(),
            response_time: Duration::milliseconds(10),
            http_status: HttpStatus::OK,
        };

        let result = parse_response_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_open_logfile() {
        let lines = open_logfile("src/test/simple-1.log");
        let (requests, responses) = lines.unwrap();

        assert_eq!(requests.len(), 2);
        assert_eq!(responses.len(), 2);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
pub mod parser;

fn evaluate(input: &str, env: &mut HashMap<String, f64>) -> Result<f64, String> {
    let mut p = parser::Parser::new(input);
    let ast = try!(p.parse());
    match ast.eval(env) {
        Some(result) => Ok(result),
        None => Err("No value for that expression!".to_string())
    }
}

pub fn main() {
    use std::f64;
    let mut env = HashMap::new();
    env.insert("wow".to_string(), 35.0f64);
    env.insert("pi".to_string(), f64::consts::PI);

    let stdin = io::stdin();

    loop {
        print!(">> ");
        io::stdout().flush().ok();

        let mut input = String::new();

        match stdin.read_line(&mut input) {
            Ok(_) => {
                let result = evaluate(&input.trim_right(), &mut env);
                match result {
                    Ok(value) => {
                        println!("=> {}", value);
                    }
                    Err(s) => {
                        println!("Error: {}", s);
                    }
                }
                io::stdout().flush().ok();
            }
            Err(_) => {
                println!("");
                break;
            }
        }
    }
}
<commit_msg>Exit when ctrl-d is entered<commit_after>use std::io;
use std::io::prelude::*;
use std::collections::HashMap;
pub mod parser;

fn evaluate(input: &str, env: &mut HashMap<String, f64>) -> Result<f64, String> {
    let mut p = parser::Parser::new(input);
    let ast = try!(p.parse());
    match ast.eval(env) {
        Some(result) => Ok(result),
        None => Err("No value for that expression!".to_string())
    }
}

pub fn main() {
    use std::f64;
    let mut env = HashMap::new();
    env.insert("wow".to_string(), 35.0f64);
    env.insert("pi".to_string(), f64::consts::PI);

    let stdin = io::stdin();

    loop {
        print!(">> ");
        io::stdout().flush().ok();

        let mut input = String::new();

        match stdin.read_line(&mut input) {
            Ok(_) => {

                if input.len() == 0 {
                    println!("");
                    return;
                }

                let expression_text = input.trim_right();

                let result = evaluate(expression_text, &mut env);
                match result {
                    Ok(value) => {
                        println!("=> {}", value);
                    }
                    Err(s) => {
                        println!("Error: {}", s);
                    }
                }
                io::stdout().flush().ok();
            }
            Err(_) => {
                println!("");
                return;
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin, macro_rules)]
//#![plugin(serde_macros)]
extern crate rustc_serialize;

extern crate hyper;
extern crate docopt;
extern crate zmq;
extern crate nanomsg;
extern crate git2;
extern crate serde;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate nix;
extern crate glob;

pub mod cluster;
pub mod agent;
pub mod jobs;
pub mod storage;
mod logging;
mod repl;
mod jq;
mod help;

//use x::logging;
use docopt::Docopt;

static USAGE: &'static str = "
builder cli.

Usage:
  bldr agent [--port=<portnumber>] [<peers>...]
  bldr repl
  bldr storage init
  bldr storage show
  bldr storage show
  bldr add job <json>
  bldr -h | --help

Options:
  -v --verbose
  -h --help

Some common bldr commands are:
    agent (describe | help)     Various commands related to agent
    storage (init | | show | help)
    help
See 'bldr help <command>' for more information on a specific command.
";

fn main() {

    let args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).version(Some("0.0.1".to_string())).parse())
        .unwrap_or_else(|e| e.exit());
    //let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    println!("args: {:?}", args);
    println!("arg vector: {:?}", args.get_vec("<args>"));

    match logging::logging::init() {
        Err(e) => println!("Unable to initialize logging system: {}", e),
        _ => {}
    }

    trace!("args: {:?}", args);
    trace!("arg vector: {:?}", args.get_vec("<args>"));

    if args.get_bool("agent")  {
        let peers = args.get_vec("<peers>");

        // args[0] program name
        // args[1] self
        for x in 1..peers.len() {
            println!("{} {}", x, peers[x]); // x: i32
        }

        //peers[0].as_ref(), args.iter().skip(1).collect::<Vec<_>>());

        info!("local: {}, peers: {:?}", args.get_str("<portnumber>"), args.get_vec("<peers>"));
        agent::start(peers);
    }
    else if args.get_bool("repl") {
        repl::start();
    }
    else if args.get_bool("storage") {
        let storage = storage::bootstrap();

        //let cmd = Command::new().args().exec();
        if args.get_bool("show") {
            storage.list();
        }

    }
    else if args.get_bool("add") && args.get_bool("job") {
        let storage = storage::bootstrap();
        // got an add command, what kind of add is it?
        // options discover add from json?
        // or assume a subsequent command to clarify type
        // right now assume sub-command for specific type of 'add'.
        let json = args.get_str("<json>");
        info!("json: {}", json);
        match jobs::from_raw_json(&storage, json) {
            Ok(_) => println!("got raw json ok."),
            Err(e) => panic!("uh oh {}", e)
        };
    }
}
<commit_msg>adding latest<commit_after>#![feature(custom_derive, plugin)]
#![feature(unboxed_closures)]

//#![plugin(serde_macros)]
extern crate rustc_serialize;

extern crate hyper;
extern crate docopt;
extern crate nanomsg;
extern crate git2;
extern crate serde;

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate nix;
extern crate glob;

pub mod cluster;
pub mod jobs;
pub mod storage;
mod logging;
mod repl;
mod jq;

use docopt::Docopt;

static USAGE: &'static str = "
builder cli.

Usage:
  bldr agent [<peers>...]
  bldr repl
  bldr storage init
  bldr storage show
  bldr jobs add <json>
  bldr jobs list
  bldr jobs rm [<id>...]
  bldr jobs show [<id...]
  bldr -h | --help

Options:
  -v --verbose
  -h --help

Some common bldr commands are:
    agent (describe | help)     Various commands related to agent
    storage (init | | show | help)
    help
See 'bldr help <command>' for more information on a specific command.
";

fn main() {

    let args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).version(Some("0.0.1".to_string())).parse())
        .unwrap_or_else(|e| e.exit());
    //let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());

    println!("args: {:?}", args);
    println!("arg vector: {:?}", args.get_vec("<args>"));

    match logging::logging::init() {
        Err(e) => println!("Unable to initialize logging system: {}", e),
        _ => {}
    }

    trace!("args: {:?}", args);
    trace!("arg vector: {:?}", args.get_vec("<args>"));

    if args.get_bool("agent")  {
        let peers = args.get_vec("<peers>");

        // args[0] program name
        // args[1] self
        for x in 1..peers.len() {
            println!("{} {}", x, peers[x]); // x: i32
        }

        //peers[0].as_ref(), args.iter().skip(1).collect::<Vec<_>>());

        info!("local: {}, peers: {:?}", args.get_str("<portnumber>"), args.get_vec("<peers>"));

        //agent::Agent::start(peers.iter().map(|s| String::from_utf8_lossy(s.to_owned())).collect::<Vec<_>>());
        //agent::Agent::start(peers.iter().map(|s| String::from_utf8_unchecked(s.to_owned())));
        //agent::Agent::start(peers.iter().map(|s| String::from_str(s)).collect::<Vec<_>>());
        //agent::Agent::start(peers.iter().map(|s| s.to_string()).collect::<Vec<_>>());

        //cluster::participate(peers[0].as_ref(), peers.iter().skip(1).collect::<Vec<_>>());
        cluster::participate(peers[0].as_ref(), peers.iter().skip(1).map(|s| s.to_string()).collect::<Vec<_>>());
    }
    else if args.get_bool("repl") {
        repl::start();
    }
    else if args.get_bool("storage") {
        let storage = storage::bootstrap();

        //let cmd = Command::new().args().exec();
        if args.get_bool("show") {
            storage.list();
        }

    }
    if args.get_bool("jobs") {

        if args.get_bool("add") {
            let storage = storage::bootstrap();
            // got an add command, what kind of add is it?
            // options discover add from json?
            // or assume a subsequent command to clarify type
            // right now assume sub-command for specific type of 'add'.
            let json = args.get_str("<json>");
            info!("json: {}", json);
            match jobs::from_raw_json(&storage, json) {
                Ok(_) => println!("got raw json ok."),
                Err(e) => panic!("error from_raw_json {}", e)
            };
        }
        else if args.get_bool("list") {
            let storage = storage::bootstrap();
            // jobs::list(&storage, move |j| {
            //     println!("job {}", j);
            // });

            jobs::list();
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
extern crate env_logger;

extern crate nerve;

use clap::{Arg, App, SubCommand};

use nerve::cmd;
use nerve::format::{OutputFormat};
use nerve::validators::{is_repopath};

fn main() {
    env_logger::init().unwrap();

    let matches = App::new("github-issues")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Arnau Siches <arnau@ustwo.com>")
                      .about("Github issues consumer.")
                      .subcommand(SubCommand::with_name("upload")
                                             .about("Upload issues from a CSV file")
                                             .about("Check for duplicates in Github for a given CSV")
                                             .arg(Arg::with_name("repopath")
                                                      .help("Repo path (e.g. ustwo/mastermind)")
                                                      .index(1)
                                                      .validator(is_repopath)
                                                      .required(true))
                                             .arg(Arg::with_name("oauth-token")
                                                      .help("Github OAuth authorisation token")
                                                      .long("oauth-token")
                                                      .value_name("oauth_token")
                                                      .required(true))
                                             .arg(Arg::with_name("input")
                                                      .help("Read input from <file>")
                                                      .long("input")
                                                      .value_name("file")
                                                      .required(true))
                                             .arg(Arg::with_name("check")
                                                      .help("Check if any records in the provided CSV have potential collisions in existing Issues. This flag makes the command noop.")
                                                      .long("check")))
                      .subcommand(SubCommand::with_name("fetch")
                                             .about("Fetch issues from Github.")
                                             .arg(Arg::with_name("repopath")
                                                      .help("Repo path (e.g. ustwo/mastermind)")
                                                      .index(1)
                                                      .validator(is_repopath)
                                                      .required(true))
                                             .arg(Arg::with_name("oauth-token")
                                                      .help("Github OAuth authorisation token")
                                                      .long("oauth-token")
                                                      .value_name("oauth_token")
                                                      .required(true))
                                             .arg(Arg::with_name("format")
                                                      .help("Output format")
                                                      .long("format")
                                                      .value_name("format")
                                                      .possible_values(&["csv", "json"])
                                                      .required(true))
                                             .arg(Arg::with_name("output")
                                                      .help("Write output to <file>")
                                                      .long("output")
                                                      .value_name("file")
                                                      .required(true))
                                             .arg(Arg::with_name("state")
                                                      .help("Issue state. Defaults to \"all\"")
                                                      .long("state")
                                                      .value_name("state")
                                                      .possible_values(&["all", "open", "closed"]))
                                             .arg(Arg::with_name("label")
                                                      .help("Github label to filter with")
                                                      .long("label")
                                                      .value_name("label")
                                                      .multiple(true)))
                      .get_matches();

    if let Some(ref matches) = matches.subcommand_matches("fetch") {
        let labels: Vec<String> = values_t!(matches, "label", String).unwrap_or(vec![]);
        let state = matches.value_of("state").unwrap_or("all").to_owned();
        let repopath = matches.value_of("repopath").unwrap().to_owned();
        let oauth_token = matches.value_of("oauth-token").unwrap().to_owned();
        let format = value_t!(matches, "format", OutputFormat).unwrap_or_else(|e| e.exit());
        let output = matches.value_of("output").unwrap().to_owned();

        cmd::fetch::run(repopath,
                        oauth_token,
                        labels,
                        state,
                        format,
                        output);
    }

    if let Some(ref matches) = matches.subcommand_matches("upload") {
        let repopath = matches.value_of("repopath").unwrap().to_owned();
        let oauth_token = matches.value_of("oauth-token").unwrap().to_owned();
        let input_file = matches.value_of("input").unwrap().to_owned();

        if matches.is_present("check") {
            cmd::check::run(repopath,
                            oauth_token,
                            input_file);
        } else {
            cmd::upload::run(repopath,
                             oauth_token,
                             input_file);
        }
    }

}
<commit_msg>feat(upload): Add upload-template command<commit_after>#[macro_use] extern crate clap;
#[macro_use] extern crate log;
extern crate env_logger;

extern crate nerve;

use clap::{Arg, App, SubCommand};

use nerve::cmd;
use nerve::format::{OutputFormat};
use nerve::validators::{is_repopath};

fn main() {
    env_logger::init().unwrap();

    let upload_about = "Upload issues from a CSV file. If the first line is
detected to be a header it will be ignored. The fields are identified and
consumed in order:

1. `title`
2. `body`
3. `labels`
4. `assignees`
5. `milestone_id`";

    let matches = App::new("github-issues")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Arnau Siches <arnau@ustwo.com>")
                      .about("Github issues consumer.")
                      .subcommand(SubCommand::with_name("upload-template")
                                             .about("Generates a CSV example as an easy start for the upload command."))
                      .subcommand(SubCommand::with_name("upload")
                                             .about(upload_about)
                                             .arg(Arg::with_name("repopath")
                                                      .help("Repo path (e.g. ustwo/mastermind)")
                                                      .index(1)
                                                      .validator(is_repopath)
                                                      .required(true))
                                             .arg(Arg::with_name("oauth-token")
                                                      .help("Github OAuth authorisation token")
                                                      .long("oauth-token")
                                                      .value_name("oauth_token")
                                                      .required(true))
                                             .arg(Arg::with_name("input")
                                                      .help("Read input from <file>")
                                                      .long("input")
                                                      .value_name("file")
                                                      .required(true))
                                             .arg(Arg::with_name("check")
                                                      .help("Check if any records in the provided CSV have potential collisions in existing Issues. This flag makes the command noop.")
                                                      .long("check")))
                      .subcommand(SubCommand::with_name("fetch")
                                             .about("Fetch issues from Github.")
                                             .arg(Arg::with_name("repopath")
                                                      .help("Repo path (e.g. ustwo/mastermind)")
                                                      .index(1)
                                                      .validator(is_repopath)
                                                      .required(true))
                                             .arg(Arg::with_name("oauth-token")
                                                      .help("Github OAuth authorisation token")
                                                      .long("oauth-token")
                                                      .value_name("oauth_token")
                                                      .required(true))
                                             .arg(Arg::with_name("format")
                                                      .help("Output format")
                                                      .long("format")
                                                      .value_name("format")
                                                      .possible_values(&["csv", "json"])
                                                      .required(true))
                                             .arg(Arg::with_name("output")
                                                      .help("Write output to <file>")
                                                      .long("output")
                                                      .value_name("file")
                                                      .required(true))
                                             .arg(Arg::with_name("state")
                                                      .help("Issue state. Defaults to \"all\"")
                                                      .long("state")
                                                      .value_name("state")
                                                      .possible_values(&["all", "open", "closed"]))
                                             .arg(Arg::with_name("label")
                                                      .help("Github label to filter with")
                                                      .long("label")
                                                      .value_name("label")
                                                      .multiple(true)))
                      .get_matches();

    if let Some(ref matches) = matches.subcommand_matches("fetch") {
        let labels: Vec<String> = values_t!(matches, "label", String).unwrap_or(vec![]);
        let state = matches.value_of("state").unwrap_or("all").to_owned();
        let repopath = matches.value_of("repopath").unwrap().to_owned();
        let oauth_token = matches.value_of("oauth-token").unwrap().to_owned();
        let format = value_t!(matches, "format", OutputFormat).unwrap_or_else(|e| e.exit());
        let output = matches.value_of("output").unwrap().to_owned();

        cmd::fetch::run(repopath,
                        oauth_token,
                        labels,
                        state,
                        format,
                        output);
    }

    if let Some(_) = matches.subcommand_matches("upload-template") {
        println!(r#"title,body,labels,assignees,milestone_id
"A nice title","A descriptive body","in_backlog,feature",arnau,1"#);
    }

    if let Some(ref matches) = matches.subcommand_matches("upload") {
        let repopath = matches.value_of("repopath").unwrap().to_owned();
        let oauth_token = matches.value_of("oauth-token").unwrap().to_owned();
        let input_file = matches.value_of("input").unwrap().to_owned();

        if matches.is_present("check") {
            cmd::check::run(repopath,
                            oauth_token,
                            input_file);
        } else {
            cmd::upload::run(repopath,
                             oauth_token,
                             input_file);
        }
    }

}
<|endoftext|>


<commit_before>extern crate combine;
extern crate nix; // As in *nix
extern crate rand;
extern crate signal;

mod commander;

// Reference: https://github.com/NixOS/nixpkgs/blob/b07051ce6c3ba3039c89b6755da279002b0c3ace/nixos/modules/virtualisation/nixos-container.pl

use nix::sys::signal::{kill, SIGTERM, SIGINT};
use std::io;
use std::io::Write;
use std::process::Command;

#[derive(Debug)]
enum Error {
    Usage(String),
    NonZero(String, i32),
    ControlError(String),
    IoError(io::Error),
    NixError(nix::Error),
    Interrupted(commander::Signal)
}

use Error::*;

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self { IoError(e) }
}

impl From<nix::Error> for Error {
    fn from(e: nix::Error) -> Self { NixError(e) }
}

impl From<commander::NonZero> for Error {
    fn from(e: commander::NonZero) -> Self { match e { commander::NonZero::NonZero(s, o) => NonZero(s, o), commander::NonZero::Interrupted(n) => Interrupted(n) } }
}

type Result<T> = std::result::Result<T, Error>;

// TODO: why can't this be inferred away
fn run<T>(cmd: &mut Command) -> Result<T> where T: commander::CommandOut { commander::run(cmd) }

fn probably_unique_name(length: usize) -> String {
    use rand::distributions::{IndependentSample, Range};
    let between = Range::new(0, 36);
    let mut rng = rand::thread_rng();
    unsafe {
        std::str::from_utf8_unchecked(&(0..length).map(|_| between.ind_sample(&mut rng)).map(|v| if v < 10 { v + 48 } else { v + 87 }).collect::<Vec<u8>>()).to_string()
    }
}

// Result is of the form "10.233.x"
fn unused_ip_block() -> Result<String> {
    // Can bail early anywhere here because we've got the lock
    let mut used = std::collections::HashSet::new();
    for entry in try!(std::fs::read_dir("/etc/containers")) {
        let entry = try!(entry);
        if try!(entry.file_type()).is_file() {
            let mut str = String::new();
            use std::io::Read;
            try!(try!(std::fs::File::open(entry.path())).read_to_string(&mut str));
            for line in str.lines() {
                use combine::{string, many1, choice, digit, token, eof, Parser, ParserExt};
                let ip_component = || { string("10.233.").with(many1::<String, _>(digit())).skip(token('.')).skip(many1::<String, _>(digit())) };
                if let Ok((c, _)) = choice([string("HOST_ADDRESS="), string("LOCAL_ADDRESS=")]).with(ip_component()).skip(eof()).parse(line) {
                    used.insert(c);
                }
            }
        }
    }
    (0..255).map(|p| p.to_string()).find(|s| !used.contains(s)).map(|s| format!("10.233.{}", s)).ok_or(ControlError("Out of IP addresses".to_string()))
}

fn mkpath(mode : u32, path : &str) -> Result<()> {
    use std::os::unix::fs::DirBuilderExt;
    match std::fs::DirBuilder::new().mode(mode).create(path) {
        Err(e) => if let std::io::ErrorKind::AlreadyExists = e.kind() { Ok(()) } else { Err(IoError(e)) },
        Ok(()) => Ok(())
    }
}

fn system_init() -> Result<()> {
    try!(mkpath(0o0755, "/etc/containers"));
    try!(mkpath(0o0700, "/var/lib/containers"));
    Ok(())
}

fn profile_dir(name : &str) -> String {
    format!("/nix/var/nix/profiles/per-container/{}", name)
}

fn container_root(name : &str) -> String {
    format!("/var/lib/containers/{}", name)
}

fn conf_file(name : &str) -> String {
    format!("/etc/containers/{}.conf", name)
}

fn create(config_file : &str) -> Result<String> {
    fn init_container_unsynced(name : &str) -> Result<()> {
        let ip_block = try!(unused_ip_block());
        // Use create_new to avoid clobbering existing container
        let mut f = try!(std::fs::OpenOptions::new().create_new(true).write(true).open(conf_file(name)));
        write!(&mut f, "PRIVATE_NETWORK=1\nHOST_ADDRESS={0}.1\nLOCAL_ADDRESS={0}.2\nAUTO_START=0\n", ip_block).map_err(IoError)
    }

    fn populate_container(name : &str, config_file : &str) -> Result<()> {
        use std::os::unix::fs::DirBuilderExt;
        // The per-container directory is restricted to prevent users on
        // the host from messing with guest users who happen to have the
        // same uid.
        try!(mkpath(0o0700, "/nix/var/nix/profiles/per-container"));
        let profile_dir = profile_dir(name);
        let mut dir_builder = std::fs::DirBuilder::new();
        try!(dir_builder.mode(0o0755).create(&profile_dir));

        let container_root = container_root(name);
        dir_builder.recursive(true);
        try!(dir_builder.mode(0o0755).create(format!("{}/etc/nixos", container_root)));

        // Write configuration.nix into the container fs
        let configuration_nix = format!("{}/etc/nixos/configuration.nix", container_root);
        {
            let mut f = try!(std::fs::File::create(format!("{}/etc/nixos/configuration.nix", container_root)));
            try!(write!(&mut f, "
    {{ config, lib, pkgs, ... }}:
    with lib;

    {{
        boot.isContainer = true;
        networking.hostName = mkDefault \"{}\";
        networking.useDHCP = false;
        imports = [ {} ];
    }}", name, config_file));
            // TODO: guaranteed sync at end of block?
        }

        // Build the container config
        run(Command::new("nix-env")
            .arg("-p").arg(format!("{}/system", profile_dir))
            .arg("-I").arg(format!("nixos-config={}", configuration_nix))
            .arg("-f").arg("<nixpkgs/nixos>")
            .arg("--set")
            .arg("-A").arg("system")
            .arg("--show-trace"))
    }

    let name = format!("fr{}", probably_unique_name(9));

    // Acquire lock
    use std::os::unix::io::IntoRawFd;
    let lock_fd = try!(std::fs::OpenOptions::new().create(true).append(true).open("/run/lock/nixos-container")).into_raw_fd();
    try!(nix::fcntl::flock(lock_fd, nix::fcntl::FlockArg::LockExclusive));

    let res = init_container_unsynced(&name);

    // Drop lock
    unsafe {
        let _ = nix::libc::close(lock_fd);  // If closing fails, ¯\_(ツ)_/¯
    }

    match res.and_then(|()| populate_container(&name, config_file)) {
        Ok(()) => Ok(name),
        // Don't leave a half-baked container behind
        Err(e) => { let (_, _) = (stop(&name), destroy(&name)); Err(e) }
    }
}

fn run_test(container_name : &str, args : &[String]) -> Result<i32> {
    try!(run(Command::new("systemctl").arg("start").arg(format!("container@{}", container_name))));
    let leader_pid = try!(run(Command::new("machinectl").arg("show").arg(container_name).arg("-p").arg("Leader")).and_then(|o : String| {
        use combine::{string, many1, digit, spaces, eof, Parser, ParserExt};
        string("Leader=").with(many1::<String, _>(digit())).skip(spaces()).skip(eof()).parse(o.as_str())
            .map(|(ds, _)| ds)
            .map_err(|_| ControlError(format!("Bad machinectl output {}", o)))
    }));
    let su_cmd = args.iter().map(|s| format!("'{}'", s.replace("'", "'\\''"))).collect::<Vec<String>>().join(" ");
    match run(Command::new("nsenter")
            .arg("-t").arg(leader_pid)
            .arg("-m").arg("-u").arg("-i").arg("-n").arg("-p")
            .arg("--").arg("/var/setuid-wrappers/su").arg("root").arg("-l").arg("-c").arg(format!("exec {}", su_cmd))) {
        Ok(()) => Ok(0),
        Err(NonZero(_, code)) => Ok(code),
        Err(e) => Err(e)
    }
}

// Remove a directory while recursively unmounting all mounted filesystems within
// that directory and unmounting/removing that directory afterwards as well.
//
// Specified path shouldn't be a mountpoint.
fn safe_remove_tree(path : &str) -> Result<()> {
    if !std::path::Path::new(path).is_dir() {
        return Ok(());
    }
    try!(run(Command::new("find").arg(path)
        .arg("-mindepth").arg("1")
        .arg("-xdev")
        .arg("(")
            .arg("-type").arg("d")
            .arg("-exec").arg("mountpoint").arg("-q").arg("{}").arg(";")
        .arg(")")
        .arg("-exec").arg("umount").arg("-fR").arg("{}").arg("+")));
    try!(run(Command::new("rm").arg("--one-file-system").arg("-rf").arg(path)));

    Ok(())
}

fn stop(container_name : &str) -> Result<()> {
    match run(Command::new("systemctl").arg("stop").arg(format!("container@{}", container_name))) {
        Ok(()) => Ok(()),
        Err(Interrupted(_)) => {
            return run(Command::new("systemctl").arg("kill").arg(format!("container@{}", container_name)))
        },
        Err(e) => Err(e)
    }
}

fn destroy(container_name : &str) -> Result<()> {
    fn log_err(e: Error) {
        println!("Error while destroying container: {:?}", e);
    }

    safe_remove_tree(&profile_dir(container_name)).unwrap_or_else(log_err);
    safe_remove_tree(&format!("/nix/var/nix/gcroots/per-container/{}", container_name)).unwrap_or_else(log_err);
    safe_remove_tree(&container_root(container_name)).unwrap_or_else(log_err);

    std::fs::remove_file(conf_file(container_name)).or_else(|e| match e.kind() {
        std::io::ErrorKind::NotFound => Ok(()),
        _ => Err(IoError(e))
    })
}

fn go() -> Result<i32> {
    // Skip program name
    let mut args = std::env::args().skip(1).peekable();

    let no_destroy = args.peek().map_or(false, |arg| arg == "--no-destroy");
    if no_destroy { args.next(); }

    let config_file = try!(args.next().ok_or(Error::Usage("Missing config file argument".to_string())));

    let test_args : Vec<String> = args.collect();
    if test_args.len() == 0 {
        return Err(Usage("Missing test args".to_string()));
    }

    let config_file = {
        let p = try!(std::fs::canonicalize(config_file).map_err(|e| Usage(format!("For config file: {}", e))));
        try!(p.to_str().ok_or(Usage("Config file path is invalid UTF-8".to_string()))).to_string()
    };

    try!(system_init());
    // We suppress signals in this process and allow the commander module to deal with child processes
    let trap = signal::trap::Trap::trap(&[SIGTERM, SIGINT]);
    let container_name = try!(create(&config_file));
    let res = match trap.wait(std::time::Instant::now()) {
        None => run_test(&container_name, &test_args),
        Some(n) => Err(Interrupted(n))
    };

    let _ = stop(&container_name);
    if !no_destroy {
        try!(destroy(&container_name));
    }

    res
}

fn main() {
    std::process::exit(go().unwrap_or_else(|e| match e {
        NonZero(cmd, code) => { writeln!(io::stderr(), "Command {:?} failed with code {:?}", cmd, code).unwrap(); 2 },
        Usage(msg) => { writeln!(io::stderr(), "Usage error: {}", msg).unwrap(); 1 },
        IoError(err) => { writeln!(io::stderr(), "{}", err).unwrap(); 2 },
        NixError(err) => { writeln!(io::stderr(), "{}", err).unwrap(); 2 },
        ControlError(msg) => { writeln!(io::stderr(), "{}", msg).unwrap(); 2 },
        Interrupted(SIGINT) => { kill(nix::unistd::getpid(), SIGINT).unwrap(); loop {} }
        Interrupted(n) => 128 + n
    }));
}
<commit_msg>Don't do dumb things<commit_after>extern crate combine;
extern crate nix; // As in *nix
extern crate rand;
extern crate signal;

mod commander;

// Reference: https://github.com/NixOS/nixpkgs/blob/b07051ce6c3ba3039c89b6755da279002b0c3ace/nixos/modules/virtualisation/nixos-container.pl

use nix::sys::signal::{kill, SIGTERM, SIGINT};
use std::io;
use std::io::Write;
use std::process::Command;

#[derive(Debug)]
enum Error {
    Usage(String),
    NonZero(String, i32),
    ControlError(String),
    IoError(io::Error),
    NixError(nix::Error),
    Interrupted(commander::Signal)
}

use Error::*;

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self { IoError(e) }
}

impl From<nix::Error> for Error {
    fn from(e: nix::Error) -> Self { NixError(e) }
}

impl From<commander::NonZero> for Error {
    fn from(e: commander::NonZero) -> Self { match e { commander::NonZero::NonZero(s, o) => NonZero(s, o), commander::NonZero::Interrupted(n) => Interrupted(n) } }
}

type Result<T> = std::result::Result<T, Error>;

// TODO: why can't this be inferred away
fn run<T>(cmd: &mut Command) -> Result<T> where T: commander::CommandOut { commander::run(cmd) }

fn probably_unique_name(length: usize) -> String {
    use rand::distributions::{IndependentSample, Range};
    let between = Range::new(0, 36);
    let mut rng = rand::thread_rng();
    unsafe {
        std::str::from_utf8_unchecked(&(0..length).map(|_| between.ind_sample(&mut rng)).map(|v| if v < 10 { v + 48 } else { v + 87 }).collect::<Vec<u8>>()).to_string()
    }
}

// Result is of the form "10.233.x"
fn unused_ip_block() -> Result<String> {
    // Can bail early anywhere here because we've got the lock
    let mut used = std::collections::HashSet::new();
    for entry in try!(std::fs::read_dir("/etc/containers")) {
        let entry = try!(entry);
        if try!(entry.file_type()).is_file() {
            let mut str = String::new();
            use std::io::Read;
            try!(try!(std::fs::File::open(entry.path())).read_to_string(&mut str));
            for line in str.lines() {
                use combine::{string, many1, choice, digit, token, eof, Parser, ParserExt};
                let ip_component = || { string("10.233.").with(many1::<String, _>(digit())).skip(token('.')).skip(many1::<String, _>(digit())) };
                if let Ok((c, _)) = choice([string("HOST_ADDRESS="), string("LOCAL_ADDRESS=")]).with(ip_component()).skip(eof()).parse(line) {
                    used.insert(c);
                }
            }
        }
    }
    (0..255).map(|p| p.to_string()).find(|s| !used.contains(s)).map(|s| format!("10.233.{}", s)).ok_or(ControlError("Out of IP addresses".to_string()))
}

fn mkpath(mode : u32, path : &str) -> Result<()> {
    use std::os::unix::fs::DirBuilderExt;
    match std::fs::DirBuilder::new().mode(mode).create(path) {
        Err(e) => if let std::io::ErrorKind::AlreadyExists = e.kind() { Ok(()) } else { Err(IoError(e)) },
        Ok(()) => Ok(())
    }
}

fn system_init() -> Result<()> {
    try!(mkpath(0o0755, "/etc/containers"));
    try!(mkpath(0o0700, "/var/lib/containers"));
    Ok(())
}

fn profile_dir(name : &str) -> String {
    format!("/nix/var/nix/profiles/per-container/{}", name)
}

fn container_root(name : &str) -> String {
    format!("/var/lib/containers/{}", name)
}

fn conf_file(name : &str) -> String {
    format!("/etc/containers/{}.conf", name)
}

fn create(config_file : &str) -> Result<String> {
    fn init_container_unsynced(name : &str) -> Result<()> {
        let ip_block = try!(unused_ip_block());
        // Use create_new to avoid clobbering existing container
        let mut f = try!(std::fs::OpenOptions::new().create_new(true).write(true).open(conf_file(name)));
        write!(&mut f, "PRIVATE_NETWORK=1\nHOST_ADDRESS={0}.1\nLOCAL_ADDRESS={0}.2\nAUTO_START=0\n", ip_block).map_err(IoError)
    }

    fn populate_container(name : &str, config_file : &str) -> Result<()> {
        use std::os::unix::fs::DirBuilderExt;
        // The per-container directory is restricted to prevent users on
        // the host from messing with guest users who happen to have the
        // same uid.
        try!(mkpath(0o0700, "/nix/var/nix/profiles/per-container"));
        let profile_dir = profile_dir(name);
        let mut dir_builder = std::fs::DirBuilder::new();
        try!(dir_builder.mode(0o0755).create(&profile_dir));

        let container_root = container_root(name);
        dir_builder.recursive(true);
        try!(dir_builder.mode(0o0755).create(format!("{}/etc/nixos", container_root)));

        // Write configuration.nix into the container fs
        let configuration_nix = format!("{}/etc/nixos/configuration.nix", container_root);
        {
            let mut f = try!(std::fs::File::create(format!("{}/etc/nixos/configuration.nix", container_root)));
            try!(write!(&mut f, "
    {{ config, lib, pkgs, ... }}:
    with lib;

    {{
        boot.isContainer = true;
        networking.hostName = mkDefault \"{}\";
        networking.useDHCP = false;
        imports = [ {} ];
    }}", name, config_file));
            // TODO: guaranteed sync at end of block?
        }

        // Build the container config
        run(Command::new("nix-env")
            .arg("-p").arg(format!("{}/system", profile_dir))
            .arg("-I").arg(format!("nixos-config={}", configuration_nix))
            .arg("-f").arg("<nixpkgs/nixos>")
            .arg("--set")
            .arg("-A").arg("system")
            .arg("--show-trace"))
    }

    let name = format!("fr{}", probably_unique_name(9));

    // Acquire lock
    use std::os::unix::io::IntoRawFd;
    let lock_fd = try!(std::fs::OpenOptions::new().create(true).append(true).open("/run/lock/nixos-container")).into_raw_fd();
    try!(nix::fcntl::flock(lock_fd, nix::fcntl::FlockArg::LockExclusive));

    let res = init_container_unsynced(&name);

    // Drop lock
    unsafe {
        let _ = nix::libc::close(lock_fd);  // If closing fails, ¯\_(ツ)_/¯
    }

    match res.and_then(|()| populate_container(&name, config_file)) {
        Ok(()) => Ok(name),
        // Don't leave a half-baked container behind
        Err(e) => { let _ = (stop(&name), destroy(&name)); Err(e) }
    }
}

fn run_test(container_name : &str, args : &[String]) -> Result<i32> {
    try!(run(Command::new("systemctl").arg("start").arg(format!("container@{}", container_name))));
    let leader_pid = try!(run(Command::new("machinectl").arg("show").arg(container_name).arg("-p").arg("Leader")).and_then(|o : String| {
        use combine::{string, many1, digit, spaces, eof, Parser, ParserExt};
        string("Leader=").with(many1::<String, _>(digit())).skip(spaces()).skip(eof()).parse(o.as_str())
            .map(|(ds, _)| ds)
            .map_err(|_| ControlError(format!("Bad machinectl output {}", o)))
    }));
    let su_cmd = args.iter().map(|s| format!("'{}'", s.replace("'", "'\\''"))).collect::<Vec<String>>().join(" ");
    match run(Command::new("nsenter")
            .arg("-t").arg(leader_pid)
            .arg("-m").arg("-u").arg("-i").arg("-n").arg("-p")
            .arg("--").arg("/var/setuid-wrappers/su").arg("root").arg("-l").arg("-c").arg(format!("exec {}", su_cmd))) {
        Ok(()) => Ok(0),
        Err(NonZero(_, code)) => Ok(code),
        Err(e) => Err(e)
    }
}

// Remove a directory while recursively unmounting all mounted filesystems within
// that directory and unmounting/removing that directory afterwards as well.
//
// Specified path shouldn't be a mountpoint.
fn safe_remove_tree(path : &str) -> Result<()> {
    if !std::path::Path::new(path).is_dir() {
        return Ok(());
    }
    try!(run(Command::new("find").arg(path)
        .arg("-mindepth").arg("1")
        .arg("-xdev")
        .arg("(")
            .arg("-type").arg("d")
            .arg("-exec").arg("mountpoint").arg("-q").arg("{}").arg(";")
        .arg(")")
        .arg("-exec").arg("umount").arg("-fR").arg("{}").arg("+")));
    try!(run(Command::new("rm").arg("--one-file-system").arg("-rf").arg(path)));

    Ok(())
}

fn stop(container_name : &str) -> Result<()> {
    match run(Command::new("systemctl").arg("stop").arg(format!("container@{}", container_name))) {
        Ok(()) => Ok(()),
        Err(Interrupted(_)) => {
            return run(Command::new("systemctl").arg("kill").arg(format!("container@{}", container_name)))
        },
        Err(e) => Err(e)
    }
}

fn destroy(container_name : &str) -> Result<()> {
    fn log_err(e: Error) {
        println!("Error while destroying container: {:?}", e);
    }

    safe_remove_tree(&profile_dir(container_name)).unwrap_or_else(log_err);
    safe_remove_tree(&format!("/nix/var/nix/gcroots/per-container/{}", container_name)).unwrap_or_else(log_err);
    safe_remove_tree(&container_root(container_name)).unwrap_or_else(log_err);

    std::fs::remove_file(conf_file(container_name)).or_else(|e| match e.kind() {
        std::io::ErrorKind::NotFound => Ok(()),
        _ => Err(IoError(e))
    })
}

fn go() -> Result<i32> {
    // Skip program name
    let mut args = std::env::args().skip(1).peekable();

    let no_destroy = args.peek().map_or(false, |arg| arg == "--no-destroy");
    if no_destroy { args.next(); }

    let config_file = try!(args.next().ok_or(Error::Usage("Missing config file argument".to_string())));

    let test_args : Vec<String> = args.collect();
    if test_args.len() == 0 {
        return Err(Usage("Missing test args".to_string()));
    }

    let config_file = {
        let p = try!(std::fs::canonicalize(config_file).map_err(|e| Usage(format!("For config file: {}", e))));
        try!(p.to_str().ok_or(Usage("Config file path is invalid UTF-8".to_string()))).to_string()
    };

    try!(system_init());
    // We suppress signals in this process and allow the commander module to deal with child processes
    let trap = signal::trap::Trap::trap(&[SIGTERM, SIGINT]);
    let container_name = try!(create(&config_file));
    let res = match trap.wait(std::time::Instant::now()) {
        None => run_test(&container_name, &test_args),
        Some(n) => Err(Interrupted(n))
    };

    let _ = stop(&container_name);
    if !no_destroy {
        try!(destroy(&container_name));
    }

    res
}

fn main() {
    std::process::exit(go().unwrap_or_else(|e| match e {
        NonZero(cmd, code) => { writeln!(io::stderr(), "Command {:?} failed with code {:?}", cmd, code).unwrap(); 2 },
        Usage(msg) => { writeln!(io::stderr(), "Usage error: {}", msg).unwrap(); 1 },
        IoError(err) => { writeln!(io::stderr(), "{}", err).unwrap(); 2 },
        NixError(err) => { writeln!(io::stderr(), "{}", err).unwrap(); 2 },
        ControlError(msg) => { writeln!(io::stderr(), "{}", msg).unwrap(); 2 },
        Interrupted(SIGINT) => { kill(nix::unistd::getpid(), SIGINT).unwrap(); loop {} }
        Interrupted(n) => 128 + n
    }));
}
<|endoftext|>


<commit_before>
#![feature(test)]
#![feature(conservative_impl_trait)]
#![feature(specialization)]

#[macro_use]

extern crate ndarray;
extern crate test;
extern crate rand;
extern crate ndarray_rand;
extern crate num;
extern crate chrono;
extern crate error_chain;
extern crate itertools;

pub mod dataframe;
pub mod error;
mod from;
pub mod types;
pub mod read;
pub mod traits;
pub mod transform;
pub mod aggregate;
pub mod process;
pub mod join;

use ndarray::arr2;
use dataframe::*;
use types::*;

use std::f64::NAN;
use traits::{Transform, Operations, Constructor, Aggregate, ToDataFrame};
use error::*;
use ndarray::{Axis, ArrayView};
use ndarray::stack;
macro_rules! dataframe {
 {
    $t:ty,
    { $ ($column:expr , $data:expr);+}
} => { {
    let mut n : Vec<String> = Vec::new();
    $(
        n.push($column.to_owned());
    )*
    let a : Matrix<$t> = stack(Axis(1), &[ $(ArrayView::from(&$data) ),+ ]).unwrap();
    let new_index : Vec<String> = (0..a.dim().0).map(|x| x.to_string()).collect();
    DataFrame::new(a).index(&new_index[..])?.columns(&n[..])?

}
}
}

macro_rules! array {
    {
        $($element : expr),+
    } => {
        arr2(&[$($element)+]).t().to_owned()
    }
}

fn main() {
    if let Err(ref e) = run() {
        use ::std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    let a = arr2(&[[2., 7.], [3., NAN], [2., 4.]]);
    // let b = arr2(&[[2., 6.], [3., 4.]]);
    let c = arr2(&[[2., 6.], [3., 4.], [2., 1.]]);
    let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"])?
        .index(&["1", "2", "3"])?;
    let df_1 = DataFrame::new(c).columns(&["c", "d"]).unwrap().index(&["1", "2", "3"]).unwrap();
    let new_data = df.select(&["2"], UtahAxis::Row).as_array();

    println!("{:?}", new_data);
    // let df_iter: DataFrameIterator = df_1.df_iter(UtahAxis::Row);
    df.impute(ImputeStrategy::Mean, UtahAxis::Column).as_df();
    let j = df.df_iter(UtahAxis::Row)
        .remove(&["1"])
        .select(&["2"])
        .append("8", new_data.view())
        .sumdf()
        .as_df();
    println!("{:?}", j);
    let res: DataFrame<f64, String> = df.impute(ImputeStrategy::Mean, UtahAxis::Column)
        .as_df();

    println!("{:?}", res);
    let res_1: DataFrame<f64, String> = df.inner_left_join(&df_1).as_df();
    println!("join result - {:?}", res_1);
    let concat = df.concat(&df_1, UtahAxis::Row).as_df();
    println!("concat result - {:?}", concat);
    // let b = arr1(&[2., 3., 2.]);
    let k: DataFrame<f64, String> = dataframe!(
        f64,
    {
        "a", array!([2., 3., 2.]);
        "b", array!([2., NAN, 2.])
    });
    println!("{:?}", k);
    Ok(())

}
<commit_msg>added dataframe macro<commit_after>
#![feature(test)]
#![feature(conservative_impl_trait)]
#![feature(specialization)]

#[macro_use]

extern crate ndarray;
extern crate test;
extern crate rand;
extern crate ndarray_rand;
extern crate num;
extern crate chrono;
extern crate error_chain;
extern crate itertools;

pub mod dataframe;
pub mod error;
mod from;
pub mod types;
pub mod read;
pub mod traits;
pub mod transform;
pub mod aggregate;
pub mod process;
pub mod join;

use ndarray::arr2;
use dataframe::*;
use types::*;

use std::f64::NAN;
use traits::{Transform, Operations, Constructor, Aggregate, ToDataFrame};
use error::*;
use ndarray::{Axis, ArrayView};
use ndarray::stack;
macro_rules! dataframe {
 {
    { $ ($column:expr => $data:expr),+}
} => { {
    let mut n : Vec<String> = Vec::new();
    $(
        n.push($column.to_owned());
    )*
    let a  = stack(Axis(1), &[ $(ArrayView::from(&$data) ),+ ]).unwrap();
    let new_index : Vec<String> = (0..a.dim().0).map(|x| x.to_string()).collect();
    DataFrame::new(a).index(&new_index[..])?.columns(&n[..])?

}
}
}

macro_rules! array {
    {
        $($element : expr),+
    } => {
        arr2(&[$($element)+]).t().to_owned()
    }
}

fn main() {
    if let Err(ref e) = run() {
        use ::std::io::Write;
        let stderr = &mut ::std::io::stderr();
        let errmsg = "Error writing to stderr";

        writeln!(stderr, "error: {}", e).expect(errmsg);

        for e in e.iter().skip(1) {
            writeln!(stderr, "caused by: {}", e).expect(errmsg);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            writeln!(stderr, "backtrace: {:?}", backtrace).expect(errmsg);
        }

        ::std::process::exit(1);
    }
}

fn run() -> Result<()> {
    let a = arr2(&[[2., 7.], [3., NAN], [2., 4.]]);
    // let b = arr2(&[[2., 6.], [3., 4.]]);
    let c = arr2(&[[2., 6.], [3., 4.], [2., 1.]]);
    let mut df: DataFrame<f64, String> = DataFrame::new(a).columns(&["a", "b"])?
        .index(&["1", "2", "3"])?;
    let df_1 = DataFrame::new(c).columns(&["c", "d"]).unwrap().index(&["1", "2", "3"]).unwrap();
    let new_data = df.select(&["2"], UtahAxis::Row).as_array();

    println!("{:?}", new_data);
    // let df_iter: DataFrameIterator = df_1.df_iter(UtahAxis::Row);
    df.impute(ImputeStrategy::Mean, UtahAxis::Column).as_df();
    let j = df.df_iter(UtahAxis::Row)
        .remove(&["1"])
        .select(&["2"])
        .append("8", new_data.view())
        .sumdf()
        .as_df();
    println!("{:?}", j);
    let res: DataFrame<f64, String> = df.impute(ImputeStrategy::Mean, UtahAxis::Column)
        .as_df();

    println!("{:?}", res);
    let res_1: DataFrame<f64, String> = df.inner_left_join(&df_1).as_df();
    println!("join result - {:?}", res_1);
    let concat = df.concat(&df_1, UtahAxis::Row).as_df();
    println!("concat result - {:?}", concat);
    // let b = arr1(&[2., 3., 2.]);
    let k: DataFrame<f64, String> = dataframe!(
    {
        "a" =>  array!([2., 3., 2.]),
        "b" =>  array!([2., NAN, 2.])
    });
    println!("{:?}", k);
    Ok(())

}
<|endoftext|>


<commit_before>extern crate libc;
extern crate errno;

use std::io::Write;

const ETH_P_ARP: libc::c_int = 0x0806;

fn main() {
    let mut args = std::env::args();
    if args.len() != 3 {
        std::io::stderr().write("Usage: arpmasqd LISTEN_ADDR SEND_ADDR\n".as_ref()).unwrap();
        panic!("number of arguments");
    }
    let listen_addr = args.next();
    let send_addr = args.next();
    let listen_socket = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_RAW, ETH_P_ARP.to_be()) };
    if listen_socket == -1 {
        let err = errno::errno();
        panic!("Error opening socket: {} ({})", err, err.0);
    }
}
<commit_msg>Added socket binding<commit_after>extern crate libc;
extern crate errno;

use std::io::Write;

const ETH_P_ARP: libc::c_int = 0x0806;

fn main() {
    let mut args = std::env::args();
    if args.len() != 3 {
        std::io::stderr().write("Usage: arpmasqd LISTEN_ADDR SEND_ADDR\n".as_ref()).unwrap();
        panic!("number of arguments");
    }
    let listen_addr = args.next();
    let send_addr = args.next();
    let listen_socket = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_RAW, ETH_P_ARP.to_be()) };
    if listen_socket == -1 {
        let err = errno::errno();
        panic!("Error opening socket: {} ({})", err, err.0);
    }
    let bind_result = unsafe { libc::bind(listen_socket, &listen_sockaddr, std::mem::size_of_val(listen_sockaddr)) };
    if bind_result == -1 {
        let err = errno::errno();
        panic!("Error binding socket: {} ({})", err, err.0);
    }
}
<|endoftext|>