<commit_before>mod config;
mod err;
mod file;
mod process;
mod series;
mod track;

use crate::config::Config;
use crate::err::Result;
use crate::file::{SaveFile, SaveFileInDir};
use crate::series::local::{EpisodeList, EpisodeMatcher};
use crate::series::remote::anilist::{self, AniList, AniListConfig};
use crate::series::remote::offline::Offline;
use crate::series::remote::{RemoteService, SeriesInfo, Status};
use crate::series::{detect, SeasonInfoList, Series};
use crate::track::SeriesTracker;
use chrono::Utc;
use clap::clap_app;
use snafu::ResultExt;
use std::io;
use std::path::PathBuf;

fn main() {
    let args = clap_app!(anup =>
        (version: env!("CARGO_PKG_VERSION"))
        (author: env!("CARGO_PKG_AUTHORS"))
        (@arg SERIES: +takes_value +required "The name of the series to watch")
        (@arg season: -s --season +takes_value "The season to watch. Meant to be used when playing from a folder that has multiple seasons merged together under one name")
        (@arg matcher: -m --matcher +takes_value "The custom pattern to match episode files with")
        (@arg offline: -o --offline "Run in offline mode")
        (@arg prefetch: --prefetch "Fetch series info from AniList. For use with offline mode")
        (@arg noinfo: --noinfo "Disables printing of series information")
    )
    .get_matches();

    if let Err(err) = run(&args) {
        err::display_error(err);
        std::process::exit(1);
    }
}

fn run(args: &clap::ArgMatches) -> Result<()> {
    let keyword = args.value_of("SERIES").unwrap();
    let config = load_config()?;

    let remote: Box<RemoteService> = if args.is_present("offline") {
        Box::new(Offline::new())
    } else {
        Box::new(init_anilist()?)
    };

    let season_num = args
        .value_of("season")
        .and_then(|num_str| num_str.parse().ok())
        .map(|num: usize| num.saturating_sub(1))
        .unwrap_or(0);

    let series = get_series(
        keyword,
        &remote,
        &config,
        season_num,
        args.value_of("matcher"),
    )?;

    let mut tracker = SeriesTracker::init(&remote, &series.info, keyword)?;
    tracker.begin_watching(&remote, &config)?;

    if !args.is_present("noinfo") {
        print_info(&config, &series, &tracker);
    }

    play_episode_loop(remote, &config, &series, &mut tracker)?;
    Ok(())
}

fn load_config() -> Result<Config> {
    match Config::load() {
        Ok(config) => Ok(config),
        Err(ref err) if err.is_file_nonexistant() => {
            // Default base directory: ~/anime/
            let mut dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("~/"));
            dir.push("anime");

            let config = Config::new(dir);
            config.save()?;
            Ok(config)
        }
        Err(err) => Err(err),
    }
}

fn load_episode_matcher<S>(keyword: S, matcher: Option<&str>) -> Result<EpisodeMatcher>
where
    S: AsRef<str>,
{
    match EpisodeMatcher::load(&keyword) {
        Ok(matcher) => Ok(matcher),
        Err(ref err) if err.is_file_nonexistant() => match matcher {
            Some(matcher) => {
                let matcher = EpisodeMatcher::with_matcher(matcher)?;
                matcher.save(keyword)?;
                Ok(matcher)
            }
            None => Ok(EpisodeMatcher::new()),
        },
        Err(err) => Err(err),
    }
}

fn init_anilist() -> Result<AniList> {
    use crate::series::remote::anilist::AccessToken;

    let config = match AniListConfig::load() {
        Ok(config) => config,
        Err(ref err) if err.is_file_nonexistant() => {
            println!(
                "need AniList login token\ngo to {}\n\npaste your token:",
                anilist::LOGIN_URL
            );

            let token = {
                let mut buffer = String::new();
                io::stdin().read_line(&mut buffer).context(err::IO)?;
                let buffer = buffer.trim_end();

                AccessToken::new(buffer)
            };

            let config = AniListConfig::new(token);
            config.save()?;
            config
        }
        Err(err) => return Err(err),
    };

    AniList::login(config)
}

fn get_season_list<R, S>(
    remote: R,
    keyword: S,
    season_num: usize,
    dir: &PathBuf,
) -> Result<SeasonInfoList>
where
    R: AsRef<RemoteService>,
    S: AsRef<str>,
{
    let keyword = keyword.as_ref();

    match SeasonInfoList::load(keyword) {
        Ok(mut seasons) => {
            if seasons.add_from_remote_upto(&remote, season_num)? {
                seasons.save(keyword)?;
            }

            Ok(seasons)
        }
        Err(ref err) if err.is_file_nonexistant() => {
            // The directory is more likely to have a complete name, which will likely match
            // better than just a keyword, which could be an abstract identifier
            let dir_name = dir
                .file_name()
                .map(|name| name.to_string_lossy().into_owned())
                .unwrap_or_else(|| keyword.into());

            let info = SeriesInfo::best_matching_from_remote(&remote, dir_name)?;

            let seasons = SeasonInfoList::from_info_and_remote(info, &remote, Some(season_num))?;
            seasons.save(keyword)?;
            Ok(seasons)
        }
        Err(err) => Err(err),
    }
}

fn get_series<R, S>(
    name: S,
    remote: R,
    config: &Config,
    season_num: usize,
    matcher: Option<&str>,
) -> Result<Series>
where
    R: AsRef<RemoteService>,
    S: AsRef<str>,
{
    // TODO: allow overriding with argument
    let dir = detect::best_matching_folder(&name, &config.series_dir)?;

    let episodes = {
        let matcher = load_episode_matcher(&name, matcher)?;
        EpisodeList::parse(&dir, &matcher)?
    };

    let seasons = get_season_list(&remote, &name, season_num, &dir)?;
    Series::from_season_list(seasons, season_num, episodes)
}

fn print_info(config: &Config, series: &Series, tracker: &SeriesTracker) {
    use std::borrow::Cow;

    let repeater = "-".repeat(series.info.title.len() + 2);

    println!("+{}+\n@ {} @\n+{}+", repeater, series.info.title, repeater);
    println!();

    println!(
        "watched: {}/{}",
        tracker.state.watched_eps(),
        series.info.episodes
    );
    println!(
        "score: {}",
        tracker
            .state
            .score()
            .map(|s| Cow::Owned(s.to_string()))
            .unwrap_or_else(|| Cow::Borrowed("none"))
    );

    println!();

    let watch_time =
        series.info.episode_length * (series.info.episodes - tracker.state.watched_eps());
    let minutes_must_watch = series.info.episode_length as f32 * config.episode.pcnt_must_watch;

    println!("time to finish: {}", hms_from_mins(watch_time as f32));
    println!("progress time: {}", ms_from_mins(minutes_must_watch as f32));

    println!();
    println!("+{}+", repeater);
    println!();
}

fn ms_from_mins(mins: f32) -> String {
    let m = mins.floor() as u32;
    let s = (mins * 60.0 % 60.0).floor() as u32;

    format!("{:02}:{:02}", m, s)
}

fn hms_from_mins(mins: f32) -> String {
    let h = (mins / 60.0).floor() as u32;
    let m = (mins % 60.0).floor() as u32;
    let s = m * 60 % 60;

    format!("{:02}:{:02}:{:02}", h, m, s)
}

#[derive(PartialEq)]
enum PlayResult {
    Continue,
    Finished,
}

fn play_episode<R>(
    remote: R,
    config: &Config,
    series: &Series,
    tracker: &mut SeriesTracker,
) -> Result<PlayResult>
where
    R: AsRef<RemoteService>,
{
    let ep_num = tracker.state.watched_eps() + 1;
    let start_time = Utc::now();

    series.play_episode(ep_num)?;

    let end_time = Utc::now();

    let mins_watched = {
        let watch_time = end_time - start_time;
        watch_time.num_seconds() as f32 / 60.0
    };

    let mins_must_watch = series.info.episode_length as f32 * config.episode.pcnt_must_watch;

    if mins_watched < mins_must_watch {
        println!("did not watch episode long enough");
        return Ok(PlayResult::Finished);
    }

    tracker.episode_completed(&remote, config)?;

    match tracker.state.status() {
        Status::Completed => {
            println!("completed!");
            Ok(PlayResult::Finished)
        }
        _ => {
            println!("{}/{} completed", ep_num, series.info.episodes);
            Ok(PlayResult::Continue)
        }
    }
}

fn play_episode_loop<R>(
    remote: R,
    config: &Config,
    series: &Series,
    tracker: &mut SeriesTracker,
) -> Result<()>
where
    R: AsRef<RemoteService>,
{
    use std::thread;
    use std::time::Duration;

    loop {
        if let PlayResult::Finished = play_episode(&remote, config, series, tracker)? {
            break Ok(());
        }

        if config.episode.seconds_before_next > 0.0 {
            let millis = (config.episode.seconds_before_next * 1000.0) as u64;
            let duration = Duration::from_millis(millis);
            thread::sleep(duration);
        }
    }
}
<commit_msg>[main] Rename noinfo argument to quiet<commit_after>mod config;
mod err;
mod file;
mod process;
mod series;
mod track;

