<commit_before>#[macro_use]
extern crate clap;

mod path_set;

use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::collections::HashSet;
use std::{env, process, io};
use std::ffi::OsStr;
use std::iter::once;
use std::process::Stdio;
use std::default::Default;

use path_set::{PathSetIter, iter};

struct Changes<'a, 'b> {
    to_remove: HashSet<String>,
    to_append: PathSetIter<clap::Values<'a>>,
    to_prepend: PathSetIter<clap::Values<'b>>,
}

fn main() {
    use clap::{App, Arg, SubCommand, AppSettings};

    let matches = App::new("env-control")
        .author("Renato Zannon <renato@rrsz.com.br>")
        .about("PATH-like string manipulation utility")
        .version(crate_version!())
        .arg_from_usage("[var-name] 'the PATH-like environment variable to manipulate. \
                         Defaults to $PATH'")
        .arg(Arg::from_usage("-a --append=[PATH]... 'Append this path to the variable'"))
        .arg(Arg::from_usage("-p --prepend=[PATH]... 'Prepend this path to the variable'"))
        .arg(Arg::from_usage("-r --remove=[PATH]... 'Remove this path from the variable'"))
        .subcommand(SubCommand::with_name("exec")
                    .about("Execute <cmd> with the modified var-name")
                    .arg_from_usage("<cmd> 'Command to execute'")
                    .arg_from_usage("[cmd-args]... 'Arguments to <cmd>'")
                    .setting(AppSettings::TrailingVarArg))
        .get_matches();

    let var_name = matches.value_of("var-name").unwrap_or("PATH");

    let current_path = match env::var(&var_name) {
        Ok(string) => string,
        Err(_)     => "".to_owned(),
    };

    let changes = Changes {
        to_remove:  path_iter(&matches, "remove").collect(),
        to_append:  path_iter(&matches, "append"),
        to_prepend: path_iter(&matches, "prepend"),
    };

    if let Some(ref exec_matches) = matches.subcommand_matches("exec") {
        let mut new_value = Vec::with_capacity(current_path.len());
        process_paths(&mut new_value, changes, &current_path).unwrap();

        env::set_var(&var_name, OsStr::from_bytes(&new_value));

        let cmd_name = exec_matches.value_of("cmd").unwrap();
        let cmd_args = exec_matches.values_of("cmd-args").unwrap_or_else(Default::default);

        process::Command::new(cmd_name)
            .args(cmd_args)
            .stdin(Stdio::inherit())
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .and_then(|mut child| child.wait())
            .unwrap();
    } else {
        let mut stdout = io::stdout();
        process_paths(&mut stdout, changes, &current_path).unwrap();
        write!(&mut stdout, "\n").unwrap();
    }
}

fn process_paths<W>(writer: &mut W, changes: Changes, current_path: &str) -> Result<(), io::Error> where W: Write {
    let Changes { to_append, to_prepend, to_remove } = changes;

    let mut combined_paths = to_prepend
        .chain(iter(once(current_path)))
        .chain(to_append)
        .filter(move |path| {
            !(path.trim().is_empty() || to_remove.contains(path))
        });

    let mut printed_paths: HashSet<String> = HashSet::new();

    if let Some(first_path) = combined_paths.next() {
        try!(write!(writer, "{}", first_path));
        printed_paths.insert(first_path);
    } else {
        return Ok(());
    }

    for path in combined_paths {
        if printed_paths.contains(&path) {
            continue
        }

        try!(write!(writer, ":{}", path));
        printed_paths.insert(path);
    }

    Ok(())
}

fn path_iter<'a>(matches: &'a clap::ArgMatches, option: &str) -> PathSetIter<clap::Values<'a>> {
    return iter(matches.values_of(option).unwrap_or_else(Default::default));
}
<commit_msg>Fix clap usage<commit_after>#[macro_use]
extern crate clap;

mod path_set;

use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::collections::HashSet;
use std::{env, process, io};
use std::ffi::OsStr;
use std::iter::once;
use std::process::Stdio;
use std::default::Default;

use path_set::{PathSetIter, iter};

struct Changes<'a, 'b> {
    to_remove: HashSet<String>,
    to_append: PathSetIter<clap::Values<'a>>,
    to_prepend: PathSetIter<clap::Values<'b>>,
}

fn main() {
    use clap::{App, Arg, SubCommand, AppSettings};

    let matches = App::new("env-control")
        .author("Renato Zannon <renato@rrsz.com.br>")
        .about("PATH-like string manipulation utility")
        .version(crate_version!())
        .arg(Arg::with_name("var-name")
             .help("the PATH-like environment variable to manipulate. Defaults to $PATH")
             .required(false)
             .index(1)
         )
        .args_from_usage("
            -a --append=[PATH]...  'Append this path to the variable'
            -p --prepend=[PATH]... 'Prepend this path to the variable'
            -r --remove=[PATH]...  'Remove this path from the variable'
        ")
        .subcommand(SubCommand::with_name("exec")
                    .about("Execute <cmd> with the modified var-name")
                    .arg_from_usage("<cmd> 'Command to execute'")
                    .arg_from_usage("[cmd-args]... 'Arguments to <cmd>'")
                    .setting(AppSettings::TrailingVarArg))
        .get_matches();

    let var_name = matches.value_of("var-name").unwrap_or("PATH");

    let current_path = match env::var(&var_name) {
        Ok(string) => string,
        Err(_)     => "".to_owned(),
    };

    let changes = Changes {
        to_remove:  path_iter(&matches, "remove").collect(),
        to_append:  path_iter(&matches, "append"),
        to_prepend: path_iter(&matches, "prepend"),
    };

    if let Some(ref exec_matches) = matches.subcommand_matches("exec") {
        let mut new_value = Vec::with_capacity(current_path.len());
        process_paths(&mut new_value, changes, &current_path).unwrap();

        env::set_var(&var_name, OsStr::from_bytes(&new_value));

        let cmd_name = exec_matches.value_of("cmd").unwrap();
        let cmd_args = exec_matches.values_of("cmd-args").unwrap_or_else(Default::default);

        process::Command::new(cmd_name)
            .args(cmd_args)
            .stdin(Stdio::inherit())
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .and_then(|mut child| child.wait())
            .unwrap();
    } else {
        let mut stdout = io::stdout();
        process_paths(&mut stdout, changes, &current_path).unwrap();
        write!(&mut stdout, "\n").unwrap();
    }
}

fn process_paths<W>(writer: &mut W, changes: Changes, current_path: &str) -> Result<(), io::Error> where W: Write {
    let Changes { to_append, to_prepend, to_remove } = changes;

    let mut combined_paths = to_prepend
        .chain(iter(once(current_path)))
        .chain(to_append)
        .filter(move |path| {
            !(path.trim().is_empty() || to_remove.contains(path))
        });

    let mut printed_paths: HashSet<String> = HashSet::new();

    if let Some(first_path) = combined_paths.next() {
        try!(write!(writer, "{}", first_path));
        printed_paths.insert(first_path);
    } else {
        return Ok(());
    }

    for path in combined_paths {
        if printed_paths.contains(&path) {
            continue
        }

        try!(write!(writer, ":{}", path));
        printed_paths.insert(path);
    }

    Ok(())
}

fn path_iter<'a>(matches: &'a clap::ArgMatches, option: &str) -> PathSetIter<clap::Values<'a>> {
    return iter(matches.values_of(option).unwrap_or_else(Default::default));
}
<|endoftext|>


<commit_before>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,
    last_spike: TimeStep,
    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            i_ext: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            last_spike: 0, // XXX
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }
}

