<commit_before>
#[macro_use] extern crate clap;
extern crate dbus;

use std::io::prelude::*;
use std::error::Error;
use std::{io, process, fs};
use clap::{App, ArgMatches};
use dbus::{Connection, Message};
use dbus::MessageItem::UInt32;

const IBUS_BUSADDR_FILE:   &'static str = ".config/ibus/bus";
const IBUS_SEND_BUS_NAME:  &'static str = "org.freedesktop.IBus.KKC";
const IBUS_SEND_OBJ_PATH:  &'static str = "/org/freedesktop/IBus/Engine/1";
const IBUS_SEND_INTERFACE: &'static str = "org.freedesktop.IBus.Engine";
const IBUS_SEND_METHOD:    &'static str = "ProcessKeyEvent";
const IBUS_SEND_WAIT: i32 = 1;  // [ms]?
const DUMMY_ZERO:     u32 = 0;  // Use for keycodes, which have no sense.

// Key triplets: [Keysym, Keycode, Modifier-State]
const KEY_TO_ON:  [u32; 3] = [106, 44, 8];  // Alt-J
const KEY_TO_OFF: [u32; 3] = [108, 46, 8];  // Alt-L

const NONE_001: &'static str = "No such file or directory.";
const NONE_002: &'static str = "Illeagal file format.";
const NONE_003: &'static str = "Cannot create dbus message.";

fn main() {
    let arg_def = load_yaml!("cli.yml");
    let args    = App::from_yaml(arg_def).get_matches();

    match exec(&args) {
        Ok(_)  => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        },
    };
}

fn exec(args: &ArgMatches) -> Result<(), Box<Error>> {
    let address = try!(get_address());
    if args.is_present("bus") {
        println!("{}", address);
        return Ok(());
    }

    let connect = try!(Connection::open_private(&address));
    let message = try!(make_message(&args));
    let _ = connect.send_with_reply_and_block(message, IBUS_SEND_WAIT);

    Ok(())
}

fn get_address() -> Result<String, Box<Error>> {
    let buff = &mut String::new();
    let file = try!(try!(try!(
                fs::read_dir(format!("{}/{}", env!("HOME"),
                                              IBUS_BUSADDR_FILE)))
                .nth(0).ok_or(NONE_001)));
    let _    = try!(fs::File::open(file.path())).read_to_string(buff);
    let line = try!(buff.lines().nth(1).ok_or(NONE_002));
    let offs = 1 + try!(line.find('=').ok_or(NONE_002));

    Ok(line[offs ..].to_string())
}

fn make_message(args: &ArgMatches) -> Result<Message, Box<Error>> {
    let triplet;
    if args.is_present("on") { triplet = KEY_TO_ON }
    else if let Some(k) = args.subcommand_matches("key") {
        triplet = [ try!(k.value_of("keysym").unwrap().parse::<u32>()),
                    DUMMY_ZERO,
                    try!(k.value_of("state").unwrap_or("0").parse::<u32>()) ]
    }
    else { triplet = KEY_TO_OFF }

    let mut message = try!(Message::new_method_call(IBUS_SEND_BUS_NAME,
                                                    IBUS_SEND_OBJ_PATH,
                                                    IBUS_SEND_INTERFACE,
                                                    IBUS_SEND_METHOD)
                           .ok_or(NONE_003));
    let wrap_key = |y: [u32; 3]| [UInt32(y[0]), UInt32(y[1]), UInt32(y[2])];
    message.append_items(&wrap_key(triplet));
    Ok(message)
}

<commit_msg>bugfix:  change env!() to env::var()<commit_after>
#[macro_use] extern crate clap;
extern crate dbus;

use std::io::prelude::*;
use std::error::Error;
use std::{io, process, fs, env};
use clap::{App, ArgMatches};
use dbus::{Connection, Message};
use dbus::MessageItem::UInt32;

const IBUS_BUSADDR_FILE:   &'static str = ".config/ibus/bus";
const IBUS_SEND_BUS_NAME:  &'static str = "org.freedesktop.IBus.KKC";
const IBUS_SEND_OBJ_PATH:  &'static str = "/org/freedesktop/IBus/Engine/1";
const IBUS_SEND_INTERFACE: &'static str = "org.freedesktop.IBus.Engine";
const IBUS_SEND_METHOD:    &'static str = "ProcessKeyEvent";
const IBUS_SEND_WAIT: i32 = 1;  // [ms]?
const DUMMY_ZERO:     u32 = 0;  // Use for keycodes, which have no sense.

// Key triplets: [Keysym, Keycode, Modifier-State]
const KEY_TO_ON:  [u32; 3] = [106, 44, 8];  // Alt-J
const KEY_TO_OFF: [u32; 3] = [108, 46, 8];  // Alt-L

const NONE_001: &'static str = "No such file or directory.";
const NONE_002: &'static str = "Illeagal file format.";
const NONE_003: &'static str = "Cannot create dbus message.";

fn main() {
    let arg_def = load_yaml!("src/cli.yml");
    let args    = App::from_yaml(arg_def).get_matches();

    match exec(&args) {
        Ok(_)  => process::exit(0),
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        },
    };
}

fn exec(args: &ArgMatches) -> Result<(), Box<Error>> {
    let address = try!(get_address());
    if args.is_present("bus") {
        println!("{}", address);
        return Ok(());
    }

    let connect = try!(Connection::open_private(&address));
    let message = try!(make_message(&args));
    let _ = connect.send_with_reply_and_block(message, IBUS_SEND_WAIT);

    Ok(())
}

fn get_address() -> Result<String, Box<Error>> {
    let buff = &mut String::new();
    let file = try!(try!(try!(
                fs::read_dir(format!("{}/{}", try!(env::var("HOME")),
                                              IBUS_BUSADDR_FILE)))
                .nth(0).ok_or(NONE_001)));
    let _    = try!(fs::File::open(file.path())).read_to_string(buff);
    let line = try!(buff.lines().nth(1).ok_or(NONE_002));
    let offs = 1 + try!(line.find('=').ok_or(NONE_002));

    Ok(line[offs ..].to_string())
}

fn make_message(args: &ArgMatches) -> Result<Message, Box<Error>> {
    let triplet;
    if args.is_present("on") { triplet = KEY_TO_ON }
    else if let Some(k) = args.subcommand_matches("key") {
        triplet = [ try!(k.value_of("keysym").unwrap().parse::<u32>()),
                    DUMMY_ZERO,
                    try!(k.value_of("state").unwrap_or("0").parse::<u32>()) ]
    }
    else { triplet = KEY_TO_OFF }

    let mut message = try!(Message::new_method_call(IBUS_SEND_BUS_NAME,
                                                    IBUS_SEND_OBJ_PATH,
                                                    IBUS_SEND_INTERFACE,
                                                    IBUS_SEND_METHOD)
                           .ok_or(NONE_003));
    let wrap_key = |y: [u32; 3]| [UInt32(y[0]), UInt32(y[1]), UInt32(y[2])];
    message.append_items(&wrap_key(triplet));
    Ok(message)
}

<|endoftext|>


<commit_before>#![allow(unused_imports, unused_must_use, dead_code)]

extern crate bencode;
extern crate rand;
extern crate bittorrent;
extern crate hyper;

use std::{env, str, thread};
use std::io::{Read, Write};
use std::collections::HashMap;
use std::net::{Ipv4Addr, TcpStream, SocketAddrV4};
use std::sync::mpsc::channel;
use bencode::{deserialize, deserialize_file, Bencode, TypedMethods, BencodeVecOption};
use rand::{Rng, thread_rng};
use bittorrent::querystring::QueryString;
use bittorrent::metadata::{MetadataDict, Metadata};
use bittorrent::bt_messages::{decode_message, test};
use hyper::Client;
use hyper::header::Connection;

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "-TR1000-";

