<commit_before>extern crate cc;
extern crate fs_extra;
extern crate metadeps;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(t) => t,
            Err(e) => panic!("{} return the error {}", stringify!($e), e),
        }
    };
}

fn main() {
    // Rerun if the c-ares source code has changed.
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=c-ares");

    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return;
    }

    // We'll compile from source.  Clean up previous build, if any.
    let outdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = outdir.join("build");
    let _ = fs::remove_dir_all(&build);
    fs::create_dir(&build).unwrap();

    // Copy the c-ares source code into $OUT_DIR, where it's safe for the build
    // process to modify it.
    let c_ares_dir = outdir.join("c-ares");
    let _ = fs::remove_dir_all(&c_ares_dir);
    let copy_options = fs_extra::dir::CopyOptions::new();
    let src = env::current_dir().unwrap().join("c-ares");
    fs_extra::dir::copy(&src, &outdir, &copy_options).unwrap();

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return;
    }

    // Prepare.
    run(Command::new("sh").current_dir(&c_ares_dir).arg("buildconf"));

    // Configure.
    let cfg = cc::Build::new();
    let compiler = cfg.get_compiler();
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    let mut cmd = Command::new("sh");
    cmd.env("CFLAGS", &cflags)
        .env("CC", compiler.path())
        .current_dir(&build)
        .arg(format!("{}", c_ares_dir.join("configure").display()))
        .arg("--enable-static")
        .arg("--disable-shared")
        .arg("--enable-optimize")
        .arg("--disable-debug")
        .arg("--disable-tests")
        .arg(format!("--prefix={}", outdir.display()));

    // This code fragment copied from curl-rust... c-ares and curl come from
    // the same developer so are usually pretty similar, and this seems to
    // work.
    //
    // NOTE GNU terminology
    // BUILD = machine where we are (cross) compiling
    // HOST = machine where the compiled binary will be used
    // TARGET = only relevant when compiling compilers
    let host = env::var("HOST").unwrap();
    if target != host && (!target.contains("windows") || !host.contains("windows")) {
        if target.contains("windows") {
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }
    run(&mut cmd);

    // Compile.
    run(Command::new(make())
        .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
        .current_dir(&build));

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/src/lib/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {
        "gmake"
    } else {
        "make"
    }
}

fn nmake(target: &str) -> Command {
    // cargo messes with the environment in a way that nmake does not like -
    // see https://github.com/rust-lang/cargo/issues/4156.  Explicitly remove
    // the unwanted variables.
    let mut cmd = cc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS");
    cmd
}

fn build_msvc(target: &str) {
    // Prepare.  We've already copied the c-ares source code into the output
    // directory.
    let outdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let c_ares_dir = outdir.join("c-ares");
    run(Command::new("cmd")
        .current_dir(&c_ares_dir)
        .arg("/c")
        .arg("buildconf.bat"));

    // Compile.
    let mut cmd = nmake(target);
    cmd.current_dir(&c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let build = outdir.join("build");
    let mut cmd = nmake(target);
    cmd.current_dir(&c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=static=libcares");
}
<commit_msg>fix windows build<commit_after>extern crate cc;
extern crate fs_extra;
extern crate metadeps;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(t) => t,
            Err(e) => panic!("{} return the error {}", stringify!($e), e),
        }
    };
}

fn main() {
    // Rerun if the c-ares source code has changed.
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=c-ares");

    // Use the installed libcares if it is available.
    if metadeps::probe().is_ok() {
        return;
    }

    // We'll compile from source.  Clean up previous build, if any.
    let outdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = outdir.join("build");
    let _ = fs::remove_dir_all(&build);
    fs::create_dir(&build).unwrap();

    // Copy the c-ares source code into $OUT_DIR, where it's safe for the build
    // process to modify it.
    let c_ares_dir = outdir.join("c-ares");
    let _ = fs::remove_dir_all(&c_ares_dir);
    let copy_options = fs_extra::dir::CopyOptions::new();
    let src = env::current_dir().unwrap().join("c-ares");
    fs_extra::dir::copy(&src, &outdir, &copy_options).unwrap();

    // MSVC builds are different.
    let target = env::var("TARGET").unwrap();
    if target.contains("msvc") {
        build_msvc(&target);
        return;
    }

    // Prepare.
    run(Command::new("sh").current_dir(&c_ares_dir).arg("buildconf"));

    // Configure.
    let cfg = cc::Build::new();
    let compiler = cfg.get_compiler();
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    let mut cmd = Command::new("sh");
    cmd.env("CFLAGS", &cflags)
        .env("CC", compiler.path())
        .current_dir(&build)
        .arg(format!("{}", c_ares_dir.join("configure").display()))
        .arg("--enable-static")
        .arg("--disable-shared")
        .arg("--enable-optimize")
        .arg("--disable-debug")
        .arg("--disable-tests")
        .arg(format!("--prefix={}", outdir.display()));

    // This code fragment copied from curl-rust... c-ares and curl come from
    // the same developer so are usually pretty similar, and this seems to
    // work.
    //
    // NOTE GNU terminology
    // BUILD = machine where we are (cross) compiling
    // HOST = machine where the compiled binary will be used
    // TARGET = only relevant when compiling compilers
    let host = env::var("HOST").unwrap();
    if target != host && (!target.contains("windows") || !host.contains("windows")) {
        if target.contains("windows") {
            cmd.arg(format!("--host={}", host));
            cmd.arg(format!("--target={}", target));
        } else {
            cmd.arg(format!("--build={}", host));
            cmd.arg(format!("--host={}", target));
        }
    }
    run(&mut cmd);

    // Compile.
    run(Command::new(make())
        .arg(format!("-j{}", env::var("NUM_JOBS").unwrap()))
        .current_dir(&build));

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/src/lib/.libs", build.display());
    println!("cargo:rustc-link-lib=static=cares");
}

fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    assert!(t!(cmd.status()).success());
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {
        "gmake"
    } else {
        "make"
    }
}

fn nmake(target: &str) -> Command {
    // cargo messes with the environment in a way that nmake does not like -
    // see https://github.com/rust-lang/cargo/issues/4156.  Explicitly remove
    // the unwanted variables.
    let mut cmd = cc::windows_registry::find(target, "nmake.exe").unwrap();
    cmd.env_remove("MAKEFLAGS").env_remove("MFLAGS");
    cmd
}

fn build_msvc(target: &str) {
    // Prepare.  We've already copied the c-ares source code into the output
    // directory.
    let outdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let c_ares_dir = outdir.join("c-ares");
    run(Command::new("cmd")
        .current_dir(&c_ares_dir)
        .arg("/c")
        .arg("buildconf.bat"));

    // Compile.
    let mut cmd = nmake(target);
    cmd.current_dir(&c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "CFG=lib-release", "c-ares"]);
    run(&mut cmd);

    // Install library.
    let build = outdir.join("build");
    let mut cmd = nmake(target);
    cmd.current_dir(&c_ares_dir);
    cmd.args(&["/f", "Makefile.msvc", "/a", "CFG=lib-release", "install"]);
    cmd.env("INSTALL_DIR", format!("{}", build.display()));
    run(&mut cmd);

    // Link to compiled library.
    println!("cargo:rustc-link-search={}/lib", build.display());
    println!("cargo:rustc-link-lib=iphlpapi");
    println!("cargo:rustc-link-lib=static=libcares");
}
<|endoftext|>


<commit_before>#![crate_name = "rustful_macros"]

#![crate_type = "dylib"]

#![doc(html_root_url = "http://ogeon.github.io/rustful/doc/")]

#![feature(macro_rules, plugin_registrar, quote, phase)]

//!This crate provides some helpful macros for rustful, including `router!` and `routes!`.
//!
//!#`router!`
//!The `router!` macro generates a `TreeRouter` containing the provided handlers and routing tree.
//!This can be useful to lower the risk of typing errors, among other things.
//!
//!##Example 1
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/about" => Get: about_us,
//!	"/user/:user" => Get: show_user,
//!	"/product/:name" => Get: show_product,
//!	"/*" => Get: show_error,
//!	"/" => Get: show_welcome
//!};
//!```
//!
//!##Example 2
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!```
//!
//!#`routes!`
//!
//!The `routes!` macro generates a vector of routes, which can be used to create a `TreeRouter`.
//!It has the same syntax as `routes!`.
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let routes = routes!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!
//!let router = TreeRouter::from_routes(&routes);
//!```

extern crate syntax;
extern crate rustc;

use std::path::BytesContainer;

