<commit_before>use std::io;
use std::mem;

use {Poll, Task, Future};
use io::ReadTask;

pub struct ReadToEnd {
    a: A,
    buf: Vec<u8>,
}

pub fn read_to_end(a: A, buf: Vec<u8>) -> ReadToEnd
    where A: ReadTask,
{
    ReadToEnd {
        a: a,
        buf: buf,
    }
}

impl Future for ReadToEnd
    where A: ReadTask,
{
    type Item = Vec<u8>;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Vec<u8>, io::Error> {
        match try_poll!(self.a.poll(task)) {
            Ok(Some(ref r)) if r.is_read() => {}
            Ok(Some(_)) => return Poll::NotReady,
            Ok(None) => return Poll::Ok(mem::replace(&mut self.buf, Vec::new())),
            Err(e) => return Poll::Err(e)
        }

        let start = self.buf.len();
        match self.a.read_to_end(task, &mut self.buf) {
            // If we get `Ok`, then we know the stream hit EOF, so we're done
            Ok(_) => Poll::Ok(mem::replace(&mut self.buf, Vec::new())),

            // If we hit WouldBlock, then the data we read so far is in the
            // buffer and we just need to wait until we're readable again.
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                debug!("read {} bytes, waiting for more",
                       self.buf.len() - start);
                Poll::NotReady
            }

            Err(e) => Poll::Err(e)
        }
    }

    fn schedule(&mut self, task: &mut Task) {
        self.a.schedule(task)
    }
}
<commit_msg>Need to read at least once in read_to_end<commit_after>use std::io;
use std::mem;

use {Poll, Task, Future};
use io::ReadTask;

pub struct ReadToEnd {
    a: A,
    buf: Vec<u8>,
    first: bool,
}

pub fn read_to_end(a: A, buf: Vec<u8>) -> ReadToEnd
    where A: ReadTask,
{
    ReadToEnd {
        a: a,
        buf: buf,
        first: true,
    }
}

impl Future for ReadToEnd
    where A: ReadTask,
{
    type Item = Vec<u8>;
    type Error = io::Error;

    fn poll(&mut self, task: &mut Task) -> Poll<Vec<u8>, io::Error> {
        // Right now I/O streams are all "edge ready" in the sense that once
        // they emit a readable notification, we may never get another readable
        // notification until all the data there was read out.
        //
        // We don't know what the state of the I/O object passed to this
        // combinator is, so the first time we `poll` we *must* perform a
        // `read`. After we've learned that there's nothing else to read though
        // we can wait for readable notifications from the underlying stream.
        if self.first {
            self.first = false;
        } else {
            match try_poll!(self.a.poll(task)) {
                Ok(Some(ref r)) if r.is_read() => {}
                Ok(Some(r)) => {
                    debug!("notification but not readable {:?}", r);
                    return Poll::NotReady
                }
                Ok(None) => {
                    return Poll::Ok(mem::replace(&mut self.buf, Vec::new()))
                }
                Err(e) => return Poll::Err(e)
            }
        }

        debug!("attempting a read to end");
        let start = self.buf.len();
        match self.a.read_to_end(task, &mut self.buf) {
            // If we get `Ok`, then we know the stream hit EOF, so we're done
            Ok(_) => Poll::Ok(mem::replace(&mut self.buf, Vec::new())),

            // If we hit WouldBlock, then the data we read so far is in the
            // buffer and we just need to wait until we're readable again.
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                debug!("read {} bytes, waiting for more",
                       self.buf.len() - start);
                Poll::NotReady
            }

            Err(e) => Poll::Err(e)
        }
    }

    fn schedule(&mut self, task: &mut Task) {
        self.a.schedule(task)
    }
}
<|endoftext|>


<commit_before>

extern crate cratesfyi;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate time;
extern crate rustwide;

use std::env;
use std::path::{Path, PathBuf};

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, RustwideBuilder, DocBuilderOptions, db};
use cratesfyi::utils::add_crate_to_queue;
use cratesfyi::start_web_server;
use cratesfyi::db::{add_path_into_database, connect_db};

pub fn main() {
    logger_init();

    let matches = App::new("cratesfyi")
        .version(cratesfyi::BUILD_VERSION)
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .subcommand(SubCommand::with_name("build")
            .about("Builds documentation in a chroot environment")
            .arg(Arg::with_name("PREFIX")
                .short("P")
                .long("prefix")
                .takes_value(true))
            .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                .long("crates-io-index-path")
                .help("Sets crates.io-index path")
                .takes_value(true))
            .arg(Arg::with_name("SKIP_IF_EXISTS")
                .short("s")
                .long("skip")
                .help("Skips building documentation if \
                                                      documentation exists"))
            .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                .long("skip-if-log-exists")
                .help("Skips building documentation if build \
                                                      log exists"))
            .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                .short("-k")
                .long("keep-build-directory")
                .help("Keeps build directory after build."))
            .subcommand(SubCommand::with_name("world").about("Builds documentation of every \
                                                              crate"))
            .subcommand(SubCommand::with_name("crate")
                .about("Builds documentation for a crate")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required_unless("LOCAL")
                    .requires("CRATE_VERSION")
                    .help("Crate name"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .help("Version of crate"))
                .arg(Arg::with_name("LOCAL")
                    .short("-l")
                    .long("--local")
                    .takes_value(true)
                    .conflicts_with_all(&["CRATE_NAME", "CRATE_VERSION"])
                    .help("Build a crate at a specific path")))
            .subcommand(SubCommand::with_name("update-toolchain")
                .about("update the curretntly installed rustup toolchain")
                .arg(Arg::with_name("ONLY_FIRST_TIME")
                     .long("only-first-time")
                     .help("update toolchain only if no toolchain is currently installed")))
            .subcommand(SubCommand::with_name("add-essential-files")
                .about("Adds essential files for the installed version of rustc"))
            .subcommand(SubCommand::with_name("lock").about("Locks cratesfyi daemon to stop \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("unlock")
                .about("Unlocks cratesfyi daemon to continue \
                                                              building new crates"))
            .subcommand(SubCommand::with_name("print-options")))
        .subcommand(SubCommand::with_name("start-web-server")
            .about("Starts web server")
            .arg(Arg::with_name("SOCKET_ADDR")
                .index(1)
                .required(false)
                .help("Socket address to listen to")))
        .subcommand(SubCommand::with_name("daemon").about("Starts cratesfyi daemon")
            .arg(Arg::with_name("FOREGROUND")
                .short("-f")
                .long("foreground")
                .help("run the server in the foreground instead of detaching a child")))
        .subcommand(SubCommand::with_name("database")
            .about("Database operations")
            .subcommand(SubCommand::with_name("move-to-s3"))
            .subcommand(SubCommand::with_name("migrate")
                .about("Run database migrations")
                .arg(Arg::with_name("VERSION")))
            .subcommand(SubCommand::with_name("update-github-fields")
                .about("Updates github stats for crates."))
            .subcommand(SubCommand::with_name("add-directory")
                .about("Adds a directory into database")
                .arg(Arg::with_name("DIRECTORY")
                    .index(1)
                    .required(true)
                    .help("Path of file or \
                                                                      directory"))
                .arg(Arg::with_name("PREFIX")
                    .index(2)
                    .help("Prefix of files in \
                                                                      database")))
            .subcommand(SubCommand::with_name("update-release-activity")
                .about("Updates montly release activity \
                                                              chart"))
            .subcommand(SubCommand::with_name("update-search-index")
                .about("Updates search index"))
            .subcommand(SubCommand::with_name("delete-crate")
                .about("Removes a whole crate from the database")
                .arg(Arg::with_name("CRATE_NAME")
                    .takes_value(true)
                    .help("Name of the crate to delete"))))
        .subcommand(SubCommand::with_name("queue")
            .about("Interactions with the build queue")
            .subcommand(SubCommand::with_name("add")
                .about("Add a crate to the build queue")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required(true)
                    .help("Name of crate to build"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .required(true)
                    .help("Version of crate to build"))
                .arg(Arg::with_name("BUILD_PRIORITY")
                    .short("p")
                    .long("priority")
                    .help("Priority of build (default: 5) (new crate builds get priority 0)")
                    .takes_value(true))))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().unwrap();
            builder.build_world(&mut docbuilder).expect("Failed to build world");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().expect("failed to initialize rustwide");
            match matches.value_of("LOCAL") {
                Some(path) => builder.build_local_package(&mut docbuilder, Path::new(path)),
                None => builder.build_package(&mut docbuilder,
                    matches.value_of("CRATE_NAME").unwrap(), matches.value_of("CRATE_VERSION").unwrap(), None),
            }.expect("Building documentation failed");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(m) = matches.subcommand_matches("update-toolchain") {
            if m.is_present("ONLY_FIRST_TIME") {
                let conn = db::connect_db().unwrap();
                let res = conn.query("SELECT * FROM config WHERE name = 'rustc_version';", &[]).unwrap();
                if !res.is_empty() {
                    println!("update-toolchain was already called in the past, exiting");
                    return;
                }
            }
            let mut builder = RustwideBuilder::init().unwrap();
            builder.update_toolchain().expect("failed to update toolchain");
        } else if matches.subcommand_matches("add-essential-files").is_some() {
            let mut builder = RustwideBuilder::init().unwrap();
            builder.add_essential_files().expect("failed to add essential files");
        } else if let Some(_) = matches.subcommand_matches("lock") {
            docbuilder.lock().expect("Failed to lock");
        } else if let Some(_) = matches.subcommand_matches("unlock") {
            docbuilder.unlock().expect("Failed to unlock");
        } else if let Some(_) = matches.subcommand_matches("print-options") {
            println!("{:?}", docbuilder.options());
        }

    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(matches) = matches.subcommand_matches("migrate") {
            let version = matches.value_of("VERSION").map(|v| v.parse::<i64>()
                                                          .expect("Version should be an integer"));
            db::migrate(version, &connect_db().expect("failed to connect to the database"))
                .expect("Failed to run database migrations");
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        } else if let Some(matches) = matches.subcommand_matches("add-directory") {
            add_path_into_database(&db::connect_db().unwrap(),
                                   matches.value_of("PREFIX").unwrap_or(""),
                                   matches.value_of("DIRECTORY").unwrap())
                .expect("Failed to add directory into database");
        } else if let Some(_) = matches.subcommand_matches("update-release-activity") {
            // FIXME: This is actually util command not database
            cratesfyi::utils::update_release_activity().expect("Failed to update release activity");
        } else if let Some(_) = matches.subcommand_matches("update-search-index") {
            let conn = db::connect_db().unwrap();
            db::update_search_index(&conn).expect("Failed to update search index");
        } else if let Some(_) = matches.subcommand_matches("move-to-s3") {
            let conn = db::connect_db().unwrap();
            let mut count = 1;
            let mut total = 0;
            while count != 0 {
                count = db::file::move_to_s3(&conn, 5_000).expect("Failed to upload batch to S3");
                total += count;
                eprintln!(
                    "moved {} rows to s3 in this batch, total moved so far: {}",
                    count, total
                );
            }
        } else if let Some(matches) = matches.subcommand_matches("delete-crate") {
            let name = matches.value_of("CRATE_NAME").expect("missing crate name");
            let conn = db::connect_db().expect("failed to connect to the database");
            db::delete_crate(&conn, &name).expect("failed to delete the crate");
        }
    } else if let Some(matches) = matches.subcommand_matches("start-web-server") {
        start_web_server(Some(matches.value_of("SOCKET_ADDR").unwrap_or("0.0.0.0:3000")));
    } else if let Some(_) = matches.subcommand_matches("daemon") {
        let foreground = matches.subcommand_matches("daemon")
            .map_or(false, |opts| opts.is_present("FOREGROUND"));
        cratesfyi::utils::start_daemon(!foreground);
    } else if let Some(matches) = matches.subcommand_matches("queue") {
        if let Some(matches) = matches.subcommand_matches("add") {
            let priority = matches.value_of("BUILD_PRIORITY").unwrap_or("5");
            let priority: i32 = priority.parse().expect("--priority was not a number");
            let conn = connect_db().expect("Could not connect to database");

            add_crate_to_queue(&conn,
                               matches.value_of("CRATE_NAME").unwrap(),
                               matches.value_of("CRATE_VERSION").unwrap(),
                               priority).expect("Could not add crate to queue");
        }
    } else {
        println!("{}", matches.usage());
    }
}