use crate::config::Config;
use crate::err::Result;
use crate::file::{SaveFile, SaveFileInDir};
use crate::series::local::{EpisodeList, EpisodeMatcher};
use crate::series::remote::anilist::{self, AniList, AniListConfig};
use crate::series::remote::offline::Offline;
use crate::series::remote::{RemoteService, SeriesInfo, Status};
use crate::series::{detect, SeasonInfoList, Series};
use crate::track::SeriesTracker;
use chrono::Utc;
use clap::clap_app;
use snafu::ResultExt;
use std::io;
use std::path::PathBuf;

fn main() {
    let args = clap_app!(anup =>
        (version: env!("CARGO_PKG_VERSION"))
        (author: env!("CARGO_PKG_AUTHORS"))
        (@arg SERIES: +takes_value +required "The name of the series to watch")
        (@arg season: -s --season +takes_value "The season to watch. Meant to be used when playing from a folder that has multiple seasons merged together under one name")
        (@arg matcher: -m --matcher +takes_value "The custom pattern to match episode files with")
        (@arg offline: -o --offline "Run in offline mode")
        (@arg prefetch: --prefetch "Fetch series info from AniList. For use with offline mode")
        (@arg quiet: -q --quiet "Don't print series information")
    )
    .get_matches();

    if let Err(err) = run(&args) {
        err::display_error(err);
        std::process::exit(1);
    }
}

fn run(args: &clap::ArgMatches) -> Result<()> {
    let keyword = args.value_of("SERIES").unwrap();
    let config = load_config()?;

    let remote: Box<RemoteService> = if args.is_present("offline") {
        Box::new(Offline::new())
    } else {
        Box::new(init_anilist()?)
    };

    let season_num = args
        .value_of("season")
        .and_then(|num_str| num_str.parse().ok())
        .map(|num: usize| num.saturating_sub(1))
        .unwrap_or(0);

    let series = get_series(
        keyword,
        &remote,
        &config,
        season_num,
        args.value_of("matcher"),
    )?;

    let mut tracker = SeriesTracker::init(&remote, &series.info, keyword)?;
    tracker.begin_watching(&remote, &config)?;

    if !args.is_present("quiet") {
        print_info(&config, &series, &tracker);
    }

    play_episode_loop(remote, &config, &series, &mut tracker)?;
    Ok(())
}

fn load_config() -> Result<Config> {
    match Config::load() {
        Ok(config) => Ok(config),
        Err(ref err) if err.is_file_nonexistant() => {
            // Default base directory: ~/anime/
            let mut dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("~/"));
            dir.push("anime");

            let config = Config::new(dir);
            config.save()?;
            Ok(config)
        }
        Err(err) => Err(err),
    }
}

fn load_episode_matcher<S>(keyword: S, matcher: Option<&str>) -> Result<EpisodeMatcher>
where
    S: AsRef<str>,
{
    match EpisodeMatcher::load(&keyword) {
        Ok(matcher) => Ok(matcher),
        Err(ref err) if err.is_file_nonexistant() => match matcher {
            Some(matcher) => {
                let matcher = EpisodeMatcher::with_matcher(matcher)?;
                matcher.save(keyword)?;
                Ok(matcher)
            }
            None => Ok(EpisodeMatcher::new()),
        },
        Err(err) => Err(err),
    }
}

fn init_anilist() -> Result<AniList> {
    use crate::series::remote::anilist::AccessToken;

    let config = match AniListConfig::load() {
        Ok(config) => config,
        Err(ref err) if err.is_file_nonexistant() => {
            println!(
                "need AniList login token\ngo to {}\n\npaste your token:",
                anilist::LOGIN_URL
            );

            let token = {
                let mut buffer = String::new();
                io::stdin().read_line(&mut buffer).context(err::IO)?;
                let buffer = buffer.trim_end();

                AccessToken::new(buffer)
            };

            let config = AniListConfig::new(token);
            config.save()?;
            config
        }
        Err(err) => return Err(err),
    };

    AniList::login(config)
}

fn get_season_list<R, S>(
    remote: R,
    keyword: S,
    season_num: usize,
    dir: &PathBuf,
) -> Result<SeasonInfoList>
where
    R: AsRef<RemoteService>,
    S: AsRef<str>,
{
    let keyword = keyword.as_ref();

    match SeasonInfoList::load(keyword) {
        Ok(mut seasons) => {
            if seasons.add_from_remote_upto(&remote, season_num)? {
                seasons.save(keyword)?;
            }

            Ok(seasons)
        }
        Err(ref err) if err.is_file_nonexistant() => {
            // The directory is more likely to have a complete name, which will likely match
            // better than just a keyword, which could be an abstract identifier
            let dir_name = dir
                .file_name()
                .map(|name| name.to_string_lossy().into_owned())
                .unwrap_or_else(|| keyword.into());

            let info = SeriesInfo::best_matching_from_remote(&remote, dir_name)?;

            let seasons = SeasonInfoList::from_info_and_remote(info, &remote, Some(season_num))?;
            seasons.save(keyword)?;
            Ok(seasons)
        }
        Err(err) => Err(err),
    }
}

fn get_series<R, S>(
    name: S,
    remote: R,
    config: &Config,
    season_num: usize,
    matcher: Option<&str>,
) -> Result<Series>
where
    R: AsRef<RemoteService>,
    S: AsRef<str>,
{
    // TODO: allow overriding with argument
    let dir = detect::best_matching_folder(&name, &config.series_dir)?;

    let episodes = {
        let matcher = load_episode_matcher(&name, matcher)?;
        EpisodeList::parse(&dir, &matcher)?
    };

    let seasons = get_season_list(&remote, &name, season_num, &dir)?;
    Series::from_season_list(seasons, season_num, episodes)
}

fn print_info(config: &Config, series: &Series, tracker: &SeriesTracker) {
    use std::borrow::Cow;

    let repeater = "-".repeat(series.info.title.len() + 2);

    println!("+{}+\n@ {} @\n+{}+", repeater, series.info.title, repeater);
    println!();

    println!(
        "watched: {}/{}",
        tracker.state.watched_eps(),
        series.info.episodes
    );
    println!(
        "score: {}",
        tracker
            .state
            .score()
            .map(|s| Cow::Owned(s.to_string()))
            .unwrap_or_else(|| Cow::Borrowed("none"))
    );

    println!();

    let watch_time =
        series.info.episode_length * (series.info.episodes - tracker.state.watched_eps());
    let minutes_must_watch = series.info.episode_length as f32 * config.episode.pcnt_must_watch;

    println!("time to finish: {}", hms_from_mins(watch_time as f32));
    println!("progress time: {}", ms_from_mins(minutes_must_watch as f32));

    println!();
    println!("+{}+", repeater);
    println!();
}

fn ms_from_mins(mins: f32) -> String {
    let m = mins.floor() as u32;
    let s = (mins * 60.0 % 60.0).floor() as u32;

    format!("{:02}:{:02}", m, s)
}

fn hms_from_mins(mins: f32) -> String {
    let h = (mins / 60.0).floor() as u32;
    let m = (mins % 60.0).floor() as u32;
    let s = m * 60 % 60;

    format!("{:02}:{:02}:{:02}", h, m, s)
}

#[derive(PartialEq)]
enum PlayResult {
    Continue,
    Finished,
}

fn play_episode<R>(
    remote: R,
    config: &Config,
    series: &Series,
    tracker: &mut SeriesTracker,
) -> Result<PlayResult>
where
    R: AsRef<RemoteService>,
{
    let ep_num = tracker.state.watched_eps() + 1;
    let start_time = Utc::now();

    series.play_episode(ep_num)?;

    let end_time = Utc::now();

    let mins_watched = {
        let watch_time = end_time - start_time;
        watch_time.num_seconds() as f32 / 60.0
    };

    let mins_must_watch = series.info.episode_length as f32 * config.episode.pcnt_must_watch;

    if mins_watched < mins_must_watch {
        println!("did not watch episode long enough");
        return Ok(PlayResult::Finished);
    }

    tracker.episode_completed(&remote, config)?;

    match tracker.state.status() {
        Status::Completed => {
            println!("completed!");
            Ok(PlayResult::Finished)
        }
        _ => {
            println!("{}/{} completed", ep_num, series.info.episodes);
            Ok(PlayResult::Continue)
        }
    }
}