use syntax::{ast, codemap};
use syntax::ext::base::{
	ExtCtxt, MacResult, MacExpr,
	NormalTT, TTMacroExpander
};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::parser;
use syntax::parse::parser::Parser;
use syntax::ptr::P;
//use syntax::print::pprust;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
	let expander = box expand_router as Box<TTMacroExpander>;
	reg.register_syntax_extension(token::intern("router"), NormalTT(expander, None));

	let expander = box expand_routes as Box<TTMacroExpander>;
	reg.register_syntax_extension(token::intern("routes"), NormalTT(expander, None));
}

fn expand_router<'cx>(cx: &'cx mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult + 'cx> {
	let router_ident = cx.ident_of("router");
	let insert_method = cx.ident_of("insert_item");

	let mut calls: Vec<P<ast::Stmt>> = vec!(
		cx.stmt_let(sp, true, router_ident, quote_expr!(&cx, ::rustful::TreeRouter::new()))
	);

	for (path, method, handler) in parse_routes(cx, tts).into_iter() {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		calls.push(cx.stmt_expr(
			cx.expr_method_call(sp, cx.expr_ident(sp, router_ident), insert_method, vec!(method_expr, path_expr, handler))
		));
	}

	let block = cx.expr_block(cx.block(sp, calls, Some(cx.expr_ident(sp, router_ident))));

	MacExpr::new(block)
}

fn expand_routes<'cx>(cx: &'cx mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult + 'cx> {
	let routes = parse_routes(cx, tts).into_iter().map(|(path, method, handler)| {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		mk_tup(sp, vec!(method_expr, path_expr, handler))
	}).collect();

	MacExpr::new(cx.expr_vec(sp, routes))
}

fn parse_routes(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Vec<(String, ast::Path, P<ast::Expr>)> {

	let mut parser = parse::new_parser_from_tts(
		cx.parse_sess(), cx.cfg(), tts.to_vec()
	);

	parse_subroutes("", cx, &mut parser)
}

fn parse_subroutes(base: &str, cx: &mut ExtCtxt, parser: &mut Parser) -> Vec<(String, ast::Path, P<ast::Expr>)> {
	let mut routes = Vec::new();

	while !parser.eat(&token::Eof) {
		match parser.parse_optional_str() {
			Some((ref s, _, _)) => {
				if !parser.eat(&token::FatArrow) {
					parser.expect(&token::FatArrow);
					break;
				}

				let mut new_base = base.to_string();
				match s.container_as_str() {
					Some(s) => {
						new_base.push_str(s.trim_chars('/'));
						new_base.push_str("/");
					},
					None => cx.span_err(parser.span, "invalid path")
				}

				if parser.eat(&token::Eof) {
					cx.span_err(parser.span, "unexpected end of routing tree");
				}

				if parser.eat(&token::OpenDelim(token::Brace)) {
					let subroutes = parse_subroutes(new_base.as_slice(), cx, parser);
					routes.push_all(subroutes.as_slice());

					if parser.eat(&token::CloseDelim(token::Brace)) {
						if !parser.eat(&token::Comma) {
							break;
						}
					} else {
						parser.expect_one_of(&[token::Comma, token::CloseDelim(token::Brace)], &[]);
					}
				} else {
					for (method, handler) in parse_handler(parser).into_iter() {
						routes.push((new_base.clone(), method, handler))
					}

					if !parser.eat(&token::Comma) {
						break;
					}
				}
			},
			None => {
				for (method, handler) in parse_handler(parser).into_iter() {
					routes.push((base.to_string(), method, handler))
				}

				if !parser.eat(&token::Comma) {
					break;
				}
			}
		}
	}

	routes
}

fn parse_handler(parser: &mut Parser) -> Vec<(ast::Path, P<ast::Expr>)> {
	let mut methods = Vec::new();

	loop {
		methods.push(parser.parse_path(parser::NoTypesAllowed));

		if parser.eat(&token::Colon) {
			break;
		}

		if !parser.eat(&token::BinOp(token::Or)) {
			parser.expect_one_of(&[token::Colon, token::BinOp(token::Or)], &[]);
		}
	}

	let handler = parser.parse_expr();

	methods.into_iter().map(|m| (m, handler.clone())).collect()
}

fn mk_tup(sp: codemap::Span, content: Vec<P<ast::Expr>>) -> P<ast::Expr> {
	dummy_expr(sp, ast::ExprTup(content))
}

fn dummy_expr(sp: codemap::Span, e: ast::Expr_) -> P<ast::Expr> {
	P(ast::Expr {
		id: ast::DUMMY_NODE_ID,
		node: e,
		span: sp,
	})
}

/**
A macro for assigning content types.

It takes a main type, a sub type and a parameter list. Instead of this:

```
response.headers.content_type = Some(MediaType {
	type_: String::from_str("text"),
	subtype: String::from_str("html"),
	parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
});
```

it can be written like this:

```
response.headers.content_type = content_type!("text", "html", "charset": "UTF-8");
```

The `"charset": "UTF-8"` part defines the parameter list for the content type.
It may contain more than one parameter, or be omitted:

```
response.headers.content_type = content_type!("application", "octet-stream", "type": "image/gif", "padding": "4");
```

```
response.headers.content_type = content_type!("image", "png");
```
**/
#[macro_export]
macro_rules! content_type(
	($main_type:expr, $sub_type:expr) => ({
		::rustful::mime::Mime (
			std::str::FromStr::from_str($main_type).unwrap(),
			std::str::FromStr::from_str($sub_type).unwrap(),
			Vec::new()
		)
	});

	($main_type:expr, $sub_type:expr, $($param:expr: $value:expr),+) => ({
		::rustful::mime::Mime (
			std::str::FromStr::from_str($main_type).unwrap(),
			std::str::FromStr::from_str($sub_type).unwrap(),
			vec!( $( (std::str::FromStr::from_str($param).unwrap(), std::str::FromStr::from_str($value).unwrap()) ),+ )
		)
	});
);

/**
A macro for callig `send` in response and aborting the handle function if it fails.

This macro will print an error to `stdout`.
**/
#[macro_export]
macro_rules! try_send(
	($writer:expr, $content:expr) => (
		match $writer.send($content) {
			Ok(v) => v,
			Err(::rustful::ResponseError::IoError(e)) => {
				println!("IO error: {}", e);
				return;
			},
			Err(::rustful::ResponseError::PluginError(e)) => {
				println!("plugin error: {}", e);
				return;
			}
		}
	);

	($writer:expr, $content:expr while $what:expr) => (
		match $writer.send($content) {
			Ok(v) => v,
			Err(::rustful::ResponseError::IoError(e)) => {
				println!("IO error while {}: {}", $what, e);
				return;
			},
			Err(::rustful::ResponseError::PluginError(e)) => {
				println!("plugin error while {}: {}", $what, e);
				return;
			}
		}
	)
);
<commit_msg>Invoke macro_rules! as a block<commit_after>#![crate_name = "rustful_macros"]

#![crate_type = "dylib"]

#![doc(html_root_url = "http://ogeon.github.io/rustful/doc/")]

#![feature(macro_rules, plugin_registrar, quote, phase)]

//!This crate provides some helpful macros for rustful, including `router!` and `routes!`.
//!
//!#`router!`
//!The `router!` macro generates a `TreeRouter` containing the provided handlers and routing tree.
//!This can be useful to lower the risk of typing errors, among other things.
//!
//!##Example 1
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/about" => Get: about_us,
//!	"/user/:user" => Get: show_user,
//!	"/product/:name" => Get: show_product,
//!	"/*" => Get: show_error,
//!	"/" => Get: show_welcome
//!};
//!```
//!
//!##Example 2
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let router = router!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!```
//!
//!#`routes!`
//!
//!The `routes!` macro generates a vector of routes, which can be used to create a `TreeRouter`.
//!It has the same syntax as `routes!`.
//!
//!```rust ignore
//!#![feature(phase)]
//!#[phase(plugin)]
//!extern crate rustful_macros;
//!
//!extern crate rustful;
//!
//!...
//!
//!
//!let routes = routes!{
//!	"/" => Get: show_home,
//!	"home" => Get: show_home,
//!	"user/:username" => {Get: show_user, Post: save_user},
//!	"product" => {
//!		Get: show_all_products,
//!
//!		"json" => Get: send_all_product_data
//!		":id" => {
//!			Get: show_product,
//!			Post | Delete: edit_product,
//!
//!			"json" => Get: send_product_data
//!		}
//!	}
//!};
//!
//!let router = TreeRouter::from_routes(&routes);
//!```

extern crate syntax;
extern crate rustc;

use std::path::BytesContainer;

use syntax::{ast, codemap};
use syntax::ext::base::{
	ExtCtxt, MacResult, MacExpr,
	NormalTT, TTMacroExpander
};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::parser;
use syntax::parse::parser::Parser;
use syntax::ptr::P;
//use syntax::print::pprust;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn macro_registrar(reg: &mut Registry) {
	let expander = box expand_router as Box<TTMacroExpander>;
	reg.register_syntax_extension(token::intern("router"), NormalTT(expander, None));

	let expander = box expand_routes as Box<TTMacroExpander>;
	reg.register_syntax_extension(token::intern("routes"), NormalTT(expander, None));
}