fn logger_init() {
    use std::io::Write;

    let mut builder = env_logger::Builder::new();
    builder.format(|buf, record| {
        writeln!(buf, "{} [{}] {}: {}",
                time::now().strftime("%Y/%m/%d %H:%M:%S").unwrap(),
                record.level(),
                record.target(),
                record.args())
    });
    builder.parse(&env::var("RUST_LOG").unwrap_or("cratesfyi=info".to_owned()));

    rustwide::logging::init_with(builder.build());
}
<commit_msg>cratesfyi.rs: improve formatting<commit_after>

extern crate cratesfyi;
extern crate clap;
extern crate log;
extern crate env_logger;
extern crate time;
extern crate rustwide;

use std::env;
use std::path::{Path, PathBuf};

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, RustwideBuilder, DocBuilderOptions, db};
use cratesfyi::utils::add_crate_to_queue;
use cratesfyi::start_web_server;
use cratesfyi::db::{add_path_into_database, connect_db};

pub fn main() {
    logger_init();

    let matches = App::new("cratesfyi")
        .version(cratesfyi::BUILD_VERSION)
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .subcommand(SubCommand::with_name("build")
            .about("Builds documentation in a chroot environment")
            .arg(Arg::with_name("PREFIX")
                .short("P")
                .long("prefix")
                .takes_value(true))
            .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                .long("crates-io-index-path")
                .help("Sets crates.io-index path")
                .takes_value(true))
            .arg(Arg::with_name("SKIP_IF_EXISTS")
                .short("s")
                .long("skip")
                .help("Skips building documentation if documentation exists"))
            .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                .long("skip-if-log-exists")
                .help("Skips building documentation if build log exists"))
            .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                .short("-k")
                .long("keep-build-directory")
                .help("Keeps build directory after build."))
            .subcommand(SubCommand::with_name("world")
                .about("Builds documentation of every crate"))
            .subcommand(SubCommand::with_name("crate")
                .about("Builds documentation for a crate")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required_unless("LOCAL")
                    .requires("CRATE_VERSION")
                    .help("Crate name"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .help("Version of crate"))
                .arg(Arg::with_name("LOCAL")
                    .short("-l")
                    .long("--local")
                    .takes_value(true)
                    .conflicts_with_all(&["CRATE_NAME", "CRATE_VERSION"])
                    .help("Build a crate at a specific path")))
            .subcommand(SubCommand::with_name("update-toolchain")
                .about("update the curretntly installed rustup toolchain")
                .arg(Arg::with_name("ONLY_FIRST_TIME")
                     .long("only-first-time")
                     .help("update toolchain only if no toolchain is currently installed")))
            .subcommand(SubCommand::with_name("add-essential-files")
                .about("Adds essential files for the installed version of rustc"))
            .subcommand(SubCommand::with_name("lock")
                .about("Locks cratesfyi daemon to stop building new crates"))
            .subcommand(SubCommand::with_name("unlock")
                .about("Unlocks cratesfyi daemon to continue building new crates"))
            .subcommand(SubCommand::with_name("print-options")))
        .subcommand(SubCommand::with_name("start-web-server")
            .about("Starts web server")
            .arg(Arg::with_name("SOCKET_ADDR")
                .index(1)
                .required(false)
                .help("Socket address to listen to")))
        .subcommand(SubCommand::with_name("daemon")
            .about("Starts cratesfyi daemon")
            .arg(Arg::with_name("FOREGROUND")
                .short("-f")
                .long("foreground")
                .help("run the server in the foreground instead of detaching a child")))
        .subcommand(SubCommand::with_name("database")
            .about("Database operations")
            .subcommand(SubCommand::with_name("move-to-s3"))
            .subcommand(SubCommand::with_name("migrate")
                .about("Run database migrations")
                .arg(Arg::with_name("VERSION")))
            .subcommand(SubCommand::with_name("update-github-fields")
                .about("Updates github stats for crates."))
            .subcommand(SubCommand::with_name("add-directory")
                .about("Adds a directory into database")
                .arg(Arg::with_name("DIRECTORY")
                    .index(1)
                    .required(true)
                    .help("Path of file or directory"))
                .arg(Arg::with_name("PREFIX")
                    .index(2)
                    .help("Prefix of files in database")))
            .subcommand(SubCommand::with_name("update-release-activity")
                .about("Updates monthly release activity chart"))
            .subcommand(SubCommand::with_name("update-search-index")
                .about("Updates search index"))
            .subcommand(SubCommand::with_name("delete-crate")
                .about("Removes a whole crate from the database")
                .arg(Arg::with_name("CRATE_NAME")
                    .takes_value(true)
                    .help("Name of the crate to delete"))))
        .subcommand(SubCommand::with_name("queue")
            .about("Interactions with the build queue")
            .subcommand(SubCommand::with_name("add")
                .about("Add a crate to the build queue")
                .arg(Arg::with_name("CRATE_NAME")
                    .index(1)
                    .required(true)
                    .help("Name of crate to build"))
                .arg(Arg::with_name("CRATE_VERSION")
                    .index(2)
                    .required(true)
                    .help("Version of crate to build"))
                .arg(Arg::with_name("BUILD_PRIORITY")
                    .short("p")
                    .long("priority")
                    .help("Priority of build (default: 5) (new crate builds get priority 0)")
                    .takes_value(true))))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().unwrap();
            builder.build_world(&mut docbuilder).expect("Failed to build world");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.load_cache().expect("Failed to load cache");
            let mut builder = RustwideBuilder::init().expect("failed to initialize rustwide");
            match matches.value_of("LOCAL") {
                Some(path) => builder.build_local_package(&mut docbuilder, Path::new(path)),
                None => builder.build_package(&mut docbuilder,
                    matches.value_of("CRATE_NAME").unwrap(), matches.value_of("CRATE_VERSION").unwrap(), None),
            }.expect("Building documentation failed");
            docbuilder.save_cache().expect("Failed to save cache");
        } else if let Some(m) = matches.subcommand_matches("update-toolchain") {
            if m.is_present("ONLY_FIRST_TIME") {
                let conn = db::connect_db().unwrap();
                let res = conn.query("SELECT * FROM config WHERE name = 'rustc_version';", &[]).unwrap();
                if !res.is_empty() {
                    println!("update-toolchain was already called in the past, exiting");
                    return;
                }
            }
            let mut builder = RustwideBuilder::init().unwrap();
            builder.update_toolchain().expect("failed to update toolchain");
        } else if matches.subcommand_matches("add-essential-files").is_some() {
            let mut builder = RustwideBuilder::init().unwrap();
            builder.add_essential_files().expect("failed to add essential files");
        } else if let Some(_) = matches.subcommand_matches("lock") {
            docbuilder.lock().expect("Failed to lock");
        } else if let Some(_) = matches.subcommand_matches("unlock") {
            docbuilder.unlock().expect("Failed to unlock");
        } else if let Some(_) = matches.subcommand_matches("print-options") {
            println!("{:?}", docbuilder.options());
        }

    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(matches) = matches.subcommand_matches("migrate") {
            let version = matches.value_of("VERSION").map(|v| v.parse::<i64>()
                                                          .expect("Version should be an integer"));
            db::migrate(version, &connect_db().expect("failed to connect to the database"))
                .expect("Failed to run database migrations");
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        } else if let Some(matches) = matches.subcommand_matches("add-directory") {
            add_path_into_database(&db::connect_db().unwrap(),
                                   matches.value_of("PREFIX").unwrap_or(""),
                                   matches.value_of("DIRECTORY").unwrap())
                .expect("Failed to add directory into database");
        } else if let Some(_) = matches.subcommand_matches("update-release-activity") {
            // FIXME: This is actually util command not database
            cratesfyi::utils::update_release_activity().expect("Failed to update release activity");
        } else if let Some(_) = matches.subcommand_matches("update-search-index") {
            let conn = db::connect_db().unwrap();
            db::update_search_index(&conn).expect("Failed to update search index");
        } else if let Some(_) = matches.subcommand_matches("move-to-s3") {
            let conn = db::connect_db().unwrap();
            let mut count = 1;
            let mut total = 0;
            while count != 0 {
                count = db::file::move_to_s3(&conn, 5_000).expect("Failed to upload batch to S3");
                total += count;
                eprintln!(
                    "moved {} rows to s3 in this batch, total moved so far: {}",
                    count, total
                );
            }
        } else if let Some(matches) = matches.subcommand_matches("delete-crate") {
            let name = matches.value_of("CRATE_NAME").expect("missing crate name");
            let conn = db::connect_db().expect("failed to connect to the database");
            db::delete_crate(&conn, &name).expect("failed to delete the crate");
        }
    } else if let Some(matches) = matches.subcommand_matches("start-web-server") {
        start_web_server(Some(matches.value_of("SOCKET_ADDR").unwrap_or("0.0.0.0:3000")));
    } else if let Some(_) = matches.subcommand_matches("daemon") {
        let foreground = matches.subcommand_matches("daemon")
            .map_or(false, |opts| opts.is_present("FOREGROUND"));
        cratesfyi::utils::start_daemon(!foreground);
    } else if let Some(matches) = matches.subcommand_matches("queue") {
        if let Some(matches) = matches.subcommand_matches("add") {
            let priority = matches.value_of("BUILD_PRIORITY").unwrap_or("5");
            let priority: i32 = priority.parse().expect("--priority was not a number");
            let conn = connect_db().expect("Could not connect to database");

            add_crate_to_queue(&conn,
                               matches.value_of("CRATE_NAME").unwrap(),
                               matches.value_of("CRATE_VERSION").unwrap(),
                               priority).expect("Could not add crate to queue");
        }
    } else {
        println!("{}", matches.usage());
    }
}