fn main() {
    let config = Config::regular_spiking();

    const PARAMS : &'static [(&'static str, Num, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", 7.0, "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", 0.0, "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    // We use a cyclic buffer
    // We use (time_step % MAX_DELAY) as index into the futures_spike array
    let mut future_spikes: Vec<Vec<SynapseId>> = (0..MAX_DELAY as usize).map(|_| Vec::new()).collect();

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 40, 17.0);
    let _ = network.connect(n2, n2, 40, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();

    let mut time_step: TimeStep = 0;

    while time_step <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }
        time_step += 1;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_ext = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut future_spikes[(time_step % (MAX_DELAY as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_ext += weight;
            }
            current_spikes.clear();
        }

        // update state
        for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
            let mut syn_i = if time_step >= 200 && time_step <= 700 { PARAMS[i].1 } else { 0.0 };
            syn_i += neuron.i_ext;

            let (new_state, fired) = neuron.state.step_1ms(syn_i, &neuron.config);
            neuron.state = new_state;
            if fired {
                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in neuron.post_synapses.iter() {
                    let future = time_step + network.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }
            }
        }
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.2)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<commit_msg>Differentiate between i_ext and i_inp<commit_after>extern crate izhikevich_neurons;
extern crate gnuplot;

use izhikevich_neurons::{Config, State, Num};
use gnuplot::{Figure, Caption, Color, AxesCommon};

type NeuronId = u32;
type SynapseId = u32;
type TimeStep = u32;
type Delay = u8;

const MAX_DELAY: u8 = 40;

struct Synapse {
    pre_neuron: NeuronId,
    post_neuron: NeuronId,
    delay: Delay,
    weight: Num,
    last_spike: TimeStep,
    // ... learning parameters
}

struct Neuron {
    state: State,
    config: Config,
    i_ext: Num,
    i_inp: Num,
    pre_synapses: Vec<SynapseId>,
    post_synapses: Vec<SynapseId>,
}

struct Network {
    neurons: Vec<Neuron>,
    synapses: Vec<Synapse>,
}

impl Network {
    fn new() -> Network {
        Network {
            neurons: Vec::new(),
            synapses: Vec::new()
        }
    }

    fn create_neuron(&mut self, config: Config) -> NeuronId {
        let neuron = Neuron {
            state: State::new(),
            config: config,
            i_ext: 0.0,
            i_inp: 0.0,
            pre_synapses: Vec::new(),
            post_synapses: Vec::new(),
        };
        let neuron_id = self.neurons.len() as u32;
        self.neurons.push(neuron);
        return neuron_id;
    }

    fn connect(&mut self, pre_neuron: NeuronId, post_neuron: NeuronId, delay: Delay, weight: Num) -> SynapseId {
        assert!((pre_neuron as usize) < self.neurons.len());
        assert!((post_neuron as usize) < self.neurons.len());
        assert!(delay > 0);
        assert!(delay <= MAX_DELAY);

        let synapse = Synapse {
            pre_neuron: pre_neuron,
            post_neuron: post_neuron,
            delay: delay,
            weight: weight,
            last_spike: 0, // XXX
        };
        let synapse_id = self.synapses.len() as u32;

        self.synapses.push(synapse);
        self.neurons[pre_neuron as usize].post_synapses.push(synapse_id);
        self.neurons[post_neuron as usize].pre_synapses.push(synapse_id);

        return synapse_id;
    }
}