fn expand_router<'cx>(cx: &'cx mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult + 'cx> {
	let router_ident = cx.ident_of("router");
	let insert_method = cx.ident_of("insert_item");

	let mut calls: Vec<P<ast::Stmt>> = vec!(
		cx.stmt_let(sp, true, router_ident, quote_expr!(&cx, ::rustful::TreeRouter::new()))
	);

	for (path, method, handler) in parse_routes(cx, tts).into_iter() {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		calls.push(cx.stmt_expr(
			cx.expr_method_call(sp, cx.expr_ident(sp, router_ident), insert_method, vec!(method_expr, path_expr, handler))
		));
	}

	let block = cx.expr_block(cx.block(sp, calls, Some(cx.expr_ident(sp, router_ident))));

	MacExpr::new(block)
}

fn expand_routes<'cx>(cx: &'cx mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult + 'cx> {
	let routes = parse_routes(cx, tts).into_iter().map(|(path, method, handler)| {
		let path_expr = cx.parse_expr(format!("\"{}\"", path));
		let method_expr = cx.expr_path(method);
		mk_tup(sp, vec!(method_expr, path_expr, handler))
	}).collect();

	MacExpr::new(cx.expr_vec(sp, routes))
}

fn parse_routes(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Vec<(String, ast::Path, P<ast::Expr>)> {

	let mut parser = parse::new_parser_from_tts(
		cx.parse_sess(), cx.cfg(), tts.to_vec()
	);

	parse_subroutes("", cx, &mut parser)
}

fn parse_subroutes(base: &str, cx: &mut ExtCtxt, parser: &mut Parser) -> Vec<(String, ast::Path, P<ast::Expr>)> {
	let mut routes = Vec::new();

	while !parser.eat(&token::Eof) {
		match parser.parse_optional_str() {
			Some((ref s, _, _)) => {
				if !parser.eat(&token::FatArrow) {
					parser.expect(&token::FatArrow);
					break;
				}

				let mut new_base = base.to_string();
				match s.container_as_str() {
					Some(s) => {
						new_base.push_str(s.trim_chars('/'));
						new_base.push_str("/");
					},
					None => cx.span_err(parser.span, "invalid path")
				}

				if parser.eat(&token::Eof) {
					cx.span_err(parser.span, "unexpected end of routing tree");
				}

				if parser.eat(&token::OpenDelim(token::Brace)) {
					let subroutes = parse_subroutes(new_base.as_slice(), cx, parser);
					routes.push_all(subroutes.as_slice());

					if parser.eat(&token::CloseDelim(token::Brace)) {
						if !parser.eat(&token::Comma) {
							break;
						}
					} else {
						parser.expect_one_of(&[token::Comma, token::CloseDelim(token::Brace)], &[]);
					}
				} else {
					for (method, handler) in parse_handler(parser).into_iter() {
						routes.push((new_base.clone(), method, handler))
					}

					if !parser.eat(&token::Comma) {
						break;
					}
				}
			},
			None => {
				for (method, handler) in parse_handler(parser).into_iter() {
					routes.push((base.to_string(), method, handler))
				}

				if !parser.eat(&token::Comma) {
					break;
				}
			}
		}
	}

	routes
}

fn parse_handler(parser: &mut Parser) -> Vec<(ast::Path, P<ast::Expr>)> {
	let mut methods = Vec::new();

	loop {
		methods.push(parser.parse_path(parser::NoTypesAllowed));

		if parser.eat(&token::Colon) {
			break;
		}

		if !parser.eat(&token::BinOp(token::Or)) {
			parser.expect_one_of(&[token::Colon, token::BinOp(token::Or)], &[]);
		}
	}

	let handler = parser.parse_expr();

	methods.into_iter().map(|m| (m, handler.clone())).collect()
}

fn mk_tup(sp: codemap::Span, content: Vec<P<ast::Expr>>) -> P<ast::Expr> {
	dummy_expr(sp, ast::ExprTup(content))
}

fn dummy_expr(sp: codemap::Span, e: ast::Expr_) -> P<ast::Expr> {
	P(ast::Expr {
		id: ast::DUMMY_NODE_ID,
		node: e,
		span: sp,
	})
}

/**
A macro for assigning content types.

It takes a main type, a sub type and a parameter list. Instead of this:

```
response.headers.content_type = Some(MediaType {
	type_: String::from_str("text"),
	subtype: String::from_str("html"),
	parameters: vec!((String::from_str("charset"), String::from_str("UTF-8")))
});
```

it can be written like this:

```
response.headers.content_type = content_type!("text", "html", "charset": "UTF-8");
```

The `"charset": "UTF-8"` part defines the parameter list for the content type.
It may contain more than one parameter, or be omitted:

```
response.headers.content_type = content_type!("application", "octet-stream", "type": "image/gif", "padding": "4");
```

```
response.headers.content_type = content_type!("image", "png");
```
**/
#[macro_export]
macro_rules! content_type {
	($main_type:expr, $sub_type:expr) => ({
		::rustful::mime::Mime (
			std::str::FromStr::from_str($main_type).unwrap(),
			std::str::FromStr::from_str($sub_type).unwrap(),
			Vec::new()
		)
	});

	($main_type:expr, $sub_type:expr, $($param:expr: $value:expr),+) => ({
		::rustful::mime::Mime (
			std::str::FromStr::from_str($main_type).unwrap(),
			std::str::FromStr::from_str($sub_type).unwrap(),
			vec!( $( (std::str::FromStr::from_str($param).unwrap(), std::str::FromStr::from_str($value).unwrap()) ),+ )
		)
	});
}

/**
A macro for callig `send` in response and aborting the handle function if it fails.

This macro will print an error to `stdout`.
**/
#[macro_export]
macro_rules! try_send {
	($writer:expr, $content:expr) => (
		match $writer.send($content) {
			Ok(v) => v,
			Err(::rustful::ResponseError::IoError(e)) => {
				println!("IO error: {}", e);
				return;
			},
			Err(::rustful::ResponseError::PluginError(e)) => {
				println!("plugin error: {}", e);
				return;
			}
		}
	);

	($writer:expr, $content:expr while $what:expr) => (
		match $writer.send($content) {
			Ok(v) => v,
			Err(::rustful::ResponseError::IoError(e)) => {
				println!("IO error while {}: {}", $what, e);
				return;
			},
			Err(::rustful::ResponseError::PluginError(e)) => {
				println!("plugin error while {}: {}", $what, e);
				return;
			}
		}
	)
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use rustc::hir::{self, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use std::boxed;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io;
use std::path;
use syntax::ast;
use webidl::ast::*;
use webidl::visitor::*;
use webidl::*;

declare_lint!(
    WEBIDL_INHERIT_CORRECT,
    Deny,
    "Warn and report usage of incorrect webidl inheritance"
);

pub struct WebIdlPass;

#[derive(Clone, Debug)]
pub enum WebIdlError {
    ParentMismatch {
        name: String,
        rust_parent: String,
        webidl_parent: String,
    },
}

impl fmt::Display for WebIdlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            WebIdlError::ParentMismatch {
                name,
                rust_parent,
                webidl_parent,
            } => {
                return write!(f, "webidl-rust inheritance mismatch, rust: {:?}, rust parent: {:?}, webidl parent: {:?}",
                    &name, &rust_parent, &webidl_parent);
            },
        }
    }
}