fn logger_init() {
    use std::io::Write;

    let mut builder = env_logger::Builder::new();
    builder.format(|buf, record| {
        writeln!(buf, "{} [{}] {}: {}",
                time::now().strftime("%Y/%m/%d %H:%M:%S").unwrap(),
                record.level(),
                record.target(),
                record.args())
    });
    builder.parse(&env::var("RUST_LOG").unwrap_or("cratesfyi=info".to_owned()));

    rustwide::logging::init_with(builder.build());
}
<|endoftext|>


<commit_before>// Copyright (C) 2016, 2017, 2018 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use crate::helpers::*;

use yaml_rust::Yaml;
use console;
use crowbook::{Result, Book, BookOptions};
use crowbook_intl_runtime::set_lang;
use crowbook::Stats;
use tempdir::TempDir;
use clap::ArgMatches;
use std::process::exit;
use std::io;
use std::io::Read;
use std::env;
use std::fs::File;
use simplelog::{Config, TermLogger, Level, LevelFilter, SimpleLogger, WriteLogger};

/// Render a book to specific format
fn render_format(book: &mut Book, emoji: bool, matches: &ArgMatches, format: &str) {
    let mut key = String::from("output.");
    key.push_str(format);

    let mut stdout = false;
    let mut file = None;

    if let Some(f) = matches.value_of("output") {
        if f == "-" {
            stdout = true;
        } else {
            file = Some(String::from(f));
        }
    }

    let res = book.options.get_path(&key);

    let result = match(file, res, stdout) {
        (Some(file), _, _) |
        (None, Ok(file), false) => book.render_format_to_file(format, file),

        (None, Err(_), _) |
        (None, _, true)
        => book.render_format_to(format, &mut io::stdout()),
    };

    match result {
        Err(err) => print_error(&format!("{}", err), emoji),
        Ok(_) => {}
    }
}