fn main() {
    let config = Config::regular_spiking();

    const PARAMS : &'static [(&'static str, Num, &'static str)] = &[
        ("Neuron 1 [7 pA current 200..700ms]", 7.0, "blue"),
        //("Neuron 2 [2.69 pA current 200..700ms]", 2.69, "red"),
        ("Neuron 2 [0.0 pA current 200..700ms]", 0.0, "red"),
        //("Neuron 3 [2.7 pA current 200..700ms]", 2.7, "green")
    ];

    let mut network = Network::new();

    let n1 = network.create_neuron(Config::regular_spiking());
    let n2 = network.create_neuron(Config::regular_spiking());
    //let n3 = network.create_neuron(Config::regular_spiking());

    // We use a cyclic buffer
    // We use (time_step % MAX_DELAY) as index into the futures_spike array
    let mut future_spikes: Vec<Vec<SynapseId>> = (0..MAX_DELAY as usize).map(|_| Vec::new()).collect();

    let _ = network.connect(n1, n2, 10, 7.0);
    let _ = network.connect(n1, n2, 5, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n1, n2, 2, 7.0);
    let _ = network.connect(n2, n2, 40, 17.0);
    let _ = network.connect(n2, n2, 40, 7.0);

    let mut states: Vec<_> = PARAMS.iter().map(|_| Vec::new()).collect();

    let mut time_step: TimeStep = 0;

    while time_step <= 1_000 {
        // record current state
        for (i, neuron) in network.neurons.iter().enumerate() {
            states[i].push(neuron.state);
        }
        time_step += 1;

        // Clear all input currents
        for neuron in network.neurons.iter_mut() {
            neuron.i_inp = 0.0;
        }

        // get all synapse input
        {
            let current_spikes = &mut future_spikes[(time_step % (MAX_DELAY as TimeStep)) as usize];
            for &syn_fired in current_spikes.iter() {
                println!("time: {}. input from synapse: {}", time_step, syn_fired);
                let (weight, post_neuron) = {
                    let syn = &network.synapses[syn_fired as usize];
                    (syn.weight, syn.post_neuron)
                };
                network.neurons[post_neuron as usize].i_inp += weight;
            }
            current_spikes.clear();
        }

        // update state
        for (i, mut neuron) in network.neurons.iter_mut().enumerate() {
            if time_step >= 200 && time_step <= 700 {
                neuron.i_ext = PARAMS[i].1;
            } else {
                neuron.i_ext = 0.0;
            }

            let syn_i = neuron.i_ext + neuron.i_inp;

            let (new_state, fired) = neuron.state.step_1ms(syn_i, &neuron.config);
            neuron.state = new_state;
            if fired {
                println!("Neuron {} fired at {} ms", i, time_step);
                for &syn_id in neuron.post_synapses.iter() {
                    let future = time_step + network.synapses[syn_id as usize].delay as TimeStep;
                    future_spikes[future as usize % MAX_DELAY as usize].push(syn_id);
                }
            }
        }
    }

    {
        let mut fg = Figure::new();
        {
            let mut diag = fg.axes2d().
                set_x_label("time (ms)", &[]).
                set_y_label("membrane potential v (mV)", &[]);
            for (i, &p) in PARAMS.iter().enumerate() {
                diag.lines(states[i].iter().enumerate().map(|(i, _)| i as f32), states[i].iter().map(|s| s.potential()), &[Caption(p.0), Color(p.2)]);
            }
        }
        fg.show();
    }

    /*
    let mut fg = Figure::new();
    {
        let mut diag = fg.axes2d().
            set_x_label("membrane potential v (mV)", &[]).
            set_y_label("recovery variable u", &[]);
        for (i, &p) in PARAMS.iter().enumerate() {
            diag.lines(states[i].iter().map(|s| s.potential()), states[i].iter().map(|s| s.recovery()), &[Caption(p.0), Color(p.2)]);
        }
    }
    fg.show();
    */

}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello World");
}
<commit_msg>variables<commit_after>fn main() {
    let x = 5*2;
    let y: f32 = 55.0;
    let (a, b) = (1, 55.9);
    println!("x = {}; y = {}; a = {}; b = {}", x, y, a, b);
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate futures;
extern crate hyper;
extern crate hyper_native_tls;
extern crate iron;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate lru_time_cache;
extern crate regex;
extern crate rlua;
extern crate router;
extern crate rusoto_core;
extern crate rusoto_sqs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate serde_yaml;
extern crate ssh2;
extern crate stderrlog;
extern crate tokio_core;

use futures::{Future, Sink, Stream};
use std::time::Duration;
use std::rc::Rc;

#[macro_use]
mod utils;
mod args;
mod bot;
mod gerrit;
mod spark;
mod sqs;

use spark::SparkClient;

fn spark_client_from_config(spark_config: args::SparkConfig) -> Rc<SparkClient> {
    if !spark_config.bot_token.is_empty() {
        Rc::new(
            spark::WebClient::new(
                spark_config.api_uri,
                spark_config.bot_token,
                spark_config.webhook_url,
            ).unwrap_or_else(|err| {
                error!("Could not create spark client: {}", err);
                std::process::exit(1);
            }),
        )
    } else {
        warn!("Using console as Spark client due to empty bot_token.");
        Rc::new(spark::ConsoleClient::new())
    }
}

fn main() {
    let args = args::parse_args();
    let config = args::parse_config(args.flag_config);
    stderrlog::new()
        .module(module_path!())
        .quiet(args.flag_quiet)
        .timestamp(stderrlog::Timestamp::Second)
        .verbosity(if args.flag_verbose { 5 } else { 2 })
        .init()
        .unwrap();
    info!("Starting");

    // load or create a new bot
    let mut bot = match bot::Bot::load("state.json") {
        Ok(bot) => {
            info!(
                "Loaded bot from 'state.json' with {} user(s).",
                bot.num_users()
            );
            bot
        }
        Err(err) => {
            warn!("Could not load bot from 'state.json': {:?}", err);
            bot::Bot::new()
        }
    };
    if config.bot.msg_expiration != 0 && config.bot.msg_capacity != 0 {
        debug!(
            "Approval LRU cache: capacity - {}, expiration - {} sec",
            config.bot.msg_capacity, config.bot.msg_expiration
        );
        bot.init_msg_cache(
            config.bot.msg_capacity,
            Duration::from_secs(config.bot.msg_expiration),
        );
    };

    // event loop
    let mut core = tokio_core::reactor::Core::new().unwrap();

    // create spark client and event stream listener
    let spark_client = spark_client_from_config(config.spark.clone());
    let spark_stream = match config.spark.mode.clone() {
        args::ModeConfig::Direct { endpoint } => {
            spark::webhook_event_stream(spark_client, &endpoint, core.remote())
        }
        args::ModeConfig::Sqs { uri, region } => spark::sqs_event_stream(spark_client, uri, region),
    };

    let spark_stream = spark_stream.unwrap_or_else(|err| {
        error!("Could not start listening to spark: {}", err);
        std::process::exit(1);
    });

    // create gerrit event stream listener
    let gerrit_config = config.gerrit.clone();
    info!(
        "(Re)connecting to Gerrit over ssh: {:?}",
        gerrit_config.host
    );

    let (gerrit_change_id_sink, gerrit_change_response_stream) = gerrit::change_sink(
        gerrit_config.host.clone(),
        gerrit_config.username.clone(),
        gerrit_config.priv_key_path.clone(),
    ).unwrap_or_else(|err| {
        error!(
            "Could not connect to Gerrit via SSH for sending commands: {}",
            err
        );
        std::process::exit(1);
    });

    let gerrit_stream = gerrit::event_stream(
        gerrit_config.host,
        gerrit_config.username,
        gerrit_config.priv_key_path,
    );

    // join spark and gerrit action streams into one and fold over actions with accumulator `bot`
    let spark_client = spark_client_from_config(config.spark.clone());
    let handle = core.handle();
    let actions = spark_stream
        .select(gerrit_stream)
        .select(gerrit_change_response_stream)
        .filter(|action| match *action {
            bot::Action::NoOp => false,
            _ => true,
        })
        .filter_map(move |action| {
            debug!("Handle action: {:?}", action);

            // fold over actions
            let old_bot = std::mem::replace(&mut bot, bot::Bot::new());
            let (new_bot, task) = bot::update(action, old_bot);
            std::mem::replace(&mut bot, new_bot);

            // Handle save task and return response.
            // Note: We have to do it here, since the value of `bot` is only
            // available in this function.
            if let Some(task) = task {
                debug!("New task {:?}", task);
                let response = match task {
                    bot::Task::Reply(response) => Some(response),
                    bot::Task::ReplyAndSave(response) => {
                        let bot_clone = bot.clone();
                        handle.spawn_fn(move || {
                            if let Err(err) = bot_clone.save("state.json") {
                                error!("Could not save state: {:?}", err);
                            }
                            Ok(())
                        });
                        Some(response)
                    }
                    bot::Task::FetchComments(user, change_id, message) => {
                        handle.spawn(
                            gerrit_change_id_sink
                                .clone()
                                .send((user, change_id, message))
                                .map_err(|e| {
                                    error!("Could not fetch comments: {}", e);
                                })
                                .then(|_| Ok(())),
                        );
                        None
                    }
                };
                return response;
            }
            None
        })
        .or_else(|err| {
            error!("Exit due to error: {:?}", err);
            Err(())
        })
        .for_each(|response| {
            debug!("Replying with: {}", response.message);
            spark_client.reply(&response.person_id, &response.message);
            Ok(())
        });

    let _ = core.run(actions);
}
<commit_msg>Initialize stderrlog before config parsing, so we can use logging macros<commit_after>extern crate docopt;
extern crate futures;
extern crate hyper;
extern crate hyper_native_tls;
extern crate iron;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate lru_time_cache;
extern crate regex;
extern crate rlua;
extern crate router;
extern crate rusoto_core;
extern crate rusoto_sqs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate serde_yaml;
extern crate ssh2;
extern crate stderrlog;
extern crate tokio_core;

use futures::{Future, Sink, Stream};
use std::time::Duration;
use std::rc::Rc;

#[macro_use]
mod utils;
mod args;
mod bot;
mod gerrit;
mod spark;
mod sqs;

use spark::SparkClient;

fn spark_client_from_config(spark_config: args::SparkConfig) -> Rc<SparkClient> {
    if !spark_config.bot_token.is_empty() {
        Rc::new(
            spark::WebClient::new(
                spark_config.api_uri,
                spark_config.bot_token,
                spark_config.webhook_url,
            ).unwrap_or_else(|err| {
                error!("Could not create spark client: {}", err);
                std::process::exit(1);
            }),
        )
    } else {
        warn!("Using console as Spark client due to empty bot_token.");
        Rc::new(spark::ConsoleClient::new())
    }
}

fn main() {
    let args = args::parse_args();
    stderrlog::new()
        .module(module_path!())
        .quiet(args.flag_quiet)
        .timestamp(stderrlog::Timestamp::Second)
        .verbosity(if args.flag_verbose { 5 } else { 2 })
        .init()
        .unwrap();
    let config = args::parse_config(args.flag_config);
    info!("Starting");

    // load or create a new bot
    let mut bot = match bot::Bot::load("state.json") {
        Ok(bot) => {
            info!(
                "Loaded bot from 'state.json' with {} user(s).",
                bot.num_users()
            );
            bot
        }
        Err(err) => {
            warn!("Could not load bot from 'state.json': {:?}", err);
            bot::Bot::new()
        }
    };
    if config.bot.msg_expiration != 0 && config.bot.msg_capacity != 0 {
        debug!(
            "Approval LRU cache: capacity - {}, expiration - {} sec",
            config.bot.msg_capacity, config.bot.msg_expiration
        );
        bot.init_msg_cache(
            config.bot.msg_capacity,
            Duration::from_secs(config.bot.msg_expiration),
        );
    };

    // event loop
    let mut core = tokio_core::reactor::Core::new().unwrap();

    // create spark client and event stream listener
    let spark_client = spark_client_from_config(config.spark.clone());
    let spark_stream = match config.spark.mode.clone() {
        args::ModeConfig::Direct { endpoint } => {
            spark::webhook_event_stream(spark_client, &endpoint, core.remote())
        }
        args::ModeConfig::Sqs { uri, region } => spark::sqs_event_stream(spark_client, uri, region),
    };

    let spark_stream = spark_stream.unwrap_or_else(|err| {
        error!("Could not start listening to spark: {}", err);
        std::process::exit(1);
    });

    // create gerrit event stream listener
    let gerrit_config = config.gerrit.clone();
    info!(
        "(Re)connecting to Gerrit over ssh: {:?}",
        gerrit_config.host
    );

    let (gerrit_change_id_sink, gerrit_change_response_stream) = gerrit::change_sink(
        gerrit_config.host.clone(),
        gerrit_config.username.clone(),
        gerrit_config.priv_key_path.clone(),
    ).unwrap_or_else(|err| {
        error!(
            "Could not connect to Gerrit via SSH for sending commands: {}",
            err
        );
        std::process::exit(1);
    });

    let gerrit_stream = gerrit::event_stream(
        gerrit_config.host,
        gerrit_config.username,
        gerrit_config.priv_key_path,
    );

    // join spark and gerrit action streams into one and fold over actions with accumulator `bot`
    let spark_client = spark_client_from_config(config.spark.clone());
    let handle = core.handle();
    let actions = spark_stream
        .select(gerrit_stream)
        .select(gerrit_change_response_stream)
        .filter(|action| match *action {
            bot::Action::NoOp => false,
            _ => true,
        })
        .filter_map(move |action| {
            debug!("Handle action: {:?}", action);

            // fold over actions
            let old_bot = std::mem::replace(&mut bot, bot::Bot::new());
            let (new_bot, task) = bot::update(action, old_bot);
            std::mem::replace(&mut bot, new_bot);

            // Handle save task and return response.
            // Note: We have to do it here, since the value of `bot` is only
            // available in this function.
            if let Some(task) = task {
                debug!("New task {:?}", task);
                let response = match task {
                    bot::Task::Reply(response) => Some(response),
                    bot::Task::ReplyAndSave(response) => {
                        let bot_clone = bot.clone();
                        handle.spawn_fn(move || {
                            if let Err(err) = bot_clone.save("state.json") {
                                error!("Could not save state: {:?}", err);
                            }
                            Ok(())
                        });
                        Some(response)
                    }
                    bot::Task::FetchComments(user, change_id, message) => {
                        handle.spawn(
                            gerrit_change_id_sink
                                .clone()
                                .send((user, change_id, message))
                                .map_err(|e| {
                                    error!("Could not fetch comments: {}", e);
                                })
                                .then(|_| Ok(())),
                        );
                        None
                    }
                };
                return response;
            }
            None
        })
        .or_else(|err| {
            error!("Exit due to error: {:?}", err);
            Err(())
        })
        .for_each(|response| {
            debug!("Replying with: {}", response.message);
            spark_client.reply(&response.person_id, &response.message);
            Ok(())
        });

    let _ = core.run(actions);
}
<|endoftext|>


<commit_before>fn main() {
    println!("Content-Type: text/html");
    println!();
    println!("
Hello, world!
");
    println!("
");
    for (key, value) in ::std::env::vars() {
        println!("
{}: {}
", key, value);
    }
    println!("
");

    ::std::process::exit(0);
}
<commit_msg>Add read from stdin.<commit_after>use std::io::{self, Read, Write};
use std::env;

fn main() {
    let content_length = env::var("CONTENT_LENGTH").unwrap_or("0".into())
        .parse::<u64>().expect("Error parsing CONTENT_LENGTH");
    let status = match handle(content_length) {
        Ok(_) => 0,
        Err(_) => 1,
    };
    ::std::process::exit(status);
}

fn handle(content_length: u64) -> io::Result<()> {
    let mut buffer = Vec::new();
    io::stdin().take(content_length).read_to_end(&mut buffer)?;

    println!("Content-Type: text/html");
    println!();
    println!("
Hello, world!
");
    println!("
");
    for (key, value) in ::std::env::vars() {
        println!("
{}: {}
", key, value);
    }
    println!("
");

    println!("
");
    io::stdout().write(&buffer[..])?;
    println!("
");

    Ok(())
}
<|endoftext|>


<commit_before>extern crate fuse;
extern crate libc;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate clap;

use std::collections::BTreeMap;
use std::path::Path;
use std::env;
use std::io::prelude::Read;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory, ReplyOpen};
use hyper::client::{Client, Response};
use rustc_serialize::json::Json;
use clap::{App, Arg};

struct TwitchFileSystem {
    attrs: BTreeMap<u64, FileAttr>,
    inodes: BTreeMap<String, u64>
}

impl TwitchFileSystem {
    fn new() -> TwitchFileSystem {
        let mut attrs = BTreeMap::new();
        let mut inodes = BTreeMap::new();
        let ts = time::now().to_timespec();
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        attrs.insert(1, attr);
        inodes.insert("/".to_owned(), 1);
        let mut body = String::new();
        Client::new()
            .get("https://api.twitch.tv/kraken/games/top")
            .send()
            .expect("Couldn't load twitch")
            .read_to_string(&mut body);

        match Json::from_str(&body) {
            Ok(data) => {
                let games = data.find("top").unwrap().as_array().unwrap();
                for (i, game) in games.iter().enumerate() {
                    let attr = FileAttr {
                        ino: i as u64 + 2,
                        size: 0,
                        blocks: 0,
                        atime: ts,
                        mtime: ts,
                        ctime: ts,
                        crtime: ts,
                        kind: FileType::RegularFile,
                        perm: 0o644,
                        nlink: 0,
                        uid: 0,
                        gid: 0,
                        rdev: 0,
                        flags: 0
                    };
                    let name = game
                        .find_path(&["game", "name"])
                        .unwrap()
                        .as_string()
                        .unwrap();

                    attrs.insert(attr.ino, attr);
                    inodes.insert(name.to_owned(), attr.ino);
                }
            },
            Err(_) => println!("Twitch returned invalid json")
        }
        TwitchFileSystem {attrs: attrs, inodes: inodes}
    }
}

impl Filesystem for TwitchFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        match self.attrs.get(&ino) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.attr(&ttl, attr);
            },
            None => reply.error(ENOENT)
        }
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        if offset == 0 {
            for (game, &inode) in &self.inodes {
                if inode == 1 { continue; }
                let offset = inode;
                reply.add(inode, offset, FileType::RegularFile, &Path::new(game));
            }
            reply.add(1, 0, FileType::Directory, &Path::new("."));
            reply.add(1, 1, FileType::Directory, &Path::new(".."));
        }

        reply.ok();
    }
    fn read(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, size: u32, reply: ReplyData) {
        reply.data("test".as_bytes());
    }
}

fn main() {
    let matches = App::new("twitch-fs")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version"))
        .arg(Arg::with_name("mountpoint")
             .index(1)
             .required(true))
        .get_matches();

    // unwrap() is safe here because the argument is set as required
    let mountpoint = matches.value_of_os("mountpoint").unwrap();
    let fs = TwitchFileSystem::new();

    fuse::mount(fs , &mountpoint, &[])
}
<commit_msg>Add lookup function<commit_after>extern crate fuse;
extern crate libc;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate clap;

use std::collections::BTreeMap;
use std::path::Path;
use std::env;
use std::io::prelude::Read;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory, ReplyOpen};
use hyper::client::{Client, Response};
use rustc_serialize::json::Json;
use clap::{App, Arg};

struct TwitchFileSystem {
    attrs: BTreeMap<u64, FileAttr>,
    inodes: BTreeMap<String, u64>
}

impl TwitchFileSystem {
    fn new() -> TwitchFileSystem {
        let mut attrs = BTreeMap::new();
        let mut inodes = BTreeMap::new();
        let ts = time::now().to_timespec();
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        attrs.insert(1, attr);
        inodes.insert("/".to_owned(), 1);
        let mut body = String::new();
        Client::new()
            .get("https://api.twitch.tv/kraken/games/top")
            .send()
            .expect("Couldn't load twitch")
            .read_to_string(&mut body);

        match Json::from_str(&body) {
            Ok(data) => {
                let games = data.find("top").unwrap().as_array().unwrap();
                for (i, game) in games.iter().enumerate() {
                    let attr = FileAttr {
                        ino: i as u64 + 2,
                        size: 0,
                        blocks: 0,
                        atime: ts,
                        mtime: ts,
                        ctime: ts,
                        crtime: ts,
                        kind: FileType::RegularFile,
                        perm: 0o644,
                        nlink: 0,
                        uid: 0,
                        gid: 0,
                        rdev: 0,
                        flags: 0
                    };
                    let name = game
                        .find_path(&["game", "name"])
                        .unwrap()
                        .as_string()
                        .unwrap();

                    attrs.insert(attr.ino, attr);
                    inodes.insert(name.to_owned(), attr.ino);
                }
            },
            Err(_) => println!("Twitch returned invalid json")
        }
        TwitchFileSystem {attrs: attrs, inodes: inodes}
    }
}

impl Filesystem for TwitchFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        match self.attrs.get(&ino) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.attr(&ttl, attr);
            },
            None => reply.error(ENOENT)
        }
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        let inode = match self.inodes.get(name.to_str().unwrap()) {
            Some(inode) => inode,
            None => {
                reply.error(ENOENT);
                return;
            }
        };
        match self.attrs.get(inode) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.entry(&ttl, attr, 0);
            },
            None => reply.error(ENOENT),
        };
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        if offset == 0 {
            for (game, &inode) in &self.inodes {
                if inode == 1 { continue; }
                let offset = inode;
                reply.add(inode, offset, FileType::RegularFile, &Path::new(game));
            }
            reply.add(1, 0, FileType::Directory, &Path::new("."));
            reply.add(1, 1, FileType::Directory, &Path::new(".."));
        }

        reply.ok();
    }
    fn read(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, size: u32, reply: ReplyData) {
        reply.data("test".as_bytes());
    }
}