impl Error for WebIdlError {
    fn description(&self) -> &str {
        "WebIdlError"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl WebIdlPass {
    pub fn new() -> WebIdlPass {
        WebIdlPass
    }
}

fn get_typ_name(typ: String) -> String {
    if let Some(i) = typ.rfind(':') {
        typ[i + 1..].to_string()
    } else {
        typ
    }
}

fn get_webidl_path(struct_name: &str) -> io::Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    dir.push("components/script/dom/webidls/");
    dir.push(format!("{}.webidl", struct_name));

    return Ok(dir);
}

fn is_webidl_ty(cx: &LateContext, ty: &ty::TyS) -> bool {
    let mut ret = false;
    ty.maybe_walk(|t| {
        match t.sty {
            ty::Adt(did, _substs) => {
                if cx.tcx.has_attr(did.did, "webidl") {
                    ret = true;
                }
                false
            },
            ty::Ref(..) => false,    // don't recurse down &ptrs
            ty::RawPtr(..) => false, // don't recurse down *ptrs
            ty::FnDef(..) | ty::FnPtr(_) => false,
            _ => true,
        }
    });
    ret
}

fn check_inherits(code: &str, name: &str, parent_name: &str) -> Result<(), Box<Error>> {
    let idl = parse_string(code)?;
    let mut visitor = InterfaceVisitor::new(name.to_string());
    visitor.visit(&idl);
    let inherits = visitor.get_inherits();

    println!("inherits: {:?}, parent_name: {:?}", inherits, parent_name);

    if inherits == parent_name {
        return Ok(());
    }
    Err(boxed::Box::from(WebIdlError::ParentMismatch {
        name: name.to_string(),
        rust_parent: parent_name.to_string(),
        webidl_parent: inherits.to_string(),
    }))
}

fn check_webidl(name: &str, parent_name: Option<String>) -> Result<(), Box<Error>> {
    let path = get_webidl_path(&name)?;
    println!("struct_webidl_path: {:?}", &path);

    if let Some(parent) = parent_name {
        let code = fs::read_to_string(path)?;
        return check_inherits(&code, &name, &parent);
    }

    Ok(())
}

impl LintPass for WebIdlPass {
    fn name(&self) -> &'static str {
        "ServoWebIDLPass"
    }

    fn get_lints(&self) -> LintArray {
        lint_array!(WEBIDL_INHERIT_CORRECT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WebIdlPass {
    fn check_struct_def(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        def: &'tcx hir::VariantData,
        n: ast::Name,
        _gen: &'tcx hir::Generics,
        id: HirId,
    ) {
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(id);
        if !is_webidl_ty(cx, cx.tcx.type_of(def_id)) {
            return;
        }

        let item = match cx.tcx.hir().get_by_hir_id(id) {
            hir::Node::Item(item) => item,
            _ => cx
                .tcx
                .hir()
                .expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)),
        };

        let struct_name = n.to_string();
        println!("struct_name: {:?}", struct_name);

        let mut parent_typ_name: Option<String> = None;
        for ref field in def.fields() {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id);
            let ty = cx.tcx.type_of(def_id);
            let typ_name = get_typ_name(ty.to_string());
            parent_typ_name = Some(typ_name);

            // Only first field is relevant.
            break;
        }

        match check_webidl(&struct_name, parent_typ_name) {
            Ok(()) => {},
            Err(e) => {
                let description = format!("{}", e);
                cx.span_lint(WEBIDL_INHERIT_CORRECT, item.ident.span, &description)
            },
        };
    }
}

struct InterfaceVisitor {
    name: String,
    inherits: String,
}

impl InterfaceVisitor {
    pub fn new(name: String) -> Self {
        InterfaceVisitor {
            name: name,
            inherits: String::new(),
        }
    }

    pub fn get_inherits(&self) -> &String {
        &self.inherits
    }
}

impl<'ast> ImmutableVisitor<'ast> for InterfaceVisitor {
    fn visit_callback_interface(&mut self, callback_interface: &'ast CallbackInterface) {
        if callback_interface.name == self.name {
            if let Some(ref inherit) = callback_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }

    fn visit_non_partial_interface(&mut self, non_partial_interface: &'ast NonPartialInterface) {
        if non_partial_interface.name == self.name {
            if let Some(ref inherit) = non_partial_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }
}
<commit_msg>Rename typ to ty and use &str where possible.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use rustc::hir::{self, HirId};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use std::boxed;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io;
use std::path;
use syntax::ast;
use webidl::ast::*;
use webidl::visitor::*;
use webidl::*;

declare_lint!(
    WEBIDL_INHERIT_CORRECT,
    Deny,
    "Warn and report usage of incorrect webidl inheritance"
);

pub struct WebIdlPass;

#[derive(Clone, Debug)]
pub enum WebIdlError {
    ParentMismatch {
        name: String,
        rust_parent: String,
        webidl_parent: String,
    },
}

impl fmt::Display for WebIdlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            WebIdlError::ParentMismatch {
                name,
                rust_parent,
                webidl_parent,
            } => {
                return write!(f, "webidl-rust inheritance mismatch, rust: {:?}, rust parent: {:?}, webidl parent: {:?}",
                    &name, &rust_parent, &webidl_parent);
            },
        }
    }
}

impl Error for WebIdlError {
    fn description(&self) -> &str {
        "WebIdlError"
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl WebIdlPass {
    pub fn new() -> WebIdlPass {
        WebIdlPass
    }
}

fn get_ty_name(ty: &str) -> &str {
    if let Some(i) = ty.rfind(':') {
        &ty[i + 1..]
    } else {
        ty
    }
}

fn get_webidl_path(struct_name: &str) -> io::Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    dir.push("components/script/dom/webidls/");
    dir.push(format!("{}.webidl", struct_name));

    return Ok(dir);
}

fn is_webidl_ty(cx: &LateContext, ty: &ty::TyS) -> bool {
    let mut ret = false;
    ty.maybe_walk(|t| {
        match t.sty {
            ty::Adt(did, _substs) => {
                if cx.tcx.has_attr(did.did, "webidl") {
                    ret = true;
                }
                false
            },
            ty::Ref(..) => false,    // don't recurse down &ptrs
            ty::RawPtr(..) => false, // don't recurse down *ptrs
            ty::FnDef(..) | ty::FnPtr(_) => false,
            _ => true,
        }
    });
    ret
}

fn check_inherits(code: &str, name: &str, parent_name: &str) -> Result<(), Box<Error>> {
    let idl = parse_string(code)?;
    let mut visitor = InterfaceVisitor::new(name.to_string());
    visitor.visit(&idl);
    let inherits = visitor.get_inherits();

    println!("inherits: {:?}, parent_name: {:?}", inherits, parent_name);

    if inherits == parent_name {
        return Ok(());
    }
    Err(boxed::Box::from(WebIdlError::ParentMismatch {
        name: name.to_string(),
        rust_parent: parent_name.to_string(),
        webidl_parent: inherits.to_string(),
    }))
}

fn check_webidl(name: &str, parent_name: Option<&str>) -> Result<(), Box<Error>> {
    let path = get_webidl_path(&name)?;
    println!("struct_webidl_path: {:?}", &path);

    if let Some(parent) = parent_name {
        let code = fs::read_to_string(path)?;
        return check_inherits(&code, &name, parent);
    }

    Ok(())
}

impl LintPass for WebIdlPass {
    fn name(&self) -> &'static str {
        "ServoWebIDLPass"
    }

    fn get_lints(&self) -> LintArray {
        lint_array!(WEBIDL_INHERIT_CORRECT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WebIdlPass {
    fn check_struct_def(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        def: &'tcx hir::VariantData,
        n: ast::Name,
        _gen: &'tcx hir::Generics,
        id: HirId,
    ) {
        let def_id = cx.tcx.hir().local_def_id_from_hir_id(id);
        if !is_webidl_ty(cx, cx.tcx.type_of(def_id)) {
            return;
        }

        let item = match cx.tcx.hir().get_by_hir_id(id) {
            hir::Node::Item(item) => item,
            _ => cx
                .tcx
                .hir()
                .expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)),
        };

        let struct_name = n.to_string();
        println!("struct_name: {:?}", struct_name);

        let ty: String;
        let mut parent_name: Option<&str> = None;
        for ref field in def.fields() {
            let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id);
            ty = cx.tcx.type_of(def_id).to_string();
            let name = get_ty_name(&ty);
            parent_name = Some(name);

            // Only first field is relevant.
            break;
        }

        match check_webidl(&struct_name, parent_name) {
            Ok(()) => {},
            Err(e) => {
                let description = format!("{}", e);
                cx.span_lint(WEBIDL_INHERIT_CORRECT, item.ident.span, &description)
            },
        };
    }
}

struct InterfaceVisitor {
    name: String,
    inherits: String,
}

impl InterfaceVisitor {
    pub fn new(name: String) -> Self {
        InterfaceVisitor {
            name: name,
            inherits: String::new(),
        }
    }

    pub fn get_inherits(&self) -> &String {
        &self.inherits
    }
}