#[derive(Debug)]
enum Address {
    TCP(Ipv4Addr, u16)
}

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = thread_rng().gen_ascii_chars()
                           .take(rand_length)
                           .collect::<String>();

    prefix.to_string() + &rand
}

fn ping_tracker (announce: &String, args: Vec<(&str, String)>) -> Option<HashMap<String, Bencode>> {
    let req_addr = announce.to_string() + "?" + &QueryString::from(args).query_string();
    println!("pinging tracker {}", req_addr);
    let client = Client::new();
    let mut res = client.get(&req_addr)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    deserialize(&body).to_singleton_dict()
}

fn get_peers <T> (tracker_response: &T) -> Vec<Address> where T:TypedMethods {
    let peers = tracker_response.get_owned_string("peers").unwrap_or_else(||panic!("no peers found"));
    //for now keep the bottom unused value, it's for ipv6. which maybe will be addressed
    (0..peers.len()/6).map(|x| {
        let ip_start = x * 6;
        let ip_end = ip_start + 4;
        let ip_bytes = &peers[ip_start..ip_end];
        let ip = Ipv4Addr::new(ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]);
        let port = (peers[ip_end] as u16)*256 + peers[ip_end+1] as u16;
        Address::TCP(ip, port)
    }).collect::<Vec<Address>>()
}

/// The peer handshake message, according to protocol
///
fn to_handshake (pstr:&str, info_hash: &[u8; 20], peer_id: &String) -> Vec<u8> {
    let reserved = [0u8; 8];
    let pstr_bytes = pstr.to_string().into_bytes();
    let a = [pstr_bytes.len() as u8];
    let b = pstr_bytes;
    let c = reserved;
    let d = info_hash.clone();
    let e = peer_id.clone().into_bytes();

    [a.iter(),
     b.iter(),
     c.iter(),
     d.iter(),
     e.iter()].iter().flat_map(|y| {
         y.to_owned().map(|x| *x).collect::<Vec<u8>>()
     }).collect::<Vec<u8>>()
}

fn decode_handshake(resp: &[u8]) -> (u8, &[u8], &[u8], &[u8], &[u8]){
    //i realize this is the goofiest looking block ever... but you cant really destructure a
    //vector so i'm sticking with the tuples for now. maybe i'll make it look normal later
    let (pstrlen, a0) = {
        let (l, r) = resp.split_at(1 as usize);
        (l[0], r)
    };
    let (protocol, a1) = a0.split_at(pstrlen as usize);
    let (reserved, a2) = a1.split_at(8);
    let (info_hash, a3) = a2.split_at(20);
    let (peer_id, _) = a3.split_at(20);

    (pstrlen, protocol, reserved, info_hash, peer_id)
}

fn connect_to_peer (address: Address, metadata: &Metadata, peer_id: &String) -> Result<Vec<u8>, String> {
    println!("connecting to {:?}", address);
    let (ip, port) = match address {
        Address::TCP(ip_address, port) => (ip_address, port)
    };

    let mut stream = match TcpStream::connect(SocketAddrV4::new(ip, port)) {
        Ok(tcp_stream) => tcp_stream,
        Err(err) => return Err(format!("unable to connect to peer {:?}", ip))
    };

    println!("connected to {:?}", address);

    let _ = stream.write_all(&to_handshake("BitTorrent protocol", &metadata.info_hash, peer_id));
    let _ = stream.flush();

    //for now enforce a maximum handshake size of 512 bytes
    let mut buffer = [0; 512];
    match stream.read(&mut buffer) {
        Ok(0) => Err(format!("invalid handshake from peer")),
        Ok(bytes_read) => {
            let something = &buffer[0..bytes_read];
            let (pstrlen, protocol, reserved, info_hash, peer_id) = decode_handshake(&buffer[0..bytes_read]);
            Ok(peer_id.to_owned())
        },
        Err(err) => Err(format!("unable to read from peer {:?}", ip))
    }
}

fn get_http_tracker_peers (peer_id: &String, metadata: &Metadata, listen_port:u32, bytes_dled: u32) -> Option<Vec<Address>> {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let bytes_left = metadata.get_total_length() - bytes_dled;

    let info_hash_escaped = QueryString::encode_component(&metadata.info_hash);
    let response = ping_tracker(&metadata.announce, vec![
                                ("info_hash", info_hash_escaped),
                                ("peer_id", peer_id.clone()),
                                ("port", listen_port.to_string()),
                                ("uploaded", 0.to_string()),
                                ("downloaded", bytes_dled.to_string()),
                                ("left", bytes_left.to_string()),
                                ("compact", 1.to_string()),
                                ("event", "started".to_string()),
                                ("num_want", "15".to_string())
                                ]);

    match response {
        Some(resp) => Some(get_peers(&resp)),
        None => panic!("no valid bencode response from tracker")
    }
}

fn init (metadata: &Metadata, listen_port: u32, bytes_dled: u32) {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let peers = match get_http_tracker_peers(&peer_id, metadata, listen_port, bytes_dled) {
        Some(peers) => peers,
        _ => panic!("cannot get peers from tracker")
    };

    println!("got {} peers", peers.len());

    let (tx, rx) = channel();

    //TODO: the sink initialization should be done outside of init() as one sink can realistically
    //handle multiple torrents relatively trivially
    //all threads will send messages asynchronously to the sink. tbh the loop could be shoved onto the main
    //thread, but for the sake of modularity lets dedicated one for the sink
    let sink = thread::spawn(move || {
        loop {
            let res = rx.recv().unwrap();
            println!("{:?}", res);
        }
    });

    for peer in peers {
        //using Arc makes the borrow checker compain. will have to revisit for maximum memory
        //efficiency :)
        let child_meta = metadata.clone();
        let peer_id = peer_id.clone();
        let tx = tx.clone();
        thread::spawn(move || {
            let conn = connect_to_peer(peer, &child_meta, &peer_id).unwrap();
            tx.send(conn);
        });
    }

    //block until the sink shuts down
    let _ = sink.join();
}

fn start_torrenting () {
    let path = env::args().nth(1)
                          .unwrap_or_else(||panic!("no path to torrent provided"));

    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));

    assert_eq!(content.len(), 1);

    let metadata = match content.first() {
        Some(&Bencode::Dict(ref dict)) => {
            //println!("{:?}", dict);
            dict.to_metadata()
        },
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    init(&metadata, 6887, 0);
}

fn main () {
    start_torrenting();
    //test();
}
<commit_msg>adding handshake validation. removed uneccessarry clone<commit_after>#![allow(unused_imports, unused_must_use, dead_code)]

extern crate bencode;
extern crate rand;
extern crate bittorrent;
extern crate hyper;

use std::{env, str, thread};
use std::io::{Read, Write};
use std::collections::HashMap;
use std::net::{Ipv4Addr, TcpStream, SocketAddrV4};
use std::sync::mpsc::channel;
use bencode::{deserialize, deserialize_file, Bencode, TypedMethods, BencodeVecOption};
use rand::{Rng, thread_rng};
use bittorrent::querystring::QueryString;
use bittorrent::metadata::{MetadataDict, Metadata};
use bittorrent::bt_messages::{decode_message, test};
use hyper::Client;
use hyper::header::Connection;

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "-TR1000-";

#[derive(Debug)]
enum Address {
    TCP(Ipv4Addr, u16)
}

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = thread_rng().gen_ascii_chars()
                           .take(rand_length)
                           .collect::<String>();

    prefix.to_string() + &rand
}