fn main() {
    let matches = App::new("twitch-fs")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version"))
        .arg(Arg::with_name("mountpoint")
             .index(1)
             .required(true))
        .get_matches();

    // unwrap() is safe here because the argument is set as required
    let mountpoint = matches.value_of_os("mountpoint").unwrap();
    let fs = TwitchFileSystem::new();

    fuse::mount(fs , &mountpoint, &[])
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

fn main() {
    let result = cargo_expand();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = try!(cmd.pipe_to(shell!("cat"), Some(&filter_cargo)));
        try!(run(cmd));
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some(try!(cmd.pipe_to(shell!(fmt), Some(&filter_rustfmt))))
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(try!(cmd.pipe_to(shell!(pyg "-l" "rust"), None))),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = try!(self.spawn());

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = try!(errcmd.spawn());
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        None
    } else {
        match env::var_os(&cmd[0].to_uppercase()) {
            Some(which) => {
                if which.is_empty() {
                    None
                } else {
                    Some(which)
                }
            }
            None => {
                let in_path = Command::new(cmd[0])
                    .args(&cmd[1..])
                    .stdin(Stdio::null())
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .spawn()
                    .is_ok();
                if in_path {
                    Some(cmd[0].into())
                } else {
                    None
                }
            }
        }
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains(": line exceeded maximum length (")
        || line.trim_right().ends_with("left behind trailing whitespace (sorry)")
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring specified output filename for 'link' output because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
        || line.contains("due to multiple output types requested, the explicitly specified output file name will be adapted for each output type")
}
<commit_msg>Use ? operator<commit_after>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

fn main() {
    let result = cargo_expand();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = cmd.pipe_to(shell!("cat"), Some(&filter_cargo))?;
        run(cmd)?;
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some(cmd.pipe_to(shell!(fmt), Some(&filter_rustfmt))?)
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(cmd.pipe_to(shell!(pyg "-l" "rust"), None)?),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = self.spawn()?;

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = errcmd.spawn()?;
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        None
    } else {
        match env::var_os(&cmd[0].to_uppercase()) {
            Some(which) => {
                if which.is_empty() {
                    None
                } else {
                    Some(which)
                }
            }
            None => {
                let in_path = Command::new(cmd[0])
                    .args(&cmd[1..])
                    .stdin(Stdio::null())
                    .stdout(Stdio::null())
                    .stderr(Stdio::null())
                    .spawn()
                    .is_ok();
                if in_path {
                    Some(cmd[0].into())
                } else {
                    None
                }
            }
        }
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains(": line exceeded maximum length (")
        || line.trim_right().ends_with("left behind trailing whitespace (sorry)")
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring specified output filename for 'link' output because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
        || line.contains("due to multiple output types requested, the explicitly specified output file name will be adapted for each output type")
}
<|endoftext|>


<commit_before>#![feature(path_ext)]

#![cfg_attr(not(test), feature(exit_status))] // we don't need exit_status feature when testing
#![cfg_attr(test, feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::getline;
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;
#[cfg(not(test))]
use std::fs::{PathExt};

pub mod racer;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match)) {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::env::set_exit_status(1);
        return;
    }
    match args[2].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 5 {
                println!("Provide more arguments!");
                print_usage();
                std::env::set_exit_status(1);
                return;
            }
            let charnum = args[3].parse::<usize>().unwrap();
            let fname = &args[4];
            let fpath = Path::new(fname);
            let src = racer::load_file(&fpath);
            let line = &*getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in racer::complete_from_file(&*src, &fpath, point) {
                match_found(m);
            }
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[2];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, racer::SearchType::StartsWith, racer::Namespace::BothNamespaces) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::env::set_exit_status(1);
        return;
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::env::set_exit_status(1);
        return;
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];
    let fpath = Path::new(fname);
    let src = racer::load_file(&fpath);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    racer::find_definition(&*src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !f.exists() {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::env::set_exit_status(1);
                return;
            } else if !f.ends_with("src") {
                println!("RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::env::set_exit_status(1);
                return;
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::env::set_exit_status(1);
        return;
    }
}

#[cfg(not(test))]
fn main() {
    check_rust_src_env_var();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::env::set_exit_status(1);
        return;
    }

    let command = &args[1][..];
    match command {
        "prefix" => prefix(),
        "complete" => complete(&match_fn),
        "complete-with-snippet" => complete(&match_with_snippet_fn),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::env::set_exit_status(1);
            return;
        }
    }
}
<commit_msg>remove dependence on feature(exit_status)<commit_after>#![feature(path_ext)]
#![cfg_attr(test, feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::getline;
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;
#[cfg(not(test))]
use std::fs::{PathExt};

