<commit_before>#![deny(warnings)]

extern crate cobalt;
extern crate clap;
extern crate env_logger;
extern crate notify;
extern crate glob;
extern crate ghp;

extern crate hyper;

#[macro_use]
extern crate log;

use clap::{Arg, App, SubCommand, AppSettings};
use std::fs;
use cobalt::Config;
use log::{LogRecord, LogLevelFilter};
use env_logger::LogBuilder;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use ghp::import_dir;
use glob::Pattern;
use cobalt::create_new_project;

use notify::{RecommendedWatcher, Error, Watcher};
use std::sync::mpsc::channel;
use std::thread;
use std::path::PathBuf;
use std::io::prelude::*;
use std::io::Result as IoResult;
use std::fs::File;

fn main() {
    let global_matches = App::new("Cobalt")
        .version("0.3.0")
        .author("Benny Klotz <r3qnbenni@gmail.com>, Johann Hofmann")
        .about("A static site generator written in Rust.")
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .arg(Arg::with_name("config")
            .short("c")
            .long("config")
            .value_name("FILE")
            .help("Config file to use [default: .cobalt.yml]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("source")
            .short("s")
            .long("source")
            .value_name("DIR")
            .help("Source folder [default: ./]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("destination")
            .short("d")
            .long("destination")
            .value_name("DIR")
            .help("Destination folder [default: ./]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("layouts")
            .short("l")
            .long("layouts")
            .value_name("DIR")
            .help("Layout templates folder [default: ./_layouts]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("posts")
            .short("p")
            .long("posts")
            .value_name("DIR")
            .help("Posts folder [default: ./posts]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("drafts")
            .long("drafts")
            .help("Include drafts.")
            .global(true)
            .takes_value(false))
        .arg(Arg::with_name("log-level")
            .short("L")
            .long("log-level")
            .possible_values(&["error", "warn", "info", "debug", "trace", "off"])
            .help("Log level [default: info]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("trace")
            .long("trace")
            .help("Log ultra-verbose (trace level) information")
            .global(true)
            .takes_value(false))
        .arg(Arg::with_name("silent")
            .long("silent")
            .help("Suppress all output")
            .global(true)
            .takes_value(false))
        .subcommand(SubCommand::with_name("new")
            .about("create a new cobalt project")
            .arg(Arg::with_name("DIRECTORY")
                .help("Suppress all output")
                .default_value("./")
                .index(1)))
        .subcommand(SubCommand::with_name("build")
            .about("build the cobalt project at the source dir")
            .arg(Arg::with_name("import")
                .short("i")
                .long("import")
                .help("Import after build to gh-pages branch")
                .takes_value(false))
            .arg(Arg::with_name("branch")
                .short("b")
                .long("branch")
                .value_name("BRANCH")
                .help("Branch that will be used to import the site to")
                .default_value("gh-pages")
                .takes_value(true))
            .arg(Arg::with_name("message")
                .short("m")
                .long("message")
                .value_name("COMMIT-MESSAGE")
                .help("Commit message that will be used on import")
                .default_value("cobalt site import")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("clean").about("cleans directory set as destination"))
        .subcommand(SubCommand::with_name("serve")
            .about("build and serve the cobalt project at the source dir")
            .arg(Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("watch")
            .about("build, serve, and watch the project at the source dir")
            .arg(Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("import")
            .about("moves the contents of the dest folder to the gh-pages branch")
            .arg(Arg::with_name("branch")
                .short("b")
                .long("branch")
                .value_name("BRANCH")
                .help("Branch that will be used to import the site to")
                .default_value("gh-pages")
                .takes_value(true))
            .arg(Arg::with_name("message")
                .short("m")
                .long("message")
                .value_name("COMMIT-MESSAGE")
                .help("Commit message that will be used on import")
                .default_value("cobalt site import")
                .takes_value(true)))
        .get_matches();

    let (command, matches) = match global_matches.subcommand() {
        (command, Some(matches)) => (command, matches),
        (_, None) => unreachable!(),
    };

    let format = |record: &LogRecord| {
        let level = format!("[{}]", record.level()).to_lowercase();
        format!("{:8} {}", level, record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    match matches.value_of("log-level").or(global_matches.value_of("log-level")) {
        Some("error") => builder.filter(None, LogLevelFilter::Error),
        Some("warn") => builder.filter(None, LogLevelFilter::Warn),
        Some("info") => builder.filter(None, LogLevelFilter::Info),
        Some("debug") => builder.filter(None, LogLevelFilter::Debug),
        Some("trace") => builder.filter(None, LogLevelFilter::Trace),
        Some("off") => builder.filter(None, LogLevelFilter::Off),
        _ => builder.filter(None, LogLevelFilter::Info),
    };

    if matches.is_present("trace") {
        builder.filter(None, LogLevelFilter::Trace);
    }

    if matches.is_present("silent") {
        builder.filter(None, LogLevelFilter::Off);
    }

    builder.init().unwrap();

    let config_path = matches.value_of("config")
        .or(global_matches.value_of("config"))
        .unwrap_or(".cobalt.yml")
        .to_string();

    // Fetch config information if available
    let mut config: Config = if fs::metadata(&config_path).is_ok() {
        info!("Using config file {}", &config_path);

        match Config::from_file(&config_path) {
            Ok(config) => config,
            Err(e) => {
                error!("Error reading config file:");
                error!("{}", e);
                std::process::exit(1);
            }
        }
    } else {
        warn!("No .cobalt.yml file found in current directory, using default config.");
        Default::default()
    };

    config.source = matches.value_of("source")
        .or(global_matches.value_of("source"))
        .map(str::to_string)
        .unwrap_or(config.source);

    config.dest = matches.value_of("destination")
        .or(global_matches.value_of("destination"))
        .map(str::to_string)
        .unwrap_or(config.dest);

    config.layouts = matches.value_of("layouts")
        .or(global_matches.value_of("layouts"))
        .map(str::to_string)
        .unwrap_or(config.layouts);

    config.posts = matches.value_of("posts")
        .or(global_matches.value_of("posts"))
        .map(str::to_string)
        .unwrap_or(config.posts);

    config.include_drafts = matches.is_present("drafts");

    match command {
        "new" => {
            let directory = matches.value_of("DIRECTORY").unwrap();

            match create_new_project(&directory.to_string()) {
                Ok(_) => info!("Created new project at {}", directory),
                Err(e) => {
                    error!("{}", e);
                    error!("Could not create a new cobalt project");
                    std::process::exit(1);
                }
            }
        }

        "build" => {
            build(&config);
            if matches.is_present("import") {
                let branch = matches.value_of("branch").unwrap().to_string();
                let message = matches.value_of("message").unwrap().to_string();
                import(&config, &branch, &message);
            }
        }

        "clean" => {
            match fs::remove_dir_all(&config.dest) {
                Ok(..) => info!("directory \"{}\" removed", &config.dest),
                Err(err) => error!("Error: {}", err),
            }
        }

        "serve" => {
            build(&config);
            let port = matches.value_of("port").unwrap().to_string();
            serve(&config.dest, &port);
        }

        "watch" => {
            build(&config);

            let dest = config.dest.clone();
            let port = matches.value_of("port").unwrap().to_string();
            thread::spawn(move || {
                serve(&dest, &port);
            });

            let (tx, rx) = channel();
            let w: Result<RecommendedWatcher, Error> = Watcher::new(tx);

            match w {
                Ok(mut watcher) => {
                    // TODO: clean up this unwrap
                    watcher.watch(&config.source).unwrap();
                    info!("Watching {:?} for changes", &config.source);

                    loop {
                        match rx.recv() {
                            Ok(val) => {
                                trace!("file changed {:?}", val);
                                if let Some(path) = val.path {
                                    // get where process was run from
                                    let cwd = std::env::current_dir().unwrap_or(PathBuf::new());

                                    // The final goal is to have a relative path. If we already
                                    // have a relative path, we still convert it to an abs path
                                    // first to handle prefix "./" correctly.
                                    let abs_path = if path.is_absolute() {
                                        path.clone()
                                    } else {
                                        cwd.join(&path)
                                    };
                                    let rel_path = abs_path.strip_prefix(&cwd).unwrap_or(&path);

                                    // check whether this path has been marked as ignored in config
                                    let rel_path_matches =
                                        |pattern| Pattern::matches_path(pattern, rel_path);
                                    let path_ignored = &config.ignore.iter().any(rel_path_matches);

                                    if !path_ignored {
                                        build(&config);
                                    }
                                }
                            }

                            Err(e) => {
                                error!("[Notify Error]: {}", e);
                                std::process::exit(1);
                            }
                        }
                    }
                }
                Err(e) => {
                    error!("[Notify Error]: {}", e);
                    std::process::exit(1);
                }
            }
        }

        "import" => {
            let branch = matches.value_of("branch").unwrap().to_string();
            let message = matches.value_of("message").unwrap().to_string();
            import(&config, &branch, &message);
        }

        _ => {
            println!("{}", global_matches.usage());
            return;
        }
    }
}

fn build(config: &Config) {
    info!("Building from {} into {}", config.source, config.dest);
    match cobalt::build(&config) {
        Ok(_) => info!("Build successful"),
        Err(e) => {
            error!("{}", e);
            error!("Build not successful");
            std::process::exit(1);
        }
    };
}

fn static_file_handler(dest: &str, req: Request, mut res: Response) -> IoResult<()> {
    // grab the requested path
    let req_path = match req.uri {
        RequestUri::AbsolutePath(p) => p,
        _ => {
            // return a 400 and exit from this request
            *res.status_mut() = hyper::status::StatusCode::BadRequest;
            let body = b"<h1> <center> 400: Bad request </center> </h1>";
            try!(res.send(body));
            return Ok(());
        }
    };

    // find the path of the file in the local system
    // (this gets rid of the '/' in `p`, so the `join()` will not replace the
    // path)
    let path = PathBuf::from(dest).join(&req_path[1..]);

    let serve_path = if path.is_file() {
        // try to point the serve path to `path` if it corresponds to a file
        path
    } else {
        // try to point the serve path into a "index.html" file in the requested
        // path
        path.join("index.html")
    };

    // if the request points to a file and it exists, read and serve it
    if serve_path.exists() {
        let mut file = try!(File::open(serve_path));

        // buffer to store the file
        let mut buffer: Vec<u8> = vec![];

        try!(file.read_to_end(&mut buffer));

        try!(res.send(&buffer));
    } else {
        // return a 404 status
        *res.status_mut() = hyper::status::StatusCode::NotFound;

        // write a simple body for the 404 page
        let body = b"<h1> <center> 404: Page not found </center> </h1>";

        try!(res.send(body));
    }

    Ok(())
}

fn serve(dest: &str, port: &str) {
    info!("Serving {:?} through static file server", dest);

    let ip = format!("127.0.0.1:{}", port);
    info!("Server Listening on {}", &ip);
    info!("Ctrl-c to stop the server");

    // attempts to create a server
    let http_server = match Server::http(&*ip) {
        Ok(server) => server,
        Err(e) => {
            error!("{}", e);
            std::process::exit(1);
        }
    };

    // need a clone because of closure's lifetime
    let dest_clone = dest.to_owned();

    // bind the handle function and start serving
    if let Err(e) = http_server.handle(move |req: Request, res: Response| {
        if let Err(e) = static_file_handler(&dest_clone, req, res) {
            error!("{}", e);
            std::process::exit(1);
        }
    }) {
        error!("{}", e);
        std::process::exit(1);
    };
}

fn import(config: &Config, branch: &str, message: &str) {
    info!("Importing {} to {}", config.dest, branch);

    let meta = match fs::metadata(&config.dest) {
        Ok(data) => data,

        Err(e) => {
            error!("{}", e);
            error!("Import not successful");
            std::process::exit(1);
        }
    };

    if meta.is_dir() {
        match import_dir(&config.dest, branch, message) {
            Ok(_) => info!("Import successful"),
            Err(e) => {
                error!("{}", e);
                error!("Import not successful");
                std::process::exit(1);
            }
        }
    } else {
        error!("Build dir is not a directory: {}", config.dest);
        error!("Import not successful");
        std::process::exit(1);
    }
}
<commit_msg>Take version for clap App from Cargo.toml<commit_after>#![deny(warnings)]

extern crate cobalt;
#[macro_use]
extern crate clap;
extern crate env_logger;
extern crate notify;
extern crate glob;
extern crate ghp;

extern crate hyper;

#[macro_use]
extern crate log;

use clap::{Arg, App, SubCommand, AppSettings};
use std::fs;
use cobalt::Config;
use log::{LogRecord, LogLevelFilter};
use env_logger::LogBuilder;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use ghp::import_dir;
use glob::Pattern;
use cobalt::create_new_project;

use notify::{RecommendedWatcher, Error, Watcher};
use std::sync::mpsc::channel;
use std::thread;
use std::path::PathBuf;
use std::io::prelude::*;
use std::io::Result as IoResult;
use std::fs::File;

fn main() {
    let global_matches = App::new("Cobalt")
        .version(crate_version!())
        .author("Benny Klotz <r3qnbenni@gmail.com>, Johann Hofmann")
        .about("A static site generator written in Rust.")
        .setting(AppSettings::SubcommandRequired)
        .setting(AppSettings::GlobalVersion)
        .arg(Arg::with_name("config")
            .short("c")
            .long("config")
            .value_name("FILE")
            .help("Config file to use [default: .cobalt.yml]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("source")
            .short("s")
            .long("source")
            .value_name("DIR")
            .help("Source folder [default: ./]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("destination")
            .short("d")
            .long("destination")
            .value_name("DIR")
            .help("Destination folder [default: ./]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("layouts")
            .short("l")
            .long("layouts")
            .value_name("DIR")
            .help("Layout templates folder [default: ./_layouts]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("posts")
            .short("p")
            .long("posts")
            .value_name("DIR")
            .help("Posts folder [default: ./posts]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("drafts")
            .long("drafts")
            .help("Include drafts.")
            .global(true)
            .takes_value(false))
        .arg(Arg::with_name("log-level")
            .short("L")
            .long("log-level")
            .possible_values(&["error", "warn", "info", "debug", "trace", "off"])
            .help("Log level [default: info]")
            .global(true)
            .takes_value(true))
        .arg(Arg::with_name("trace")
            .long("trace")
            .help("Log ultra-verbose (trace level) information")
            .global(true)
            .takes_value(false))
        .arg(Arg::with_name("silent")
            .long("silent")
            .help("Suppress all output")
            .global(true)
            .takes_value(false))
        .subcommand(SubCommand::with_name("new")
            .about("create a new cobalt project")
            .arg(Arg::with_name("DIRECTORY")
                .help("Suppress all output")
                .default_value("./")
                .index(1)))
        .subcommand(SubCommand::with_name("build")
            .about("build the cobalt project at the source dir")
            .arg(Arg::with_name("import")
                .short("i")
                .long("import")
                .help("Import after build to gh-pages branch")
                .takes_value(false))
            .arg(Arg::with_name("branch")
                .short("b")
                .long("branch")
                .value_name("BRANCH")
                .help("Branch that will be used to import the site to")
                .default_value("gh-pages")
                .takes_value(true))
            .arg(Arg::with_name("message")
                .short("m")
                .long("message")
                .value_name("COMMIT-MESSAGE")
                .help("Commit message that will be used on import")
                .default_value("cobalt site import")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("clean").about("cleans directory set as destination"))
        .subcommand(SubCommand::with_name("serve")
            .about("build and serve the cobalt project at the source dir")
            .arg(Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("watch")
            .about("build, serve, and watch the project at the source dir")
            .arg(Arg::with_name("port")
                .short("P")
                .long("port")
                .value_name("INT")
                .help("Port to serve from")
                .default_value("3000")
                .takes_value(true)))
        .subcommand(SubCommand::with_name("import")
            .about("moves the contents of the dest folder to the gh-pages branch")
            .arg(Arg::with_name("branch")
                .short("b")
                .long("branch")
                .value_name("BRANCH")
                .help("Branch that will be used to import the site to")
                .default_value("gh-pages")
                .takes_value(true))
            .arg(Arg::with_name("message")
                .short("m")
                .long("message")
                .value_name("COMMIT-MESSAGE")
                .help("Commit message that will be used on import")
                .default_value("cobalt site import")
                .takes_value(true)))
        .get_matches();

    let (command, matches) = match global_matches.subcommand() {
        (command, Some(matches)) => (command, matches),
        (_, None) => unreachable!(),
    };

    let format = |record: &LogRecord| {
        let level = format!("[{}]", record.level()).to_lowercase();
        format!("{:8} {}", level, record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    match matches.value_of("log-level").or(global_matches.value_of("log-level")) {
        Some("error") => builder.filter(None, LogLevelFilter::Error),
        Some("warn") => builder.filter(None, LogLevelFilter::Warn),
        Some("info") => builder.filter(None, LogLevelFilter::Info),
        Some("debug") => builder.filter(None, LogLevelFilter::Debug),
        Some("trace") => builder.filter(None, LogLevelFilter::Trace),
        Some("off") => builder.filter(None, LogLevelFilter::Off),
        _ => builder.filter(None, LogLevelFilter::Info),
    };

    if matches.is_present("trace") {
        builder.filter(None, LogLevelFilter::Trace);
    }

    if matches.is_present("silent") {
        builder.filter(None, LogLevelFilter::Off);
    }

    builder.init().unwrap();

    let config_path = matches.value_of("config")
        .or(global_matches.value_of("config"))
        .unwrap_or(".cobalt.yml")
        .to_string();

    // Fetch config information if available
    let mut config: Config = if fs::metadata(&config_path).is_ok() {
        info!("Using config file {}", &config_path);

        match Config::from_file(&config_path) {
            Ok(config) => config,
            Err(e) => {
                error!("Error reading config file:");
                error!("{}", e);
                std::process::exit(1);
            }
        }
    } else {
        warn!("No .cobalt.yml file found in current directory, using default config.");
        Default::default()
    };

    config.source = matches.value_of("source")
        .or(global_matches.value_of("source"))
        .map(str::to_string)
        .unwrap_or(config.source);

    config.dest = matches.value_of("destination")
        .or(global_matches.value_of("destination"))
        .map(str::to_string)
        .unwrap_or(config.dest);

    config.layouts = matches.value_of("layouts")
        .or(global_matches.value_of("layouts"))
        .map(str::to_string)
        .unwrap_or(config.layouts);

    config.posts = matches.value_of("posts")
        .or(global_matches.value_of("posts"))
        .map(str::to_string)
        .unwrap_or(config.posts);

    config.include_drafts = matches.is_present("drafts");

    match command {
        "new" => {
            let directory = matches.value_of("DIRECTORY").unwrap();

            match create_new_project(&directory.to_string()) {
                Ok(_) => info!("Created new project at {}", directory),
                Err(e) => {
                    error!("{}", e);
                    error!("Could not create a new cobalt project");
                    std::process::exit(1);
                }
            }
        }

        "build" => {
            build(&config);
            if matches.is_present("import") {
                let branch = matches.value_of("branch").unwrap().to_string();
                let message = matches.value_of("message").unwrap().to_string();
                import(&config, &branch, &message);
            }
        }

        "clean" => {
            match fs::remove_dir_all(&config.dest) {
                Ok(..) => info!("directory \"{}\" removed", &config.dest),
                Err(err) => error!("Error: {}", err),
            }
        }

        "serve" => {
            build(&config);
            let port = matches.value_of("port").unwrap().to_string();
            serve(&config.dest, &port);
        }

        "watch" => {
            build(&config);

            let dest = config.dest.clone();
            let port = matches.value_of("port").unwrap().to_string();
            thread::spawn(move || {
                serve(&dest, &port);
            });

            let (tx, rx) = channel();
            let w: Result<RecommendedWatcher, Error> = Watcher::new(tx);

            match w {
                Ok(mut watcher) => {
                    // TODO: clean up this unwrap
                    watcher.watch(&config.source).unwrap();
                    info!("Watching {:?} for changes", &config.source);

                    loop {
                        match rx.recv() {
                            Ok(val) => {
                                trace!("file changed {:?}", val);
                                if let Some(path) = val.path {
                                    // get where process was run from
                                    let cwd = std::env::current_dir().unwrap_or(PathBuf::new());

                                    // The final goal is to have a relative path. If we already
                                    // have a relative path, we still convert it to an abs path
                                    // first to handle prefix "./" correctly.
                                    let abs_path = if path.is_absolute() {
                                        path.clone()
                                    } else {
                                        cwd.join(&path)
                                    };
                                    let rel_path = abs_path.strip_prefix(&cwd).unwrap_or(&path);

                                    // check whether this path has been marked as ignored in config
                                    let rel_path_matches =
                                        |pattern| Pattern::matches_path(pattern, rel_path);
                                    let path_ignored = &config.ignore.iter().any(rel_path_matches);

                                    if !path_ignored {
                                        build(&config);
                                    }
                                }
                            }

                            Err(e) => {
                                error!("[Notify Error]: {}", e);
                                std::process::exit(1);
                            }
                        }
                    }
                }
                Err(e) => {
                    error!("[Notify Error]: {}", e);
                    std::process::exit(1);
                }
            }
        }

        "import" => {
            let branch = matches.value_of("branch").unwrap().to_string();
            let message = matches.value_of("message").unwrap().to_string();
            import(&config, &branch, &message);
        }

        _ => {
            println!("{}", global_matches.usage());
            return;
        }
    }
}

fn build(config: &Config) {
    info!("Building from {} into {}", config.source, config.dest);
    match cobalt::build(&config) {
        Ok(_) => info!("Build successful"),
        Err(e) => {
            error!("{}", e);
            error!("Build not successful");
            std::process::exit(1);
        }
    };
}

fn static_file_handler(dest: &str, req: Request, mut res: Response) -> IoResult<()> {
    // grab the requested path
    let req_path = match req.uri {
        RequestUri::AbsolutePath(p) => p,
        _ => {
            // return a 400 and exit from this request
            *res.status_mut() = hyper::status::StatusCode::BadRequest;
            let body = b"<h1> <center> 400: Bad request </center> </h1>";
            try!(res.send(body));
            return Ok(());
        }
    };

    // find the path of the file in the local system
    // (this gets rid of the '/' in `p`, so the `join()` will not replace the
    // path)
    let path = PathBuf::from(dest).join(&req_path[1..]);

    let serve_path = if path.is_file() {
        // try to point the serve path to `path` if it corresponds to a file
        path
    } else {
        // try to point the serve path into a "index.html" file in the requested
        // path
        path.join("index.html")
    };

    // if the request points to a file and it exists, read and serve it
    if serve_path.exists() {
        let mut file = try!(File::open(serve_path));

        // buffer to store the file
        let mut buffer: Vec<u8> = vec![];

        try!(file.read_to_end(&mut buffer));

        try!(res.send(&buffer));
    } else {
        // return a 404 status
        *res.status_mut() = hyper::status::StatusCode::NotFound;

        // write a simple body for the 404 page
        let body = b"<h1> <center> 404: Page not found </center> </h1>";

        try!(res.send(body));
    }

    Ok(())
}

fn serve(dest: &str, port: &str) {
    info!("Serving {:?} through static file server", dest);

    let ip = format!("127.0.0.1:{}", port);
    info!("Server Listening on {}", &ip);
    info!("Ctrl-c to stop the server");

    // attempts to create a server
    let http_server = match Server::http(&*ip) {
        Ok(server) => server,
        Err(e) => {
            error!("{}", e);
            std::process::exit(1);
        }
    };

    // need a clone because of closure's lifetime
    let dest_clone = dest.to_owned();

    // bind the handle function and start serving
    if let Err(e) = http_server.handle(move |req: Request, res: Response| {
        if let Err(e) = static_file_handler(&dest_clone, req, res) {
            error!("{}", e);
            std::process::exit(1);
        }
    }) {
        error!("{}", e);
        std::process::exit(1);
    };
}

fn import(config: &Config, branch: &str, message: &str) {
    info!("Importing {} to {}", config.dest, branch);

    let meta = match fs::metadata(&config.dest) {
        Ok(data) => data,

        Err(e) => {
            error!("{}", e);
            error!("Import not successful");
            std::process::exit(1);
        }
    };

    if meta.is_dir() {
        match import_dir(&config.dest, branch, message) {
            Ok(_) => info!("Import successful"),
            Err(e) => {
                error!("{}", e);
                error!("Import not successful");
                std::process::exit(1);
            }
        }
    } else {
        error!("Build dir is not a directory: {}", config.dest);
        error!("Import not successful");
        std::process::exit(1);
    }
}
<|endoftext|>


<commit_before>extern crate rppal;

use std::env;
use std::ffi::OsString;
use rppal::gpio::{GPIO,Mode,Level};

const LAST_PIN_NUMBER: u8 = 27;
const HELP_CMD_STR: &'static str = "help";
const SET_CMD_STR: &'static str = "set";
const GET_CMD_STR: &'static str = "get";
const HIGH_PIN_STATE_STR: &'static str = "high";
const LOW_PIN_STATE_STR: &'static str = "low";
const ALL_PINS_STR: &'static str = "all";
const HELP_EXAMPLE_STR: &'static str = "sudo pi3gpio help";

fn main() {
	handle_cmd ( env::args_os() );
}

fn handle_cmd (mut cmd: env::ArgsOs) {
	match cmd.nth(1) {
		Some (action) => {
			if action == OsString::from(HELP_CMD_STR) {
				print_help_text ();
			}
			else if action == OsString::from(SET_CMD_STR) {
				set_pins (cmd);
			}
			else if action == OsString::from(GET_CMD_STR) {
				read_pins (cmd);
			}
			else {
				panic! ("Unknown command {:?}! \nFor help run \"{}\"", action, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("No command found! \nFor help run \"{}\"", HELP_EXAMPLE_STR ),
	}
}

fn print_help_text () {
	println! ("SYNTAX: sudo pi3gpio command [state] [pins]");
	println! ("	command: ");
	println! ("		{}	prints the help text", HELP_CMD_STR );
	println! ("		{}	sets the value of the indicated pins to the indicated value", SET_CMD_STR );
	println! ("		{}	prints the state of the indicated pins", GET_CMD_STR );
	println! ("	state: ");
	println! ("		{}	logical 1 for the indicated pins, equivalent voltage 3.3[V]", HIGH_PIN_STATE_STR );
	println! ("		{}	logical 0 for the indicated pins, equivalent voltage 0[V]", LOW_PIN_STATE_STR );
	println! ("	pins: ");
	println! ("		{}	BCM pins between 0 and {}", ALL_PINS_STR, LAST_PIN_NUMBER );
	println! ("Examples:");
	println! ("	sudo pi3gpio help ");
	println! ("	sudo pi3gpio get all");
	println! ("	sudo pi3gpio get 4");
	println! ("	sudo pi3gpio get 10 11");
	println! ("	sudo pi3gpio set low all");
	println! ("	sudo pi3gpio set high 12");
	println! ("	sudo pi3gpio set low 2 5 7");
}

trait ReadState{
	fn read_state (self, gpio: &mut GPIO);
}

impl ReadState for OsString {
	fn read_state (self, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => read_pin ( gpio, pin ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn read_all_pins ( gpio: &mut GPIO ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		read_pin ( gpio, pin );
	}
}

fn read_pin ( gpio: &mut GPIO, pin: u8) {
	gpio.set_mode( pin, Mode::Input );
	match gpio.read(pin) {
		Ok(state) =>	println! ("Pin {} = {:?}", pin, state ),
		Err (_) => println! ("Could not read state of pin {}",pin),
	}
}

fn read_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				read_all_pins ( &mut gpio );
				return;
			}
			else {
				pin_as_os_string.read_state ( &mut gpio );
			}
		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.read_state ( &mut gpio );
	}

}

trait ToU8 {
	fn to_u8 (self) -> Result<u8, &'static str >;
}

impl ToU8 for OsString {
	fn to_u8 (self) -> Result<u8, &'static str> {
		match self.into_string() {
			Ok(x) => match x.parse::<u8>() {
				Ok (y) => return Ok (y),
				Err(_) => return Err("String indicating pin number could not be converted to u8!" ),
			},
			Err(_) => return Err("OsString indicating pin number could not be converted to String!" ),
		}
	}
}

fn initiate_gpio_handle () -> GPIO {
    let gpio: GPIO;
    match GPIO::new(){
	    Ok (x) => gpio = x,
	    Err (e) => panic! ("Could not access GPIO memory! {}",e),
    }

    gpio
}

fn get_pin_state ( argument: Option<OsString>  ) -> Level {
	let mut pin_state = Level::Low;
	match argument {
		Some (state) => {
			if state == OsString::from(HIGH_PIN_STATE_STR) {
				pin_state = Level::High;
			}
			else if state != OsString::from(LOW_PIN_STATE_STR) {
				panic! ("State {:?} is invalid! \nFor help run \"{}\"", state, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("State not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

    pin_state
}

trait SetState{
	fn set_state (self, pin_state: Level ,gpio: &mut GPIO);
}

impl SetState for OsString {
	fn set_state (self, pin_state: Level, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => set_pin ( gpio, pin, pin_state ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn set_all_pins ( gpio: &mut GPIO, pin_state: Level ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		set_pin ( gpio, pin, pin_state );
	}
}

fn set_pin ( gpio: &mut GPIO, pin: u8, pin_state: Level ) {
	println! ("Set pin {} to {:?}", pin, pin_state);
	gpio.set_mode( pin, Mode::Output );
	gpio.write ( pin, pin_state );
}

fn set_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();
	gpio.set_clear_on_drop ( false );

	let pin_state = get_pin_state( cmd.nth(0) );

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				set_all_pins ( &mut gpio, pin_state );
				return;
			}
			else {
				pin_as_os_string.set_state( pin_state, &mut gpio );
			}

		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.set_state( pin_state, &mut gpio );
	}
}
<commit_msg>Update main.rs<commit_after>extern crate rppal;

use std::env;
use std::ffi::OsString;
use rppal::gpio::{GPIO,Mode,Level};

const LAST_PIN_NUMBER: u8 = 27;
const HELP_CMD_STR: &'static str = "help";
const SET_CMD_STR: &'static str = "set";
const GET_CMD_STR: &'static str = "get";
const HIGH_PIN_STATE_STR: &'static str = "high";
const LOW_PIN_STATE_STR: &'static str = "low";
const ALL_PINS_STR: &'static str = "all";
const HELP_EXAMPLE_STR: &'static str = "sudo ./pi3gpio help";

fn main() {
	handle_cmd ( env::args_os() );
}

fn handle_cmd (mut cmd: env::ArgsOs) {
	match cmd.nth(1) {
		Some (action) => {
			if action == OsString::from(HELP_CMD_STR) {
				print_help_text ();
			}
			else if action == OsString::from(SET_CMD_STR) {
				set_pins (cmd);
			}
			else if action == OsString::from(GET_CMD_STR) {
				read_pins (cmd);
			}
			else {
				panic! ("Unknown command {:?}! \nFor help run \"{}\"", action, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("No command found! \nFor help run \"{}\"", HELP_EXAMPLE_STR ),
	}
}

fn print_help_text () {
	println! ("SYNTAX: sudo ./pi3gpio command [state] [pins]");
	println! ("	command: ");
	println! ("		{}	prints the help text", HELP_CMD_STR );
	println! ("		{}	sets the value of the indicated pins to the indicated value", SET_CMD_STR );
	println! ("		{}	prints the state of the indicated pins", GET_CMD_STR );
	println! ("	state: ");
	println! ("		{}	logical 1 for the indicated pins, equivalent voltage 3.3[V]", HIGH_PIN_STATE_STR );
	println! ("		{}	logical 0 for the indicated pins, equivalent voltage 0[V]", LOW_PIN_STATE_STR );
	println! ("	pins: ");
	println! ("		{}	BCM pins between 0 and {}", ALL_PINS_STR, LAST_PIN_NUMBER );
	println! ("Examples:");
	println! ("	sudo ./pi3gpio help ");
	println! ("	sudo ./pi3gpio get all");
	println! ("	sudo ./pi3gpio get 4");
	println! ("	sudo ./pi3gpio get 10 11");
	println! ("	sudo ./pi3gpio set low all");
	println! ("	sudo ./pi3gpio set high 12");
	println! ("	sudo ./pi3gpio set low 2 5 7");
}

trait ReadState{
	fn read_state (self, gpio: &mut GPIO);
}

impl ReadState for OsString {
	fn read_state (self, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => read_pin ( gpio, pin ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn read_all_pins ( gpio: &mut GPIO ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		read_pin ( gpio, pin );
	}
}

fn read_pin ( gpio: &mut GPIO, pin: u8) {
	gpio.set_mode( pin, Mode::Input );
	match gpio.read(pin) {
		Ok(state) =>	println! ("Pin {} = {:?}", pin, state ),
		Err (_) => println! ("Could not read state of pin {}",pin),
	}
}

fn read_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				read_all_pins ( &mut gpio );
				return;
			}
			else {
				pin_as_os_string.read_state ( &mut gpio );
			}
		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.read_state ( &mut gpio );
	}

}

trait ToU8 {
	fn to_u8 (self) -> Result<u8, &'static str >;
}

impl ToU8 for OsString {
	fn to_u8 (self) -> Result<u8, &'static str> {
		match self.into_string() {
			Ok(x) => match x.parse::<u8>() {
				Ok (y) => return Ok (y),
				Err(_) => return Err("String indicating pin number could not be converted to u8!" ),
			},
			Err(_) => return Err("OsString indicating pin number could not be converted to String!" ),
		}
	}
}

fn initiate_gpio_handle () -> GPIO {
    let gpio: GPIO;
    match GPIO::new(){
	    Ok (x) => gpio = x,
	    Err (e) => panic! ("Could not access GPIO memory! {}",e),
    }

    gpio
}

fn get_pin_state ( argument: Option<OsString>  ) -> Level {
	let mut pin_state = Level::Low;
	match argument {
		Some (state) => {
			if state == OsString::from(HIGH_PIN_STATE_STR) {
				pin_state = Level::High;
			}
			else if state != OsString::from(LOW_PIN_STATE_STR) {
				panic! ("State {:?} is invalid! \nFor help run \"{}\"", state, HELP_EXAMPLE_STR );
			}
		},
		None => panic! ("State not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

    pin_state
}

trait SetState{
	fn set_state (self, pin_state: Level ,gpio: &mut GPIO);
}

impl SetState for OsString {
	fn set_state (self, pin_state: Level, gpio: &mut GPIO) {
		match self.to_u8() {
			Ok (pin) => set_pin ( gpio, pin, pin_state ),
			Err (e) => {
				panic! ("{} \nFor help run \"{}\"", e,  HELP_EXAMPLE_STR );
			},
		}
	}
}

fn set_all_pins ( gpio: &mut GPIO, pin_state: Level ) {
	for pin in 0..(LAST_PIN_NUMBER+1) {
		set_pin ( gpio, pin, pin_state );
	}
}

fn set_pin ( gpio: &mut GPIO, pin: u8, pin_state: Level ) {
	println! ("Set pin {} to {:?}", pin, pin_state);
	gpio.set_mode( pin, Mode::Output );
	gpio.write ( pin, pin_state );
}

fn set_pins (mut cmd: env::ArgsOs) {
	let mut gpio = initiate_gpio_handle();
	gpio.set_clear_on_drop ( false );

	let pin_state = get_pin_state( cmd.nth(0) );

	match cmd.nth(0) {
		Some (pin_as_os_string) => {
			if pin_as_os_string == OsString::from(ALL_PINS_STR) {
				set_all_pins ( &mut gpio, pin_state );
				return;
			}
			else {
				pin_as_os_string.set_state( pin_state, &mut gpio );
			}

		}
		None => panic! ("Pin not found! \nFor help run \"{}\"",  HELP_EXAMPLE_STR ),
	}

	for argument in cmd {
		argument.set_state( pin_state, &mut gpio );
	}
}
<|endoftext|>


<commit_before>extern crate serde_json;
extern crate clap;

use serde_json::Value;
use serde_json::Deserializer;
use std::io::{self, Write};
use clap::{App, Arg};
use std::fs;
use std::result;
use std::error::Error;
use std::vec::Vec;
use std::string::String;

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

fn run() -> Result<()> {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .about("Extract JSON elements from a stream via JSON Pointers")
        .arg(Arg::with_name("INPUT")
            .short("i")
            .long("input")
            .takes_value(true)
            .help("input file to use if not receiving on stdin"))
        .arg(Arg::with_name("DELIMITER")
            .short("d")
            .long("delimiter")
            .takes_value(true)
            .help("delimiter between output values, default is tab"))
        .arg(Arg::with_name("POINTER")
            .required(true)
            .multiple(true)
            .help("JSON Pointer expressions to match on input"))
        .get_matches();

    let input = matches.value_of("INPUT").unwrap_or("-");
    let rdr: Box<io::Read> = match input {
        "-" => Box::new(io::stdin()),
        _ => Box::new(try!(fs::File::open(input))),
    };

    let delim = matches.value_of("DELIMITER").unwrap_or("\t");

    let mut pointers = Vec::new();
    // unwrap is safe as POINTER is required
    for p in matches.values_of("POINTER").unwrap() {
        pointers.push(p);
    }

    let iter = Deserializer::from_reader(rdr).into_iter::<Value>();
    for rv in iter {
        let v = try!(rv);
        let mut line = String::new();
        for p in &pointers {
            line.push_str(&render(v.pointer(p).unwrap_or(&Value::Null)));
            line.push_str(delim);
        }
        line.pop(); // remove the final tab
        println!("{}", line);
    }
    Ok(())
}

fn main() {
    match run() {
        Ok(_) => {}
        Err(e) => {
            writeln!(&mut io::stderr(), "error: {}", e).unwrap();
            std::process::exit(1);
        }
    }
}

fn render(v: &Value) -> String {
    match v {
        &Value::Null => String::new(),
        &Value::Bool(ref b) => format!("{}", b),
        &Value::Number(ref b) => format!("{}", b),
        &Value::String(_ /*ref s*/) => format!("{}", v),
        &Value::Array(_) => format!("{}", v),
        &Value::Object(_) => format!("{}", v),
    }
}
<commit_msg>Escape newlines in string output<commit_after>extern crate serde_json;
extern crate clap;

use serde_json::Value;
use serde_json::Deserializer;
use std::io::{self, Write};
use clap::{App, Arg};
use std::fs;
use std::result;
use std::error::Error;
use std::vec::Vec;
use std::string::String;

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

fn run() -> Result<()> {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .about("Extract JSON elements from a stream via JSON Pointers")
        .arg(Arg::with_name("INPUT")
            .short("i")
            .long("input")
            .takes_value(true)
            .help("input file to use if not receiving on stdin"))
        .arg(Arg::with_name("DELIMITER")
            .short("d")
            .long("delimiter")
            .takes_value(true)
            .help("delimiter between output values, default is tab"))
        .arg(Arg::with_name("POINTER")
            .required(true)
            .multiple(true)
            .help("JSON Pointer expressions to match on input"))
        .get_matches();

    let input = matches.value_of("INPUT").unwrap_or("-");
    let rdr: Box<io::Read> = match input {
        "-" => Box::new(io::stdin()),
        _ => Box::new(try!(fs::File::open(input))),
    };

    let delim = matches.value_of("DELIMITER").unwrap_or("\t");

    let mut pointers = Vec::new();
    // unwrap is safe as POINTER is required
    for p in matches.values_of("POINTER").unwrap() {
        pointers.push(p);
    }

    let iter = Deserializer::from_reader(rdr).into_iter::<Value>();
    for rv in iter {
        let v = try!(rv);
        let mut line = String::new();
        for p in &pointers {
            line.push_str(&render(v.pointer(p).unwrap_or(&Value::Null)));
            line.push_str(delim);
        }
        line.pop(); // remove the final tab
        println!("{}", line);
    }
    Ok(())
}

fn main() {
    match run() {
        Ok(_) => {}
        Err(e) => {
            writeln!(&mut io::stderr(), "error: {}", e).unwrap();
            std::process::exit(1);
        }
    }
}

fn render(v: &Value) -> String {
    match v {
        &Value::Null => String::new(),
        &Value::Bool(ref b) => format!("{}", b),
        &Value::Number(ref b) => format!("{}", b),
        &Value::String(ref s) => format!("{}", s.replace("\n", "\\n")),
        &Value::Array(_) => format!("{}", v),
        &Value::Object(_) => format!("{}", v),
    }
}
<|endoftext|>


<commit_before>//#![feature(plugin)]
//
//#[plugin]
//extern crate clippy;

extern crate cli;
extern crate getopts;
extern crate hyper;

use std::os;
use std::env;
use std::old_io::fs;
use getopts::Options;

fn main() {
    let mut opts = Options::new();
    cli::helpopt(&mut opts);
    cli::versionopt(&mut opts);
    opts.optflag("l", "list", "List installed fonts");
    opts.optopt("s", "search", "Search font", "FONTNAME");
    opts.optmulti("i", "install", "Install font(s) require a --source", "FONTNAME");
    opts.optmulti("d", "delete", "Delete font(s)", "FONTNAME");
    opts.optmulti("s", "source", "Source file to use", "FILENAME");

    let matches = cli::parse_args(&opts);

    if matches.opt_present("help") {
        println!("{}", cli::usage_string(&opts));
        return;
    }
    if matches.opt_present("version") {
        println!("{}", cli::version_string("0.0.1"));
        return;
    }
    if matches.opt_present("list") {
        list_installed_fonts();
    }
    if matches.opt_present("search") {
        search_font(&*matches.opt_str("search").unwrap());
    }
    if matches.opt_present("install") {
        if matches.opt_present("source") {
            install_font(&*matches.opt_str("source").unwrap(), &*matches.opt_str("install").unwrap());
        } else {
            println!("{}", opts.usage("ttoo"));
        }
    }
    if matches.opt_present("delete") {
        delete_font(&*matches.opt_str("delete").unwrap());
    }
}

fn get_font_dir() -> Path {
    match env::consts::OS {
        "linux" => {
            match env::home_dir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "macos" => {
            match env::home_dir() {
                Some(ref p) => p.join("Library").join("Fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "windows" => {
            match os::getenv("SystemRoot") {
                Some(val) => Path::new(val).join("Fonts"),
                None => panic!("Impossible to get your font dir")
            }
        },
        _ => unreachable!(),
    }
}

fn get_font_path(font_name: &str) -> Path {
    get_font_dir().join(font_name)
}

fn list_installed_fonts() {
    let font_dir = get_font_dir();
    match fs::readdir(&font_dir) {
        Ok(fonts) => for font in fonts.iter() {
            if let Some(font_name) = font.filename_str() {
                println!("{}", font_name);
            }
        },
        Err(msg) => println!("{}", msg)
    }
}

fn search_font(font_name: &str) {
    let mut client = hyper::Client::new();
    let url = format!("http://api.github.com/search/repositories?q={}+in:name&sort=stars&order=desc", font_name);
    let resp = client.get(&*url).send();
    match resp {
        Ok(mut data) => match data.read_to_string() {
            Ok(body) => println!("body={}", body),
            Err(err) => println!("{}", err)
        },
        Err(err) => println!("{}", err)
    };
}

fn install_font(source: &str, font_name: &str) {
    let dest_font_path = get_font_path(font_name);
    match fs::copy(&Path::new(source), &dest_font_path) {
        Ok(_) => println!("Font {} installed successfully", font_name),
        Err(msg) => println!("{}", msg)
    }
}

fn delete_font(font_name: &str) {
    let font_path = get_font_path(font_name);
    match fs::unlink(&font_path) {
        Ok(_) => println!("Font {} deleted successfully", font_name),
        Err(msg) => println!("{}", msg)
    }
}

<commit_msg>add filter on list fonts<commit_after>//#![feature(plugin)]
//
//#[plugin]
//extern crate clippy;

extern crate cli;
extern crate getopts;
extern crate hyper;

use std::os;
use std::env;
use std::old_io::fs;
use getopts::Options;

static FONT_EXTENSIONS : [&'static str; 2] = ["ttf", "otf", "pcf", "bdf"];

fn main() {
    let mut opts = Options::new();
    cli::helpopt(&mut opts);
    cli::versionopt(&mut opts);
    opts.optflag("l", "list", "List installed fonts");
    opts.optopt("s", "search", "Search font", "FONTNAME");
    opts.optmulti("i", "install", "Install font(s) require a --source", "FONTNAME");
    opts.optmulti("d", "delete", "Delete font(s)", "FONTNAME");
    opts.optmulti("s", "source", "Source file to use", "FILENAME");

    let matches = cli::parse_args(&opts);

    if matches.opt_present("help") {
        println!("{}", cli::usage_string(&opts));
        return;
    }
    if matches.opt_present("version") {
        println!("{}", cli::version_string("0.0.1"));
        return;
    }
    if matches.opt_present("list") {
        list_installed_fonts();
    }
    if matches.opt_present("search") {
        search_font(&*matches.opt_str("search").unwrap());
    }
    if matches.opt_present("install") {
        if matches.opt_present("source") {
            install_font(&*matches.opt_str("source").unwrap(), &*matches.opt_str("install").unwrap());
        } else {
            println!("{}", opts.usage("ttoo"));
        }
    }
    if matches.opt_present("delete") {
        delete_font(&*matches.opt_str("delete").unwrap());
    }
}

fn get_font_dir() -> Path {
    match env::consts::OS {
        "linux" => {
            match env::home_dir() {
                Some(ref p) => p.join(".fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "macos" => {
            match env::home_dir() {
                Some(ref p) => p.join("Library").join("Fonts"),
                None => panic!("Impossible to get your home dir!")
            }
        },
        "windows" => {
            match os::getenv("SystemRoot") {
                Some(val) => Path::new(val).join("Fonts"),
                None => panic!("Impossible to get your font dir!")
            }
        },
        _ => unreachable!(),
    }
}

fn get_font_path(font_name: &str) -> Path {
    get_font_dir().join(font_name)
}

fn list_installed_fonts() {
    let font_dir = get_font_dir();
    match fs::readdir(&font_dir) {
        Ok(fonts) => {
            let mut it_fonts = fonts.iter().filter(|&f| {
                FONT_EXTENSIONS.iter().find(|&ext| {
                    *f.extension_str().unwrap().to_string() == *ext.to_string()
                }).is_some()
            });
            for font in it_fonts {
                if let Some(font_name) = font.filename_str() {
                    println!("{}", font_name);
                }
            }
        }
        Err(msg) => println!("{}", msg)
    }
}

fn search_font(font_name: &str) {
    let mut client = hyper::Client::new();
    let url = format!("http://api.github.com/search/repositories?q={}+in:name&sort=stars&order=desc", font_name);
    let resp = client.get(&*url).send();
    match resp {
        Ok(mut data) => match data.read_to_string() {
            Ok(body) => println!("body={}", body),
            Err(err) => println!("{}", err)
        },
        Err(err) => println!("{}", err)
    };
}

fn install_font(source: &str, font_name: &str) {
    let dest_font_path = get_font_path(font_name);
    match fs::copy(&Path::new(source), &dest_font_path) {
        Ok(_) => println!("Font {} installed successfully", font_name),
        Err(msg) => println!("{}", msg)
    }
}

fn delete_font(font_name: &str) {
    let font_path = get_font_path(font_name);
    match fs::unlink(&font_path) {
        Ok(_) => println!("Font {} deleted successfully", font_name),
        Err(msg) => println!("{}", msg)
    }
}

<|endoftext|>


<commit_before>use std::io::Read;
use std::collections::HashMap;
use std::str::Split;

pub struct Command<'a> {
    command: &'a str,
    exec: Box<Fn(Vec<&str>)>,
    complete: Option<Box<Fn(Vec<&str>)>>
}

impl<'a> Command<'a> {
    fn new<T: Fn(Vec<&str>) + 'static, U: Fn(Vec<&str>) + 'static>(cmd: &'a str, exec_handler: T, complete_handler: Option<U>) -> Command {
        let mut obj = Command {
            command: cmd,
            exec: Box::new(exec_handler),
            complete: None
        };

        if let Some(cb) = complete_handler {
            obj.complete = Some(Box::new(cb));
        }

        obj
    }
}

pub struct Cli<'a> {
    commands: HashMap<&'a str, Command<'a>>
}

impl<'a> Cli<'a>{

    fn new() -> Cli<'a> {
        Cli {
            commands: HashMap::new()
        }
    }

    fn register<T: Fn(Vec<&str>) + 'static>(&mut self, cmd: &'a str, exec: T) -> Result<(), Command> {

        let tmp = Command {
            command: cmd,
            exec: Box::new(exec),
            complete: None
        };

        match self.commands.insert(cmd, tmp) {
            Some(existing) => Err(existing),
            None => Ok(())
        }
    }

    fn complete(&self, argv: &str) -> Vec<&str> {
        Vec::new()
    }

    fn exec(&self, cmd: &str) {
        if let Some(command) = self.commands.get(cmd) {
            //TODO: figure out why I can't do that in one line
            let ref x = command.exec;
            x(vec!["blah"]);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn testRegister() {
        let mut cli = Cli::new();
        let mut called = false;

        cli.register("my first command", | args | { println!("called"); } );
        cli.exec("my first command");

        assert!(called == true)
    }
}

    //fn new(callback: Option<Box<Fn()>>) -> Cli<'a> {
        //Cli {
            //commands: HashMap::new(),
            //exec: callback,
            //complete_cb: None,
        //}
    //}

    //fn register<T: Fn() + 'static>(&mut self, command: Vec<&'a str>, callback: T) {
        //let mut it = command.iter();
        //self._register(it, callback);
    //}

    //fn _register<T: Fn() + 'static>(&mut self, mut it: std::slice::Iter<&'a str>, callback: T) {
        //if let Some(portion) = it.next() {
            //if !self.commands.contains_key(portion) {
                //self.commands.insert(portion, Cli::new(Some(Box::new(callback))));
            //}

            //self.commands.get_mut(portion).unwrap()._register(it, callback);
        //}
    //}

    //fn suggest(&mut self, command: &str) -> Vec<&str> {
        //let mut portions = command.trim().split(" ");
        //let mut suggestions = self._suggest(&mut portions);
        //if let Some(ref cb) = self.complete_cb {
            //cb();
            //println!("got callback");
        //}
        //suggestions
    //}

    //fn _suggest(&self, portions: &mut std::str::Split<&str>) -> Vec<&str> {
        //let mut ret = Vec::with_capacity(self.commands.len());

        //if let Some(portion) = portions.next() {
            //if !portion.is_empty() {
                //if let Some(cmd) = self.commands.get(portion) {
                    //ret = cmd._suggest(portions);
                //}
            //} else {
                //for key in self.commands.keys() {
                    //ret.push(*key);
                //}
            //}
        //} else {
            //for key in self.commands.keys() {
                //ret.push(*key);
            //}
        //}

        //ret
    //}
//}

//fn foo() {

//}

fn main() {
    //let mut cli = Cli::new(Some(Box::new(foo)));

    //cli.register(vec!["show", "stuff"], foo);
    //cli.register(vec!["show", "other"], foo);
    //cli.register(vec!["list", "other", "cool"], foo);
    //cli.register(vec!["list", "other", "uncool"], foo);

    //loop {
        //let mut line = String::new();
        //std::io::stdin().read_line(&mut line).unwrap();

        //println!("got: {:?}", cli.suggest(&line));
    //}
}
<commit_msg>use FnMut so that we can mutate our environment<commit_after>use std::io::Read;
use std::collections::HashMap;
use std::str::Split;

pub struct Command<'a> {
    command: &'a str,
    exec: Box<FnMut(Vec<&str>) + 'a>,
    complete: Option<Box<FnMut(Vec<&str>) + 'a>>
}

impl<'a> Command<'a> {
    fn new<T: FnMut(Vec<&str>) + 'a, U: FnMut(Vec<&str>) + 'a>(cmd: &'a str, exec_handler: T, complete_handler: Option<U>) -> Command<'a> {
        let mut obj = Command {
            command: cmd,
            exec: Box::new(exec_handler),
            complete: None
        };

        if let Some(cb) = complete_handler {
            obj.complete = Some(Box::new(cb));
        }

        obj
    }
}

pub struct Cli<'a> {
    commands: HashMap<&'a str, Command<'a>>
}

impl<'a> Cli<'a>{

    fn new() -> Cli<'a> {
        Cli {
            commands: HashMap::new()
        }
    }

    fn register<T: FnMut(Vec<&str>) + 'a>(&mut self, cmd: &'a str, exec: T) -> Result<(), Command> {
        let tmp = Command {
            command: cmd,
            exec: Box::new(exec),
            complete: None
        };

        match self.commands.insert(cmd, tmp) {
            Some(existing) => Err(existing),
            None => Ok(())
        }
    }

    fn complete(&self, argv: &str) -> Vec<&str> {
        Vec::new()
    }

    fn exec(&mut self, cmd: &str) {
        if let Some(command) = self.commands.get_mut(cmd) {
            //TODO: figure out why I can't do that in one line
            let ref mut x = command.exec;
            x(vec!["blah"]);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn testRegister() {
        let mut called = false;
        {
            let mut cli = Cli::new();
            cli.register("my first command", | args | { called=true } );
            cli.exec("my first command");
        }
        assert!(called == true)
    }
}

    //fn new(callback: Option<Box<Fn()>>) -> Cli<'a> {
        //Cli {
            //commands: HashMap::new(),
            //exec: callback,
            //complete_cb: None,
        //}
    //}

    //fn register<T: Fn() + 'static>(&mut self, command: Vec<&'a str>, callback: T) {
        //let mut it = command.iter();
        //self._register(it, callback);
    //}

    //fn _register<T: Fn() + 'static>(&mut self, mut it: std::slice::Iter<&'a str>, callback: T) {
        //if let Some(portion) = it.next() {
            //if !self.commands.contains_key(portion) {
                //self.commands.insert(portion, Cli::new(Some(Box::new(callback))));
            //}

            //self.commands.get_mut(portion).unwrap()._register(it, callback);
        //}
    //}

    //fn suggest(&mut self, command: &str) -> Vec<&str> {
        //let mut portions = command.trim().split(" ");
        //let mut suggestions = self._suggest(&mut portions);
        //if let Some(ref cb) = self.complete_cb {
            //cb();
            //println!("got callback");
        //}
        //suggestions
    //}

    //fn _suggest(&self, portions: &mut std::str::Split<&str>) -> Vec<&str> {
        //let mut ret = Vec::with_capacity(self.commands.len());

        //if let Some(portion) = portions.next() {
            //if !portion.is_empty() {
                //if let Some(cmd) = self.commands.get(portion) {
                    //ret = cmd._suggest(portions);
                //}
            //} else {
                //for key in self.commands.keys() {
                    //ret.push(*key);
                //}
            //}
        //} else {
            //for key in self.commands.keys() {
                //ret.push(*key);
            //}
        //}

        //ret
    //}
//}

//fn foo() {

//}

fn main() {
    //let mut cli = Cli::new(Some(Box::new(foo)));

    //cli.register(vec!["show", "stuff"], foo);
    //cli.register(vec!["show", "other"], foo);
    //cli.register(vec!["list", "other", "cool"], foo);
    //cli.register(vec!["list", "other", "uncool"], foo);

    //loop {
        //let mut line = String::new();
        //std::io::stdin().read_line(&mut line).unwrap();

        //println!("got: {:?}", cli.suggest(&line));
    //}
}
<|endoftext|>


<commit_before>#![feature(core)]

extern crate rand;

use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

const N: usize = 50;
const P: usize = 128;

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

fn main() {
    let mut rng = rand::thread_rng();
    let range = Range::new(-512.03_f64, 511.97);

    // initialize population
    let population = Vec::from_iter((0..P).map(|_| {
        Vec::from_iter((0..N).map(|_| {
            range.ind_sample(&mut rng)
        }))
    }));

    println!("{:?}", population); // debug print of solutions

    let solution = population.iter().min_by(|x| schwefel(x) as i64).unwrap();
    println!("The best solution was {:?}", solution);
    println!("Its fitness was {}", schwefel(solution));
}
<commit_msg>Implement struct Individual<commit_after>#![feature(core)]

extern crate rand;

use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

struct Individual {
    solution: Vec<f64>,
    fitness: f64,
}

impl Individual {
    fn new() -> Individual {
        let n = 50;
        let mut rng = rand::thread_rng();
        let range = Range::new(-512.03_f64, 511.97);

        let mut i = Individual {
            solution: Vec::from_iter((0..n).map(|_| range.ind_sample(&mut rng))),
            fitness: 0_f64,
        };
        i.fitness = schwefel(&i.solution);
        i
    }
}

fn main() {
    let pop_size = 128;

    // initialize population
    let population = Vec::from_iter((0..pop_size).map(|_| Individual::new()));

    let best = population.iter().min_by(|x| schwefel(&x.solution) as i64).unwrap();
    println!("The best solution was {:?}", best.solution);
    println!("Its fitness was {}", schwefel(&best.solution));
}
<|endoftext|>


<commit_before>fn intro() {
    println!("{:^60}", "LUNAR");
    println!("{:^60}", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
    println!("\n\n");
    println!("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR");
    println!("LANDING CAPSULE.");
    println!("\n");
    println!("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY");
    println!("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.");
    println!("");
    println!("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN");
    println!("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.");
    println!("SET NEW BURN RATE EVERY 10 SECONDS.");
    println!("");
    println!("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.");
    println!("\n\n");
    println!("GOOD LUCK");
}

fn main() {
    intro();
}

<commit_msg>happily humming along...<commit_after>fn intro() {
    println!("{:^60}", "LUNAR");
    println!("{:^60}", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY");
    println!("\n\n");
    println!("THIS IS A COMPUTER SIMULATION OF AN APOLLO LUNAR");
    println!("LANDING CAPSULE.");
    println!("\n");
    println!("THE ON-BOARD COMPUTER HAS FAILED (IT WAS MADE BY");
    println!("XEROX) SO YOU HAVE TO LAND THE CAPSULE MANUALLY.");
    println!("");
    println!("SET BURN RATE OF RETRO ROCKETS TO ANY VALUE BETWEEN");
    println!("0 (FREE FALL) AND 200 (MAXIMUM BURN) POUNDS PER SECOND.");
    println!("SET NEW BURN RATE EVERY 10 SECONDS.");
    println!("");
    println!("CAPSULE WEIGHT 32,500 LBS; FUEL WEIGHT 16,500 LBS.");
    println!("\n\n");
    println!("GOOD LUCK");
}

fn main() {
    intro();
    let l = 0;
}
<|endoftext|>


<commit_before>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

extern crate rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;

use std::env;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod convert;

mod layout;
mod compositor;

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    debug!("Launching way-cooler...");

    // Initialize callbacks
    callbacks::init();

    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").expect("Asserted unwrap!"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handler.");

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // Hand control over to wlc's event loop
    run_wlc();
}
<commit_msg>Move logging initialization to its own public method<commit_after>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

extern crate rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;

use std::env;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod convert;

mod layout;
mod compositor;

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

/// Initializes the logging system.
/// Can be called from within test methods.
pub fn init_logs() {
    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").expect("Asserted unwrap!"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handlers.");
}

fn main() {
    println!("Launching way-cooler...");

    // Start logging first
    init_logs();

    // Initialize callbacks
    callbacks::init();

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // Hand control over to wlc's event loop
    info!("Running wlc...");
    run_wlc();
}
<|endoftext|>


<commit_before>#![recursion_limit = "1024" ]
#[macro_use] extern crate clap;
#[macro_use] extern crate error_chain;
extern crate migrant_lib;

#[cfg(feature="update")]
extern crate self_update;

use std::io;
use std::fs;
use std::env;
use std::path::PathBuf;
use migrant_lib::{Config, Direction, Migrator, DbKind};
use migrant_lib::config::{SqliteSettingsBuilder, PostgresSettingsBuilder};

mod cli;
mod errors {
    use super::*;
    error_chain! {
        foreign_links {
            MigrantLib(migrant_lib::Error);
            SelfUpdate(self_update::errors::Error) #[cfg(feature="update")];
            Io(io::Error);
        }
    }
}
use errors::*;

static APP_VERSION: &'static str = crate_version!();
static APP_NAME: &'static str = "Migrant";

quick_main!(my_main);

fn my_main() -> Result<()> {
    let matches = cli::build_cli().get_matches();
    let dir = env::current_dir()?;

    run(&dir, &matches)
}

fn run(dir: &PathBuf, matches: &clap::ArgMatches) -> Result<()> {
    if let Some(self_matches) = matches.subcommand_matches("self") {
        if let Some(update_matches) = self_matches.subcommand_matches("update") {
            update(update_matches)?;
            return Ok(())
        }

        if let Some(compl_matches) = self_matches.subcommand_matches("bash-completions") {
            let mut out: Box<io::Write> = {
                if let Some(install_matches) = compl_matches.subcommand_matches("install") {
                    let install_path = install_matches.value_of("path").unwrap();
                    let prompt = format!("** Completion file will be installed at: `{}`\n** Is this Ok? [Y/n] ", install_path);
                    confirm(&prompt)?;
                    let file = fs::File::create(install_path)?;
                    Box::new(file)
                } else {
                    Box::new(io::stdout())
                }
            };
            cli::build_cli().gen_completions_to(APP_NAME.to_lowercase(), clap::Shell::Bash, &mut out);
            eprintln!("** Success!");
            return Ok(())
        }
        println!("migrant: see `--help`");
        return Ok(())
    }

    let config_path = migrant_lib::search_for_settings_file(dir);

    if matches.is_present("init") || config_path.is_none() {
        let config = match matches.subcommand_matches("init") {
            None => Config::init_in(&dir),
            Some(init_matches) => {
                let dir = init_matches.value_of("location").map(PathBuf::from).unwrap_or_else(|| dir.to_owned());
                let mut config = Config::init_in(&dir);
                let interactive = !init_matches.is_present("no-confirm");
                config.interactive(interactive);
                if let Some(db_kind) = init_matches.value_of("type") {
                    match db_kind.parse::<DbKind>()? {
                        DbKind::Sqlite => {
                            config.with_sqlite_options(&SqliteSettingsBuilder::empty());
                        }
                        DbKind::Postgres => {
                            config.with_postgres_options(&PostgresSettingsBuilder::empty());
                        }
                    }
                }
                config
            }
        };
        config.initialize()?;
        return Ok(())
    }

    let config_path = config_path.unwrap();    // absolute path of `.migrant` file
    let config = Config::from_settings_file(&config_path)?;

    if matches.is_present("setup") {
        config.setup()?;
        return Ok(())
    }

    if matches.is_present("connect-string") {
        if config.database_type() == DbKind::Sqlite {
            let path = config.database_path()?;
            let path = path.to_str().ok_or_else(|| format!("PathError: Invalid utf8: {:?}", path))?;
            println!("{}", path);
        } else {
            println!("{}", config.connect_string()?);
        }
        return Ok(())
    }

    match matches.subcommand() {
        ("list", _) => {
            // load applied migrations from the database
            let config = config.reload()?;

            migrant_lib::list(&config)?;
        }
        ("new", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let tag = matches.value_of("tag").unwrap();
            migrant_lib::new(&config, tag)?;
            migrant_lib::list(&config)?;
        }
        ("apply", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let force = matches.is_present("force");
            let fake = matches.is_present("fake");
            let all = matches.is_present("all");
            let direction = if matches.is_present("down") { Direction::Down } else { Direction::Up };

            Migrator::with_config(&config)
                .direction(direction)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;

            let config = config.reload()?;
            migrant_lib::list(&config)?;
        }
        ("redo", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let force = matches.is_present("force");
            let fake = matches.is_present("fake");
            let all = matches.is_present("all");

            Migrator::with_config(&config)
                .direction(Direction::Down)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;
            let config = config.reload()?;
            migrant_lib::list(&config)?;

            Migrator::with_config(&config)
                .direction(Direction::Up)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;
            let config = config.reload()?;
            migrant_lib::list(&config)?;
        }
        ("shell", _) => {
            migrant_lib::shell(&config)?;
        }
        ("edit", Some(matches)) => {
            let tag = matches.value_of("tag").unwrap();
            let up_down = if matches.is_present("down") { Direction::Down } else { Direction::Up };
            migrant_lib::edit(&config, &tag, &up_down)?;
        }
        ("which-config", _) => {
            println!("{}", config_path.to_str().unwrap());
        }
        _ => {
            println!("migrant: see `--help`");
        }
    };
    Ok(())
}

#[cfg(feature="update")]
fn update(matches: &clap::ArgMatches) -> Result<()> {
    let mut builder = self_update::backends::github::Update::configure()?;

    builder.repo_owner("jaemk")
        .repo_name("migrant")
        .target(&self_update::get_target()?)
        .bin_name("migrant")
        .show_download_progress(true)
        .no_confirm(matches.is_present("no_confirm"))
        .current_version(APP_VERSION);

    if matches.is_present("quiet") {
        builder.show_output(false)
            .show_download_progress(false);
    }

    let status = builder.build()?.update()?;
    match status {
        self_update::Status::UpToDate(v) => {
            println!("Already up to date [v{}]!", v);
        }
        self_update::Status::Updated(v) => {
            println!("Updated to {}!", v);
        }
    }
    return Ok(());
}

#[cfg(not(feature="update"))]
fn update(_: &clap::ArgMatches) -> Result<()> {
    bail!("This executable was not compiled with `self_update` features enabled via `--features update`")
}

/// Get confirmation on a prompt
/// Returns `Ok` for 'yes' and `Err` for anything else
fn confirm(s: &str) -> Result<()> {
    use io::Write;
    print!("{}", s);
    io::stdout().flush()?;
    let mut s = String::new();
    io::stdin().read_line(&mut s)?;
    let s = s.trim().to_lowercase();
    if !s.is_empty() && s != "y" { bail!("Unable to confirm...") }
    Ok(())
}

<commit_msg>cleanup<commit_after>#![recursion_limit = "1024" ]
#[macro_use] extern crate clap;
#[macro_use] extern crate error_chain;
extern crate migrant_lib;

#[cfg(feature="update")]
extern crate self_update;

use std::io;
use std::fs;
use std::env;
use std::path::PathBuf;
use migrant_lib::{Config, Direction, Migrator, DbKind};
use migrant_lib::config::{SqliteSettingsBuilder, PostgresSettingsBuilder};

mod cli;
mod errors {
    use super::*;
    error_chain! {
        foreign_links {
            MigrantLib(migrant_lib::Error);
            SelfUpdate(self_update::errors::Error) #[cfg(feature="update")];
            Io(io::Error);
        }
    }
}
use errors::*;

static APP_VERSION: &'static str = crate_version!();
static APP_NAME: &'static str = "Migrant";

quick_main!(my_main);

fn my_main() -> Result<()> {
    let matches = cli::build_cli().get_matches();
    let dir = env::current_dir()?;

    run(&dir, &matches)
}

fn run(dir: &PathBuf, matches: &clap::ArgMatches) -> Result<()> {
    if let Some(self_matches) = matches.subcommand_matches("self") {
        if let Some(update_matches) = self_matches.subcommand_matches("update") {
            update(update_matches)?;
            return Ok(())
        }

        if let Some(compl_matches) = self_matches.subcommand_matches("bash-completions") {
            let mut out: Box<io::Write> = {
                if let Some(install_matches) = compl_matches.subcommand_matches("install") {
                    let install_path = install_matches.value_of("path").unwrap();
                    let prompt = format!("** Completion file will be installed at: `{}`\n** Is this Ok? [Y/n] ", install_path);
                    confirm(&prompt)?;
                    let file = fs::File::create(install_path)?;
                    Box::new(file)
                } else {
                    Box::new(io::stdout())
                }
            };
            cli::build_cli().gen_completions_to(APP_NAME.to_lowercase(), clap::Shell::Bash, &mut out);
            eprintln!("** Success!");
            return Ok(())
        }
        println!("migrant: see `--help`");
        return Ok(())
    }

    let config_path = migrant_lib::search_for_settings_file(dir);

    if matches.is_present("init") || config_path.is_none() {
        let config = match matches.subcommand_matches("init") {
            None => Config::init_in(&dir),
            Some(init_matches) => {
                let dir = init_matches.value_of("location").map(PathBuf::from).unwrap_or_else(|| dir.to_owned());
                let mut config = Config::init_in(&dir);
                let interactive = !init_matches.is_present("no-confirm");
                config.interactive(interactive);
                if let Some(db_kind) = init_matches.value_of("type") {
                    match db_kind.parse::<DbKind>()? {
                        DbKind::Sqlite => {
                            config.with_sqlite_options(&SqliteSettingsBuilder::empty());
                        }
                        DbKind::Postgres => {
                            config.with_postgres_options(&PostgresSettingsBuilder::empty());
                        }
                    }
                }
                config
            }
        };
        config.initialize()?;
        return Ok(())
    }

    // Absolute path of `Migrant.toml` file
    // This file must exist at this point, created by the block above
    let config_path = config_path.expect("Settings file must exist");
    let config = Config::from_settings_file(&config_path)?;

    if matches.is_present("setup") {
        config.setup()?;
        return Ok(())
    }

    if matches.is_present("connect-string") {
        match config.database_type() {
            DbKind::Sqlite => {
                let path = config.database_path()?;
                let path = path.to_str().ok_or_else(|| format!("PathError: Invalid utf8: {:?}", path))?;
                println!("{}", path);
            }
            DbKind::Postgres => {
                println!("{}", config.connect_string()?);
            }
        }
        return Ok(())
    }

    match matches.subcommand() {
        ("list", _) => {
            // load applied migrations from the database
            let config = config.reload()?;

            migrant_lib::list(&config)?;
        }
        ("new", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let tag = matches.value_of("tag").unwrap();
            migrant_lib::new(&config, tag)?;
            migrant_lib::list(&config)?;
        }
        ("apply", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let force = matches.is_present("force");
            let fake = matches.is_present("fake");
            let all = matches.is_present("all");
            let direction = if matches.is_present("down") { Direction::Down } else { Direction::Up };

            Migrator::with_config(&config)
                .direction(direction)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;

            let config = config.reload()?;
            migrant_lib::list(&config)?;
        }
        ("redo", Some(matches)) => {
            // load applied migrations from the database
            let config = config.reload()?;

            let force = matches.is_present("force");
            let fake = matches.is_present("fake");
            let all = matches.is_present("all");

            Migrator::with_config(&config)
                .direction(Direction::Down)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;
            let config = config.reload()?;
            migrant_lib::list(&config)?;

            Migrator::with_config(&config)
                .direction(Direction::Up)
                .force(force)
                .fake(fake)
                .all(all)
                .apply()?;
            let config = config.reload()?;
            migrant_lib::list(&config)?;
        }
        ("shell", _) => {
            migrant_lib::shell(&config)?;
        }
        ("edit", Some(matches)) => {
            let tag = matches.value_of("tag").unwrap();
            let up_down = if matches.is_present("down") { Direction::Down } else { Direction::Up };
            migrant_lib::edit(&config, &tag, &up_down)?;
        }
        ("which-config", _) => {
            let path = config_path.to_str().ok_or_else(|| format!("PathError: Invalid utf8: {:?}", config_path))?;
            println!("{}", path);
        }
        _ => {
            println!("migrant: see `--help`");
        }
    };
    Ok(())
}

#[cfg(feature="update")]
fn update(matches: &clap::ArgMatches) -> Result<()> {
    let mut builder = self_update::backends::github::Update::configure()?;

    builder.repo_owner("jaemk")
        .repo_name("migrant")
        .target(&self_update::get_target()?)
        .bin_name("migrant")
        .show_download_progress(true)
        .no_confirm(matches.is_present("no_confirm"))
        .current_version(APP_VERSION);

    if matches.is_present("quiet") {
        builder.show_output(false)
            .show_download_progress(false);
    }

    let status = builder.build()?.update()?;
    match status {
        self_update::Status::UpToDate(v) => {
            println!("Already up to date [v{}]!", v);
        }
        self_update::Status::Updated(v) => {
            println!("Updated to {}!", v);
        }
    }
    return Ok(());
}

#[cfg(not(feature="update"))]
fn update(_: &clap::ArgMatches) -> Result<()> {
    bail!("This executable was not compiled with `self_update` features enabled via `--features update`")
}

/// Get confirmation on a prompt
/// Returns `Ok` for 'yes' and `Err` for anything else
fn confirm(s: &str) -> Result<()> {
    use io::Write;
    print!("{}", s);
    io::stdout().flush()?;
    let mut s = String::new();
    io::stdin().read_line(&mut s)?;
    let s = s.trim().to_lowercase();
    if !s.is_empty() && s != "y" { bail!("Unable to confirm...") }
    Ok(())
}

<|endoftext|>