pub fn try_main() -> Result<()> {
    let lang = get_lang()
        .or_else(|| {
            match env::var("LANG") {
                Ok(val) => {
                    Some(val)
                },
                Err(_) => None,
            }
        });
    if let Some(val) = lang {
        if val.starts_with("fr") {
            set_lang("fr");
        } else {
            set_lang("en");
        }
    }

    let mut fancy_ui = true;
    let mut emoji = console::Term::stderr().features().wants_emoji();

    let (matches, help, version) = create_matches();

    if matches.is_present("force-emoji") {
        emoji = true;
    }

    if !matches.is_present("quiet") {
        display_header(emoji);
    }

    if matches.is_present("list-options") {
        println!("{}", BookOptions::description(false));
        exit(0);
    }

    if matches.is_present("no-fancy") || matches.is_present("stats") {
        fancy_ui = false;
        emoji = false;
    }

    if matches.is_present("list-options-md") {
        println!("{}", BookOptions::description(true));
        exit(0);
    }

    if matches.is_present("print-template") {
        let template = matches.value_of("print-template").unwrap();
        let mut book = Book::new();
        set_book_options(&mut book, &matches);
        let result = book.get_template(template.as_ref());
        match result {
            Ok(s) => {
                println!("{}", s);
                exit(0);
            }
            Err(_) => print_error_and_exit(&lformat!("{} is not a valid template name.",
                                                     template),
                                           emoji),
        }
    }

    if matches.is_present("help") {
        println!("{}", help);
        exit(0);
    }

    if matches.is_present("version") {
        println!("{}", version);
        exit(0);
    }

    if matches.is_present("create") {
        create_book(&matches);
    }

    if !matches.is_present("BOOK") {
        print_error_and_exit(&lformat!("You must pass the file of a book configuration \
                               file.\n\n{}\n\nFor more information try --help.",
                                       matches.usage()),
                             emoji);
    }

    // ok to unwrap since clap checks it's there
    let s = matches.value_of("BOOK").unwrap();

    // Initalize logger
    let mut log_config = Config::default();
    log_config.target = None;
    log_config.location = None;
    log_config.time = None;
    let verbosity = if matches.is_present("verbose") && !matches.is_present("stats") {
        log_config.time = Some(Level::Error);
        log_config.target = Some(Level::Error);
        fancy_ui = false;
        LevelFilter::Debug
    } else if matches.is_present("quiet") {
        fancy_ui = false;
        LevelFilter::Error
    } else if fancy_ui {
        LevelFilter::Warn
    } else {
        LevelFilter::Info
    };

    let error_dir = TempDir::new("crowbook").unwrap();
    let error_path = "error.log";
    if fancy_ui {
        let errors = File::create(error_dir.path().join(error_path)).unwrap();
        let _ = WriteLogger::init(verbosity, log_config, errors);
    } else {
        if TermLogger::init(verbosity, log_config, simplelog::TerminalMode::Stderr).is_err() {
            // If it failed, not much we can do, we just won't display log
            let _ = SimpleLogger::init(verbosity, log_config);
        }
    }

    {
        let mut book = Book::new();
        if matches.is_present("autograph") {
            println!("{}", &lformat!("Enter autograph: "));
            let mut autograph = String::new();
            match io::stdin().read_to_string(&mut autograph) {
                Ok(_) => {
                    book.options.set_yaml(Yaml::String("autograph".to_string()), Yaml::String(autograph)).unwrap();
                },
                Err(_) => print_error(&lformat!("could not read autograph from stdin"), emoji),
            }
        }

        if fancy_ui {
            book.add_progress_bar(emoji);
        }
        book.set_options(&get_book_options(&matches));

        {
            let res = if matches.is_present("single") {
                if s != "-" {
                    book.load_markdown_file(s)
                } else {
                    book.read_markdown_config(io::stdin())
                }
            } else if s != "-" {
                book.load_file(s)
            } else {
                book.read_config(io::stdin())
            }.map(|_| ());

            match res {
                Ok(..) => {},
                Err(err) => {
                    book.set_error(&format!("{}", err));
                    return Err(err);
                }
            }
        }

        set_book_options(&mut book, &matches);

        if matches.is_present("stats") {
            let stats = Stats::new(&book, matches.is_present("verbose"));
            println!("{}", stats);
            exit(0);
        }

        if let Some(format) = matches.value_of("to") {
            render_format(&mut book, emoji,& matches, format);
        } else {
            book.render_all();
        }
    }
    if fancy_ui {
        let mut errors = String::new();
        let mut file = File::open(error_dir.path().join(error_path)).unwrap();
        file.read_to_string(&mut errors).unwrap();
        if !errors.is_empty() {
            print_warning(&lformat!("Crowbook exited successfully, but the following errors occurred:"),
                          emoji);
            // Non-efficient dedup algorithm but we need to keep the order
            let mut lines: Vec<String> = vec!();
            for line in errors.lines().into_iter() {
                let mut contains = false;
                for l in &lines {
                    if &*l == line {
                        contains = true;
                        break;
                    }
                }
                if !contains {
                    lines.push(line.to_string());
                }
            }
            for line in &lines {
                if line.starts_with("[ERROR]") {
                    let line = &line[8..];
                    print_error(line, emoji);
                } else if line.starts_with("[WARN]") {
                    let line = &line[7..];
                    print_warning(line, emoji);
                }
            }
        }
    }

    Ok(())
}

pub fn real_main() {
    if let Err(err) = try_main() {
        print_error_and_exit(&format!("{}", err), false);
    }
}
<commit_msg>Fix display of warnings/errors when using indicatif<commit_after>// Copyright (C) 2016, 2017, 2018, 2019 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use crate::helpers::*;

use yaml_rust::Yaml;
use console;
use crowbook::{Result, Book, BookOptions};
use crowbook_intl_runtime::set_lang;
use crowbook::Stats;
use tempdir::TempDir;
use clap::ArgMatches;
use std::process::exit;
use std::io;
use std::io::Read;
use std::env;
use std::fs::File;
use simplelog::{Config, TermLogger, Level, LevelFilter, SimpleLogger, WriteLogger};

/// Render a book to specific format
fn render_format(book: &mut Book, emoji: bool, matches: &ArgMatches, format: &str) {
    let mut key = String::from("output.");
    key.push_str(format);

    let mut stdout = false;
    let mut file = None;

    if let Some(f) = matches.value_of("output") {
        if f == "-" {
            stdout = true;
        } else {
            file = Some(String::from(f));
        }
    }

    let res = book.options.get_path(&key);

    let result = match(file, res, stdout) {
        (Some(file), _, _) |
        (None, Ok(file), false) => book.render_format_to_file(format, file),

        (None, Err(_), _) |
        (None, _, true)
        => book.render_format_to(format, &mut io::stdout()),
    };

    match result {
        Err(err) => print_error(&format!("{}", err), emoji),
        Ok(_) => {}
    }
}

pub fn try_main() -> Result<()> {
    let lang = get_lang()
        .or_else(|| {
            match env::var("LANG") {
                Ok(val) => {
                    Some(val)
                },
                Err(_) => None,
            }
        });
    if let Some(val) = lang {
        if val.starts_with("fr") {
            set_lang("fr");
        } else {
            set_lang("en");
        }
    }

    let mut fancy_ui = true;
    let mut emoji = console::Term::stderr().features().wants_emoji();

    let (matches, help, version) = create_matches();

    if matches.is_present("force-emoji") {
        emoji = true;
    }

    if !matches.is_present("quiet") {
        display_header(emoji);
    }

    if matches.is_present("list-options") {
        println!("{}", BookOptions::description(false));
        exit(0);
    }

    if matches.is_present("no-fancy") || matches.is_present("stats") {
        fancy_ui = false;
        emoji = false;
    }

    if matches.is_present("list-options-md") {
        println!("{}", BookOptions::description(true));
        exit(0);
    }

    if matches.is_present("print-template") {
        let template = matches.value_of("print-template").unwrap();
        let mut book = Book::new();
        set_book_options(&mut book, &matches);
        let result = book.get_template(template.as_ref());
        match result {
            Ok(s) => {
                println!("{}", s);
                exit(0);
            }
            Err(_) => print_error_and_exit(&lformat!("{} is not a valid template name.",
                                                     template),
                                           emoji),
        }
    }

    if matches.is_present("help") {
        println!("{}", help);
        exit(0);
    }

    if matches.is_present("version") {
        println!("{}", version);
        exit(0);
    }

    if matches.is_present("create") {
        create_book(&matches);
    }

    if !matches.is_present("BOOK") {
        print_error_and_exit(&lformat!("You must pass the file of a book configuration \
                               file.\n\n{}\n\nFor more information try --help.",
                                       matches.usage()),
                             emoji);
    }

    // ok to unwrap since clap checks it's there
    let s = matches.value_of("BOOK").unwrap();

    // Initalize logger
    let mut log_config = Config::default();
    log_config.target = None;
    log_config.location = None;
    log_config.time = None;
    let verbosity = if matches.is_present("verbose") && !matches.is_present("stats") {
        log_config.time = Some(Level::Error);
        log_config.target = Some(Level::Error);
        fancy_ui = false;
        LevelFilter::Debug
    } else if matches.is_present("quiet") {
        fancy_ui = false;
        LevelFilter::Error
    } else if fancy_ui {
        LevelFilter::Warn
    } else {
        LevelFilter::Info
    };

    let error_dir = TempDir::new("crowbook").unwrap();
    let error_path = "error.log";
    if fancy_ui {
        let errors = File::create(error_dir.path().join(error_path)).unwrap();
        let _ = WriteLogger::init(verbosity, log_config, errors);
    } else {
        if TermLogger::init(verbosity, log_config, simplelog::TerminalMode::Stderr).is_err() {
            // If it failed, not much we can do, we just won't display log
            let _ = SimpleLogger::init(verbosity, log_config);
        }
    }

    {
        let mut book = Book::new();
        if matches.is_present("autograph") {
            println!("{}", &lformat!("Enter autograph: "));
            let mut autograph = String::new();
            match io::stdin().read_to_string(&mut autograph) {
                Ok(_) => {
                    book.options.set_yaml(Yaml::String("autograph".to_string()), Yaml::String(autograph)).unwrap();
                },
                Err(_) => print_error(&lformat!("could not read autograph from stdin"), emoji),
            }
        }

        if fancy_ui {
            book.add_progress_bar(emoji);
        }
        book.set_options(&get_book_options(&matches));

        {
            let res = if matches.is_present("single") {
                if s != "-" {
                    book.load_markdown_file(s)
                } else {
                    book.read_markdown_config(io::stdin())
                }
            } else if s != "-" {
                book.load_file(s)
            } else {
                book.read_config(io::stdin())
            }.map(|_| ());

            match res {
                Ok(..) => {},
                Err(err) => {
                    book.set_error(&format!("{}", err));
                    return Err(err);
                }
            }
        }

        set_book_options(&mut book, &matches);

        if matches.is_present("stats") {
            let stats = Stats::new(&book, matches.is_present("verbose"));
            println!("{}", stats);
            exit(0);
        }

        if let Some(format) = matches.value_of("to") {
            render_format(&mut book, emoji,& matches, format);
        } else {
            book.render_all();
        }
    }
    if fancy_ui {
        let mut errors = String::new();
        let mut file = File::open(error_dir.path().join(error_path)).unwrap();
        file.read_to_string(&mut errors).unwrap();
        if !errors.is_empty() {
            print_warning(&lformat!("Crowbook exited successfully, but the following errors occurred:"),
                          emoji);
            // Non-efficient dedup algorithm but we need to keep the order
            let mut lines: Vec<String> = vec!();
            for line in errors.lines().into_iter() {
                let mut contains = false;
                for l in &lines {
                    if &*l == line {
                        contains = true;
                        break;
                    }
                }
                if !contains {
                    lines.push(line.to_string());
                }
            }
            for line in &lines {
                if line.starts_with("[ ERROR]") {
                    let line = &line[9..];
                    print_error(line, emoji);
                } else if line.starts_with("[ WARN]") {
                    let line = &line[8..];
                    print_warning(line, emoji);
                }
            }
        }
    }

    Ok(())
}