pub mod racer;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match)) {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[2].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 5 {
                println!("Provide more arguments!");
                print_usage();
                std::process::exit(1);
            }
            let charnum = args[3].parse::<usize>().unwrap();
            let fname = &args[4];
            let fpath = Path::new(fname);
            let src = racer::load_file(&fpath);
            let line = &*getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in racer::complete_from_file(&*src, &fpath, point) {
                match_found(m);
            }
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[2];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, racer::SearchType::StartsWith, racer::Namespace::BothNamespaces) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];
    let fpath = Path::new(fname);
    let src = racer::load_file(&fpath);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    racer::find_definition(&*src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !f.exists() {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !f.ends_with("src") {
                println!("RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn main() {
    check_rust_src_env_var();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    let command = &args[1][..];
    match command {
        "prefix" => prefix(),
        "complete" => complete(&match_fn),
        "complete-with-snippet" => complete(&match_with_snippet_fn),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>extern crate toml;

use std::{env, process};
use std::io::prelude::*;
use std::io::{BufReader, ErrorKind};
use std::collections::BTreeMap;
use std::fs::File;

static OVERRIDES_PATH : &'static str = ".multirust/overrides";
static SETTINGS_PATH : &'static str = ".rustup/settings.toml";
static OLD_SETTINGS_PATH : &'static str = ".multirust/settings.toml";

enum OverridesDatabase {
    Plain(BTreeMap<String, String>),
    Toml(BTreeMap<String, toml::Value>),
}

impl OverridesDatabase {
    pub fn get(&self, key: &str) -> Option<&str> {
        use OverridesDatabase::*;

        match *self {
            Plain(ref db) => db.get(key).map(|s| &s[..]),
            Toml(ref db) => {
                db.get(key).map(|v| v.as_str().expect("Expected value is not a string."))
            }
        }
    }
}

fn with_date<'a>(short: &'a str, toolchain: &'a str) -> Option<&'a str> {
    let date_start = short.len() + 1;
    let date_end   = short.len() + 3 + 4 + 2 + 2;
    let char_range = toolchain.chars()
        .skip(date_start)
        .take(4)
        .all(char::is_numeric);

    if toolchain.len() > date_start && char_range {
        Some(&toolchain[0..date_end])
    } else {
        None
    }
}

fn clean_toolchain_name(toolchain: &str) -> &str {
    static SHORTNAMES : &'static [&'static str] = &["stable", "nightly", "beta"];

    for short in SHORTNAMES {
        if toolchain.starts_with(short) {
            return match with_date(short, toolchain) {
                Some(s) => s,
                None => short
            }
        }
    }

    toolchain
}

fn plain_overrides_file(f: File) {
    let overrides = BufReader::new(f);

    let mut overrides_map = BTreeMap::new();

    for line in overrides.lines() {
        let line = line.expect("No valid line found");
        let mut s = line.split(';');
        let path = s.next().expect("No path in line");
        let toolchain = s.next().expect("No toolchain in line");

        overrides_map.insert(path.into(), toolchain.into());
    }

    let database = OverridesDatabase::Plain(overrides_map);
    toolchain(database);
}

fn settings_toml(mut settings: File) -> Result<(), ()> {
    let mut content = String::new();
    settings.read_to_string(&mut content).expect("Can't read settings file");

    let database = try!(toml::Parser::new(&content).parse()
        .and_then(|toml| toml.get("overrides").cloned())
        .and_then(|overrides| overrides.as_table().cloned())
        .and_then(|database| Some(OverridesDatabase::Toml(database)))
        .ok_or(()));

    toolchain(database);
    Ok(())
}

fn toolchain(database: OverridesDatabase) {
    let mut cwd = match env::current_dir() {
        Ok(cwd) => cwd,
        Err(_) => return,
    };

    loop {
        let path = format!("{}", cwd.display());

        if let Some(toolchain) =  database.get(&path) {
            println!("{}", clean_toolchain_name(toolchain));
            return;
        }

        if !cwd.pop() {
            break;
        }
    }
    println!("default");
}

fn main() {
    let home = env::home_dir().expect("Impossible to get your home dir!");

    let mut overrides_path = home.clone();
    overrides_path.push(OVERRIDES_PATH);

    match File::open(&overrides_path) {
        Ok(f) => {
            plain_overrides_file(f);
            process::exit(0);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => { /* ignored */ },
        Err(_) => {
            println!("default");
            process::exit(0);
        }
    }

    let mut settings_path = home.clone();
    settings_path.push(SETTINGS_PATH);

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f).unwrap_or_else(|_| println!("default"));
        process::exit(0);
    }

    let mut settings_path = home.clone();
    settings_path.push(OLD_SETTINGS_PATH);
    println!("Fall through");

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f).unwrap_or_else(|_| println!("default"));
        process::exit(0);
    }

    println!("default");
}

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

    #[test]
    fn simple_name() {
        assert_eq!("nightly", clean_toolchain_name("nightly-x86_64-unknown-linux-gnu"));
        assert_eq!("nightly", clean_toolchain_name("nightly"));
    }

    #[test]
    fn name_with_date() {
        assert_eq!("nightly-2016-06-05", clean_toolchain_name("nightly-2016-06-05-x86_64-unknown-linux-gnu"));
    }
}
<commit_msg>fix: Remove debug print<commit_after>extern crate toml;