fn play_episode_loop<R>(
    remote: R,
    config: &Config,
    series: &Series,
    tracker: &mut SeriesTracker,
) -> Result<()>
where
    R: AsRef<RemoteService>,
{
    use std::thread;
    use std::time::Duration;

    loop {
        if let PlayResult::Finished = play_episode(&remote, config, series, tracker)? {
            break Ok(());
        }

        if config.episode.seconds_before_next > 0.0 {
            let millis = (config.episode.seconds_before_next * 1000.0) as u64;
            let duration = Duration::from_millis(millis);
            thread::sleep(duration);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
extern crate dotenv;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;

mod schema;
mod db;
mod note;
mod models;

use db::establish_connection;
use note::{get_notes, create_note};
use models::*;
use rocket_contrib::JSON;

#[get("/note", format = "application/json")]
fn notes_get() -> Option<JSON<Vec<Note>>> {
    let connection = establish_connection();
    let notes = get_notes(&connection);
    Some(JSON(notes))
}

#[post("/note", format = "application/json", data = "<note>")]
fn note_create(note: NewNote) -> JSON<Note> {
    let connection = establish_connection();
    JSON(create_note(&connection, note))
}

fn main() {
    rocket::ignite().mount("/", routes![note_create, notes_get]).launch();
}
<commit_msg>Refactored my get and post handler to use the same code style<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
extern crate dotenv;
extern crate serde_json;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;

mod schema;
mod db;
mod note;
mod models;

use db::establish_connection;
use note::{get_notes, create_note};
use models::*;
use rocket_contrib::JSON;

#[get("/note", format = "application/json")]
fn notes_get() -> JSON<Vec<Note>> {
    let connection = establish_connection();
    let notes = get_notes(&connection);
    JSON(notes)
}

#[post("/note", format = "application/json", data = "<note>")]
fn note_create(note: NewNote) -> JSON<Note> {
    let connection = establish_connection();
    let created_note = create_note(&connection, note);
    JSON(created_note)
}

fn main() {
    rocket::ignite().mount("/", routes![note_create, notes_get]).launch();
}
<|endoftext|>


<commit_before>pub mod api;
pub mod lila;
pub mod model;
pub mod db;

use clap::Clap;
use axum::{handler::get, extract::Extension, Router, AddExtensionLayer};
use std::net::SocketAddr;
use std::sync::Arc;
use crate::db::Database;

#[derive(Clap)]
struct Opt {
    #[clap(long = "bind", default_value = "127.0.0.1:9000")]
    bind: SocketAddr,
}

#[tokio::main]
async fn main() {
    let opt = Opt::parse();

    let db: &'static Database = Box::leak(Box::new(Database::open()));

    let app = Router::new()
        .route("/", get(hello_world))
        .layer(AddExtensionLayer::new(db));

    axum::Server::bind(&opt.bind)
        .serve(app.into_make_service())
        .await
        .expect("bind");
}

async fn hello_world(Extension(db): Extension<&'static Database>) -> String {
    db.inner.put("hello", "world").expect("put");
    String::from_utf8(db.inner.get("hello").expect("get").expect("present")).expect("utf-8")
}
<commit_msg>gracefully shutdown database on ctrl+c<commit_after>pub mod api;
pub mod lila;
pub mod model;
pub mod db;

use clap::Clap;
use axum::{handler::get, extract::Extension, Router, AddExtensionLayer};
use std::net::SocketAddr;
use std::sync::Arc;
use crate::db::Database;

#[derive(Clap)]
struct Opt {
    #[clap(long = "bind", default_value = "127.0.0.1:9000")]
    bind: SocketAddr,
}

#[tokio::main]
async fn main() {
    let opt = Opt::parse();

    let db = Arc::new(Database::open());

    let app = Router::new()
        .route("/", get(hello_world))
        .layer(AddExtensionLayer::new(db));

    axum::Server::bind(&opt.bind)
        .serve(app.into_make_service())
        .with_graceful_shutdown(async {
            tokio::signal::ctrl_c().await.expect("wait for ctrl-c");
        })
        .await
        .expect("bind");
}

async fn hello_world(Extension(db): Extension<Arc<Database>>) -> String {
    db.inner.put("hello", "world").expect("put");
    String::from_utf8(db.inner.get("hello").expect("get").expect("present")).expect("utf-8")
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

extern crate rs_es;
use rs_es::Client;
use rs_es::operations::search::{Sort, SortField, Order};
use rs_es::query::{Filter, Query};

extern crate postgres;
extern crate postgres_array;
use postgres::{Connection, SslMode};

mod user;
use user::User;

mod filters;
use filters::BuildTermsOfArray;

#[derive(Debug, RustcDecodable)]
struct TalentsSearchResult {
  id: i32
}

const PG_URL: &'static str = "postgres://lando@localhost/lando_development";
const ES_INDEXES: &'static [&'static str] = &["honeypot_dev_talents"];

fn main() {
  let mut es = Client::new("localhost", 9200);
  let     pg = Connection::connect(PG_URL, SslMode::None).unwrap();

  let roles:         Vec<&'static str> = vec!["Frontend", "Backend"];
  let languages:     Vec<&'static str> = vec![];
  let experience:    Vec<&'static str> = vec![];
  let locations:     Vec<&'static str> = vec![];
  let authorization: Vec<&'static str> = vec![];
  let company_ids:   Vec<i32>          = vec![];

  let query = Query::build_filtered(
                Filter::build_bool()
                       .with_must(
                          vec![
                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_roles", &roles
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_languages", &languages
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_experience", &experience
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_locations", &locations
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_authorization", &authorization
                            )
                          ].into_iter()
                           .flat_map(|x| x)
                           .collect::<Vec<Filter>>()
                        )
                       .with_must_not(
                          vec![
                            <Filter as BuildTermsOfArray<i32>>::build_terms(
                              "company_ids", &company_ids
                            ),

                            <Filter as BuildTermsOfArray<i32>>::build_terms(
                              "blocked_companies", &company_ids
                            )
                          ].into_iter()
                           .flat_map(|x| x)
                           .collect::<Vec<Filter>>()
                        ).build()
              ).build();

  let result = es.search_query()
                 .with_indexes(ES_INDEXES)
                 .with_query(&query)
                 .with_sort(&Sort::new(vec![
                   SortField::new("updated_at", Some(Order::Desc)).build()
                 ]))
                 .send()
                 .ok()
                 .unwrap();

  /* Actually ES returns lots of stuff here.
     We could consider to fetch very few fields from the database */
  for hit in result.hits.hits {
    let talent: TalentsSearchResult = hit.source().unwrap();

    match User::find(&pg, &talent.id) {
      Some(user) => println!("{:#?}", user),
      None       => {}
    }
  }
}
<commit_msg>main: avoid block comments<commit_after>extern crate rustc_serialize;

extern crate rs_es;
use rs_es::Client;
use rs_es::operations::search::{Sort, SortField, Order};
use rs_es::query::{Filter, Query};

extern crate postgres;
extern crate postgres_array;
use postgres::{Connection, SslMode};

mod user;
use user::User;

mod filters;
use filters::BuildTermsOfArray;

#[derive(Debug, RustcDecodable)]
struct TalentsSearchResult {
  id: i32
}

const PG_URL: &'static str = "postgres://lando@localhost/lando_development";
const ES_INDEXES: &'static [&'static str] = &["honeypot_dev_talents"];

fn main() {
  let mut es = Client::new("localhost", 9200);
  let     pg = Connection::connect(PG_URL, SslMode::None).unwrap();

  let roles:         Vec<&'static str> = vec!["Frontend", "Backend"];
  let languages:     Vec<&'static str> = vec![];
  let experience:    Vec<&'static str> = vec![];
  let locations:     Vec<&'static str> = vec![];
  let authorization: Vec<&'static str> = vec![];
  let company_ids:   Vec<i32>          = vec![];

  let query = Query::build_filtered(
                Filter::build_bool()
                       .with_must(
                          vec![
                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_roles", &roles
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_languages", &languages
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_experience", &experience
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_locations", &locations
                            ),

                            <Filter as BuildTermsOfArray<&'static str>>::build_terms(
                              "work_authorization", &authorization
                            )
                          ].into_iter()
                           .flat_map(|x| x)
                           .collect::<Vec<Filter>>()
                        )
                       .with_must_not(
                          vec![
                            <Filter as BuildTermsOfArray<i32>>::build_terms(
                              "company_ids", &company_ids
                            ),

                            <Filter as BuildTermsOfArray<i32>>::build_terms(
                              "blocked_companies", &company_ids
                            )
                          ].into_iter()
                           .flat_map(|x| x)
                           .collect::<Vec<Filter>>()
                        ).build()
              ).build();

  let result = es.search_query()
                 .with_indexes(ES_INDEXES)
                 .with_query(&query)
                 .with_sort(&Sort::new(vec![
                   SortField::new("updated_at", Some(Order::Desc)).build()
                 ]))
                 .send()
                 .ok()
                 .unwrap();

  // Actually ES returns lots of stuff here.
  // We could consider to fetch very few fields from the database */
  for hit in result.hits.hits {
    let talent: TalentsSearchResult = hit.source().unwrap();

    match User::find(&pg, &talent.id) {
      Some(user) => println!("{:#?}", user),
      None       => {}
    }
  }
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate getopts;
extern crate selecta;

use getopts::{optopt ,getopts};
use selecta::configuration::Configuration;
use selecta::search::Search;