fn ping_tracker (announce: &String, args: Vec<(&str, String)>) -> Option<HashMap<String, Bencode>> {
    let req_addr = announce.to_string() + "?" + &QueryString::from(args).query_string();
    println!("pinging tracker {}", req_addr);
    let client = Client::new();
    let mut res = client.get(&req_addr)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    deserialize(&body).to_singleton_dict()
}

/// Gets peer addresses from a received tracker response. These are just Ipv4 addresses currently
fn get_peers <T> (tracker_response: &T) -> Vec<Address> where T:TypedMethods {
    let peers = tracker_response.get_owned_string("peers").unwrap_or_else(||panic!("no peers found"));
    //for now keep the bottom unused value, it's for ipv6. which maybe will be addressed
    (0..peers.len()/6).map(|x| {
        let ip_start = x * 6;
        let ip_end = ip_start + 4;
        let ip_bytes = &peers[ip_start..ip_end];
        let ip = Ipv4Addr::new(ip_bytes[0], ip_bytes[1], ip_bytes[2], ip_bytes[3]);
        let port = (peers[ip_end] as u16)*256 + peers[ip_end+1] as u16;
        Address::TCP(ip, port)
    }).collect::<Vec<Address>>()
}

/// The peer handshake message, according to protocol
///
fn to_handshake (pstr:&str, info_hash: &[u8; 20], peer_id: &String) -> Vec<u8> {
    let reserved = [0u8; 8];
    let pstr_bytes = pstr.to_string().into_bytes();
    let a = [pstr_bytes.len() as u8];
    let b = pstr_bytes;
    let c = reserved;
    let d = info_hash;
    let e = peer_id.clone().into_bytes();

    [a.iter(),
     b.iter(),
     c.iter(),
     d.iter(),
     e.iter()].iter().flat_map(|y| {
         y.to_owned().map(|x| *x).collect::<Vec<u8>>()
     }).collect::<Vec<u8>>()
}

fn decode_handshake(resp: &[u8]) -> (&[u8], &[u8], &[u8], &[u8]){
    //i realize this is the goofiest looking block ever... but you cant really destructure a
    //vector so i'm sticking with the tuples for now. maybe i'll make it look normal later
    let (pstrlen, a0) = {
        let (l, r) = resp.split_at(1 as usize);
        (l[0], r)
    };
    let (protocol, a1) = a0.split_at(pstrlen as usize);
    let (reserved, a2) = a1.split_at(8);
    let (info_hash, a3) = a2.split_at(20);
    let (peer_id, _) = a3.split_at(20);

    (protocol, reserved, info_hash, peer_id)
}

fn connect_to_peer (address: Address, metadata: &Metadata, peer_id: &String) -> Result<Vec<u8>, String> {
    println!("connecting to {:?}", address);
    let (ip, port) = match address {
        Address::TCP(ip_address, port) => (ip_address, port)
    };

    let mut stream = match TcpStream::connect(SocketAddrV4::new(ip, port)) {
        Ok(tcp_stream) => tcp_stream,
        Err(err) => return Err(format!("unable to connect to peer {:?}", ip))
    };

    println!("connected to {:?}", address);

    let _ = stream.write_all(&to_handshake("BitTorrent protocol", &metadata.info_hash, peer_id));
    let _ = stream.flush();

    //for now enforce a maximum handshake size of 512 bytes
    let mut buffer = [0; 512];
    match stream.read(&mut buffer) {
        Ok(0) => Err(format!("invalid handshake from peer")),
        Ok(bytes_read) => {
            let something = &buffer[0..bytes_read];
            let (protocol, reserved, info_hash, peer_id) = decode_handshake(&buffer[0..bytes_read]);
            let info_hash = metadata.info_hash;
            match (protocol, info_hash) {
                (b"BitTorrent protocol", info_hash) => Ok(peer_id.to_owned()),
                _ => Err(format!("invalid peer handshake"))
            }
        },
        Err(err) => Err(format!("unable to read from peer {:?}", ip))
    }
}

fn get_http_tracker_peers (peer_id: &String, metadata: &Metadata, listen_port:u32, bytes_dled: u32) -> Option<Vec<Address>> {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let bytes_left = metadata.get_total_length() - bytes_dled;

    let info_hash_escaped = QueryString::encode_component(&metadata.info_hash);
    let response = ping_tracker(&metadata.announce, vec![
                                ("info_hash", info_hash_escaped),
                                ("peer_id", peer_id.clone()),
                                ("port", listen_port.to_string()),
                                ("uploaded", 0.to_string()),
                                ("downloaded", bytes_dled.to_string()),
                                ("left", bytes_left.to_string()),
                                ("compact", 1.to_string()),
                                ("event", "started".to_string()),
                                ("num_want", "15".to_string())
                                ]);

    match response {
        Some(resp) => Some(get_peers(&resp)),
        None => panic!("no valid bencode response from tracker")
    }
}

fn init (metadata: &Metadata, listen_port: u32, bytes_dled: u32) {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let peers = match get_http_tracker_peers(&peer_id, metadata, listen_port, bytes_dled) {
        Some(peers) => peers,
        _ => panic!("cannot get peers from tracker")
    };

    println!("got {} peers", peers.len());

    let (tx, rx) = channel();

    //TODO: the sink initialization should be done outside of init() as one sink can realistically
    //handle multiple torrents relatively trivially
    //all threads will send messages asynchronously to the sink. tbh the loop could be shoved onto the main
    //thread, but for the sake of modularity lets dedicated one for the sink
    let sink = thread::spawn(move || {
        loop {
            let res = rx.recv().unwrap();
            println!("{:?}", res);
        }
    });

    for peer in peers {
        let child_meta = metadata.clone();
        let peer_id = peer_id.clone();
        let tx = tx.clone();
        thread::spawn(move || {
            let conn = connect_to_peer(peer, &child_meta, &peer_id).unwrap();
            tx.send(conn);
        });
    }

    //block until the sink shuts down
    let _ = sink.join();
}

fn start_torrenting () {
    let path = env::args().nth(1)
                          .unwrap_or_else(||panic!("no path to torrent provided"));

    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));

    assert_eq!(content.len(), 1);

    let metadata = match content.first() {
        Some(&Bencode::Dict(ref dict)) => dict.to_metadata(),
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    init(&metadata, 6887, 0);
}

fn main () {
    start_torrenting();
    //test();
}
<|endoftext|>


<commit_before>#![feature(collections, core, old_io, old_path, rustc_private, env)]
#![feature(test)]   // need this for unit tests, but annoyingly puts a warning when building non-test

#[macro_use] extern crate log;

extern crate syntax;
extern crate collections;
extern crate core;