use std::{env, process};
use std::io::prelude::*;
use std::io::{BufReader, ErrorKind};
use std::collections::BTreeMap;
use std::fs::File;

static OVERRIDES_PATH : &'static str = ".multirust/overrides";
static SETTINGS_PATH : &'static str = ".rustup/settings.toml";
static OLD_SETTINGS_PATH : &'static str = ".multirust/settings.toml";

enum OverridesDatabase {
    Plain(BTreeMap<String, String>),
    Toml(BTreeMap<String, toml::Value>),
}

impl OverridesDatabase {
    pub fn get(&self, key: &str) -> Option<&str> {
        use OverridesDatabase::*;

        match *self {
            Plain(ref db) => db.get(key).map(|s| &s[..]),
            Toml(ref db) => {
                db.get(key).map(|v| v.as_str().expect("Expected value is not a string."))
            }
        }
    }
}

fn with_date<'a>(short: &'a str, toolchain: &'a str) -> Option<&'a str> {
    let date_start = short.len() + 1;
    let date_end   = short.len() + 3 + 4 + 2 + 2;
    let char_range = toolchain.chars()
        .skip(date_start)
        .take(4)
        .all(char::is_numeric);

    if toolchain.len() > date_start && char_range {
        Some(&toolchain[0..date_end])
    } else {
        None
    }
}

fn clean_toolchain_name(toolchain: &str) -> &str {
    static SHORTNAMES : &'static [&'static str] = &["stable", "nightly", "beta"];

    for short in SHORTNAMES {
        if toolchain.starts_with(short) {
            return match with_date(short, toolchain) {
                Some(s) => s,
                None => short
            }
        }
    }

    toolchain
}

fn plain_overrides_file(f: File) {
    let overrides = BufReader::new(f);

    let mut overrides_map = BTreeMap::new();

    for line in overrides.lines() {
        let line = line.expect("No valid line found");
        let mut s = line.split(';');
        let path = s.next().expect("No path in line");
        let toolchain = s.next().expect("No toolchain in line");

        overrides_map.insert(path.into(), toolchain.into());
    }

    let database = OverridesDatabase::Plain(overrides_map);
    toolchain(database);
}

fn settings_toml(mut settings: File) -> Result<(), ()> {
    let mut content = String::new();
    settings.read_to_string(&mut content).expect("Can't read settings file");

    let database = try!(toml::Parser::new(&content).parse()
        .and_then(|toml| toml.get("overrides").cloned())
        .and_then(|overrides| overrides.as_table().cloned())
        .and_then(|database| Some(OverridesDatabase::Toml(database)))
        .ok_or(()));

    toolchain(database);
    Ok(())
}