pub fn real_main() {
    if let Err(err) = try_main() {
        print_error_and_exit(&format!("{}", err), false);
    }
}
<|endoftext|>


<commit_before>//! Command pools

use crate::command::{
    CommandBuffer, IntoRawCommandBuffer, RawLevel, SecondaryCommandBuffer, Shot,
    SubpassCommandBuffer,
};
use crate::queue::capability::{Graphics, Supports};
use crate::Backend;

use std::any::Any;
use std::marker::PhantomData;

bitflags!(
    /// Command pool creation flags.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub struct CommandPoolCreateFlags: u8 {
        /// Indicates short-lived command buffers.
        /// Memory optimization hint for implementations.
        const TRANSIENT = 0x1;
        /// Allow command buffers to be reset individually.
        const RESET_INDIVIDUAL = 0x2;
    }
);

/// The allocated command buffers are associated with the creating command queue.
pub trait RawCommandPool<B: Backend>: Any + Send + Sync {
    /// Reset the command pool and the corresponding command buffers.
    ///
    /// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
    unsafe fn reset(&mut self);

    /// Allocate a single command buffers from the pool.
    fn allocate_one(&mut self, level: RawLevel) -> B::CommandBuffer {
        self.allocate_vec(1, level).pop().unwrap()
    }

    /// Allocate new command buffers from the pool.
    fn allocate_vec(&mut self, num: usize, level: RawLevel) -> Vec<B::CommandBuffer> {
        (0..num).map(|_| self.allocate_one(level)).collect()
    }

    /// Free command buffers which are allocated from this pool.
    unsafe fn free<I>(&mut self, buffers: I)
    where
        I: IntoIterator<Item = B::CommandBuffer>;
}

/// Strong-typed command pool.
pub struct CommandPool<B: Backend, C> {
    raw: B::CommandPool,
    _capability: PhantomData<C>,
}

impl<B: Backend, C> CommandPool<B, C> {
    /// Create typed command pool from raw.
    ///
    /// # Safety
    ///
    /// `<C as Capability>::supported_by(queue_type)` must return true
    /// for `queue_type` being the type of queues from family this `raw` pool is associated with.
    ///
    pub unsafe fn new(raw: B::CommandPool) -> Self {
        CommandPool {
            raw,
            _capability: PhantomData,
        }
    }

    /// Reset the command pool and the corresponding command buffers.
    ///
    /// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
    pub unsafe fn reset(&mut self) {
        self.raw.reset();
    }

    /// Allocates a new primary command buffer from the pool.
    pub fn acquire_command_buffer<S: Shot>(&mut self) -> CommandBuffer<B, C, S> {
        let buffer = self.raw.allocate_one(RawLevel::Primary);
        unsafe { CommandBuffer::new(buffer) }
    }

    /// Allocates a new secondary command buffer from the pool.
    pub fn acquire_secondary_command_buffer<S: Shot>(&mut self) -> SecondaryCommandBuffer<B, C, S> {
        let buffer = self.raw.allocate_one(RawLevel::Secondary);
        unsafe { SecondaryCommandBuffer::new(buffer) }
    }

    /// Free the given iterator of command buffers from the pool.
    pub unsafe fn free<I>(&mut self, cmd_buffers: I)
    where
        I: IntoIterator,
        I::Item: IntoRawCommandBuffer<B, C>,
    {
        self.raw
            .free(cmd_buffers.into_iter().map(|cmb| cmb.into_raw()))
    }

    /// Downgrade a typed command pool to untyped one.
    pub fn into_raw(self) -> B::CommandPool {
        self.raw
    }
}

impl<B: Backend, C: Supports<Graphics>> CommandPool<B, C> {
    /// Allocates a new subpass command buffer from the pool.
    pub fn acquire_subpass_command_buffer<'a, S: Shot>(&mut self) -> SubpassCommandBuffer<B, S> {
        let buffer = self.raw.allocate_one(RawLevel::Secondary);
        unsafe { SubpassCommandBuffer::new(buffer) }
    }
}
<commit_msg>[hal] remove unused lifetimes<commit_after>//! Command pools

use crate::command::{
    CommandBuffer, IntoRawCommandBuffer, RawLevel, SecondaryCommandBuffer, Shot,
    SubpassCommandBuffer,
};
use crate::queue::capability::{Graphics, Supports};
use crate::Backend;

use std::any::Any;
use std::marker::PhantomData;

bitflags!(
    /// Command pool creation flags.
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub struct CommandPoolCreateFlags: u8 {
        /// Indicates short-lived command buffers.
        /// Memory optimization hint for implementations.
        const TRANSIENT = 0x1;
        /// Allow command buffers to be reset individually.
        const RESET_INDIVIDUAL = 0x2;
    }
);

/// The allocated command buffers are associated with the creating command queue.
pub trait RawCommandPool<B: Backend>: Any + Send + Sync {
    /// Reset the command pool and the corresponding command buffers.
    ///
    /// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
    unsafe fn reset(&mut self);

    /// Allocate a single command buffers from the pool.
    fn allocate_one(&mut self, level: RawLevel) -> B::CommandBuffer {
        self.allocate_vec(1, level).pop().unwrap()
    }

    /// Allocate new command buffers from the pool.
    fn allocate_vec(&mut self, num: usize, level: RawLevel) -> Vec<B::CommandBuffer> {
        (0..num).map(|_| self.allocate_one(level)).collect()
    }

    /// Free command buffers which are allocated from this pool.
    unsafe fn free<I>(&mut self, buffers: I)
    where
        I: IntoIterator<Item = B::CommandBuffer>;
}

/// Strong-typed command pool.
pub struct CommandPool<B: Backend, C> {
    raw: B::CommandPool,
    _capability: PhantomData<C>,
}

impl<B: Backend, C> CommandPool<B, C> {
    /// Create typed command pool from raw.
    ///
    /// # Safety
    ///
    /// `<C as Capability>::supported_by(queue_type)` must return true
    /// for `queue_type` being the type of queues from family this `raw` pool is associated with.
    ///
    pub unsafe fn new(raw: B::CommandPool) -> Self {
        CommandPool {
            raw,
            _capability: PhantomData,
        }
    }