impl<'ast> ImmutableVisitor<'ast> for InterfaceVisitor {
    fn visit_callback_interface(&mut self, callback_interface: &'ast CallbackInterface) {
        if callback_interface.name == self.name {
            if let Some(ref inherit) = callback_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }

    fn visit_non_partial_interface(&mut self, non_partial_interface: &'ast NonPartialInterface) {
        if non_partial_interface.name == self.name {
            if let Some(ref inherit) = non_partial_interface.inherits {
                self.inherits = inherit.to_string()
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use libc::c_int;
use libc::SIGKILL;
use libc::getpid;
use libc::kill;
use std::{thread, time};

pub struct Kill {
    signal: c_int
}

impl Kill {
    pub fn new() -> Self {
        Self {
            signal: SIGKILL,
        }
    }

    pub fn setSignal(&mut self, signal: c_int) {
        self.signal = signal;
    }
}

impl ::std::fmt::Display for Kill {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Kill")
    }
}

impl super::Action for Kill {
    fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) -> Result<(), ::err::Error> {
        eprintln!("\njvmkill killing current process");
        unsafe {
            kill(getpid(), self.signal);
        }

        // Allow any thread dump time to appear.
        thread::sleep(time::Duration::from_millis(5000));

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    extern crate nix;

    use std::sync::atomic::{AtomicBool, Ordering};
    use std::{time, thread};
    use super::super::Action;
    use libc::SIGUSR1;
    use self::nix::sys::signal;

    lazy_static! {
        static ref FIRED: AtomicBool = AtomicBool::new(false);
    }

    extern fn handler(sig: i32) {
        if sig == SIGUSR1 {
            FIRED.store(true, Ordering::SeqCst);
        }
    }

    #[test]
    fn sends_signal() {
        set_signal_handler();

        let mut kill = super::Kill::new();
        kill.setSignal(SIGUSR1);
        kill.on_oom(::env::JniEnv::new(::std::ptr::null_mut()), 0).expect("on_oom failed");

        // Allow time for signal to be dispatched.
        thread::sleep(time::Duration::from_millis(100));

        assert!(FIRED.load(Ordering::SeqCst));

        reset_signal_handler();
    }

    fn set_signal_handler() {
        sig_action(signal::SigHandler::Handler(handler));
    }

    fn reset_signal_handler() {
        sig_action(signal::SigHandler::SigDfl);
    }

    fn sig_action(action: signal::SigHandler) {
        let sig_action = signal::SigAction::new(action,
                                                signal::SaFlags::empty(),
                                                signal::SigSet::empty());
        unsafe {
            signal::sigaction(signal::SIGUSR1, &sig_action).expect("sigaction failed");
        }
    }
}
<commit_msg>Work around message not appearing<commit_after>/*
 * Copyright (c) 2015-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use libc::c_int;
use libc::SIGKILL;
use libc::getpid;
use libc::kill;
use std::{thread, time};

pub struct Kill {
    signal: c_int
}

impl Kill {
    pub fn new() -> Self {
        Self {
            signal: SIGKILL,
        }
    }

    pub fn setSignal(&mut self, signal: c_int) {
        self.signal = signal;
    }
}

impl ::std::fmt::Display for Kill {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "Kill")
    }
}

impl super::Action for Kill {
    fn on_oom(&self, _: ::env::JniEnv, _: ::jvmti::jint) -> Result<(), ::err::Error> {
        eprintln!("\njvmkill killing current process");
        // Allow time for above message to appear. This should not be necessary if standard error is written synchronously.
        thread::sleep(time::Duration::from_millis(1000));
        unsafe {
            kill(getpid(), self.signal);
        }

        // Allow any thread dump time to appear.
        thread::sleep(time::Duration::from_millis(5000));

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    extern crate nix;

    use std::sync::atomic::{AtomicBool, Ordering};
    use std::{time, thread};
    use super::super::Action;
    use libc::SIGUSR1;
    use self::nix::sys::signal;

    lazy_static! {
        static ref FIRED: AtomicBool = AtomicBool::new(false);
    }

    extern fn handler(sig: i32) {
        if sig == SIGUSR1 {
            FIRED.store(true, Ordering::SeqCst);
        }
    }

    #[test]
    fn sends_signal() {
        set_signal_handler();

        let mut kill = super::Kill::new();
        kill.setSignal(SIGUSR1);
        kill.on_oom(::env::JniEnv::new(::std::ptr::null_mut()), 0).expect("on_oom failed");

        // Allow time for signal to be dispatched.
        thread::sleep(time::Duration::from_millis(100));

        assert!(FIRED.load(Ordering::SeqCst));

        reset_signal_handler();
    }

    fn set_signal_handler() {
        sig_action(signal::SigHandler::Handler(handler));
    }

    fn reset_signal_handler() {
        sig_action(signal::SigHandler::SigDfl);
    }

    fn sig_action(action: signal::SigHandler) {
        let sig_action = signal::SigAction::new(action,
                                                signal::SaFlags::empty(),
                                                signal::SigSet::empty());
        unsafe {
            signal::sigaction(signal::SIGUSR1, &sig_action).expect("sigaction failed");
        }
    }
}
<|endoftext|>


<commit_before>// TODO: Clean code, please
// TODO: Check types used. Try to minimize the memory used
// TODO: Add more tests.
// TODO: Better UI. Colors? Num of matches?
// TODO: Try to do the fuzzy search async?
extern crate scout;
extern crate docopt;
extern crate termios;
extern crate termion;

use std::env;

use termios::{Termios, TCSANOW, ECHO, ICANON, tcsetattr};
use termion::event::Key;
use termion::input::TermRead;
use termion::screen::*;
use std::io::{self, Read, Write};
use std::os::unix::io::AsRawFd;

const USAGE: &'static str = "
Scout: Small fuzzy finder

This program expects a list of items in the
standard input, so it is better to use it
with pipes.

Usage:
  scout [options]

Options:
  -h --help      Show this screen.
  -v --version   Show version.

Example:
  $ ls | scout
";

fn magic() -> Result<String, io::Error> {
    // Collect initial input
    let mut buffer = String::new();
    try!(io::stdin().read_to_string(&mut buffer));
    let input: Vec<&str> = buffer.split("\n")
        .filter(|s| !s.is_empty())
        .collect();
    let width = format!("{}", input.len()).len();

    // I need to transform tty into raw mode to get chars byte by byte.
    // Check termios crate
    // see: http://stackoverflow.com/a/37416107
    let tty = termion::get_tty().unwrap();
    let fd = tty.as_raw_fd();
    let original_tty = Termios::from_fd(fd).unwrap();
    let mut new_tty = original_tty.clone();  // make a mutable copy of termios
                                            // that we will modify
    new_tty.c_lflag &= !(ICANON | ECHO); // no echo and canonical mode
    tcsetattr(fd, TCSANOW, &mut new_tty).unwrap();

    // Then we can use this tty to create our screen with the help
    // of termion crate
    let mut screen = AlternateScreen::from(tty);
    let mut result = String::new();
    let mut query: Vec<char> = vec![];
    let mut buffer: Vec<u8> = Vec::with_capacity(2);

    'event: loop {
        let s: String = query.iter().cloned().collect();
        let query_chars: Vec<char> = query.iter().cloned().collect();
        let choices = scout::explore(&input, &query_chars);

        // Clear the screen and put the cursor at the beginning
        writeln!(
            &mut screen,
            "{}{}",
            termion::clear::All,
            termion::cursor::Goto(1, 1),
        ).unwrap();

        // Print all the choices
        for choice in choices.iter().take(21).cloned() {
            writeln!(&mut screen, "{}", choice).unwrap();
        }

        // Go to the beginning again and redraw the prompt.
        // This will put the cursor at the end of it
        let prompt = format!("{:width$} > {}", choices.len(), s, width = width);
        write!(&mut screen, "{}{}", termion::cursor::Goto(1, 1), prompt).unwrap();

        screen.flush().unwrap();

        // Some chars are 2 bytes at a time, so better
        // to read 2 by 2. E.g: Arrow keys
        let mut int_buffer = [0;2];
        buffer.clear();
        // Ensure that we read 2 bytes in an intermediate buffer
        //
        // If the amount of real bytes read is less than 2,
        // put only that byte in the buffer so we don't carry
        // junk.
        //
        // If the amount is 2, put both in the buffer
        match screen.read(&mut int_buffer) {
            Ok(1) => {
                buffer.push(int_buffer[0])
            },
            Ok(2) => {
                buffer = int_buffer.iter().map(|&x| x).collect()
            }
            Ok(_) => {},
            Err(_) => {}
        };

        // Now this buffer has the exact amount of bytes from
        // the input so we can use the #keys() function from termion
        // to read and transform those bytes into proper keys
        for c in buffer.keys() {
            match c.unwrap() {
                Key::Esc => break 'event,
                Key::Backspace => {
                    let _ = query.pop();
                },
                Key::Char('\n') => {
                    if let Some(choice) = choices.first() {
                        result = choice.to_string();
                    }
                    break 'event
                },
                Key::Char(c) => {
                    query.push(c as char);
                },
                _ => {},
            }
        }
    };

    tcsetattr(fd, TCSANOW, & original_tty).unwrap();  // reset the stdin to

    Ok(result)
}

pub fn main() {
    docopt::Docopt::new(USAGE)
        .and_then(|doc| {
            doc.argv(env::args())
                .version(Some(scout::version()))
                .parse()
        })
        .unwrap_or_else(|e| e.exit());;

    match magic() {
        Ok(result) => println!("{}", result),
        Err(e) => println!("{:?}", e),
    }
}
<commit_msg>Remove extra whitespace from input.<commit_after>// TODO: Clean code, please
// TODO: Check types used. Try to minimize the memory used
// TODO: Add more tests.
// TODO: Better UI. Colors? Num of matches?
// TODO: Try to do the fuzzy search async?
extern crate scout;
extern crate docopt;
extern crate termios;
extern crate termion;

use std::env;

use termios::{Termios, TCSANOW, ECHO, ICANON, tcsetattr};
use termion::event::Key;
use termion::input::TermRead;
use termion::screen::*;
use std::io::{self, Read, Write};
use std::os::unix::io::AsRawFd;

const USAGE: &'static str = "
Scout: Small fuzzy finder

This program expects a list of items in the
standard input, so it is better to use it
with pipes.

Usage:
  scout [options]

Options:
  -h --help      Show this screen.
  -v --version   Show version.

Example:
  $ ls | scout
";

fn magic() -> Result<String, io::Error> {
    // Collect initial input
    let mut buffer = String::new();
    try!(io::stdin().read_to_string(&mut buffer));
    let input: Vec<&str> = buffer.split("\n")
        .map(|s| s.trim())
        .filter(|s| !s.is_empty())
        .collect();
    let width = format!("{}", input.len()).len();

    // I need to transform tty into raw mode to get chars byte by byte.
    // Check termios crate
    // see: http://stackoverflow.com/a/37416107
    let tty = termion::get_tty().unwrap();
    let fd = tty.as_raw_fd();
    let original_tty = Termios::from_fd(fd).unwrap();
    let mut new_tty = original_tty.clone();  // make a mutable copy of termios
                                            // that we will modify
    new_tty.c_lflag &= !(ICANON | ECHO); // no echo and canonical mode
    tcsetattr(fd, TCSANOW, &mut new_tty).unwrap();

    // Then we can use this tty to create our screen with the help
    // of termion crate
    let mut screen = AlternateScreen::from(tty);
    let mut result = String::new();
    let mut query: Vec<char> = vec![];
    let mut buffer: Vec<u8> = Vec::with_capacity(2);

    'event: loop {
        let s: String = query.iter().cloned().collect();
        let query_chars: Vec<char> = query.iter().cloned().collect();
        let choices = scout::explore(&input, &query_chars);

        // Clear the screen and put the cursor at the beginning
        writeln!(
            &mut screen,
            "{}{}",
            termion::clear::All,
            termion::cursor::Goto(1, 1),
        ).unwrap();

        // Print all the choices
        for choice in choices.iter().take(21).cloned() {
            writeln!(&mut screen, "{}", choice).unwrap();
        }

        // Go to the beginning again and redraw the prompt.
        // This will put the cursor at the end of it
        let prompt = format!("{:width$} > {}", choices.len(), s, width = width);
        write!(&mut screen, "{}{}", termion::cursor::Goto(1, 1), prompt).unwrap();

        screen.flush().unwrap();

        // Some chars are 2 bytes at a time, so better
        // to read 2 by 2. E.g: Arrow keys
        let mut int_buffer = [0;2];
        buffer.clear();
        // Ensure that we read 2 bytes in an intermediate buffer
        //
        // If the amount of real bytes read is less than 2,
        // put only that byte in the buffer so we don't carry
        // junk.
        //
        // If the amount is 2, put both in the buffer
        match screen.read(&mut int_buffer) {
            Ok(1) => {
                buffer.push(int_buffer[0])
            },
            Ok(2) => {
                buffer = int_buffer.iter().map(|&x| x).collect()
            }
            Ok(_) => {},
            Err(_) => {}
        };

        // Now this buffer has the exact amount of bytes from
        // the input so we can use the #keys() function from termion
        // to read and transform those bytes into proper keys
        for c in buffer.keys() {
            match c.unwrap() {
                Key::Esc => break 'event,
                Key::Backspace => {
                    let _ = query.pop();
                },
                Key::Char('\n') => {
                    if let Some(choice) = choices.first() {
                        result = choice.to_string();
                    }
                    break 'event
                },
                Key::Char(c) => {
                    query.push(c as char);
                },
                _ => {},
            }
        }
    };

    tcsetattr(fd, TCSANOW, & original_tty).unwrap();  // reset the stdin to

    Ok(result)
}

pub fn main() {
    docopt::Docopt::new(USAGE)
        .and_then(|doc| {
            doc.argv(env::args())
                .version(Some(scout::version()))
                .parse()
        })
        .unwrap_or_else(|e| e.exit());;

    match magic() {
        Ok(result) => println!("{}", result),
        Err(e) => println!("{:?}", e),
    }
}
<|endoftext|>


<commit_before>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Workspace};
use util;
use vcs::{self, Vcs};
use core::url::build_url;

/// Toplevel application
pub enum Command<'a> {
  Init(InitCommand<'a>),
  Add(AddCommand<'a>),
  Clone(CloneCommand<'a>),
  Scan(ScanCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(InitCommand::make_app(SubCommand::with_name("init")))
       .subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
       .subcommand(ScanCommand::make_app(SubCommand::with_name("scan")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("init", Some(m)) => Command::Init(m.into()),
      ("add", Some(m)) => Command::Add(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      ("scan", Some(m)) => Command::Scan(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Init(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
      Command::Scan(m) => m.run(),
    }
  }
}

pub struct AddCommand<'a> {
  path: Option<&'a Path>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repository under management")
       .arg_from_usage("[path]  'Path of local repository'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand { path: m.value_of("path").map(Path::new) }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_none() {
      Err("Given path is not a repository")?;
    }

    let repo = Repository::from_path(path)?;

    let mut workspace = Workspace::new(None)?;
    workspace.add_repository(repo);
    workspace.save_cache()?;

    Ok(())
  }
}

/// Subcommand `new`
pub struct InitCommand<'a> {
  path: Option<&'a Path>,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
  dry_run: bool,
}

use util::process;

impl<'a> ClapApp for InitCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new Git repository with intuitive directory structure")
       .arg_from_usage("[path]                'Path of target repository (current directory by default)'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
       .arg_from_usage("-n, --dry-run         'Do not actually perform commands'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for InitCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> InitCommand<'a> {
    InitCommand {
      path: m.value_of("path").map(Path::new),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for InitCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    let posthook = self.posthook.and_then(|s| shlex::split(s));

    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();

    if !self.dry_run {
      vcs.do_init(&path)?;
      if let Some(posthook) = posthook {
        if posthook.len() >= 1 {
          let command = posthook[0].clone();
          let args: Vec<_> = posthook.into_iter().skip(1).collect();
          process::inherit(&command).args(args)
            .current_dir(&path)
            .status()?;
        }
      }

      let repo = Repository::from_path(path)?;

      let mut workspace = Workspace::new(None)?;
      workspace.add_repository(repo);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  root: Option<&'a Path>,
  arg: Option<&'a str>,
  dry_run: bool,
  ssh: bool,
  vcs: Option<Vcs>,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories into the root directory")
       .arg_from_usage("<query>         'URL or query of remote repository'")
       .arg_from_usage("--root=[root]   'Target root directory of cloned repository'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for Git command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute Git command'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      root: m.value_of("root").map(Path::new),
      arg: m.value_of("arg"),
      dry_run: m.is_present("dry-run"),
      ssh: m.is_present("ssh"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest = {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone: \"{}\" \"{}\" {}, {:?}",
             url,
             dest.display(),
             util::join_str(&args),
             vcs);

    if !self.dry_run {
      vcs.do_clone(&dest, &url, &args)?;

      let mut repo = Repository::from_path(dest)?;
      repo.set_url(url);
      workspace.add_repository(repo);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `scan`
pub struct ScanCommand<'a> {
  verbose: bool,
  prune: bool,
  depth: Option<usize>,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ScanCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan directories to create cache of repositories list")
       .arg_from_usage("-v, --verbose    'Use verbose output'")
       .arg_from_usage("-p, --prune      'Ignore repositories located at outside of base directories'")
       .arg_from_usage("--depth=[depth]  'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ScanCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ScanCommand<'a> {
    ScanCommand {
      verbose: m.is_present("verbose"),
      prune: m.is_present("prune"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for ScanCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.scan_repositories(self.verbose, self.prune, self.depth)?;
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<commit_msg>rhq clone: add arguments [dest]<commit_after>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Workspace};
use util;
use vcs::{self, Vcs};
use core::url::build_url;

/// Toplevel application
pub enum Command<'a> {
  Init(InitCommand<'a>),
  Add(AddCommand<'a>),
  Clone(CloneCommand<'a>),
  Scan(ScanCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(InitCommand::make_app(SubCommand::with_name("init")))
       .subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
       .subcommand(ScanCommand::make_app(SubCommand::with_name("scan")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("init", Some(m)) => Command::Init(m.into()),
      ("add", Some(m)) => Command::Add(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      ("scan", Some(m)) => Command::Scan(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Init(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
      Command::Scan(m) => m.run(),
    }
  }
}

pub struct AddCommand<'a> {
  path: Option<&'a Path>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repository under management")
       .arg_from_usage("[path]  'Path of local repository'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand { path: m.value_of("path").map(Path::new) }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_none() {
      Err("Given path is not a repository")?;
    }

    let repo = Repository::from_path(path)?;

    let mut workspace = Workspace::new(None)?;
    workspace.add_repository(repo);
    workspace.save_cache()?;

    Ok(())
  }
}

/// Subcommand `new`
pub struct InitCommand<'a> {
  path: Option<&'a Path>,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
  dry_run: bool,
}

use util::process;

impl<'a> ClapApp for InitCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new Git repository with intuitive directory structure")
       .arg_from_usage("[path]                'Path of target repository (current directory by default)'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
       .arg_from_usage("-n, --dry-run         'Do not actually perform commands'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for InitCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> InitCommand<'a> {
    InitCommand {
      path: m.value_of("path").map(Path::new),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for InitCommand<'a> {
  fn run(self) -> ::Result<()> {
    let path: Cow<Path> = {
      self.path
          .map(Into::into)
          .map(Result::Ok)
          .unwrap_or_else(|| env::current_dir().map(Into::into))?
    };
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    let posthook = self.posthook.and_then(|s| shlex::split(s));

    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();

    if !self.dry_run {
      vcs.do_init(&path)?;
      if let Some(posthook) = posthook {
        if posthook.len() >= 1 {
          let command = posthook[0].clone();
          let args: Vec<_> = posthook.into_iter().skip(1).collect();
          process::inherit(&command).args(args)
            .current_dir(&path)
            .status()?;
        }
      }

      let repo = Repository::from_path(path)?;

      let mut workspace = Workspace::new(None)?;
      workspace.add_repository(repo);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  dest: Option<&'a Path>,
  root: Option<&'a Path>,
  ssh: bool,
  arg: Option<&'a str>,
  vcs: Option<Vcs>,
  dry_run: bool,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories, and then add it under management")
       .arg_from_usage("<query>         'an URL or a string to determine the URL of remote repository'")
       .arg_from_usage("[dest]          'Destination directory of cloned repository'")
       .arg_from_usage("--root=[root]   'Path to determine the destination directory of cloned repository'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for VCS command'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
       .arg_from_usage("-n, --dry-run   'Do not actually execute VCS command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      dest: m.value_of("dest").map(Path::new),
      root: m.value_of("root").map(Path::new),
      ssh: m.is_present("ssh"),
      arg: m.value_of("arg"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest: Cow<Path> = if let Some(dest) = self.dest {
      dest.into()
    } else {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone from {} into {} by using {:?} (with arguments: {})",
             url,
             dest.display(),
             vcs,
             util::join_str(&args),
    );

    if !self.dry_run {
      vcs.do_clone(&dest, &url, &args)?;

      let mut repo = Repository::from_path(dest)?;
      repo.set_url(url);
      workspace.add_repository(repo);
      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `scan`
pub struct ScanCommand<'a> {
  verbose: bool,
  prune: bool,
  depth: Option<usize>,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ScanCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan directories to create cache of repositories list")
       .arg_from_usage("-v, --verbose    'Use verbose output'")
       .arg_from_usage("-p, --prune      'Ignore repositories located at outside of base directories'")
       .arg_from_usage("--depth=[depth]  'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ScanCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ScanCommand<'a> {
    ScanCommand {
      verbose: m.is_present("verbose"),
      prune: m.is_present("prune"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for ScanCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.scan_repositories(self.verbose, self.prune, self.depth)?;
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>use error::{ToResult};
use std::env;
use std::path::{PathBuf};

pub fn resolve(pathname: &str) -> ToResult<PathBuf> {
    let mut absolute = try!(env::current_dir());
            absolute.push(pathname);

    let canonical = try!(absolute.canonicalize());

    return Ok(canonical);
}

pub fn basename(path: &PathBuf) -> ToResult<String> {
    if let Some(stem) = path.file_stem() {
        let value = stem.to_os_string();

        return match value.into_string() {
            Ok(s) => Ok(s),
            Err(_) => Ok(String::from("")),
        };
    }

    return Ok(String::from(""));

    // return None;
    // fn basename<'a>(path: &'a PathBuf) -> Option<String>{

    // return match path.file_stem() {
    //     // Everything is fine until it is converted to_str which consumes the value confusing the compiler.
    //     Some(value) => Some("foo"),
    //     None => Some(""),
    // };

    // let d = directory.clone();
    // let option = match d.file_stem() {
    //     // Everything is fine until it is converted to_str which consumes the value confusing the compiler.
    //     Some(value) => value,
    //     None => panic!("TODO: handle this case."),
    // };
    //
    // let basename = option.clone().to_str().unwrap();
}

#[cfg(test)]
mod tests {
    extern crate env_logger;

    use std::env;
    use std::path::{PathBuf};
    use super::*;

    #[test]
    fn relative() {
        let _ = env_logger::init();

        let actual = resolve("src").expect("should not fail");
        let mut expected = env::current_dir().expect("should not fail");
                expected.push("src");
        assert_eq!(actual, expected);

        let actual = resolve("src").expect("should not fail");
        assert_eq!(actual, expected);
    }

    #[test]
    fn dot() {
        let _ = env_logger::init();

        let actual = resolve(".").expect("should not fail");
        let expected = env::current_dir().expect("should not fail");

        assert_eq!(actual, expected);
    }

    #[test]
    fn dot_dot() {
        let _ = env_logger::init();

        let actual = resolve("../to-directory/src").expect("should not fail");
        let mut expected = env::current_dir().expect("should not fail");
                expected.pop();
                expected.push("to-directory");
                expected.push("src");

        assert_eq!(actual, expected);
    }

    #[test]
    fn test_basename() {
        let _ = env_logger::init();

        let pathname = PathBuf::from("/foo/bar");
        let basename = basename(&pathname).expect("should not fail");
        assert_eq!(basename, String::from("bar"));
    }
}
<commit_msg>Clean up.<commit_after>use error::{ToResult};
use std::env;
use std::path::{PathBuf};

pub fn resolve(pathname: &str) -> ToResult<PathBuf> {
    let mut absolute = try!(env::current_dir());
            absolute.push(pathname);

    let canonical = try!(absolute.canonicalize());

    return Ok(canonical);
}

pub fn basename(path: &PathBuf) -> ToResult<String> {
    if let Some(stem) = path.file_stem() {
        let os_string = stem.to_os_string();

        return match os_string.into_string() {
            Ok(string) => Ok(string),
            Err(_) => Ok(String::from("")),
        };
    }

    return Ok(String::from(""));
}

#[cfg(test)]
mod tests {
    extern crate env_logger;

    use std::env;
    use std::path::{PathBuf};
    use super::*;

    #[test]
    fn relative() {
        let _ = env_logger::init();

        let actual = resolve("src").expect("should not fail");
        let mut expected = env::current_dir().expect("should not fail");
                expected.push("src");
        assert_eq!(actual, expected);

        let actual = resolve("src").expect("should not fail");
        assert_eq!(actual, expected);
    }

    #[test]
    fn dot() {
        let _ = env_logger::init();

        let actual = resolve(".").expect("should not fail");
        let expected = env::current_dir().expect("should not fail");

        assert_eq!(actual, expected);
    }

    #[test]
    fn dot_dot() {
        let _ = env_logger::init();

        let actual = resolve("../to-directory/src").expect("should not fail");
        let mut expected = env::current_dir().expect("should not fail");
                expected.pop();
                expected.push("to-directory");
                expected.push("src");

        assert_eq!(actual, expected);
    }

    #[test]
    fn test_basename() {
        let _ = env_logger::init();

        let pathname = PathBuf::from("/foo/bar");
        let basename = basename(&pathname).expect("should not fail");
        assert_eq!(basename, String::from("bar"));
    }
}
<|endoftext|>


<commit_before>#![allow(unsafe_code)]

use std::ptr;

pub type Item = u64;

/// A simple doubly linked list for use in the `Lru`
#[derive(Debug)]
pub(crate) struct Node {
    inner: Item,
    next: *mut Node,
    prev: *mut Node,
}

impl Node {
    fn unwire(&mut self) {
        unsafe {
            if !self.prev.is_null() {
                (*self.prev).next = self.next;
            }

            if !self.next.is_null() {
                (*self.next).prev = self.prev;
            }
        }

        self.next = ptr::null_mut();
        self.prev = ptr::null_mut();
    }
}

/// A simple non-cyclical doubly linked
/// list where items can be efficiently
/// removed from the middle, for the purposes
/// of backing an LRU cache.
pub struct DoublyLinkedList {
    head: *mut Node,
    tail: *mut Node,
    len: usize,
}

impl Drop for DoublyLinkedList {
    fn drop(&mut self) {
        let mut cursor = self.head;
        while !cursor.is_null() {
            unsafe {
                let node = Box::from_raw(cursor);

                // don't need to check for cycles
                // because this Dll is non-cyclical
                cursor = node.prev;

                // this happens without the manual drop,
                // but we keep it for explicitness
                drop(node);
            }
        }
    }
}

impl Default for DoublyLinkedList {
    fn default() -> Self {
        Self { head: ptr::null_mut(), tail: ptr::null_mut(), len: 0 }
    }
}

impl DoublyLinkedList {
    pub(crate) const fn len(&self) -> usize {
        self.len
    }

    pub(crate) fn push_head(&mut self, item: Item) -> *mut Node {
        self.len += 1;

        let node = Node { inner: item, next: ptr::null_mut(), prev: self.head };

        let ptr = Box::into_raw(Box::new(node));

        self.push_head_ptr(ptr)
    }

    fn push_head_ptr(&mut self, ptr: *mut Node) -> *mut Node {
        if !self.head.is_null() {
            unsafe {
                (*self.head).next = ptr;
            }
        }

        if self.tail.is_null() {
            self.tail = ptr;
        }

        self.head = ptr;

        ptr
    }

    #[cfg(test)]
    pub(crate) fn push_tail(&mut self, item: Item) {
        self.len += 1;

        let node = Node { inner: item, next: self.tail, prev: ptr::null_mut() };

        let ptr = Box::into_raw(Box::new(node));

        if !self.tail.is_null() {
            unsafe {
                (*self.tail).prev = ptr;
            }
        }

        if self.head.is_null() {
            self.head = ptr;
        }

        self.tail = ptr;
    }

    pub(crate) fn promote(&mut self, ptr: *mut Node) -> *mut Node {
        if self.head == ptr {
            return ptr;
        }

        unsafe {
            if self.tail == ptr {
                self.tail = (*ptr).next;
            }

            if self.head == ptr {
                self.head = (*ptr).prev;
            }

            (*ptr).unwire();

            self.push_head_ptr(ptr)
        }
    }

    #[cfg(test)]
    pub(crate) fn pop_head(&mut self) -> Option<Item> {
        if self.head.is_null() {
            return None;
        }

        self.len -= 1;

        unsafe {
            let mut head = Box::from_raw(self.head);

            if self.head == self.tail {
                self.tail = ptr::null_mut();
            }

            self.head = head.prev;

            head.unwire();

            Some(head.inner)
        }
    }

    pub(crate) fn pop_tail(&mut self) -> Option<Item> {
        if self.tail.is_null() {
            return None;
        }

        self.len -= 1;

        unsafe {
            let mut tail = Box::from_raw(self.tail);

            if self.head == self.tail {
                self.head = ptr::null_mut();
            }

            self.tail = tail.next;

            tail.unwire();

            Some(tail.inner)
        }
    }

    #[cfg(test)]
    pub(crate) fn into_vec(mut self) -> Vec<Item> {
        let mut res = vec![];
        while let Some(val) = self.pop_head() {
            res.push(val);
        }
        res
    }
}

#[allow(unused_results)]
#[test]
fn test_dll() {
    let mut dll = DoublyLinkedList::default();
    dll.push_head(5);
    dll.push_tail(6);
    dll.push_head(4);
    dll.push_tail(7);
    dll.push_tail(8);
    dll.push_head(3);
    dll.push_tail(9);
    dll.push_head(2);
    dll.push_head(1);
    assert_eq!(dll.len(), 9);
    assert_eq!(dll.into_vec(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
<commit_msg>Fix memory leak in Dll for Lru<commit_after>#![allow(unsafe_code)]

use std::ptr;

pub type Item = u64;

/// A simple doubly linked list for use in the `Lru`
#[derive(Debug)]
pub(crate) struct Node {
    inner: Item,
    next: *mut Node,
    prev: *mut Node,
}

impl Node {
    fn unwire(&mut self) {
        unsafe {
            if !self.prev.is_null() {
                (*self.prev).next = self.next;
            }

            if !self.next.is_null() {
                (*self.next).prev = self.prev;
            }
        }

        self.next = ptr::null_mut();
        self.prev = ptr::null_mut();
    }
}

/// A simple non-cyclical doubly linked
/// list where items can be efficiently
/// removed from the middle, for the purposes
/// of backing an LRU cache.
pub struct DoublyLinkedList {
    head: *mut Node,
    tail: *mut Node,
    len: usize,
}

impl Drop for DoublyLinkedList {
    fn drop(&mut self) {
        let mut cursor = self.head;
        while !cursor.is_null() {
            unsafe {
                let node = Box::from_raw(cursor);

                // don't need to check for cycles
                // because this Dll is non-cyclical
                cursor = node.prev;

                // this happens without the manual drop,
                // but we keep it for explicitness
                drop(node);
            }
        }
    }
}

impl Default for DoublyLinkedList {
    fn default() -> Self {
        Self { head: ptr::null_mut(), tail: ptr::null_mut(), len: 0 }
    }
}

impl DoublyLinkedList {
    pub(crate) const fn len(&self) -> usize {
        self.len
    }

    pub(crate) fn push_head(&mut self, item: Item) -> *mut Node {
        self.len += 1;

        let node = Node { inner: item, next: ptr::null_mut(), prev: self.head };

        let ptr = Box::into_raw(Box::new(node));

        self.push_head_ptr(ptr)
    }

    fn push_head_ptr(&mut self, ptr: *mut Node) -> *mut Node {
        if !self.head.is_null() {
            unsafe {
                (*self.head).next = ptr;
                (*ptr).prev = self.head;
            }
        }

        if self.tail.is_null() {
            self.tail = ptr;
        }

        self.head = ptr;

        ptr
    }

    #[cfg(test)]
    pub(crate) fn push_tail(&mut self, item: Item) {
        self.len += 1;

        let node = Node { inner: item, next: self.tail, prev: ptr::null_mut() };

        let ptr = Box::into_raw(Box::new(node));

        if !self.tail.is_null() {
            unsafe {
                (*self.tail).prev = ptr;
            }
        }

        if self.head.is_null() {
            self.head = ptr;
        }

        self.tail = ptr;
    }

    pub(crate) fn promote(&mut self, ptr: *mut Node) -> *mut Node {
        if self.head == ptr {
            return ptr;
        }

        unsafe {
            if self.tail == ptr {
                self.tail = (*ptr).next;
            }

            if self.head == ptr {
                self.head = (*ptr).prev;
            }

            (*ptr).unwire();

            self.push_head_ptr(ptr)
        }
    }

    #[cfg(test)]
    pub(crate) fn pop_head(&mut self) -> Option<Item> {
        if self.head.is_null() {
            return None;
        }

        self.len -= 1;

        unsafe {
            let mut head = Box::from_raw(self.head);

            if self.head == self.tail {
                self.tail = ptr::null_mut();
            }

            self.head = head.prev;

            head.unwire();

            Some(head.inner)
        }
    }

    pub(crate) fn pop_tail(&mut self) -> Option<Item> {
        if self.tail.is_null() {
            return None;
        }

        self.len -= 1;

        unsafe {
            let mut tail = Box::from_raw(self.tail);

            if self.head == self.tail {
                self.head = ptr::null_mut();
            }

            self.tail = tail.next;

            tail.unwire();

            Some(tail.inner)
        }
    }

    #[cfg(test)]
    pub(crate) fn into_vec(mut self) -> Vec<Item> {
        let mut res = vec![];
        while let Some(val) = self.pop_head() {
            res.push(val);
        }
        res
    }
}

#[allow(unused_results)]
#[test]
fn test_dll() {
    let mut dll = DoublyLinkedList::default();
    dll.push_head(5);
    dll.push_tail(6);
    dll.push_head(4);
    dll.push_tail(7);
    dll.push_tail(8);
    dll.push_head(3);
    dll.push_tail(9);
    dll.push_head(2);
    dll.push_head(1);
    assert_eq!(dll.len(), 9);
    assert_eq!(dll.into_vec(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
}
<|endoftext|>