#[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};
#[cfg(not(test))]
use racer::scopes;

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.as_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.as_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 main() {
    if std::env::var("RUST_SRC_PATH").is_err() {
        println!("RUST_SRC_PATH environment variable must be set");
        std::env::set_exit_status(1);
        return;
    }

    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>Updated feature gates (exit_status)<commit_after>#![feature(collections, core, old_io, old_path, rustc_private, exit_status)]
#![feature(test)]   // need this for unit tests, but annoyingly puts a warning when building non-test

#[macro_use] extern crate log;

extern crate syntax;
extern crate collections;
extern crate core;

#[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};
#[cfg(not(test))]
use racer::scopes;

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.as_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.as_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 main() {
    if std::env::var("RUST_SRC_PATH").is_err() {
        println!("RUST_SRC_PATH environment variable must be set");
        std::env::set_exit_status(1);
        return;
    }

    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;
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

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

use std::process::exit;

use clap::App;
use semver::Identifier;

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

fn execute() -> Result<i32, error::FatalError> {

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

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

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

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

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

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

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

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

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

fn main() {
    let _ = App::new("cargo release")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Ning Sun <sunng@about.me>")
        .about("Cargo subcommand for you to smooth your release process.")
        // TODO: .args_from_usage("")
        .get_matches();

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

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

use std::process::exit;

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

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

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

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

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

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

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

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

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

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

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

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

    Ok(0)
}

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

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


<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls};
use rustc::session::{config, CompileIncomplete, Session};
use rustc::session::config::{ErrorOutputType, Input};
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::{self, Command};
use syntax::ast;
use std::io::{self, Write};

extern crate cargo_metadata;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        Self {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default
            .early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default
            .no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        crate_stores: &rustc::middle::cstore::CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default
            .late_callback(matches, sess, crate_stores, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(
                        state.session,
                        state
                            .krate
                            .as_ref()
                            .expect(
                                "at this compilation stage \
                                 the krate must be parsed",
                            )
                            .span,
                    );
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry {
                        early_lint_passes,
                        late_lint_passes,
                        lint_groups,
                        llvm_passes,
                        attributes,
                        ..
                    } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package
    -V, --version            Print version info and exit
    --all                    Run over all packages in the current workspace

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

#[allow(print_stdout)]
fn show_version() {
    println!("{}", env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }
    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
        // this arm is executed on the initial call to `cargo clippy`

        let manifest_path_arg = std::env::args()
            .skip(2)
            .find(|val| val.starts_with("--manifest-path="));

        let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref))
        {
            metadata
        } else {
            let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n"));
            process::exit(101);
        };

        let manifest_path = manifest_path_arg.map(|arg| {
            Path::new(&arg["--manifest-path=".len()..])
                .canonicalize()
                .expect("manifest path could not be canonicalized")
        });

        let packages = if std::env::args().any(|a| a == "--all") {
            metadata.packages
        } else {
            let package_index = {
                if let Some(manifest_path) = manifest_path {
                    metadata.packages.iter().position(|package| {
                        let package_manifest_path = Path::new(&package.manifest_path)
                            .canonicalize()
                            .expect("package manifest path could not be canonicalized");
                        package_manifest_path == manifest_path
                    })
                } else {
                    let package_manifest_paths: HashMap<_, _> = metadata
                        .packages
                        .iter()
                        .enumerate()
                        .map(|(i, package)| {
                            let package_manifest_path = Path::new(&package.manifest_path)
                                .parent()
                                .expect("could not find parent directory of package manifest")
                                .canonicalize()
                                .expect("package directory cannot be canonicalized");
                            (package_manifest_path, i)
                        })
                        .collect();

                    let current_dir = std::env::current_dir()
                        .expect("could not read current directory")
                        .canonicalize()
                        .expect("current directory cannot be canonicalized");

                    let mut current_path: &Path = &current_dir;

                    // This gets the most-recent parent (the one that takes the fewest `cd ..`s to
                    // reach).
                    loop {
                        if let Some(&package_index) = package_manifest_paths.get(current_path) {
                            break Some(package_index);
                        } else {
                            // We'll never reach the filesystem root, because to get to this point in the
                            // code
                            // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to
                            // unwrap the current path's parent.
                            current_path = current_path
                                .parent()
                                .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display()));
                        }
                    }
                }
            }.expect("could not find matching package");

            vec![metadata.packages.remove(package_index)]
        };

        for package in packages {
            let manifest_path = package.manifest_path;

            for target in package.targets {
                let args = std::env::args()
                    .skip(2)
                    .filter(|a| a != "--all" && !a.starts_with("--manifest-path="));

                let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args);
                if let Some(first) = target.kind.get(0) {
                    if target.kind.len() > 1 || first.ends_with("lib") {
                        if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) {
                            std::process::exit(code);
                        }
                    } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                        if let Err(code) = process(
                            vec![format!("--{}", first), target.name]
                                .into_iter()
                                .chain(args),
                        ) {
                            std::process::exit(code);
                        }
                    }
                } else {
                    panic!("badly formatted cargo metadata: target::kind is an empty array");
                }
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC`
        // env var set to itself

        let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
        let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
        let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
            format!("{}/toolchains/{}", home, toolchain)
        } else {
            option_env!("SYSROOT")
                .map(|s| s.to_owned())
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .expect(
                    "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust",
                )
        };

        rustc_driver::in_rustc_thread(|| {
            // this conditional check for the --sysroot flag is there so users can call
            // `cargo-clippy` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
                env::args().collect()
            } else {
                env::args()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::args().any(|s| s == "--emit=metadata");

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
            }

            let mut ccc = ClippyCompilerCalls::new(clippy_enabled);
            let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);
            if let Err(CompileIncomplete::Errored(_)) = result {
                std::process::exit(1);
            }
        }).expect("rustc_thread failed");
    }
}

fn process<I>(old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("--emit=metadata".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC", path)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<commit_msg>Set RUSTC_WRAPPER instead of RUSTC when invoking Cargo<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, Compilation, CompilerCalls, RustcDefaultCalls};
use rustc::session::{config, CompileIncomplete, Session};
use rustc::session::config::{ErrorOutputType, Input};
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::{self, Command};
use syntax::ast;
use std::io::{self, Write};

extern crate cargo_metadata;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        Self {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default
            .early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default
            .no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        matches: &getopts::Matches,
        sess: &Session,
        crate_stores: &rustc::middle::cstore::CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default
            .late_callback(matches, sess, crate_stores, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(
                        state.session,
                        state
                            .krate
                            .as_ref()
                            .expect(
                                "at this compilation stage \
                                 the krate must be parsed",
                            )
                            .span,
                    );
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry {
                        early_lint_passes,
                        late_lint_passes,
                        lint_groups,
                        llvm_passes,
                        attributes,
                        ..
                    } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package
    -V, --version            Print version info and exit
    --all                    Run over all packages in the current workspace

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

#[allow(print_stdout)]
fn show_version() {
    println!("{}", env!("CARGO_PKG_VERSION"));
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }
    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if "clippy" == std::env::args().nth(1).as_ref().expect("cargo-clippy should be called with at least one argument!") {
        // this arm is executed on the initial call to `cargo clippy`

        let manifest_path_arg = std::env::args()
            .skip(2)
            .find(|val| val.starts_with("--manifest-path="));

        let mut metadata = if let Ok(metadata) = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref))
        {
            metadata
        } else {
            let _ = io::stderr().write_fmt(format_args!("error: Could not obtain cargo metadata.\n"));
            process::exit(101);
        };

        let manifest_path = manifest_path_arg.map(|arg| {
            Path::new(&arg["--manifest-path=".len()..])
                .canonicalize()
                .expect("manifest path could not be canonicalized")
        });

        let packages = if std::env::args().any(|a| a == "--all") {
            metadata.packages
        } else {
            let package_index = {
                if let Some(manifest_path) = manifest_path {
                    metadata.packages.iter().position(|package| {
                        let package_manifest_path = Path::new(&package.manifest_path)
                            .canonicalize()
                            .expect("package manifest path could not be canonicalized");
                        package_manifest_path == manifest_path
                    })
                } else {
                    let package_manifest_paths: HashMap<_, _> = metadata
                        .packages
                        .iter()
                        .enumerate()
                        .map(|(i, package)| {
                            let package_manifest_path = Path::new(&package.manifest_path)
                                .parent()
                                .expect("could not find parent directory of package manifest")
                                .canonicalize()
                                .expect("package directory cannot be canonicalized");
                            (package_manifest_path, i)
                        })
                        .collect();

                    let current_dir = std::env::current_dir()
                        .expect("could not read current directory")
                        .canonicalize()
                        .expect("current directory cannot be canonicalized");

                    let mut current_path: &Path = &current_dir;

                    // This gets the most-recent parent (the one that takes the fewest `cd ..`s to
                    // reach).
                    loop {
                        if let Some(&package_index) = package_manifest_paths.get(current_path) {
                            break Some(package_index);
                        } else {
                            // We'll never reach the filesystem root, because to get to this point in the
                            // code
                            // the call to `cargo_metadata::metadata` must have succeeded. So it's okay to
                            // unwrap the current path's parent.
                            current_path = current_path
                                .parent()
                                .unwrap_or_else(|| panic!("could not find parent of path {}", current_path.display()));
                        }
                    }
                }
            }.expect("could not find matching package");

            vec![metadata.packages.remove(package_index)]
        };

        for package in packages {
            let manifest_path = package.manifest_path;

            for target in package.targets {
                let args = std::env::args()
                    .skip(2)
                    .filter(|a| a != "--all" && !a.starts_with("--manifest-path="));

                let args = std::iter::once(format!("--manifest-path={}", manifest_path)).chain(args);
                if let Some(first) = target.kind.get(0) {
                    if target.kind.len() > 1 || first.ends_with("lib") {
                        if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args)) {
                            std::process::exit(code);
                        }
                    } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                        if let Err(code) = process(
                            vec![format!("--{}", first), target.name]
                                .into_iter()
                                .chain(args),
                        ) {
                            std::process::exit(code);
                        }
                    }
                } else {
                    panic!("badly formatted cargo metadata: target::kind is an empty array");
                }
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC_WRAPPER`
        // env var set to itself

        let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
        let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
        let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
            format!("{}/toolchains/{}", home, toolchain)
        } else {
            option_env!("SYSROOT")
                .map(|s| s.to_owned())
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| s.trim().to_owned())
                })
                .expect(
                    "need to specify SYSROOT env var during clippy compilation, or use rustup or multirust",
                )
        };

        rustc_driver::in_rustc_thread(|| {
            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programatically, so we ignore this/
            let orig_args: Vec<String> = env::args().skip(1).collect();

            // this conditional check for the --sysroot flag is there so users can call
            // `cargo-clippy` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if orig_args.iter().any(|s| s == "--sysroot") {
                orig_args.clone()
            } else {
                orig_args.clone().into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = orig_args.iter().any(|s| s == "--emit=metadata");

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
            }

            let mut ccc = ClippyCompilerCalls::new(clippy_enabled);
            let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);
            if let Err(CompileIncomplete::Errored(_)) = result {
                std::process::exit(1);
            }
        }).expect("rustc_thread failed");
    }
}