fn toolchain(database: OverridesDatabase) {
    let mut cwd = match env::current_dir() {
        Ok(cwd) => cwd,
        Err(_) => return,
    };

    loop {
        let path = format!("{}", cwd.display());

        if let Some(toolchain) =  database.get(&path) {
            println!("{}", clean_toolchain_name(toolchain));
            return;
        }

        if !cwd.pop() {
            break;
        }
    }
    println!("default");
}

fn main() {
    let home = env::home_dir().expect("Impossible to get your home dir!");

    let mut overrides_path = home.clone();
    overrides_path.push(OVERRIDES_PATH);

    match File::open(&overrides_path) {
        Ok(f) => {
            plain_overrides_file(f);
            process::exit(0);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => { /* ignored */ },
        Err(_) => {
            println!("default");
            process::exit(0);
        }
    }

    let mut settings_path = home.clone();
    settings_path.push(SETTINGS_PATH);

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f).unwrap_or_else(|_| println!("default"));
        process::exit(0);
    }

    let mut settings_path = home.clone();
    settings_path.push(OLD_SETTINGS_PATH);

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f).unwrap_or_else(|_| println!("default"));
        process::exit(0);
    }

    println!("default");
}

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

    #[test]
    fn simple_name() {
        assert_eq!("nightly", clean_toolchain_name("nightly-x86_64-unknown-linux-gnu"));
        assert_eq!("nightly", clean_toolchain_name("nightly"));
    }

    #[test]
    fn name_with_date() {
        assert_eq!("nightly-2016-06-05", clean_toolchain_name("nightly-2016-06-05-x86_64-unknown-linux-gnu"));
    }
}
<|endoftext|>


<commit_before>
#![feature(macro_rules)]

use std::collections::HashMap;
use std::comm::{Receiver, Sender};
use std::io::{Acceptor, BufferedReader, BufWriter, Listener, MemReader, MemWriter, TcpListener, TcpStream};
use std::io::stdin;
use std::num::ToStrRadix;
use std::rand::random;

type Id = u32;
type NullResult<T> = Result<T, ()>;
type Packet = Vec<u8>;

enum Message {
    RemovePlayer(Id),
    HandlePacket(Id, Packet),
    AddPlayer(TcpStream),
}

struct Player {
    id: Id,
    tcp: TcpStream,
    name: String,
    send: Sender<Packet>,
}

struct Server {
    players: HashMap<Id, Player>,
    send: Sender<Message>,
    recv: Receiver<Message>,
}

fn main() {
    println!("NoLifePony Server");
    let mut server = Server::new();
    server.run();
    println!("Shutting down");
}

fn new_packet() -> MemWriter {
    let mut buf = MemWriter::new();
    buf.write([0, 0, 0, 0]).unwrap();
    buf
}

fn packet_sender(recv: Receiver<Packet>, mut tcp: TcpStream) {
    for mut msg in recv.iter() {
        println!("Got packet to send!");
        let len = msg.len() as u32 - 4;
        {
            let mut buf = BufWriter::new(msg.mut_slice_to(4));
            buf.write_be_u32(len).unwrap();
        }
        let msg = msg;
        tcp.write(msg.as_slice()).unwrap();
    }
}

fn packet_receiver(send: Sender<Message>, tcp: TcpStream, id: Id) {
    struct Packets {
        buf: BufferedReader<TcpStream>,
    }
    impl Iterator<Packet> for Packets {
        fn next(&mut self) -> Option<Packet> {
            self.buf.read_be_u32().and_then(|len| self.buf.read_exact(len as uint)).ok()
        }
    }
    let mut packets = Packets {
        buf: BufferedReader::new(tcp),
    };
    for packet in packets {
        println!("Got packet!");
        send.send(HandlePacket(id, packet));
    }
    send.send(RemovePlayer(id));
}

fn listener(send: Sender<Message>) {
    let listen = TcpListener::bind("0.0.0.0", 273);
    let mut accept = listen.listen();
    for stream in accept.incoming() {
        match stream {
            Ok(stream) => send.send(AddPlayer(stream)),
            Err(_) => return,
        }
    }
}

fn commands(_: Sender<Message>) {
    let mut cin = stdin();
    for line in cin.lines() {
        let line = line.unwrap();
        let line: String = line.as_slice().chars().map(|c| c.to_lowercase())
            .filter(|c| *c != '\n' && *c != '\r').collect();
        match line.as_slice() {
            _ => println!("Unknown command"),
        }
    }
}

impl Player {
    fn default_name(id: Id) -> String {
        "Pony".to_string().append(id.to_str_radix(10).as_slice())
    }
    fn new(id: Id, tcp: TcpStream, send: Sender<Message>) -> Player {
        let tcp2 = tcp.clone();
        spawn(proc() packet_receiver(send, tcp2, id));
        let (send, recv) = channel::<Packet>();
        let tcp2 = tcp.clone();
        spawn(proc() packet_sender(recv, tcp2));
        Player {
            id: id,
            tcp: tcp,
            name: Player::default_name(id),
            send: send,
        }
    }
}

impl Server {
    fn new() -> Server {
        let (send, recv) = channel::<Message>();
        let send2 = send.clone();
        spawn(proc() listener(send2));
        let send2 = send.clone();
        spawn(proc() commands(send2));
        Server {
            players: HashMap::new(),
            send: send,
            recv: recv,
        }
    }
    fn gen_id(&self) -> Id {
        loop {
            let id = random();
            if self.players.find(&id).is_none() { return id }
        }
    }
    fn add_player(&mut self, mut tcp: TcpStream) {
        match tcp.peer_name() {
            Ok(name) => println!("Player connected from {}", name),
            Err(_) => println!("Failed to get player peer name"),
        }
        let id = self.gen_id();
        let player = Player::new(id, tcp, self.send.clone());
        self.players.insert(player.id, player);
    }
    fn remove_player(&mut self, id: Id) {
        let mut player = match self.players.pop(&id) {
            Some(player) => player,
            None => return,
        };
        println!("Removing player {}", id);
        player.tcp.close_read().unwrap();
        player.tcp.close_write().unwrap();
    }
    fn handle_packet(&mut self, id: Id, packet: Packet) {
        let player = match self.players.find_mut(&id) {
            Some(player) => player,
            None => { println!("Packet from non-existant player: {}", id); return },
        };
        let mut packet = MemReader::new(packet);
        let opcode = match packet.read_be_u16() {
            Ok(opcode) => opcode,
            Err(_) => { println!("Failed to read opcode from player: {}", id); return },
        };
        match opcode {
            _ => println!("Unknown opcode {}", opcode),
        }
    }
    fn run(&mut self) {
        loop {
            let message = self.recv.recv();
            match message {
                AddPlayer(tcp) => self.add_player(tcp),
                RemovePlayer(id) => self.remove_player(id),
                HandlePacket(id, packet) => self.handle_packet(id, packet),
            }
        }
    }
}
<commit_msg>A few more tweaks.<commit_after>
#![feature(macro_rules)]

use std::collections::HashMap;
use std::comm::{Receiver, Sender};
use std::io::{Acceptor, BufferedReader, BufWriter, Listener, MemReader, MemWriter, TcpListener, TcpStream};
use std::io::stdin;
use std::rand::random;

type Id = u32;
type NullResult<T> = Result<T, ()>;
type Packet = Vec<u8>;

enum Message {
    RemovePlayer(Id),
    HandlePacket(Id, Packet),
    AddPlayer(TcpStream),
}