fn main() {
    let initial_query = extract_initial_query();
    let lines = read_lines();

    let config = Configuration::from_inputs(lines, initial_query, Some(10));
    let search = Search::blank(config).append_to_search("e");

    println!("{:?}", search.selection);
}

fn extract_initial_query() -> Option<String> {
    let args: Vec<String> = std::os::args();
    let opts = &[
        optopt("s", "search", "initial search query", ""),
    ];
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    matches.opt_str("s")
}

fn read_lines() -> Vec<String> {
    let mut lines: Vec<String> = Vec::new();
    let mut reader = std::io::stdio::stdin();

    loop {
        match reader.read_line() {
            Err(_) => break,
            Ok(l) => {
                let message = l.trim_left().trim_right();
                lines.push(message.to_string());
            },
        };
    };
    lines
}
<commit_msg>Improves the rough main method<commit_after>#![allow(unstable)]

extern crate getopts;
extern crate selecta;

use getopts::{optopt ,getopts};
use selecta::configuration::Configuration;
use selecta::search::Search;
use selecta::renderer::Renderer;
use selecta::tty::TTY;
use selecta::tty::IO;
use selecta::screen::Screen;

fn main() {
    let initial_query = extract_initial_query();
    let lines = read_lines();

    let config = Configuration::from_inputs(lines, initial_query, Some(20));
    let mut search = Search::blank(config);

    let mut tty = TTY::new();
    let screen = Screen;

    while !search.is_done() {
        let input = tty.read();
        match input {
            Some(n) => {
                search = screen.handle_keystroke(search,n.to_string().as_slice());
            },
            None => break,
        };
        println!("{:?}", search);
    }

    let result = Renderer::new(search).render();

    println!("{:?}", result);
}

fn extract_initial_query() -> Option<String> {
    let args: Vec<String> = std::os::args();
    let opts = &[
        optopt("s", "search", "initial search query", ""),
    ];
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    matches.opt_str("s")
}

fn read_lines() -> Vec<String> {
    let mut lines: Vec<String> = Vec::new();
    let mut reader = std::io::stdio::stdin();

    loop {
        match reader.read_line() {
            Err(_) => break,
            Ok(l) => {
                let message = l.trim_left().trim_right();
                lines.push(message.to_string());
            },
        };
    };
    lines
}
<|endoftext|>


<commit_before>extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::DownloadError;
use lib::converter::Converter;

use std::fs::{remove_file,remove_dir};

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;
static CODE_FAILED: i8 = 3;
static CODE_SUCCESS: i8 = 2;

lazy_static! {
    pub static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] broken, enum not usable as of #10292
// enum QueryCodes {
//     Waiting = 0,
//     InProgress = 1,
//     Finished = 2,
//     Failed = 3,
// }

fn main() {

    let pool = lib::db_connect(lib::mysql_options(), SLEEP_MS);

    let converter = Converter::new(&CONFIG.general.ffmpeg_bin,&CONFIG.general.mp3_quality , pool.clone());
    let mut print_pause = true;
    loop {
        if let Some(result) = lib::request_entry(& pool) {
            print_pause = true;
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            lib::set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");
            lib::set_query_state(&pool.clone(),&qid, "started", false);

            let succes;
            {
                let mut left_files: Vec<String> = Vec::with_capacity(2);
                if result.playlist {
                    succes = match handle_playlist(result, &converter,&mut left_files) {
                        Ok(v) => Ok(v),
                        Err(e) => {println!("Playlist Error: {:?}", e); Err(e) }
                    };
                }else{
                    succes = match handle_download(result, &None, &converter,&mut left_files) {
                        Ok(v) => Ok(v),
                        Err(e) => {println!("Download Error: {:?}", e); Err(e) }
                    };
                }

                if !left_files.is_empty() {
                    println!("cleaning up files");
                    for i in &left_files {
                        match remove_file(&i) {
                            Ok(_) => (println!("cleaning up {}",i)),
                            Err(e) => println!("unable to remove file '{}' {}",i,e),
                        }
                    }
                }
            }

            let code: i8 = if succes.is_ok() {
                CODE_SUCCESS//QueryCode
            } else {
                CODE_FAILED//QueryCode
            };
            lib::set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");

            let state = if code == 2 {
                "finished"
            } else {
                "failed"
            };
            lib::set_query_state(&pool.clone(),&qid, state, true);

        } else {
            if print_pause { println!("Pausing.."); print_pause = false; }
            std::thread::sleep_ms(SLEEP_MS);
        }
    }
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video separately and convert them together
///In case of a playlist download it depends on the target download folder & if it should be bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, the video but with the highest quality.
///Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, it's moved after a successful download, converted etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode'd name of the file is stored in the DB
fn handle_download<'a>(downl_db: DownloadDB, folder: &Option<String>, converter: &Converter, file_db: &mut Vec<String>) -> Result<Option<String>,DownloadError>{
    //update progress
    let is_zipped = match *folder {
        Some(_) => true,
        None => false,
    };
    if !downl_db.compress {
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, 0,false);
    }

    let download = Downloader::new(&downl_db, &CONFIG.general);
    //get filename, check for DMCA
    let mut dmca = false; // "succ." dmca -> file already downloaded

    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib.. // k if( k == Err(DownloadError::DMCAError) )
            println!("DMCA error!");
            match download.lib_request_video() {
                Err(err) => { println!("Offliberty-call error {:?}", err); return Err(err); },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / restricted source etc.. abort
            println!("Unknown error: {:?}", e);
            return Err(e);
        },
    };

    let name_http_valid = lib::format_file_name(&name, &download, &downl_db.qid);

    let file_path = lib::format_file_path(&downl_db.qid, folder.clone(), false);
    file_db.push(file_path.clone());
    let save_path = lib::format_save_path(folder.clone(),&name, &download, &downl_db.qid);

    println!("Filename: {}", name);

    let is_splitted_video = if dmca {
        false
    } else {
        lib::is_split_container(&downl_db.quality)
    };
    let convert_audio = CONFIG.extensions.mp3.contains(&downl_db.quality);

    let total_steps = if dmca {
        if download.is_audio() {
            3
        } else {
            2
        }
    } else if is_splitted_video {
        4
    } else if download.is_audio() {
        3
    } else {
        2
    };

    if !dmca {
        if !downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, total_steps,false);
        }

        //download first file, download audio raw source if specified or video
        try!(download.download_file(&file_path, convert_audio));

        if is_splitted_video {
            // download audio file & convert together
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 3, total_steps,false);

            let audio_path = lib::format_file_path(&downl_db.qid, folder.clone(), true);
            file_db.push(audio_path.clone());

            println!("Downloading audio.. {}", audio_path);
            try!(download.download_file(&audio_path, true));

            if !downl_db.compress {
                lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 4, total_steps,false);
            }

            match converter.merge_files(&downl_db.qid,&file_path, &audio_path,&save_path, !downl_db.compress) {
                Err(e) => {println!("merge error: {:?}",e); return Err(e);},
                Ok(()) => {},
            }

            try!(remove_file(&audio_path));
            file_db.pop();

        }else{ // we're already done, only need to copy if it's not raw audio source
            if !download.is_audio() {
                try!(lib::move_file(&file_path, &save_path));
            }
        }
    }

    if download.is_audio(){ // if audio-> convert m4a to mp3, which converts directly to downl. dir
        if !downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, false);
        }
        try!(converter.extract_audio(&file_path, &save_path,convert_audio));
        try!(remove_file(&file_path));
    }else{
        if is_splitted_video {
            try!(remove_file(&file_path));
        }else{
            try!(lib::move_file(&file_path, &save_path));
        }
    }
    file_db.pop();

    if !is_zipped { // add file to list, except it's for zip-compression later (=folder set)
        lib::add_file_entry(&downl_db.pool.clone(), &downl_db.qid,&name_http_valid, &name);
    }
    if !downl_db.compress {
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, true);
    }

    if folder.is_some() {
        Ok(Some(save_path))
    } else {
        Ok(None)
    }
}