fn process<I>(old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("--emit=metadata".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WRAPPER", path)
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<|endoftext|>


<commit_before>
extern crate chrono;
extern crate docopt;
extern crate riemann_client;

use riemann_client::Client;
use riemann_client::proto::Event;

use std::process::Command;

use std::io::prelude::*;
use std::net::TcpStream;

use docopt::Docopt;

use std::str::FromStr;

// Write the Docopt usage string. dfrites ?
static USAGE: &'static str = "
Usage: durite -l HOSTNAME [-g GHOSTNAME [-p PORT]] [-r RHOSTNAME [-o RPORT]]
       durite (--help | -h)

Options:
    -h, --help          Show this screen.
    -l HOSTNAME         Hostname to advertise.
    -g GHOSTNAME        Graphite Hostname.
    -r RHOSTNAME        Riemann Hostname.
    -o RPORT            Riemann port [default: 5555]
    -p PORT             Graphite port [default: 2003]
";

#[cfg(not(any(target_os="macos")))]
fn disk_free() -> std::process::Output {
	Command::new("df")
		.arg("--portability").output().unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}

#[cfg(any(target_os="macos"))]
fn disk_free() -> std::process::Output {
	Command::new("df")
		.arg("-k").output().unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}

fn send_content(stream: &mut std::net::TcpStream, hostname: &str, probe_and_value: String, timestamp: i64) {
	let content = format!("durite.{}.{} {}\n", hostname, probe_and_value, timestamp);
	let _ = stream.write(&content.as_bytes());
}

fn main() {

	// Parse argv and exit the program with an error message if it fails.
	let args = Docopt::new(USAGE)
		.and_then(|d| d.argv(std::env::args().into_iter()).parse())
		.unwrap_or_else(|e| e.exit());

    let graphite_connect_string: Option<String> = if args.get_str("-g") != "" {
        Some(format!("{}:{}", args.get_str("-g"), args.get_str("-p")))
    } else {
        None
    };

    let mut riemann_connection: Option<Client> = if args.get_str("-r") != "" {
        match Client::connect(&(args.get_str("-r"), u16::from_str(args.get_str("-o")).unwrap())) {
            Ok(c) => Some(c),
            Err(e) => {println!("Oups: {:?}", e); None}
        }
    } else {
        None
    };

    println!("Connect string is {:?}", graphite_connect_string);
    let my_hostname = args.get_str("-l");

	while true {
	    let dt = chrono::UTC::now();
	    let timestamp = dt.timestamp();
	    let o = disk_free();
		let stdout = String::from_utf8(o.stdout).
			ok().
			unwrap();

		let lines = stdout.split("\n");

        for line in lines {
            if line.starts_with("/") {
                let values: Vec<&str> = line.split(" ").filter(|e| {
                    e.len() != 0
                }).collect();

                let disk = values[0];
                // du reports kbytes
                let all: u64 = u64::from_str(values[1]).unwrap() / 1024;
                let available: u64 = u64::from_str(values[3]).unwrap() / 1024;
                if values.len() > 8 {
                }
                // let w = values[8].to_string();
                // let mut st: StatFs = Default::default();
                // let mp = CString::new(w.into_bytes()).unwrap();
                // unsafe {
                //  let o = statfs(mp.as_ptr(), &mut st);
                //  println!("o{} {:?}", o, st.f_bfree);
                // }

                // {:6E} 6 digit, lower exponential format

                match graphite_connect_string {
                    Some(ref connect_string) => {
                        let cs: &str = connect_string.as_ref();
                        match TcpStream::connect(cs) {
                            Ok(mut stream) => {
                                send_content(&mut stream, my_hostname, format!("{}.available {:3.3}", disk, available), timestamp);
                                send_content(&mut stream, my_hostname, format!("{}.all {}", disk, all), timestamp);
                            },
                            Err(e) => println!("Unable to connect to {}: {:?}\nIgnoring this data point.", connect_string, e)
                        }
                    },
                    None => {}
                }
                match riemann_connection {
                    Some(ref mut client) => {
                        client.event({
                                let mut event = Event::new();
                                event.set_service(format!("durite {} disk {} percent used", my_hostname, disk).to_string());
                                let percent_used: u64 = 100 - (available *100)/(all * 100);
                                event.set_metric_d(percent_used as f64 / 100 as f64);
                                event
                            }).unwrap();
                    },
                    None => {}
                }
            }
        }
	 	std::thread::sleep_ms(10000);
	}
}
<commit_msg>Debug<commit_after>
extern crate chrono;
extern crate docopt;
extern crate riemann_client;

use riemann_client::Client;
use riemann_client::proto::Event;

use std::process::Command;

use std::io::prelude::*;
use std::net::TcpStream;

use docopt::Docopt;

use std::str::FromStr;

// Write the Docopt usage string. dfrites ?
static USAGE: &'static str = "
Usage: durite -l HOSTNAME [-g GHOSTNAME [-p PORT]] [-r RHOSTNAME [-o RPORT]]
       durite (--help | -h)

Options:
    -h, --help          Show this screen.
    -l HOSTNAME         Hostname to advertise.
    -g GHOSTNAME        Graphite Hostname.
    -r RHOSTNAME        Riemann Hostname.
    -o RPORT            Riemann port [default: 5555]
    -p PORT             Graphite port [default: 2003]
";

#[cfg(not(any(target_os="macos")))]
fn disk_free() -> std::process::Output {
	Command::new("df")
		.arg("--portability").output().unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}

#[cfg(any(target_os="macos"))]
fn disk_free() -> std::process::Output {
	Command::new("df")
		.arg("-k").output().unwrap_or_else(|e| { panic!("failed to execute process: {}", e) })
}

fn send_content(stream: &mut std::net::TcpStream, hostname: &str, probe_and_value: String, timestamp: i64) {
	let content = format!("durite.{}.{} {}\n", hostname, probe_and_value, timestamp);
	let _ = stream.write(&content.as_bytes());
}

fn main() {

	// Parse argv and exit the program with an error message if it fails.
	let args = Docopt::new(USAGE)
		.and_then(|d| d.argv(std::env::args().into_iter()).parse())
		.unwrap_or_else(|e| e.exit());

    let graphite_connect_string: Option<String> = if args.get_str("-g") != "" {
        Some(format!("{}:{}", args.get_str("-g"), args.get_str("-p")))
    } else {
        None
    };

    let mut riemann_connection: Option<Client> = if args.get_str("-r") != "" {
        match Client::connect(&(args.get_str("-r"), u16::from_str(args.get_str("-o")).unwrap())) {
            Ok(c) => Some(c),
            Err(e) => {println!("Oups: {:?}", e); None}
        }
    } else {
        None
    };

    println!("Connect string is {:?}", graphite_connect_string);
    let my_hostname = args.get_str("-l");

	while true {
	    let dt = chrono::UTC::now();
	    let timestamp = dt.timestamp();
	    let o = disk_free();
		let stdout = String::from_utf8(o.stdout).
			ok().
			unwrap();

		let lines = stdout.split("\n");

        for line in lines {
            if line.starts_with("/") {
                let values: Vec<&str> = line.split(" ").filter(|e| {
                    e.len() != 0
                }).collect();

                let disk = values[0];
                // du reports kbytes
                let all: u64 = u64::from_str(values[1]).unwrap() / 1024;
                let available: u64 = u64::from_str(values[3]).unwrap() / 1024;
                if values.len() > 8 {
                }
                // let w = values[8].to_string();
                // let mut st: StatFs = Default::default();
                // let mp = CString::new(w.into_bytes()).unwrap();
                // unsafe {
                //  let o = statfs(mp.as_ptr(), &mut st);
                //  println!("o{} {:?}", o, st.f_bfree);
                // }

                // {:6E} 6 digit, lower exponential format

                match graphite_connect_string {
                    Some(ref connect_string) => {
                        let cs: &str = connect_string.as_ref();
                        match TcpStream::connect(cs) {
                            Ok(mut stream) => {
                                send_content(&mut stream, my_hostname, format!("{}.available {:3.3}", disk, available), timestamp);
                                send_content(&mut stream, my_hostname, format!("{}.all {}", disk, all), timestamp);
                            },
                            Err(e) => println!("Unable to connect to {}: {:?}\nIgnoring this data point.", connect_string, e)
                        }
                    },
                    None => {}
                }
                match riemann_connection {
                    Some(ref mut client) => {
                        client.event({
                                let mut event = Event::new();
                                event.set_service(format!("durite {} disk {} percent used", my_hostname, disk).to_string());
                                let percent_used: u64 = 100 - (available *100)/(all * 100);
                                println!("{}, {},  {} {}", percent_used, available, all, disk);
                                event.set_metric_d(percent_used as f64 / 100 as f64);
                                event
                            }).unwrap();
                    },
                    None => {}
                }
            }
        }
	 	std::thread::sleep_ms(10000);
	}
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

extern crate rand;
extern crate serde;
extern crate serde_yaml;

extern crate ansi_term;

use std::fs::File;
use std::io::Read;
use std::io;
use std::env;
use std::fmt;
use ansi_term::Colour::RGB;

const OFF_COLOR: ansi_term::Colour = RGB(153, 102, 0);
const ON_COLOR: ansi_term::Colour = RGB(255, 204, 0);
const OFF_PIXEL: &'static str = "...";
const ON_PIXEL: &'static str = "###";

#[derive(Default, Serialize, Deserialize)]
struct CPU {
    v: [u8; 16],
    i: u16,
    dt: u8,
    st: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
}

impl fmt::Debug for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "v : ").unwrap();
        for v in &self.v {
            write!(f, "{:x}, ", v).unwrap();
        }
        write!(f, "\n").unwrap();

        write!(f, "i : {:x}\n", self.i).unwrap();
        write!(f, "dt: {:x}\n", self.dt).unwrap();
        write!(f, "st: {:x}\n", self.st).unwrap();
        write!(f, "pc: {:x}\n", self.pc).unwrap();
        write!(f, "sp: {:x}\n", self.sp).unwrap();

        write!(f, "sk: ").unwrap();
        for s in &self.stack {
            write!(f, "{:x}, ", s).unwrap();
        }
        write!(f, "")
    }
}