    /// Reset the command pool and the corresponding command buffers.
    ///
    /// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
    pub unsafe fn reset(&mut self) {
        self.raw.reset();
    }

    /// Allocates a new primary command buffer from the pool.
    pub fn acquire_command_buffer<S: Shot>(&mut self) -> CommandBuffer<B, C, S> {
        let buffer = self.raw.allocate_one(RawLevel::Primary);
        unsafe { CommandBuffer::new(buffer) }
    }

    /// Allocates a new secondary command buffer from the pool.
    pub fn acquire_secondary_command_buffer<S: Shot>(&mut self) -> SecondaryCommandBuffer<B, C, S> {
        let buffer = self.raw.allocate_one(RawLevel::Secondary);
        unsafe { SecondaryCommandBuffer::new(buffer) }
    }

    /// Free the given iterator of command buffers from the pool.
    pub unsafe fn free<I>(&mut self, cmd_buffers: I)
    where
        I: IntoIterator,
        I::Item: IntoRawCommandBuffer<B, C>,
    {
        self.raw
            .free(cmd_buffers.into_iter().map(|cmb| cmb.into_raw()))
    }

    /// Downgrade a typed command pool to untyped one.
    pub fn into_raw(self) -> B::CommandPool {
        self.raw
    }
}

impl<B: Backend, C: Supports<Graphics>> CommandPool<B, C> {
    /// Allocates a new subpass command buffer from the pool.
    pub fn acquire_subpass_command_buffer<S: Shot>(&mut self) -> SubpassCommandBuffer<B, S> {
        let buffer = self.raw.allocate_one(RawLevel::Secondary);
        unsafe { SubpassCommandBuffer::new(buffer) }
    }
}
<|endoftext|>


<commit_before>extern crate arguments;
extern crate temporary;

use std::collections::HashMap;
use std::fmt::Display;
use std::fs::File;
use std::io::{Read, Write};
use std::process::{Command, Stdio};
use temporary::Directory;

const USAGE: &'static str = "
Usage: cite [options]

Options:
    --bib <FILE>       A bibliography file (required).
    --ref <NAME>       A reference name (required).
    --tex <FILE>       A template file.

    --help             Display this message.
";

const TEMPLATE: &'static str = r#"
\documentclass[journal]{IEEEtran}
\pagestyle{empty}
\renewcommand{\refname}{}

\begin{document}
\nocite{<reference>}
\bibliography{IEEEabrv,<bibliography>}
\bibliographystyle{IEEEtran}
\end{document}
"#;

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => raise!(error),
    });
);

macro_rules! raise(
    ($error:expr) => (return Err(Box::new($error)));
    ($($arg:tt)*) => (raise!(format!($($arg)*)));
);

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

fn main() {
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = match arguments::parse(std::env::args()) {
        Ok(arguments) => arguments,
        Err(error) => raise!(error),
    };

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }

    let bibliography = match arguments.get::<String>("bib") {
        Some(bibliography) => bibliography,
        _ => raise!("a bibliography file is required"),
    };
    let reference = match arguments.get::<String>("ref") {
        Some(reference) => reference,
        _ => raise!("a reference name is required"),
    };

    match arguments.get::<String>("tex") {
        Some(ref template) => {
            let mut file = ok!(File::open(template));
            let mut template = String::new();
            ok!(file.read_to_string(&mut template));
            process(&template, &bibliography, &reference)
        },
        _ => {
            process(TEMPLATE, &bibliography, &reference)
        },
    }
}

fn process(template: &str, bibliography: &str, reference: &str) -> Result<()> {
    let root = ok!(Directory::new("cite"));

    macro_rules! cmd(
        ($command:expr) => (
            Command::new($command).current_dir(&root)
                                  .stdout(Stdio::null())
                                  .stderr(Stdio::null())
        );
    );
    macro_rules! run(
        ($command:expr) => ({
            let status = ok!($command.status());
            if !status.success() {
                raise!(status);
            }
        });
    );

    {
        let mut map = HashMap::new();
        map.insert("<bibliography>", bibliography);
        map.insert("<reference>", reference);
        let tex = replace(template, &map);

        let mut file = ok!(File::create(root.join("paper.tex")));
        ok!(file.write_all(tex.as_bytes()));
    }

    run!(cmd!("latex").arg("paper.tex"));
    run!(cmd!("bibtex").arg("paper"));
    run!(cmd!("latex").arg("paper.tex"));
    run!(cmd!("latex").arg("paper.tex"));
    run!(cmd!("dvipdf").arg("paper.dvi"));
    run!(cmd!("pdftotext").arg("paper.pdf"));

    let mut buffer = Vec::new();
    {
        let mut file = ok!(File::open(root.join("paper.txt")));
        ok!(file.read_to_end(&mut buffer));
    }

    let content = String::from_utf8_lossy(&buffer);
    println!("{}", content.trim());

    Ok(())
}

fn replace(text: &str, map: &HashMap<&str, &str>) -> String {
    let mut text = text.to_string();
    for (key, value) in map {
        text = text.replace(key, value);
    }
    text
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: Error) -> ! {
    use std::io::{stderr, Write};
    let message = format!("Error: {}.\n{}", &*error, USAGE);
    stderr().write_all(message.as_bytes()).unwrap();
    std::process::exit(1);
}
<commit_msg>Show the output when a command fails<commit_after>extern crate arguments;
extern crate temporary;

use std::collections::HashMap;
use std::fmt::Display;
use std::fs::File;
use std::io::{stderr, stdout, Read, Write};
use std::process::Command;
use temporary::Directory;

const USAGE: &'static str = "
Usage: cite [options]

Options:
    --bib <FILE>       A bibliography file (required).
    --ref <NAME>       A reference name (required).
    --tex <FILE>       A template file.

    --help             Display this message.
";

const TEMPLATE: &'static str = r#"
\documentclass[journal]{IEEEtran}
\pagestyle{empty}
\renewcommand{\refname}{}

\begin{document}
\nocite{<reference>}
\bibliography{IEEEabrv,<bibliography>}
\bibliographystyle{IEEEtran}
\end{document}
"#;

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => raise!(error),
    });
);

macro_rules! raise(
    ($error:expr) => (return Err(Box::new($error)));
    ($($arg:tt)*) => (raise!(format!($($arg)*)));
);

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

fn main() {
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = match arguments::parse(std::env::args()) {
        Ok(arguments) => arguments,
        Err(error) => raise!(error),
    };

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }

    let bibliography = match arguments.get::<String>("bib") {
        Some(bibliography) => bibliography,
        _ => raise!("a bibliography file is required"),
    };
    let reference = match arguments.get::<String>("ref") {
        Some(reference) => reference,
        _ => raise!("a reference name is required"),
    };

    match arguments.get::<String>("tex") {
        Some(ref template) => {
            let mut file = ok!(File::open(template));
            let mut template = String::new();
            ok!(file.read_to_string(&mut template));
            process(&template, &bibliography, &reference)
        },
        _ => {
            process(TEMPLATE, &bibliography, &reference)
        },
    }
}

fn process(template: &str, bibliography: &str, reference: &str) -> Result<()> {
    let root = ok!(Directory::new("cite"));

    macro_rules! run(
        ($program:expr, $argument:expr) => ({
            let mut command = Command::new($program);
            command.arg($argument).current_dir(&root);
            let output = match command.output() {
                Ok(output) => output,
                Err(error) => raise!(format!("`{}` has failed: {}", $program, error)),
            };
            if !output.status.success() {
                let _ = stdout().write_all(&output.stdout);
                let _ = stderr().write_all(&output.stderr);
                raise!(format!("`{}` has failed", $program));
            }
        });
    );

    {
        let mut map = HashMap::new();
        map.insert("<bibliography>", bibliography);
        map.insert("<reference>", reference);
        let tex = replace(template, &map);

        let mut file = ok!(File::create(root.join("paper.tex")));
        ok!(file.write_all(tex.as_bytes()));
    }

    run!("latex", "paper.tex");
    run!("bibtex", "paper");
    run!("latex", "paper.tex");
    run!("latex", "paper.tex");
    run!("dvipdf", "paper.dvi");
    run!("pdftotext", "paper.pdf");

    let mut buffer = Vec::new();
    {
        let mut file = ok!(File::open(root.join("paper.txt")));
        ok!(file.read_to_end(&mut buffer));
    }

    let content = String::from_utf8_lossy(&buffer);
    println!("{}", content.trim());

    Ok(())
}