///Handles a playlist request
///If zipping isn't requested the downloads will be split up,
///so for each video in the playlist an own query entry will be created
fn handle_playlist(mut downl_db: DownloadDB, converter: &Converter, file_db: &mut Vec<String>) -> Result<Option<String>, DownloadError>{
    let mut max_steps: i32 = if downl_db.compress { 4 } else { 3 };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, max_steps,false);

    let pl_id: i64 = downl_db.qid;
    downl_db.update_folder(format!("{}/{}",&CONFIG.general.save_dir,pl_id));
    println!("Folder:  {}",downl_db.folder);

    let db_copy = downl_db.clone();
    let download = Downloader::new(&db_copy, &CONFIG.general);

    let mut playlist_name = String::new();
    if downl_db.compress {
        playlist_name = try!(download.get_playlist_name());
        playlist_name = lib::url_encode(&playlist_name);
        println!("pl name {}",playlist_name);
        try!(std::fs::create_dir(&downl_db.folder));
        file_db.push(downl_db.folder.clone());
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, max_steps,false);
    println!("retriving playlist videos..");
    let file_ids: Vec<String> = try!(download.get_playlist_ids());

    let handler_folder = if downl_db.compress {
        Some(pl_id.to_string())
    }else {
        None
    };

    println!("got em");
    max_steps += file_ids.len() as i32;
    let mut current_step = 2;
    let mut current_url: String;
    // we'll store all files and delete em later, so we don't need rm -rf
    let mut file_delete_list: Vec<String> = Vec::with_capacity(if downl_db.compress { file_ids.len() } else { 0 });
    for id in file_ids.iter() {
        current_step += 1;
        if downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, max_steps,false);
        }
        downl_db.update_video(format!("https://wwww.youtube.com/watch?v={}",id), current_step);
        println!("id: {}",id);
        let db_copy = downl_db.clone();
        match handle_download(db_copy, &handler_folder, converter, file_db) {
            Err(e) => println!("error downloading {}: {:?}",id,e),
            Ok(e) => {  if downl_db.compress {
                            file_delete_list.push(e.unwrap());
                        }
                },
        }
    }

    println!("downloaded all videos");
    if downl_db.compress { // zip to file, add to db & remove all sources
        let zip_name = format!("{}.zip",playlist_name);
        let zip_file = format!("{}/{}",&CONFIG.general.save_dir,zip_name);
        try!(lib::zip_folder(&downl_db.folder, &zip_file));
        lib::add_file_entry(&downl_db.pool.clone(), &pl_id,&zip_name, &playlist_name);
        try!(lib::delete_files(file_delete_list));
        try!(remove_dir(downl_db.folder));
        file_db.pop();
    }

    Ok(None)
}
<commit_msg>fixed step updater<commit_after>extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::DownloadError;
use lib::converter::Converter;

use std::fs::{remove_file,remove_dir};

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;
static CODE_FAILED: i8 = 3;
static CODE_SUCCESS: i8 = 2;

lazy_static! {
    pub static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] broken, enum not usable as of #10292
// enum QueryCodes {
//     Waiting = 0,
//     InProgress = 1,
//     Finished = 2,
//     Failed = 3,
// }

fn main() {

    let pool = lib::db_connect(lib::mysql_options(), SLEEP_MS);

    let converter = Converter::new(&CONFIG.general.ffmpeg_bin,&CONFIG.general.mp3_quality , pool.clone());
    let mut print_pause = true;
    loop {
        if let Some(result) = lib::request_entry(& pool) {
            print_pause = true;
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            lib::set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");
            lib::set_query_state(&pool.clone(),&qid, "started", false);

            let succes;
            {
                let mut left_files: Vec<String> = Vec::with_capacity(2);
                if result.playlist {
                    succes = match handle_playlist(result, &converter,&mut left_files) {
                        Ok(v) => Ok(v),
                        Err(e) => {println!("Playlist Error: {:?}", e); Err(e) }
                    };
                }else{
                    succes = match handle_download(result, &None, &converter,&mut left_files) {
                        Ok(v) => Ok(v),
                        Err(e) => {println!("Download Error: {:?}", e); Err(e) }
                    };
                }

                if !left_files.is_empty() {
                    println!("cleaning up files");
                    for i in &left_files {
                        match remove_file(&i) {
                            Ok(_) => (println!("cleaning up {}",i)),
                            Err(e) => println!("unable to remove file '{}' {}",i,e),
                        }
                    }
                }
            }

            let code: i8 = if succes.is_ok() {
                CODE_SUCCESS//QueryCode
            } else {
                CODE_FAILED//QueryCode
            };
            lib::set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");

            let state = if code == 2 {
                "finished"
            } else {
                "failed"
            };
            lib::set_query_state(&pool.clone(),&qid, state, true);

        } else {
            if print_pause { println!("Pausing.."); print_pause = false; }
            std::thread::sleep_ms(SLEEP_MS);
        }
    }
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video separately and convert them together
///In case of a playlist download it depends on the target download folder & if it should be bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, the video but with the highest quality.
///Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, it's moved after a successful download, converted etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode'd name of the file is stored in the DB
fn handle_download<'a>(downl_db: DownloadDB, folder: &Option<String>, converter: &Converter, file_db: &mut Vec<String>) -> Result<Option<String>,DownloadError>{
    //update progress
    let is_zipped = match *folder {
        Some(_) => true,
        None => false,
    };
    if !downl_db.compress {
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, 0,false);
    }

    let download = Downloader::new(&downl_db, &CONFIG.general);
    //get filename, check for DMCA
    let mut dmca = false; // "succ." dmca -> file already downloaded

    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib.. // k if( k == Err(DownloadError::DMCAError) )
            println!("DMCA error!");
            match download.lib_request_video() {
                Err(err) => { println!("Offliberty-call error {:?}", err); return Err(err); },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / restricted source etc.. abort
            println!("Unknown error: {:?}", e);
            return Err(e);
        },
    };

    let name_http_valid = lib::format_file_name(&name, &download, &downl_db.qid);

    let file_path = lib::format_file_path(&downl_db.qid, folder.clone(), false);
    file_db.push(file_path.clone());
    let save_path = lib::format_save_path(folder.clone(),&name, &download, &downl_db.qid);

    println!("Filename: {}", name);

    let is_splitted_video = if dmca {
        false
    } else {
        lib::is_split_container(&downl_db.quality)
    };
    let convert_audio = CONFIG.extensions.mp3.contains(&downl_db.quality);

    let total_steps = if dmca {
        if download.is_audio() {
            3
        } else {
            2
        }
    } else if is_splitted_video {
        4
    } else if download.is_audio() {
        3
    } else {
        2
    };

    if !dmca {
        if !downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, total_steps,false);
        }

        //download first file, download audio raw source if specified or video
        try!(download.download_file(&file_path, convert_audio));

        if is_splitted_video {
            // download audio file & convert together
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 3, total_steps,false);

            let audio_path = lib::format_file_path(&downl_db.qid, folder.clone(), true);
            file_db.push(audio_path.clone());

            println!("Downloading audio.. {}", audio_path);
            try!(download.download_file(&audio_path, true));

            if !downl_db.compress {
                lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 4, total_steps,false);
            }

            match converter.merge_files(&downl_db.qid,&file_path, &audio_path,&save_path, !downl_db.compress) {
                Err(e) => {println!("merge error: {:?}",e); return Err(e);},
                Ok(()) => {},
            }

            try!(remove_file(&audio_path));
            file_db.pop();

        }else{ // we're already done, only need to copy if it's not raw audio source
            if !download.is_audio() {
                try!(lib::move_file(&file_path, &save_path));
            }
        }
    }

    if download.is_audio(){ // if audio-> convert m4a to mp3, which converts directly to downl. dir
        if !downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, false);
        }
        try!(converter.extract_audio(&file_path, &save_path,convert_audio));
        try!(remove_file(&file_path));
    }else{
        if is_splitted_video {
            try!(remove_file(&file_path));
        }else{
            try!(lib::move_file(&file_path, &save_path));
        }
    }
    file_db.pop();

    if !is_zipped { // add file to list, except it's for zip-compression later (=folder set)
        lib::add_file_entry(&downl_db.pool.clone(), &downl_db.qid,&name_http_valid, &name);
    }
    if !downl_db.compress {
        lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, total_steps, total_steps, true);
    }

    if folder.is_some() {
        Ok(Some(save_path))
    } else {
        Ok(None)
    }
}

///Handles a playlist request
///If zipping isn't requested the downloads will be split up,
///so for each video in the playlist an own query entry will be created
fn handle_playlist(mut downl_db: DownloadDB, converter: &Converter, file_db: &mut Vec<String>) -> Result<Option<String>, DownloadError>{
    let mut max_steps: i32 = if downl_db.compress { 4 } else { 3 };
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 1, max_steps,false);

    let pl_id: i64 = downl_db.qid;
    downl_db.update_folder(format!("{}/{}",&CONFIG.general.save_dir,pl_id));
    println!("Folder:  {}",downl_db.folder);

    let db_copy = downl_db.clone();
    let download = Downloader::new(&db_copy, &CONFIG.general);

    let mut playlist_name = String::new();
    if downl_db.compress {
        playlist_name = try!(download.get_playlist_name());
        playlist_name = lib::url_encode(&playlist_name);
        println!("pl name {}",playlist_name);
        try!(std::fs::create_dir(&downl_db.folder));
        file_db.push(downl_db.folder.clone());
    }
    lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, 2, max_steps,false);
    println!("retriving playlist videos..");
    let file_ids: Vec<String> = try!(download.get_playlist_ids());

    let handler_folder = if downl_db.compress {
        Some(pl_id.to_string())
    }else {
        None
    };

    println!("got em");
    max_steps += file_ids.len() as i32;
    let mut current_step = 2;
    let mut current_url: String;
    // we'll store all files and delete em later, so we don't need rm -rf
    let mut file_delete_list: Vec<String> = Vec::with_capacity(if downl_db.compress { file_ids.len() } else { 0 });
    for id in file_ids.iter() {
        current_step += 1;
        if downl_db.compress {
            lib::update_steps(&downl_db.pool.clone(),&downl_db.qid, current_step, max_steps,false);
        }
        downl_db.update_video(format!("https://wwww.youtube.com/watch?v={}",id), current_step as i64);
        println!("id: {}",id);
        let db_copy = downl_db.clone();
        match handle_download(db_copy, &handler_folder, converter, file_db) {
            Err(e) => println!("error downloading {}: {:?}",id,e),
            Ok(e) => {  if downl_db.compress {
                            file_delete_list.push(e.unwrap());
                        }
                },
        }
    }

    println!("downloaded all videos");
    if downl_db.compress { // zip to file, add to db & remove all sources
        let zip_name = format!("{}.zip",playlist_name);
        let zip_file = format!("{}/{}",&CONFIG.general.save_dir,zip_name);
        try!(lib::zip_folder(&downl_db.folder, &zip_file));
        lib::add_file_entry(&downl_db.pool.clone(), &pl_id,&zip_name, &playlist_name);
        try!(lib::delete_files(file_delete_list));
        try!(remove_dir(downl_db.folder));
        file_db.pop();
    }

    Ok(None)
}
<|endoftext|>