struct Player {
    id: Id,
    tcp: TcpStream,
    name: String,
    send: Sender<Packet>,
}

struct Server {
    players: HashMap<Id, Player>,
    send: Sender<Message>,
    recv: Receiver<Message>,
}

fn main() {
    println!("NoLifePony Server");
    let mut server = Server::new();
    server.run();
    println!("Shutting down");
}

fn new_packet() -> MemWriter {
    let mut buf = MemWriter::new();
    buf.write([0, 0, 0, 0]).unwrap();
    buf
}

fn packet_sender(recv: Receiver<Packet>, mut tcp: TcpStream) {
    for mut msg in recv.iter() {
        println!("Got packet to send!");
        let len = msg.len() as u32 - 4;
        {
            let mut buf = BufWriter::new(msg.mut_slice_to(4));
            buf.write_be_u32(len).unwrap();
        }
        let msg = msg;
        tcp.write(msg.as_slice()).unwrap();
    }
}

fn packet_receiver(send: Sender<Message>, tcp: TcpStream, id: Id) {
    struct Packets {
        buf: BufferedReader<TcpStream>,
    }
    impl Iterator<Packet> for Packets {
        fn next(&mut self) -> Option<Packet> {
            self.buf.read_be_u32().and_then(|len| self.buf.read_exact(len as uint)).ok()
        }
    }
    let mut packets = Packets {
        buf: BufferedReader::new(tcp),
    };
    for packet in packets {
        send.send(HandlePacket(id, packet));
    }
    send.send(RemovePlayer(id));
}

fn listener(send: Sender<Message>) {
    let listen = TcpListener::bind("0.0.0.0", 273);
    let mut accept = listen.listen();
    for stream in accept.incoming() {
        match stream {
            Ok(stream) => send.send(AddPlayer(stream)),
            Err(_) => return,
        }
    }
}

fn commands(_: Sender<Message>) {
    let mut cin = stdin();
    for line in cin.lines() {
        let line = line.unwrap();
        let line: String = line.as_slice().chars().map(|c| c.to_lowercase())
            .filter(|c| *c != '\n' && *c != '\r').collect();
        match line.as_slice() {
            _ => println!("Unknown command"),
        }
    }
}

impl Player {
    fn default_name(id: Id) -> String {
        format!("Pony{:08X}", id)
    }
    fn new(id: Id, mut tcp: TcpStream, send: Sender<Message>) -> Player {
        let tcp2 = tcp.clone();
        spawn(proc() packet_receiver(send, tcp2, id));
        let (send, recv) = channel::<Packet>();
        let tcp2 = tcp.clone();
        spawn(proc() packet_sender(recv, tcp2));
        let name = Player::default_name(id);
        match tcp.peer_name() {
            Ok(ip) => println!("{} connected from {}", name, ip),
            Err(_) => println!("{} connected from unknown", name),
        }
        Player {
            id: id,
            tcp: tcp,
            name: name,
            send: send,
        }
    }
}

impl Server {
    fn new() -> Server {
        let (send, recv) = channel::<Message>();
        let send2 = send.clone();
        spawn(proc() listener(send2));
        let send2 = send.clone();
        spawn(proc() commands(send2));
        Server {
            players: HashMap::new(),
            send: send,
            recv: recv,
        }
    }
    fn gen_id(&self) -> Id {
        loop {
            let id = random();
            if self.players.find(&id).is_none() { return id }
        }
    }
    fn add_player(&mut self, tcp: TcpStream) {
        let id = self.gen_id();
        let player = Player::new(id, tcp, self.send.clone());
        self.players.insert(player.id, player);
    }
    fn remove_player(&mut self, id: Id) {
        let mut player = match self.players.pop(&id) {
            Some(player) => player,
            None => return,
        };
        println!("{} disconnected", player.name);
        player.tcp.close_read().unwrap();
        player.tcp.close_write().unwrap();
    }
    fn handle_packet(&mut self, id: Id, packet: Packet) {
        let player = match self.players.find_mut(&id) {
            Some(player) => player,
            None => { println!("Packet from non-existant player: {}", id); return },
        };
        let mut packet = MemReader::new(packet);
        let opcode = match packet.read_be_u16() {
            Ok(opcode) => opcode,
            Err(_) => { println!("Failed to read opcode from player: {}", id); return },
        };
        match opcode {
            _ => println!("Unknown opcode {} from {}", opcode, player.name),
        }
    }
    fn run(&mut self) {
        loop {
            let message = self.recv.recv();
            match message {
                AddPlayer(tcp) => self.add_player(tcp),
                RemovePlayer(id) => self.remove_player(id),
                HandlePacket(id, packet) => self.handle_packet(id, packet),
            }
        }
    }
}
<|endoftext|>


<commit_before>/// Rosten
/// Track Bring packages in Rust
/// For testing use "TESTPACKAGE-AT-PICKUPPOINT" as tracking number
/// https://www.mybring.com/tracking/api

extern crate rustc_serialize;
extern crate hyper;

mod json_response;

use std::io::Read;
use std::fs::File;
use std::path::Path;
use std::error::Error;
use rustc_serialize::json;
use hyper::{Client};
use json_response::BringResponse;

pub fn main() {
    let client = Client::new();
    let url = "https://www.mybring.com/tracking/api";

    // TODO Figure out ~/ path so compiler can find the file easily
    let path = Path::new("/home/stian/projects/rosten/tracking.json");
    let display = path.display();

    let mut file = match File::open(&path) {
    Err(e) => panic!("unable to open {}: {}", display, e.description()),
    Ok(file) => file,
    };

    let mut buffer = String::new();
    file.read_to_string(&mut buffer).unwrap();

    // TODO Better names
    let deserialize :BringResponse = json::decode(&buffer).unwrap();
    let sets = deserialize.consignmentSet;
    // Iterate over consignmentSet and get package status description
    for i in 0..sets.len() {
        let set = &sets[i];
        println!("Sets is {}", set.senderName);
        for x in 0..set.packageSet.len() {
            let package_set = &set.packageSet[x];
            println!("Packageset number is {}", x);
            println!("Packageset is {}", package_set.statusDescription);
        }
    }
}
<commit_msg>query bring api return & parse response<commit_after>/// Rosten
/// Track Bring packages in Rust
/// For testing use "TESTPACKAGE-AT-PICKUPPOINT" as tracking number
/// https://www.mybring.com/tracking/api

extern crate rustc_serialize;
extern crate hyper;

mod json_response;

use std::io::Read;
use rustc_serialize::json;
use hyper::{Client};
use json_response::BringResponse;

pub fn main() {

    // TODO Implement query
    // Wrap in function?
    let url = "https://tracking.bring.com/tracking.json?q=TESTPACKAGE-AT-PICKUPPOINT";
    let client = Client::new();
    let mut response = match client.get(url).send() {
        Ok(response) => response,
        Err(_) => panic!("Failed to get http response"),
    };
    let mut buf = String::new();
    match response.read_to_string(&mut buf) {
        Ok(buf) => buf,
        Err(_) => panic!("Failed to read to buffer"),
    };

    let deserialize :BringResponse = json::decode(&buf).unwrap();
    let sets = deserialize.consignmentSet;
    // Iterate over consignmentSet and get package status description
    for i in 0..sets.len() {
        let set = &sets[i];
        println!("Sets is {}", set.senderName);
        for x in 0..set.packageSet.len() {
            let package_set = &set.packageSet[x];
            println!("Packageset number is {}", x);
            println!("Packageset is {}", package_set.statusDescription);
        }
    }
}
<|endoftext|>