fn replace(text: &str, map: &HashMap<&str, &str>) -> String {
    let mut text = text.to_string();
    for (key, value) in map {
        text = text.replace(key, value);
    }
    text
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: Error) -> ! {
    let message = format!("Error: {}.\n{}", &*error, USAGE);
    let _ = stderr().write_all(message.as_bytes());
    std::process::exit(1);
}
<|endoftext|>


<commit_before>mod vm;
mod command;
mod parse;
mod program;

use std::io::{Write, Read};
use std::env;
use std::path::Path;
use std::fs::File;

use vm::VM;
use program::Program;
use parse::parse;

fn main() {
    let vm = VM::new();
    let program = Program::new();
    match env::args().nth(1) {
        None => repl(vm, program),
        Some(arg) => interpreter(arg, vm, program),
    }
}

fn repl (mut vm: VM, mut program: Program) -> () {
    loop {
        print!("{}", if program.is_seeking {"... "} else {"bf> "});
        std::io::stdout().flush().unwrap();

        let mut line = String::new();
        let commands = match std::io::stdin().read_line(&mut line) {
            Ok(0) => break,
            Ok(_) => parse(&line),
            Err(error) => panic!(error),
        };
        program.append(&commands);
        program.execute(&mut vm);
    }
}

fn interpreter(arg: String, mut vm: VM, mut program: Program) -> () {
    let path = Path::new(&arg);
    let mut contents = String::new();
    File::open(&path)
        .unwrap()
        .read_to_string(&mut contents)
        .unwrap();

    program.append(&parse(&contents));
    program.execute(&mut vm);
}
<commit_msg>Change prompt for REPL to say "tf" instead of "bf"<commit_after>mod vm;
mod command;
mod parse;
mod program;

use std::io::{Write, Read};
use std::env;
use std::path::Path;
use std::fs::File;

use vm::VM;
use program::Program;
use parse::parse;

fn main() {
    let vm = VM::new();
    let program = Program::new();
    match env::args().nth(1) {
        None => repl(vm, program),
        Some(arg) => interpreter(arg, vm, program),
    }
}

fn repl (mut vm: VM, mut program: Program) -> () {
    loop {
        print!("{}", if program.is_seeking {"... "} else {"tf> "});
        std::io::stdout().flush().unwrap();

        let mut line = String::new();
        let commands = match std::io::stdin().read_line(&mut line) {
            Ok(0) => break,
            Ok(_) => parse(&line),
            Err(error) => panic!(error),
        };
        program.append(&commands);
        program.execute(&mut vm);
    }
}

fn interpreter(arg: String, mut vm: VM, mut program: Program) -> () {
    let path = Path::new(&arg);
    let mut contents = String::new();
    File::open(&path)
        .unwrap()
        .read_to_string(&mut contents)
        .unwrap();

    program.append(&parse(&contents));
    program.execute(&mut vm);
}
<|endoftext|>


<commit_before>#![feature(async_await, await_macro, futures_api, pin)]
#![feature(arbitrary_self_types, fn_traits, unboxed_closures)]

#![warn(rust_2018_idioms)]
#![deny(proc_macro_derive_resolution_fallback)]

#[macro_use]
mod macros;

mod bus;
mod config;
// mod discord_client;
mod error;
mod irc_client;
mod message;
mod util;

use actix::prelude::*;
use failure::Fail;
use futures::{compat::*, prelude::*};
use log::*;

pub use crate::{
    bus::{Bus, BusId},
    config::{Config, fetch_config},
    error::Error,
    message::MessageCreated,
    util::{AddrExt, GetBusId},
};

fn main() -> Result<(), failure::Error> {
    env_logger::init();

    let cfg = config::Config::from_path("dev.toml")?;
    config::update(cfg);

    let code = System::run(move || {
        let f = async move {
            let _irc = irc_client::Irc::new()?.start();
            let inspector = Inspector { bus_id: Bus::new_id() }.start();
            let _ = await!(inspector.subscribe::<MessageCreated>());
            Ok(())
        };

        let f = f.map_err(|err: Error| {
            error!("{}", err);
            if let Some(bt) = err.backtrace() {
                info!("{}", bt);
            }
            ()
        });

        Arbiter::spawn(f.boxed().compat(TokioDefaultSpawn));

        // let discord = actix::SyncArbiter::start(3, move || {
        //     discord_client::Discord::new(&discord_bot_token).unwrap()
        // });

        // std::thread::spawn(move || {
        //     let mut id_map = HashMap::new();
        //     id_map.insert(irc_bus_id, "IRC".to_owned());
        //     id_map.insert(discord_bus_id, "Discord".to_owned());
        //     inspect_bus(bus, id_map);
        // });
    });
    std::process::exit(code);
}

struct Inspector {
    bus_id: BusId
}

impl actix::Actor for Inspector {
    type Context = actix::Context<Self>;
}

impl Handler<GetBusId> for Inspector {
    type Result = BusId;
    fn handle(&mut self, _: GetBusId, _: &mut Self::Context) -> Self::Result {
        self.bus_id
    }
}

impl actix::Handler<message::MessageCreated> for Inspector {
    type Result = ();

    fn handle(&mut self, msg: message::MessageCreated, _: &mut Self::Context) -> Self::Result {
        info!("{:#?}", msg);
    }
}

// fn inspect_bus(bus: message::Bus, id_map: HashMap<message::BusId, String>) {
//     for payload in bus {
//         use message::Message::*;
//         match payload.message {
//             ChannelUpdated { channels } => {
//                 info!("discord channels: {:?}", channels);
//             }
//             MessageCreated(msg) => {
//                 if let Some(name) = id_map.get(&payload.sender) {
//                     info!("from {} {} {}: {}", name, msg.channel, msg.nickname, msg.content);
//                 }
//             },
//             _ => { }
//         }
//     }
// }
<commit_msg>Refactor<commit_after>#![feature(async_await, await_macro, futures_api, pin)]
#![feature(arbitrary_self_types, fn_traits, unboxed_closures)]

#![warn(rust_2018_idioms)]
#![deny(proc_macro_derive_resolution_fallback)]

#[macro_use]
mod macros;

mod bus;
mod config;
// mod discord_client;
mod error;
mod irc_client;
mod message;
mod util;

use actix::prelude::*;
use failure::Fail;
use futures::{compat::*, prelude::*};
use log::*;

pub use crate::{
    bus::{Bus, BusId},
    config::{Config, fetch_config},
    error::Error,
    message::MessageCreated,
    util::{AddrExt, GetBusId},
};

fn main() -> Result<(), failure::Error> {
    env_logger::init();

    let cfg = config::Config::from_path("dev.toml")?;
    config::update(cfg);

    let code = System::run(move || {
        let f = async move {
            let _irc = irc_client::Irc::new()?.start();
            let inspector = Inspector { bus_id: Bus::new_id() }.start();
            let _ = await!(inspector.subscribe::<MessageCreated>());
            Ok(())
        };

        let f = f.map_err(|err: Error| {
            error!("{}", err);
            if let Some(bt) = err.backtrace() {
                info!("{}", bt);
            }
            ()
        });

        Arbiter::spawn(f.boxed().compat(TokioDefaultSpawn));

        // let discord = actix::SyncArbiter::start(3, move || {
        //     discord_client::Discord::new(&discord_bot_token).unwrap()
        // });

        // std::thread::spawn(move || {
        //     let mut id_map = HashMap::new();
        //     id_map.insert(irc_bus_id, "IRC".to_owned());
        //     id_map.insert(discord_bus_id, "Discord".to_owned());
        //     inspect_bus(bus, id_map);
        // });
    });
    std::process::exit(code);
}

struct Inspector {
    bus_id: BusId
}

impl actix::Actor for Inspector {
    type Context = actix::Context<Self>;
}

impl_get_bus_id!(Inspector);

impl actix::Handler<message::MessageCreated> for Inspector {
    type Result = ();

    fn handle(&mut self, msg: message::MessageCreated, _: &mut Self::Context) -> Self::Result {
        info!("{:#?}", msg);
    }
}

// fn inspect_bus(bus: message::Bus, id_map: HashMap<message::BusId, String>) {
//     for payload in bus {
//         use message::Message::*;
//         match payload.message {
//             ChannelUpdated { channels } => {
//                 info!("discord channels: {:?}", channels);
//             }
//             MessageCreated(msg) => {
//                 if let Some(name) = id_map.get(&payload.sender) {
//                     info!("from {} {} {}: {}", name, msg.channel, msg.nickname, msg.content);
//                 }
//             },
//             _ => { }
//         }
//     }
// }
<|endoftext|>