<commit_before>#![deny(bare_trait_objects, anonymous_parameters, elided_lifetimes_in_paths)]

use cargo;
use env_logger;

#[macro_use]
mod macros;
mod cargo_ops;
use crate::cargo_ops::{ElaborateWorkspace, TempProject};

use cargo::core::maybe_allow_nightly_features;
use cargo::core::shell::Verbosity;
use cargo::core::Workspace;
use cargo::util::important_paths::find_root_manifest_for_wd;
use cargo::util::{CargoResult, CliError, Config};
use docopt::Docopt;

pub const USAGE: &str = "
Displays information about project dependency versions

USAGE:
    cargo outdated [options]

Options:
    -a, --aggressive            Ignores channels for latest updates
    -h, --help                  Prints help information
        --format FORMAT         Output formatting [default: list]
                                [values: list, json]
    -q, --quiet                 Suppresses warnings
    -R, --root-deps-only        Only check root dependencies (Equivalent to --depth=1)
    -V, --version               Prints version information
    -v, --verbose ...           Use verbose output
    -w, --workspace             Checks updates for all workspace members rather than
                                only the root package
        --color COLOR           Coloring: auto, always, never [default: auto]
                                [values: auto, always, never]
    -d, --depth NUM             How deep in the dependency chain to search
                                (Defaults to all dependencies when omitted)
        --exit-code NUM         The exit code to return on new versions found [default: 0]
        --features FEATURES     Space-separated list of features
    -m, --manifest-path FILE    An absolute path to the Cargo.toml file to use
                                (Defaults to Cargo.toml in project root)
    -p, --packages PKGS         Packages to inspect for updates
    -r, --root ROOT             Package to treat as the root package
";

/// Options from CLI arguments
#[derive(serde_derive::Deserialize, Debug)]
pub struct Options {
    flag_format: Option<String>,
    flag_color: Option<String>,
    flag_features: Vec<String>,
    flag_manifest_path: Option<String>,
    flag_quiet: bool,
    flag_verbose: u32,
    flag_exit_code: i32,
    flag_packages: Vec<String>,
    flag_root: Option<String>,
    flag_depth: Option<i32>,
    flag_root_deps_only: bool,
    flag_workspace: bool,
    flag_aggressive: bool,
}

impl Options {
    fn all_features(&self) -> bool {
        self.flag_features.is_empty()
    }

    fn no_default_features(&self) -> bool {
        !(self.flag_features.is_empty() || self.flag_features.contains(&"default".to_owned()))
    }

    fn locked(&self) -> bool {
        false
    }

    fn frozen(&self) -> bool {
        false
    }
}

fn main() {
    env_logger::init();
    let options = {
        let mut options: Options = Docopt::new(USAGE)
            .and_then(|d| {
                d.version(Some(
                    concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION")).to_owned(),
                ))
                .deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        fn flat_split(arg: &[String]) -> Vec<String> {
            arg.iter()
                .flat_map(|s| s.split_whitespace())
                .flat_map(|s| s.split(','))
                .filter(|s| !s.is_empty())
                .map(ToString::to_string)
                .collect()
        }
        options.flag_features = flat_split(&options.flag_features);
        options.flag_packages = flat_split(&options.flag_packages);
        if options.flag_root_deps_only {
            options.flag_depth = Some(1);
        }
        options
    };

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = cargo::core::Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };
    let exit_code = options.flag_exit_code;
    let result = execute(options, &mut config);
    match result {
        Err(e) => {
            config.shell().set_verbosity(Verbosity::Normal);
            let cli_error = CliError::new(e, 1);
            cargo::exit_with_error(cli_error, &mut *config.shell())
        }
        Ok(i) => {
            if i > 0 {
                std::process::exit(exit_code);
            } else {
                std::process::exit(0);
            }
        }
    }
}

pub fn execute(options: Options, config: &mut Config) -> CargoResult<i32> {
    config.configure(
        options.flag_verbose,
        None,
        &options.flag_color,
        options.frozen(),
        options.locked(),
        false,
        &None,
        &[],
    )?;
    debug!(config, format!("options: {:?}", options));

    // Needed to allow nightly features
    maybe_allow_nightly_features();

    verbose!(config, "Parsing...", "current workspace");
    // the Cargo.toml that we are actually working on
    let curr_manifest = if let Some(ref manifest_path) = options.flag_manifest_path {
        manifest_path.into()
    } else {
        find_root_manifest_for_wd(config.cwd())?
    };
    let curr_workspace = Workspace::new(&curr_manifest, config)?;
    verbose!(config, "Resolving...", "current workspace");
    if options.flag_verbose == 0 {
        config.shell().set_verbosity(Verbosity::Quiet);
    }
    let ela_curr = ElaborateWorkspace::from_workspace(&curr_workspace, &options)?;
    if options.flag_verbose > 0 {
        config.shell().set_verbosity(Verbosity::Verbose);
    } else {
        config.shell().set_verbosity(Verbosity::Normal);
    }

    verbose!(config, "Parsing...", "compat workspace");
    let compat_proj =
        TempProject::from_workspace(&ela_curr, &curr_manifest.to_string_lossy(), &options)?;
    compat_proj.write_manifest_semver(
        curr_workspace.root(),
        compat_proj.temp_dir.path(),
        &ela_curr,
    )?;
    verbose!(config, "Updating...", "compat workspace");
    compat_proj.cargo_update()?;
    verbose!(config, "Resolving...", "compat workspace");
    let compat_workspace = compat_proj.workspace.borrow();
    let ela_compat =
        ElaborateWorkspace::from_workspace(compat_workspace.as_ref().unwrap(), &options)?;

    verbose!(config, "Parsing...", "latest workspace");
    let latest_proj =
        TempProject::from_workspace(&ela_curr, &curr_manifest.to_string_lossy(), &options)?;
    latest_proj.write_manifest_latest(
        curr_workspace.root(),
        compat_proj.temp_dir.path(),
        &ela_curr,
    )?;
    verbose!(config, "Updating...", "latest workspace");
    latest_proj.cargo_update()?;
    verbose!(config, "Resolving...", "latest workspace");
    let latest_workspace = latest_proj.workspace.borrow();
    let ela_latest =
        ElaborateWorkspace::from_workspace(latest_workspace.as_ref().unwrap(), &options)?;

    if ela_curr.workspace_mode {
        let mut sum = 0;
        if options.flag_format == Some("list".to_string()) {
            verbose!(config, "Printing...", "Package status in list format");
        } else if options.flag_format == Some("json".to_string()) {
            verbose!(config, "Printing...", "Package status in json format");
        }

        for member in ela_curr.workspace.members() {
            ela_curr.resolve_status(
                &ela_compat,
                &ela_latest,
                &options,
                config,
                member.package_id(),
            )?;
            if options.flag_format == Some("list".to_string()) {
                sum += ela_curr.print_list(&options, member.package_id(), sum > 0)?;
            } else if options.flag_format == Some("json".to_string()) {
                sum += ela_curr.print_json(&options, member.package_id(), sum > 0)?;
            }
        }
        if sum == 0 {
            println!("All dependencies are up to date, yay!");
        }
        Ok(sum)
    } else {
        verbose!(config, "Resolving...", "package status");
        let root = ela_curr.determine_root(&options)?;
        ela_curr.resolve_status(&ela_compat, &ela_latest, &options, config, root)?;
        verbose!(config, "Printing...", "list format");
        let mut count = 0;

        if options.flag_format == Some("list".to_string()) {
            count = ela_curr.print_list(&options, root, false)?;
        } else if options.flag_format == Some("json".to_string()) {
            ela_curr.print_json(&options, root, false)?;
        } else {
            println!("Error, did not specify list or json output formatting");
            std::process::exit(2);
        }

        Ok(count)
    }
}
<commit_msg>Moved member.package_id() and root to references in main.rs<commit_after>#![deny(bare_trait_objects, anonymous_parameters, elided_lifetimes_in_paths)]

use cargo;
use env_logger;

#[macro_use]
mod macros;
mod cargo_ops;
use crate::cargo_ops::{ElaborateWorkspace, TempProject};

use cargo::core::maybe_allow_nightly_features;
use cargo::core::shell::Verbosity;
use cargo::core::Workspace;
use cargo::util::important_paths::find_root_manifest_for_wd;
use cargo::util::{CargoResult, CliError, Config};
use docopt::Docopt;

pub const USAGE: &str = "
Displays information about project dependency versions

USAGE:
    cargo outdated [options]

Options:
    -a, --aggressive            Ignores channels for latest updates
    -h, --help                  Prints help information
        --format FORMAT         Output formatting [default: list]
                                [values: list, json]
    -q, --quiet                 Suppresses warnings
    -R, --root-deps-only        Only check root dependencies (Equivalent to --depth=1)
    -V, --version               Prints version information
    -v, --verbose ...           Use verbose output
    -w, --workspace             Checks updates for all workspace members rather than
                                only the root package
        --color COLOR           Coloring: auto, always, never [default: auto]
                                [values: auto, always, never]
    -d, --depth NUM             How deep in the dependency chain to search
                                (Defaults to all dependencies when omitted)
        --exit-code NUM         The exit code to return on new versions found [default: 0]
        --features FEATURES     Space-separated list of features
    -m, --manifest-path FILE    An absolute path to the Cargo.toml file to use
                                (Defaults to Cargo.toml in project root)
    -p, --packages PKGS         Packages to inspect for updates
    -r, --root ROOT             Package to treat as the root package
";

/// Options from CLI arguments
#[derive(serde_derive::Deserialize, Debug)]
pub struct Options {
    flag_format: Option<String>,
    flag_color: Option<String>,
    flag_features: Vec<String>,
    flag_manifest_path: Option<String>,
    flag_quiet: bool,
    flag_verbose: u32,
    flag_exit_code: i32,
    flag_packages: Vec<String>,
    flag_root: Option<String>,
    flag_depth: Option<i32>,
    flag_root_deps_only: bool,
    flag_workspace: bool,
    flag_aggressive: bool,
}

impl Options {
    fn all_features(&self) -> bool {
        self.flag_features.is_empty()
    }

    fn no_default_features(&self) -> bool {
        !(self.flag_features.is_empty() || self.flag_features.contains(&"default".to_owned()))
    }

    fn locked(&self) -> bool {
        false
    }

    fn frozen(&self) -> bool {
        false
    }
}

fn main() {
    env_logger::init();
    let options = {
        let mut options: Options = Docopt::new(USAGE)
            .and_then(|d| {
                d.version(Some(
                    concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION")).to_owned(),
                ))
                .deserialize()
            })
            .unwrap_or_else(|e| e.exit());
        fn flat_split(arg: &[String]) -> Vec<String> {
            arg.iter()
                .flat_map(|s| s.split_whitespace())
                .flat_map(|s| s.split(','))
                .filter(|s| !s.is_empty())
                .map(ToString::to_string)
                .collect()
        }
        options.flag_features = flat_split(&options.flag_features);
        options.flag_packages = flat_split(&options.flag_packages);
        if options.flag_root_deps_only {
            options.flag_depth = Some(1);
        }
        options
    };

    let mut config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = cargo::core::Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };
    let exit_code = options.flag_exit_code;
    let result = execute(options, &mut config);
    match result {
        Err(e) => {
            config.shell().set_verbosity(Verbosity::Normal);
            let cli_error = CliError::new(e, 1);
            cargo::exit_with_error(cli_error, &mut *config.shell())
        }
        Ok(i) => {
            if i > 0 {
                std::process::exit(exit_code);
            } else {
                std::process::exit(0);
            }
        }
    }
}