// #[derive(Default)]
struct Computer {
    ram: [u8; 4096],
    cpu: CPU,
}

impl Default for Computer {
     fn default() -> Computer {
         Computer {
             ram: [0u8; 4096],
             cpu: Default::default(),
         }
     }
}

fn combine(arr: &[u8]) -> u16 {
    let mut val: u16 = 0;
    for v in arr {
        val <<= 4;
        val += *v as u16;
    }
    val
}

// fn expand(byte: u8) -> Vec<bool> {
//     let mut ret = Vec::new();
// }

// fn flip_bit(byte: u8, addr: u8) -> (u8, bool) {
//     let old = get_bit(byte, addr);
//     byte ^= 1 << addr;
//     let new = get_bit(byte, addr);

//     return (byte, old == true && new == false);
// }

// fn get_bit(byte: u8, addr: u8) -> bool {
//     return ((byte >> addr) & 1) != 0;
// }

impl Computer {
    fn ld_i_addr(&mut self, inst: &[u8; 4]) {
        let addr = combine(&inst[1..]);
        self.cpu.i = addr;
    }

    fn rnd_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let random_byte = rand::random::<u8>();
        let byte: u8 = kk & random_byte;
        self.cpu.v[inst[1] as usize] = byte;
    }

    fn se_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let vx = self.cpu.v[inst[1] as usize];
        if kk == vx {
            self.cpu.pc += 2;
        }
    }

    fn drw_vx_vy_nibble(&mut self, inst: &[u8; 4]) {
        let x = self.cpu.v[inst[1] as usize];
        let y = self.cpu.v[inst[2] as usize];
        let n = inst[3] as u8;
        let mut sprite: Vec<u8> = Vec::new();
        // sprite.reserve_exact(n as usize);
        sprite.extend_from_slice(&self.ram[(self.cpu.i as usize)..((self.cpu.i+(n as u16)) as usize)]);
        let offset: u8 = x % 8;
        let mut collided = false;
        for i in 0..n {
            let first_byte: usize = (((y + i) * 8) + (x / 8)) as usize;
            let second_byte: usize = ((y + i) * 8 + ((x + 8) % 64) / 8) as usize;

            let mut shift: u8 = sprite[i as usize] >> offset;
            collided = collided || ((shift & self.ram[first_byte]) != 0);
            self.ram[first_byte] ^= shift;

            shift = sprite[i as usize] << (7 - offset);
            collided = collided || ((shift & self.ram[second_byte]) != 0);
            self.ram[second_byte] ^= shift;
        }
        self.cpu.v[0xf] = if collided { 1 } else { 0 };
    }

    fn add_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        self.cpu.v[inst[1] as usize] += kk;
    }

    fn jmp_addr(&mut self, inst: &[u8; 4]) {
        self.cpu.pc = combine(&inst[1..]) as u16;
    }

    fn ld_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        self.cpu.v[inst[1] as usize] = kk;
    }
}