<commit_before>extern crate docopt;
extern crate rustc_serialize;
extern crate kafka;

use docopt::Docopt;
use kafka::client::KafkaClient;

// usage string
static USAGE: &'static str = "
kcat - cat for Kafka.

Usage:
    kcat [-b BROKER] -t TOPIC
    kcat (-h | --help)

Options:
    -h, --help                  Show this message.
    -b BROKER, --broker=BROKER  Kafka broker [default: localhost:9092].
    -t TOPIC, --topic=TOPIC     Kafka topic.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_broker: String,
    flag_topic: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let mut client = KafkaClient::new(vec!(args.flag_broker));
    let meta_res = client.load_metadata_all();
    if meta_res.is_err() {
        match meta_res.err() {
            Some(err) => println!("Error: {}", err),
            None => println!("Non-specific error")
        }
        return;
    }

    let mut prev_offset:i64 = 0;
    loop {
        let res = client.fetch_messages(
            args.flag_topic.to_string(), // topic
            0,                           // partition
            prev_offset + 1              // offset
        );
        if res.is_ok() {
            for tmsg in res.unwrap() {
                println!("{}", String::from_utf8(tmsg.message).unwrap());
                prev_offset = tmsg.offset;
            }
        }
    }
}
<commit_msg>Fixed 1 off error on initial offset<commit_after>extern crate docopt;
extern crate rustc_serialize;
extern crate kafka;

use docopt::Docopt;
use kafka::client::KafkaClient;

// usage string
static USAGE: &'static str = "
kcat - cat for Kafka.

Usage:
    kcat [-b BROKER] -t TOPIC
    kcat (-h | --help)

Options:
    -h, --help                  Show this message.
    -b BROKER, --broker=BROKER  Kafka broker [default: localhost:9092].
    -t TOPIC, --topic=TOPIC     Kafka topic.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_broker: String,
    flag_topic: String,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let mut client = KafkaClient::new(vec!(args.flag_broker));
    let meta_res = client.load_metadata_all();
    if meta_res.is_err() {
        match meta_res.err() {
            Some(err) => println!("Error: {}", err),
            None => println!("Non-specific error")
        }
        return;
    }

    let mut prev_offset:i64 = -1;
    loop {
        let res = client.fetch_messages(
            args.flag_topic.to_string(), // topic
            0,                           // partition
            prev_offset + 1              // offset
        );
        if res.is_ok() {
            for tmsg in res.unwrap() {
                println!("{}", String::from_utf8(tmsg.message).unwrap());
                prev_offset = tmsg.offset;
            }
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[macro_use] extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;
extern crate clap;

use std::process::exit;

use clap::{App, ArgMatches};
use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute(args: &ArgMatches) -> Result<i32, error::FatalError> {
    let dry_run = args.occurrences_of("dry-run") > 0;

    // STEP 0: Check if working directory is clean
    if !try!(git::status()) {
        println!("Uncommitted changes detected, please commit before release");
        if !dry_run {
            return Ok(101);
        }
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("version"))
        .and_then(|f| f.as_str())
        .and_then(|f| config::parse_version(f).ok())
        .unwrap();

    // STEP 2: Remove pre extension, save and commit
    if version.is_prerelease() {
        version.pre.clear();
        let new_version_string = version.to_string();
        if !dry_run {
            try!(config::rewrite_cargo_version(&new_version_string));
            // sync Cargo.toml and Cargo.lock
            try!(cargo::update());
        }

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !dry_run {
            if !try!(git::commit_all(&commit_msg)) {
                // commit failed, abort release
                return Ok(102);
            }
        }
    }

    // STEP 3: cargo publish
    if !dry_run {
        if !try!(cargo::publish()) {
            return Ok(103);
        }
    }

    // STEP 4: Tag
    let current_version = version.to_string();
    let tag_message = format!("(cargo-release) version {}", current_version);
    if !dry_run {
        if !try!(git::tag(&current_version, &tag_message)) {
            // tag failed, abort release
            return Ok(104);
        }
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    if !dry_run {
        try!(config::rewrite_cargo_version(&updated_version_string));
        try!(cargo::update());
    }
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !dry_run {
        if !try!(git::commit_all(&commit_msg)) {
            return Ok(105);
        }
    }

    // STEP 6: git push
    if !dry_run {
        if !try!(git::push()) {
            return Ok(106);
        }
    }

    Ok(0)
}

fn main() {
    let matches = App::new("cargo release")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Ning Sun <sunng@about.me>")
        .about("Cargo subcommand for you to smooth your release process.")
        .args_from_usage("
        [dry-run]... --dry-run 'Donot actually change anything.'")
        .get_matches();

    match execute(&matches) {
        Ok(code) => exit(code),
        Err(e) => {
            println!("Fatal: {}", e);
            exit(128);
        }
    }
}
<commit_msg>(feat) added option level<commit_after>#![allow(dead_code)]

#[macro_use] extern crate quick_error;
extern crate regex;
extern crate toml;
extern crate semver;
extern crate clap;

use std::process::exit;

use clap::{App, ArgMatches};
use semver::Identifier;

mod config;
mod error;
mod cmd;
mod git;
mod cargo;

fn execute(args: &ArgMatches) -> Result<i32, error::FatalError> {
    let dry_run = args.occurrences_of("dry-run") > 0;

    // STEP 0: Check if working directory is clean
    if !try!(git::status()) {
        println!("Uncommitted changes detected, please commit before release");
        if !dry_run {
            return Ok(101);
        }
    }

    // STEP 1: Read version from Cargo.toml and remove
    let result = try!(config::parse_cargo_config());

    let mut version = result.get("package")
        .and_then(|f| f.as_table())
        .and_then(|f| f.get("version"))
        .and_then(|f| f.as_str())
        .and_then(|f| config::parse_version(f).ok())
        .unwrap();

    // STEP 2: Remove pre extension, save and commit
    match args.value_of("level") {
        Some(level) => {
            match level {
                "major" => {
                    version.increment_major();
                },
                "minor" => {
                    version.increment_minor();
                },
                "patch" => {
                    version.increment_patch();
                },
                _ => {
                    panic!("Invalid level: {}", level);
                }
            }
        },
        None => {
            version.pre.clear();
        }
    }

    //FIXME: support version bump level
    if version.is_prerelease() {
        version.pre.clear();
        let new_version_string = version.to_string();
        if !dry_run {
            try!(config::rewrite_cargo_version(&new_version_string));
            // sync Cargo.toml and Cargo.lock
            try!(cargo::update());
        }

        let commit_msg = format!("(cargo-release) version {}", new_version_string);
        if !dry_run {
            if !try!(git::commit_all(&commit_msg)) {
                // commit failed, abort release
                return Ok(102);
            }
        }
    }

    // STEP 3: cargo publish
    if !dry_run {
        if !try!(cargo::publish()) {
            return Ok(103);
        }
    }

    // STEP 4: Tag
    let current_version = version.to_string();
    let tag_message = format!("(cargo-release) version {}", current_version);
    if !dry_run {
        if !try!(git::tag(&current_version, &tag_message)) {
            // tag failed, abort release
            return Ok(104);
        }
    }

    // STEP 5: bump version
    version.increment_patch();
    version.pre.push(Identifier::AlphaNumeric("pre".to_owned()));
    println!("Starting next development cycle {}", version);
    let updated_version_string = version.to_string();
    if !dry_run {
        try!(config::rewrite_cargo_version(&updated_version_string));
        try!(cargo::update());
    }
    let commit_msg = format!("(cargo-release) start next development cycle {}",
                             updated_version_string);
    if !dry_run {
        if !try!(git::commit_all(&commit_msg)) {
            return Ok(105);
        }
    }

    // STEP 6: git push
    if !dry_run {
        if !try!(git::push()) {
            return Ok(106);
        }
    }

    Ok(0)
}

fn main() {
    let matches = App::new("cargo release")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Ning Sun <sunng@about.me>")
        .about("Cargo subcommand for you to smooth your release process.")
        .args_from_usage("
        -l=[level] 'Release level: bumpping major|minor|patch version on release or removing prerelease extensions by default'
        [dry-run]... --dry-run 'Donot actually change anything.'")
        .get_matches();

    match execute(&matches) {
        Ok(code) => exit(code),
        Err(e) => {
            println!("Fatal: {}", e);
            exit(128);
        }
    }
}
<|endoftext|>