pub fn execute(options: Options, config: &mut Config) -> CargoResult<i32> {
    config.configure(
        options.flag_verbose,
        None,
        &options.flag_color,
        options.frozen(),
        options.locked(),
        false,
        &None,
        &[],
    )?;
    debug!(config, format!("options: {:?}", options));

    // Needed to allow nightly features
    maybe_allow_nightly_features();

    verbose!(config, "Parsing...", "current workspace");
    // the Cargo.toml that we are actually working on
    let curr_manifest = if let Some(ref manifest_path) = options.flag_manifest_path {
        manifest_path.into()
    } else {
        find_root_manifest_for_wd(config.cwd())?
    };
    let curr_workspace = Workspace::new(&curr_manifest, config)?;
    verbose!(config, "Resolving...", "current workspace");
    if options.flag_verbose == 0 {
        config.shell().set_verbosity(Verbosity::Quiet);
    }
    let ela_curr = ElaborateWorkspace::from_workspace(&curr_workspace, &options)?;
    if options.flag_verbose > 0 {
        config.shell().set_verbosity(Verbosity::Verbose);
    } else {
        config.shell().set_verbosity(Verbosity::Normal);
    }

    verbose!(config, "Parsing...", "compat workspace");
    let compat_proj =
        TempProject::from_workspace(&ela_curr, &curr_manifest.to_string_lossy(), &options)?;
    compat_proj.write_manifest_semver(
        curr_workspace.root(),
        compat_proj.temp_dir.path(),
        &ela_curr,
    )?;
    verbose!(config, "Updating...", "compat workspace");
    compat_proj.cargo_update()?;
    verbose!(config, "Resolving...", "compat workspace");
    let compat_workspace = compat_proj.workspace.borrow();
    let ela_compat =
        ElaborateWorkspace::from_workspace(compat_workspace.as_ref().unwrap(), &options)?;

    verbose!(config, "Parsing...", "latest workspace");
    let latest_proj =
        TempProject::from_workspace(&ela_curr, &curr_manifest.to_string_lossy(), &options)?;
    latest_proj.write_manifest_latest(
        curr_workspace.root(),
        compat_proj.temp_dir.path(),
        &ela_curr,
    )?;
    verbose!(config, "Updating...", "latest workspace");
    latest_proj.cargo_update()?;
    verbose!(config, "Resolving...", "latest workspace");
    let latest_workspace = latest_proj.workspace.borrow();
    let ela_latest =
        ElaborateWorkspace::from_workspace(latest_workspace.as_ref().unwrap(), &options)?;

    if ela_curr.workspace_mode {
        let mut sum = 0;
        if options.flag_format == Some("list".to_string()) {
            verbose!(config, "Printing...", "Package status in list format");
        } else if options.flag_format == Some("json".to_string()) {
            verbose!(config, "Printing...", "Package status in json format");
        }

        for member in ela_curr.workspace.members() {
            ela_curr.resolve_status(
                &ela_compat,
                &ela_latest,
                &options,
                config,
                member.package_id(),
            )?;
            if options.flag_format == Some("list".to_string()) {
                sum += ela_curr.print_list(&options, &member.package_id(), sum > 0)?;
            } else if options.flag_format == Some("json".to_string()) {
                sum += ela_curr.print_json(&options, &member.package_id(), sum > 0)?;
            }
        }
        if sum == 0 {
            println!("All dependencies are up to date, yay!");
        }
        Ok(sum)
    } else {
        verbose!(config, "Resolving...", "package status");
        let root = ela_curr.determine_root(&options)?;
        ela_curr.resolve_status(&ela_compat, &ela_latest, &options, config, root)?;
        verbose!(config, "Printing...", "list format");
        let mut count = 0;

        if options.flag_format == Some("list".to_string()) {
            count = ela_curr.print_list(&options, root, false)?;
        } else if options.flag_format == Some("json".to_string()) {
            ela_curr.print_json(&options, &root, false)?;
        } else {
            println!("Error, did not specify list or json output formatting");
            std::process::exit(2);
        }

        Ok(count)
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libsnatch;
extern crate num_cpus;

use ansi_term::Colour::{Green, Yellow, Red};
use clap::{App, Arg};
use libsnatch::download::download_chunks;
use libsnatch::write::OutputFileWriter;
use libsnatch::util::prompt_user;
use libsnatch::filesize::format_filesize;
use libsnatch::cargo_helper::get_cargo_info;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

static DEFAULT_FILENAME: &'static str = "index.html";

fn main() {

    // Parse arguments

    let argparse = App::new("Snatch")
        .about("Snatch, a simple, fast and interruptable download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    let url = argparse.value_of("url").unwrap();

    let file = argparse
        .value_of("file")
        .unwrap_or_else(|| url.split('/').last().unwrap_or(DEFAULT_FILENAME));

    let threads: usize = value_t!(argparse, "threads", usize).unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        println!("# [{}] version: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 crate_version!());
        println!("# [{}] file: {}", Yellow.bold().paint("DEBUG_MODE"), file);
        println!("# [{}] threads: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 threads);
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(Yellow.bold(),
                                         "[WARNING] The path to store the file already exists! \
                                          Do you want to override it? [y/N]");

            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            println!("{}",
                     Yellow
                         .bold()
                         .paint("[WARNING] The path to store the file already exists! \
                                 It is going to be overriden."));
        }
    }

    let cargo_info = get_cargo_info(&url).expect("fail to parse url");
    println!("# Remote content length: {}",
             format_filesize(cargo_info.content_length));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file
        .set_len(cargo_info.content_length)
        .expect("[ERROR] Cannot extend file to download size!");
    let out_file = OutputFileWriter::new(local_file);

    if download_chunks(cargo_info, out_file, threads as u64, &url) {
        println!("{} Your download is available in {}",
                 Green.bold().paint("Done!"),
                 local_path.to_str().unwrap());
    } else {
        // If the file is not ok, delete it from the file system
        print!("{} An error occured - erasing file... ",
               Red.bold().paint("Failed!"));
        match remove_file(local_path) {
            Ok(_) => println!("done !"),
            Err(e) => println!("failed ({}) !", e),
        }
    }

}
<commit_msg>If 0 thread is used (!!), get the machine configuration<commit_after>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libsnatch;
extern crate num_cpus;

use ansi_term::Colour::{Green, Yellow, Red};
use clap::{App, Arg};
use libsnatch::download::download_chunks;
use libsnatch::write::OutputFileWriter;
use libsnatch::util::prompt_user;
use libsnatch::filesize::format_filesize;
use libsnatch::cargo_helper::get_cargo_info;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

static DEFAULT_FILENAME: &'static str = "index.html";

fn main() {

    // Parse arguments

    let argparse = App::new("Snatch")
        .about("Snatch, a simple, fast and interruptable download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    let url = argparse.value_of("url").unwrap();

    let file = argparse
        .value_of("file")
        .unwrap_or_else(|| url.split('/').last().unwrap_or(DEFAULT_FILENAME));

    let threads: usize = value_t!(argparse, "threads", usize)
        .and_then(|v| if v != 0 {
                      Ok(v)
                  } else {
                      Err(clap::Error::with_description("Cannot download a file using 0 thread",
                                                        clap::ErrorKind::InvalidValue))
                  })
        .unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        println!("# [{}] version: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 crate_version!());
        println!("# [{}] file: {}", Yellow.bold().paint("DEBUG_MODE"), file);
        println!("# [{}] threads: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 threads);
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(Yellow.bold(),
                                         "[WARNING] The path to store the file already exists! \
                                          Do you want to override it? [y/N]");

            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            println!("{}",
                     Yellow
                         .bold()
                         .paint("[WARNING] The path to store the file already exists! \
                                 It is going to be overriden."));
        }
    }

    let cargo_info = get_cargo_info(&url).expect("fail to parse url");
    println!("# Remote content length: {}",
             format_filesize(cargo_info.content_length));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file
        .set_len(cargo_info.content_length)
        .expect("[ERROR] Cannot extend file to download size!");
    let out_file = OutputFileWriter::new(local_file);

    if download_chunks(cargo_info, out_file, threads as u64, &url) {
        println!("{} Your download is available in {}",
                 Green.bold().paint("Done!"),
                 local_path.to_str().unwrap());
    } else {
        // If the file is not ok, delete it from the file system
        print!("{} An error occured - erasing file... ",
               Red.bold().paint("Failed!"));
        match remove_file(local_path) {
            Ok(_) => println!("done !"),
            Err(e) => println!("failed ({}) !", e),
        }
    }

}
<|endoftext|>


<commit_before>#![feature(box_syntax,box_patterns,slice_patterns)]

#[macro_use]
extern crate nom;

use nom::{IResult, digit};

#[derive(Debug)]
enum Expr {
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
    Num(i32),
}

named!(parens<Expr>, ws!(delimited!(tag!("("), expression, tag!(")"))));

named!(factor<Expr>,
       alt!(
           map_res!(
               ws!(digit),
               |value: &[u8]|
                   std::str::from_utf8(value).unwrap().parse::<i32>().map(Expr::Num)
           )
           | parens
       )
);

named!(term<Expr>,
       do_parse!(
           lhs: factor >>
           res: fold_many0!(
               do_parse!(
                   op: alt!(tag!("*") | tag!("/")) >>
                   value: factor >>
                   (op, value)
               ),
               lhs,
               |acc, (op, value): (&[u8], Expr)| {
                   if op[0] as char == '*' {
                       Expr::Mul(box acc, box value)
                   } else {
                       Expr::Div(box acc, box value)
                   }
               }
           ) >>
           (res)
       )
);

named!(expression<Expr>,
       do_parse!(
           lhs: term >>
           res: fold_many0!(
               do_parse!(
                   op: alt!(tag!("+") | tag!("-")) >>
                   value: term >>
                   (op, value)
               ),
               lhs,
               |acc, (op, value): (&[u8], Expr)| {
                   if op[0] as char == '+' {
                       Expr::Add(box acc, box value)
                   } else {
                       Expr::Sub(box acc, box value)
                   }
               }
           ) >>
           (res)
       )
);

fn consume(tree: Expr) -> i32 {
    use Expr::*;

    match tree {
        Add(box lhs, box rhs) => consume(lhs) + consume(rhs),
        Sub(box lhs, box rhs) => consume(lhs) - consume(rhs),
        Mul(box lhs, box rhs) => consume(lhs) * consume(rhs),
        Div(box lhs, box rhs) => consume(lhs) / consume(rhs),
        Num(value) => value,
    }
}

fn main() {
    let exp = expression(&b"42 +3 * 7- 1/1"[..]);
    println!("Expression: {:?}", exp);
    if let IResult::Done(&[], exp) = exp {
        println!("Value: {}", consume(exp));
    } else {
        println!("Error while parsing: {:?}", exp);
    }
}
<commit_msg>Added RPN + borrow when consuming<commit_after>#![feature(box_syntax,box_patterns,slice_patterns)]

#[macro_use]
extern crate nom;

use nom::{IResult, digit};

#[derive(Debug)]
enum Expr {
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
    Num(i32),
}

named!(parens<Expr>, ws!(delimited!(tag!("("), expression, tag!(")"))));

named!(factor<Expr>,
       alt!(
           map_res!(
               ws!(digit),
               |value: &[u8]|
                   std::str::from_utf8(value).unwrap().parse::<i32>().map(Expr::Num)
           )
           | parens
       )
);

named!(term<Expr>,
       do_parse!(
           lhs: factor >>
           res: fold_many0!(
               do_parse!(
                   op: alt!(tag!("*") | tag!("/")) >>
                   value: factor >>
                   (op, value)
               ),
               lhs,
               |acc, (op, value): (&[u8], Expr)| {
                   if op[0] as char == '*' {
                       Expr::Mul(box acc, box value)
                   } else {
                       Expr::Div(box acc, box value)
                   }
               }
           ) >>
           (res)
       )
);

named!(expression<Expr>,
       do_parse!(
           lhs: term >>
           res: fold_many0!(
               do_parse!(
                   op: alt!(tag!("+") | tag!("-")) >>
                   value: term >>
                   (op, value)
               ),
               lhs,
               |acc, (op, value): (&[u8], Expr)| {
                   if op[0] as char == '+' {
                       Expr::Add(box acc, box value)
                   } else {
                       Expr::Sub(box acc, box value)
                   }
               }
           ) >>
           (res)
       )
);

fn consume(tree: &Expr) -> i32 {
    use Expr::*;

    match tree {
        &Add(box ref lhs, box ref rhs) => consume(&lhs) + consume(&rhs),
        &Sub(box ref lhs, box ref rhs) => consume(&lhs) - consume(&rhs),
        &Mul(box ref lhs, box ref rhs) => consume(&lhs) * consume(&rhs),
        &Div(box ref lhs, box ref rhs) => consume(&lhs) / consume(&rhs),
        &Num(value) => value,
    }
}

fn reverse_polish(tree: &Expr) -> String {
    use Expr::*;

    match tree {
        &Add(box ref lhs, box ref rhs) => format!("{} {} +", reverse_polish(&lhs), reverse_polish(&rhs)),
        &Sub(box ref lhs, box ref rhs) => format!("{} {} -", reverse_polish(&lhs), reverse_polish(&rhs)),
        &Mul(box ref lhs, box ref rhs) => format!("{} {} *", reverse_polish(&lhs), reverse_polish(&rhs)),
        &Div(box ref lhs, box ref rhs) => format!("{} {} /", reverse_polish(&lhs), reverse_polish(&rhs)),
        &Num(value) => value.to_string(),
    }
}

fn main() {
    let exp = expression(&b"42 +3 * 7- 1/1"[..]);
    println!("Expression: {:?}", exp);
    if let IResult::Done(&[], exp) = exp {
        println!("Value: {}", consume(&exp));
        println!("RPN: {}", reverse_polish(&exp));
    } else {
        println!("Error while parsing: {:?}", exp);
    }
}
<|endoftext|>