fn draw_screen(screen: &[u8]) {
    for i in 0..32 {
        for j in 0..8 {
            let byte = screen[i*j];
            for k in 0..8 {
                if ((byte >> k) & 1) != 0 {
                    print!("{}", OFF_COLOR.on(ON_COLOR).paint(ON_PIXEL));
                } else {
                    print!("{}", ON_COLOR.on(OFF_COLOR).paint(OFF_PIXEL));
                }
            }
        }
        println!("");
    }
}

// cargo run -- ./games/TANK

fn main() {
    let mut computer: Computer = Default::default();
    computer.cpu.pc = 0x200;
    let mut f = File::open(env::args().nth(1).unwrap()).unwrap();

    {
        let end: usize = 0x200 + f.metadata().unwrap().len() as usize;
        let mut slice = &mut computer.ram[0x200..end];
        f.read_exact(slice).unwrap();
    }

    let offset = computer.ram.len() - 256 - 1;

    loop {
        let mut should_inc = true;

        let inst: [u8; 4] = {
            let inst0 = computer.ram[computer.cpu.pc as usize];
            let inst1 = computer.ram[(computer.cpu.pc + 1) as usize];

            let tet0 = inst0 >> 4;
            let tet1 = 0x0f & inst0;
            let tet2 = inst1 >> 4;
            let tet3 = 0x0f & inst1;

            [tet0, tet1, tet2, tet3]
        };

        let inst_name: &str;

        match inst[0] {
            0x3 => {
                inst_name = "set_vx_byte";
                computer.se_vx_byte(&inst);
            },
            0xa => {
                inst_name = "ld_i_addr";
                computer.ld_i_addr(&inst);
            },
            0xc => {
                inst_name = "rnd_vx_byte";
                computer.rnd_vx_byte(&inst);
            },
            0xd => {
                inst_name = "drw_vx_vy_nibble";
                computer.drw_vx_vy_nibble(&inst);
                draw_screen(&computer.ram[offset..]);
            },
            0x7 => {
                inst_name = "add_vx_byte";
                computer.add_vx_byte(&inst);
            },
            0x1 => {
                inst_name = "jmp_addr";
                computer.jmp_addr(&inst);
                should_inc = false;
            },
            0x6 => {
                inst_name = "ld_vx_byte";
                computer.ld_vx_byte(&inst);
            }
            _ => panic!("unimplemented instruction: {:x}", inst[0])
        }
        print!("inst: ");
        for x in &inst {
            print!("{:x}", x);
        }
        println!(" ({})", inst_name);

        if should_inc {
            computer.cpu.pc += 2;
        }

        println!("{:?}", computer.cpu);

        // step on newline
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();
    }
}

#[test]
fn combine_test1() {
    let inst = [0x1, 0x2, 0x3];
    let combo = combine(&inst);
    assert!(0x123 == combo);
}

#[test]
fn combine_test2() {
    let inst = [0x3];
    let combo = combine(&inst);
    assert!(0x3 == combo);
}

#[test]
fn combine_test3() {
    let inst = [0x1, 0x2, 0x3, 0x4];
    let combo = combine(&inst);
    assert!(0x1234 == combo);
}
<commit_msg>Fix Draw<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

extern crate rand;
extern crate serde;
extern crate serde_yaml;

extern crate ansi_term;

use std::fs::File;
use std::io::Read;
use std::io;
use std::env;
use std::fmt;
use ansi_term::Colour::RGB;

const OFF_COLOR: ansi_term::Colour = RGB(153, 102, 0);
const ON_COLOR: ansi_term::Colour = RGB(255, 204, 0);
const OFF_PIXEL: &'static str = "...";
const ON_PIXEL: &'static str = "###";

#[derive(Default, Serialize, Deserialize)]
struct CPU {
    v: [u8; 16],
    i: u16,
    dt: u8,
    st: u8,
    pc: u16,
    sp: u8,
    stack: [u16; 16],
}

impl fmt::Debug for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "v : ").unwrap();
        for v in &self.v {
            write!(f, "{:x}, ", v).unwrap();
        }
        write!(f, "\n").unwrap();

        write!(f, "i : {:x}\n", self.i).unwrap();
        write!(f, "dt: {:x}\n", self.dt).unwrap();
        write!(f, "st: {:x}\n", self.st).unwrap();
        write!(f, "pc: {:x}\n", self.pc).unwrap();
        write!(f, "sp: {:x}\n", self.sp).unwrap();

        write!(f, "sk: ").unwrap();
        for s in &self.stack {
            write!(f, "{:x}, ", s).unwrap();
        }
        write!(f, "")
    }
}

// #[derive(Default)]
struct Computer {
    ram: [u8; 4096],
    cpu: CPU,
}

impl Default for Computer {
     fn default() -> Computer {
         Computer {
             ram: [0u8; 4096],
             cpu: Default::default(),
         }
     }
}

fn combine(arr: &[u8]) -> u16 {
    let mut val: u16 = 0;
    for v in arr {
        val <<= 4;
        val += *v as u16;
    }
    val
}

// fn expand(byte: u8) -> Vec<bool> {
//     let mut ret = Vec::new();
// }

// fn flip_bit(byte: u8, addr: u8) -> (u8, bool) {
//     let old = get_bit(byte, addr);
//     byte ^= 1 << addr;
//     let new = get_bit(byte, addr);

//     return (byte, old == true && new == false);
// }

// fn get_bit(byte: u8, addr: u8) -> bool {
//     return ((byte >> addr) & 1) != 0;
// }

impl Computer {
    fn ld_i_addr(&mut self, inst: &[u8; 4]) {
        let addr = combine(&inst[1..]);
        self.cpu.i = addr;
    }

    fn rnd_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let random_byte = rand::random::<u8>();
        let byte: u8 = kk & random_byte;
        self.cpu.v[inst[1] as usize] = byte;
    }

    fn se_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        let vx = self.cpu.v[inst[1] as usize];
        if kk == vx {
            self.cpu.pc += 2;
        }
    }

    fn drw_vx_vy_nibble(&mut self, inst: &[u8; 4]) {
        let screen_start: usize = self.ram.len() - 256 - 1;
        let x = self.cpu.v[inst[1] as usize];
        let y = self.cpu.v[inst[2] as usize];
        let n = inst[3] as u8;
        let mut sprite: Vec<u8> = Vec::new();
        // sprite.reserve_exact(n as usize);
        sprite.extend_from_slice(&self.ram[(self.cpu.i as usize)..((self.cpu.i+(n as u16)) as usize)]);
        let offset: u8 = x % 8;
        let mut collided = false;
        for i in 0..n {
            let first_byte: usize = (((y + i) * 8) + (x / 8)) as usize + screen_start;
            let second_byte: usize = ((y + i) * 8 + ((x + 8) % 64) / 8) as usize + screen_start;

            let mut shift: u8 = sprite[i as usize] >> offset;
            collided = collided || ((shift & self.ram[first_byte]) != 0);
            self.ram[first_byte] ^= shift;

            shift = sprite[i as usize] << (7 - offset);
            collided = collided || ((shift & self.ram[second_byte]) != 0);
            self.ram[second_byte] ^= shift;
        }
        self.cpu.v[0xf] = if collided { 1 } else { 0 };
    }

    fn add_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        self.cpu.v[inst[1] as usize] += kk;
    }

    fn jmp_addr(&mut self, inst: &[u8; 4]) {
        self.cpu.pc = combine(&inst[1..]) as u16;
    }

    fn ld_vx_byte(&mut self, inst: &[u8; 4]) {
        let kk = combine(&inst[2..]) as u8;
        self.cpu.v[inst[1] as usize] = kk;
    }
}

fn draw_screen(screen: &[u8]) {
    for i in 0..32 {
        for j in 0..8 {
            let byte = screen[(i * 8) + j];
            for k in 0..8 {
                if ((byte >> k) & 1) != 0 {
                    print!("{}", OFF_COLOR.on(ON_COLOR).paint(ON_PIXEL));
                } else {
                    print!("{}", ON_COLOR.on(OFF_COLOR).paint(OFF_PIXEL));
                }
            }
        }
        println!("");
    }
    println!("");
}

// cargo run -- ./games/TANK

fn main() {
    let mut computer: Computer = Default::default();
    computer.cpu.pc = 0x200;
    let mut f = File::open(env::args().nth(1).unwrap()).unwrap();

    {
        let end: usize = 0x200 + f.metadata().unwrap().len() as usize;
        let mut slice = &mut computer.ram[0x200..end];
        f.read_exact(slice).unwrap();
    }

    let offset = computer.ram.len() - 256 - 1;

    loop {
        let mut should_inc = true;

        let inst: [u8; 4] = {
            let inst0 = computer.ram[computer.cpu.pc as usize];
            let inst1 = computer.ram[(computer.cpu.pc + 1) as usize];

            let tet0 = inst0 >> 4;
            let tet1 = 0x0f & inst0;
            let tet2 = inst1 >> 4;
            let tet3 = 0x0f & inst1;

            [tet0, tet1, tet2, tet3]
        };

        let inst_name: &str;

        match inst[0] {
            0x3 => {
                inst_name = "set_vx_byte";
                computer.se_vx_byte(&inst);
            },
            0xa => {
                inst_name = "ld_i_addr";
                computer.ld_i_addr(&inst);
            },
            0xc => {
                inst_name = "rnd_vx_byte";
                computer.rnd_vx_byte(&inst);
            },
            0xd => {
                inst_name = "drw_vx_vy_nibble";
                computer.drw_vx_vy_nibble(&inst);
                draw_screen(&computer.ram[offset..]);
            },
            0x7 => {
                inst_name = "add_vx_byte";
                computer.add_vx_byte(&inst);
            },
            0x1 => {
                inst_name = "jmp_addr";
                computer.jmp_addr(&inst);
                should_inc = false;
            },
            0x6 => {
                inst_name = "ld_vx_byte";
                computer.ld_vx_byte(&inst);
            }
            _ => panic!("unimplemented instruction: {:x}", inst[0])
        }
        // print!("inst: ");
        // for x in &inst {
        //     print!("{:x}", x);
        // }
        // println!(" ({})", inst_name);

        if should_inc {
            computer.cpu.pc += 2;
        }

        // println!("{:?}", computer.cpu);

        // step on newline
        // let mut input = String::new();
        // io::stdin().read_line(&mut input).unwrap();
    }
}

#[test]
fn combine_test1() {
    let inst = [0x1, 0x2, 0x3];
    let combo = combine(&inst);
    assert!(0x123 == combo);
}

#[test]
fn combine_test2() {
    let inst = [0x3];
    let combo = combine(&inst);
    assert!(0x3 == combo);
}

#[test]
fn combine_test3() {
    let inst = [0x1, 0x2, 0x3, 0x4];
    let combo = combine(&inst);
    assert!(0x1234 == combo);
}
<|endoftext|>


<commit_before>extern crate dotenv;
extern crate deploy;
extern crate pencil;
#[macro_use] extern crate lazy_static;

use dotenv::dotenv;
use std::env;
use pencil::{Pencil, Response, Request, PencilResult};
use deploy::*;

lazy_static! {
  pub static ref SECRET: String = env::var("TENJAVA_DEPLOY_SECRET").expect("no deploy secret set");
}

fn deploy_webhook(r: &mut Request) -> PencilResult {
  let (signature, event) = {
    let headers = r.headers();
    let signature: &XHubSignature = headers.get().unwrap();
    let event: &XGitHubEvent = headers.get().unwrap();
    (signature.clone(), event.clone())
  };
  if *event != "push" {
    return Ok("not a push event, but thanks anyway".into());
  }
  if !deploy::check_signature(r, &signature, &SECRET) {
    let mut res = Response::new("invalid signature");
    res.status_code = 401;
    return Ok(res);
  }
  Ok("okay".into())
}

fn main() {
  dotenv().ok();
  let mut app = Pencil::new("/static");
  app.post("/deploy", "deploy", deploy_webhook);
  app.run("0.0.0.0:32260");
}
<commit_msg>feat: actually update a repo<commit_after>extern crate dotenv;
extern crate deploy;
extern crate pencil;
#[macro_use] extern crate lazy_static;

use dotenv::dotenv;
use std::env;
use std::thread;
use std::process::{Stdio, Command};
use std::path::Path;
use pencil::{Pencil, Response, Request, PencilResult};
use deploy::*;

lazy_static! {
  pub static ref SECRET: String = env::var("TENJAVA_DEPLOY_SECRET").expect("missing TENJAVA_DEPLOY_SECRET");
  pub static ref REPO: String = env::var("TENJAVA_WEBSITE_REPO").expect("mssing TENJAVA_WEBSITE_REPO");
}

fn deploy_webhook(r: &mut Request) -> PencilResult {
  let (signature, event) = {
    let headers = r.headers();
    let signature: &XHubSignature = headers.get().unwrap();
    let event: &XGitHubEvent = headers.get().unwrap();
    (signature.clone(), event.clone())
  };
  if *event != "push" {
    return Ok("not a push event, but thanks anyway".into());
  }
  if !deploy::check_signature(r, &signature, &SECRET) {
    let mut res = Response::new("invalid signature");
    res.status_code = 401;
    return Ok(res);
  }
  update_repo();
  Ok("deploy initiated".into())
}

fn update_repo() {
  thread::spawn(move || {
    let status = Command::new("git")
      .arg("pull")
      .stdout(Stdio::null())
      .current_dir(Path::new(&*REPO))
      .status()
      .expect("could not start git");
    if !status.success() {
      match status.code() {
        Some(code) => {
          println!("git exited with code {}", code);
        },
        None => {
          println!("git exited with an unknown status code");
        }
      }
    }
  });
}

fn inner() -> i32 {
  // load up env
  dotenv().ok();

  // check env
  if (&*SECRET).is_empty() {
    println!("oops, no TENJAVA_DEPLOY_SECRET was specified");
    return 1;
  }
  if (&*REPO).is_empty() {
    println!("oops, no TENJAVA_WEBSITE_REPO was specified");
    return 1;
  }
  let mut app = Pencil::new("/static");
  app.post("/deploy", "deploy", deploy_webhook);
  app.run("0.0.0.0:32260");
  0
}

fn main() {
  let exit_code = inner();
  std::process::exit(exit_code);
}
<|endoftext|>