<commit_before>#![feature(core)]
#![feature(path)]

#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex;
extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;
use regex::Regex;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}
/*
fn to_key(s: String) -> String {
    let re = regex!(r"\s{2,}"); // 2 or more whitespaces
    //let re = regex::Regex::new(r"\s{2,}");
    re.replace_all(s.as_slice(), "")
}
*/

#[derive(Debug)]
enum State {
    Other, Addition, Deletion
}

//fn transition_from_add_or_del(state: State, added: String, deleted: String) {

//}

fn dump_diffdelta(delta: DiffDelta) {
    println!("delta: nfiles={} status={:?} old_file=(id={} path_bytes={:?} path={:?} tsize={}) new_file=(id={} path_bytes={:?} path={:?} tsize={})",
            delta.nfiles(), delta.status(),
            delta.old_file().id(), delta.old_file().path_bytes(), delta.old_file().path(), delta.old_file().size(),
            delta.new_file().id(), delta.new_file().path_bytes(), delta.new_file().path(), delta.new_file().size());
}

fn format_key(key: String) -> String {
    let removeWhiteSpace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    removeWhiteSpace.replace_all(key.as_slice(), "")
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    //let mut results: Vec<Output> = Vec::new();

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();

    let mut keys: Vec<String> = Vec::new();  // TODO Will become hashmap.

	//let mut current_hunk: Vec<String> = Vec::new();
	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("top of loop: keys={:?}", keys);
        println!("top of loop: added={:?} deleted={:?}", added, deleted);

        // 'origin' is wrapped in pipes to ease displaying space characters.
        print!("line: old={:?} new={:?} offset={} |origin|=|{}|\n      content={}",
                 line.old_lineno(), line.new_lineno(), line.content_offset(),
                 line.origin(), str::from_utf8(line.content()).unwrap());

        //dump_diffdelta(delta);

        let re = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.

		match line.origin() {
            /*
            // Context
			' ' | '=' => {
                print!("= {}", str::from_utf8(line.content()).unwrap());
                offset += 1;
                true
            },
			// Headers
			'F' | 'H' => {
                print!("F {}", str::from_utf8(line.content()).unwrap());
                offset += 1;
                true
            },
            */
			// Additions
			'+' | '>' => {
                println!("In additions. state={:?}", state);

                added.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Deletion => {
                        keys.push(format_key(deleted.clone()));
                        deleted = String::new();
                    },
                    _ => {}
                }

                state = State::Addition;
				true
			},
			// Deletions
			'-' | '<' => {
                println!("In deletion. state={:?}", state);

                deleted.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Addition => {
                        keys.push(format_key(added.clone()));
                        added = String::new();
                    },
                    _ => {}
                }

                state = State::Deletion;
				true
			},
			// Other (We don't care about these.)
			_         => {
                println!("in _. state={:?}", state);

                match state {
                    State::Addition => {
                        keys.push(format_key(added.clone()));
                        added = String::new();
                    },
                    State::Deletion => {
                        keys.push(format_key(deleted.clone()));
                        deleted = String::new();
                    },
                    State::Other => {}
                }

                state = State::Other;
                true
            }
		}

			// Look at that match statement, what a hunk. So hunky.
			// match maybe_hunk {
			//     Some(hunk) => unimplemented!(),
			//     None => unimplemented!(),
			// }
	});

    println!("KEYS={:?}", keys);

    Ok(vec![Output {
	    old_commit: old.id(),
	    new_commit: new.id(),
	    origin_line: 0,
	    destination_line: 0,
	    num_lines: 0
    }])
}

#[derive(Debug)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<commit_msg>Remove commented out code.<commit_after>#![feature(core)]
#![feature(path)]

#![feature(plugin)]
#![plugin(regex_macros)]
extern crate regex;
extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;
use regex::Regex;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}

#[derive(Debug)]
enum State {
    Other, Addition, Deletion
}

fn dump_diffdelta(delta: DiffDelta) {
    println!("delta: nfiles={} status={:?} old_file=(id={} path_bytes={:?} path={:?} tsize={}) new_file=(id={} path_bytes={:?} path={:?} tsize={})",
            delta.nfiles(), delta.status(),
            delta.old_file().id(), delta.old_file().path_bytes(), delta.old_file().path(), delta.old_file().size(),
            delta.new_file().id(), delta.new_file().path_bytes(), delta.new_file().path(), delta.new_file().size());
}

fn format_key(key: String) -> String {
    let removeWhiteSpace = regex!(r"\s{2,}"); // 2 or more whitespaces    // TODO Removes whitespace from a string.
    removeWhiteSpace.replace_all(key.as_slice(), "")
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));

    let mut state = State::Other;
    let mut added = String::new();
    let mut deleted = String::new();

    let mut keys: Vec<String> = Vec::new();  // TODO Will become hashmap.

	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {

		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("top of loop: keys={:?}", keys);
        println!("top of loop: added={:?} deleted={:?}", added, deleted);

        // 'origin' is wrapped in pipes to ease displaying space characters.
        print!("line: old={:?} new={:?} offset={} |origin|=|{}|\n      content={}",
                 line.old_lineno(), line.new_lineno(), line.content_offset(),
                 line.origin(), str::from_utf8(line.content()).unwrap());

        //dump_diffdelta(delta);

		match line.origin() {
			// Additions
			'+' | '>' => {
                println!("In additions. state={:?}", state);

                added.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Deletion => {
                        keys.push(format_key(deleted.clone()));
                        deleted = String::new();
                    },
                    _ => {}
                }

                state = State::Addition;
				true
			},
			// Deletions
			'-' | '<' => {
                println!("In deletion. state={:?}", state);

                deleted.push_str(str::from_utf8(line.content()).unwrap());

                match state {
                    State::Addition => {
                        keys.push(format_key(added.clone()));
                        added = String::new();
                    },
                    _ => {}
                }

                state = State::Deletion;
				true
			},
			// Other
			_         => {
                println!("in _. state={:?}", state);

                match state {
                    State::Addition => {
                        keys.push(format_key(added.clone()));
                        added = String::new();
                    },
                    State::Deletion => {
                        keys.push(format_key(deleted.clone()));
                        deleted = String::new();
                    },
                    State::Other => {}
                }

                state = State::Other;
                true
            }
		}
	});

    println!("KEYS={:?}", keys);

    Ok(vec![Output {
	    old_commit: old.id(),
	    new_commit: new.id(),
	    origin_line: 0,
	    destination_line: 0,
	    num_lines: 0
    }])
}

#[derive(Debug)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<|endoftext|>


<commit_before>extern crate html5ever;
#[macro_use(qualname,ns,atom)]
extern crate string_cache;
#[macro_use(format_tendril)]
extern crate tendril;

use html5ever::rcdom::NodeEnum::Element;
use html5ever::rcdom::{RcDom, Handle};
use html5ever::serialize::{SerializeOpts, serialize};
use html5ever::tendril::TendrilSink;
use html5ever::tree_builder::{TreeBuilderOpts, TreeSink, NodeOrText};
use html5ever::{ParseOpts, parse_document};
use std::string::String;
use std::io;

enum Section {
    Method(Handle),
}

fn main() {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts { drop_doctype: true, ..Default::default() },
        ..Default::default()
    };

    let stdin = io::stdin();
    let mut dom = parse_document(RcDom::default(), opts)
                      .from_utf8()
                      .read_from(&mut stdin.lock())
                      .unwrap();

    let mut sections = vec![];
    walk(&dom.document, &mut sections);

    // https://kapeli.com/docsets#tableofcontents
    // https://kapeli.com/docsets#supportedentrytypes
    for section in sections {
        match section {
            Section::Method(p) => {
                add_dash_link(&mut dom, &p, "method", "42")
            }
        }
    }

    let mut bytes = vec![];
    serialize(&mut bytes, &dom.document, SerializeOpts::default()).unwrap();
    let result = String::from_utf8(bytes).unwrap();
    println!("{}", result);
}

fn add_dash_link(dom: &mut RcDom, p: &Handle, entrytype: &str, entryname: &str) {
    let class_attr = html5ever::Attribute {
        name: qualname!("", "class"),
        value: format_tendril!("dashAnchor"),
    };

    let name_attr = html5ever::Attribute {
        name: qualname!("", "name"),
        value: format_tendril!("//apple_ref/cpp/{}/{}", entrytype, entryname),
    };

    let dash_link = dom.create_element(qualname!(html, "a"), vec![name_attr, class_attr.clone()]);
    let _ = dom.append_before_sibling(p.clone(), NodeOrText::AppendNode(dash_link));
}

fn walk(h: &Handle, sections: &mut Vec<Section>) {
    let node = h.borrow();
    for e in node.children.iter() {
        if let Element(_, _, ref attrs) = e.borrow().node {
            if let Some(attr) = attrs.iter().find(|ref x| x.name == qualname!("", "class")) {
                match attr.clone().value.to_string().as_str() {
                    "method" => sections.push(Section::Method(e.clone())),
                    _ => {}
                }
            }
        }
        walk(e, sections);
    }
}
<commit_msg>Wrap tree walking in find_entries methods<commit_after>extern crate html5ever;
#[macro_use(qualname,ns,atom)]
extern crate string_cache;
#[macro_use(format_tendril)]
extern crate tendril;

use html5ever::rcdom::NodeEnum::Element;
use html5ever::rcdom::{RcDom, Handle};
use html5ever::serialize::{SerializeOpts, serialize};
use html5ever::tendril::TendrilSink;
use html5ever::tree_builder::{TreeBuilderOpts, TreeSink, NodeOrText};
use html5ever::{ParseOpts, parse_document};
use std::string::String;
use std::io;

enum Entry {
    Method(Handle),
}

fn main() {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts { drop_doctype: true, ..Default::default() },
        ..Default::default()
    };

    let stdin = io::stdin();
    let mut dom = parse_document(RcDom::default(), opts)
                      .from_utf8()
                      .read_from(&mut stdin.lock())
                      .unwrap();

    let entries = find_entries(&mut dom);

    // https://kapeli.com/docsets#tableofcontents
    // https://kapeli.com/docsets#supportedentrytypes
    for entry in entries {
        match entry {
            Entry::Method(p) => {
                add_dash_link(&mut dom, &p, "method", "42")
            }
        }
    }

    let mut bytes = vec![];
    serialize(&mut bytes, &dom.document, SerializeOpts::default()).unwrap();
    let result = String::from_utf8(bytes).unwrap();
    println!("{}", result);
}

fn add_dash_link(dom: &mut RcDom, p: &Handle, entrytype: &str, entryname: &str) {
    let class_attr = html5ever::Attribute {
        name: qualname!("", "class"),
        value: format_tendril!("dashAnchor"),
    };

    let name_attr = html5ever::Attribute {
        name: qualname!("", "name"),
        value: format_tendril!("//apple_ref/cpp/{}/{}", entrytype, entryname),
    };

    let dash_link = dom.create_element(qualname!(html, "a"), vec![name_attr, class_attr.clone()]);
    let _ = dom.append_before_sibling(p.clone(), NodeOrText::AppendNode(dash_link));
}

fn find_entries(dom: &mut RcDom) -> Vec<Entry> {
    let mut entries = vec![];
    walk_tree(&dom.document, &mut entries);
    entries
}

fn walk_tree(h: &Handle, entries: &mut Vec<Entry>) {
    let node = h.borrow();
    for e in node.children.iter() {
        if let Element(_, _, ref attrs) = e.borrow().node {
            if let Some(attr) = attrs.iter().find(|ref x| x.name == qualname!("", "class")) {
                match attr.clone().value.to_string().as_str() {
                    "method" => entries.push(Entry::Method(e.clone())),
                    _ => {}
                }
            }
        }
        walk_tree(e, entries);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{BufReader, BufRead};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";
static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct CrateInfo {
    name: String,
    vers: String,
    deps: Vec<DepInfo>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct DepInfo {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

fn build_dependency_map() -> HashMap<String, Vec<String>> {
    let mut match_options = glob::MatchOptions::new();
    match_options.require_literal_leading_dot = true;

    let index_paths1 = glob::glob_with("crates.io-index/*/*/*", &match_options).unwrap();
    let index_paths2 = glob::glob_with("crates.io-index/[12]/*", &match_options).unwrap();

    let index_paths = index_paths1.chain(index_paths2);

    let mut map = HashMap::new();

    for glob_result in index_paths { let index_path = glob_result.unwrap();
        let file = fs::File::open(&index_path).unwrap();
        let last_line = BufReader::new(file).lines().last().unwrap().unwrap();
        let crate_info: CrateInfo = rustc_serialize::json::decode(&last_line).unwrap();
        let deps_names = crate_info.deps.iter().map(|d| d.name.clone()).collect();
        map.insert(crate_info.name, deps_names);
    }

    map
}

fn main() {
    if fs::metadata(INDEX_LOCAL_PATH).is_err() {
        println!("Cloning crates.io-index");
        git2::Repository::clone(INDEX_GIT_URL, INDEX_LOCAL_PATH).unwrap();
    }

    let dep_map = build_dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.get_method(),
            request.get_url(),
            request.get_headers()
        );

        let response = tiny_http::Response::from_string("hello world".to_string());
        request.respond(response);
    }
}
<commit_msg>Fix weird formatting<commit_after>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{BufReader, BufRead};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";
static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct CrateInfo {
    name: String,
    vers: String,
    deps: Vec<DepInfo>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct DepInfo {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

fn build_dependency_map() -> HashMap<String, Vec<String>> {
    let mut match_options = glob::MatchOptions::new();
    match_options.require_literal_leading_dot = true;

    let index_paths1 = glob::glob_with("crates.io-index/*/*/*", &match_options).unwrap();
    let index_paths2 = glob::glob_with("crates.io-index/[12]/*", &match_options).unwrap();

    let index_paths = index_paths1.chain(index_paths2);

    let mut map = HashMap::new();

    for glob_result in index_paths {
        let index_path = glob_result.unwrap();
        let file = fs::File::open(&index_path).unwrap();
        let last_line = BufReader::new(file).lines().last().unwrap().unwrap();
        let crate_info: CrateInfo = rustc_serialize::json::decode(&last_line).unwrap();
        let deps_names = crate_info.deps.iter().map(|d| d.name.clone()).collect();
        map.insert(crate_info.name, deps_names);
    }

    map
}

fn main() {
    if fs::metadata(INDEX_LOCAL_PATH).is_err() {
        println!("Cloning crates.io-index");
        git2::Repository::clone(INDEX_GIT_URL, INDEX_LOCAL_PATH).unwrap();
    }

    let dep_map = build_dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.get_method(),
            request.get_url(),
            request.get_headers()
        );

        let response = tiny_http::Response::from_string("hello world".to_string());
        request.respond(response);
    }
}
<|endoftext|>


<commit_before>extern crate bspl;
extern crate tempfile;
extern crate rustyline;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use tempfile::NamedTempFile;
use bspl::constants::VERSION;
use bspl::lexer::Lexer;
use bspl::parser::Parser;
use bspl::evaluator::Evaluator;
// use bspl::error::ParserError;

fn prelude() {
    println!("bspl {}", VERSION);
    println!("Bit-Shift-Print Loop");
    println!("Type 'help', or 'license' for more information.");
}

fn repl() {
    let mut repl = Editor::<()>::new();
    let tmp_file = NamedTempFile::new().unwrap();
    let _ = repl.load_history(tmp_file.path());
    let mut lexer = Lexer::new();
    let mut parser = Parser::default();
    // let mut evaluator = Evaluator::new();

    loop {
        match repl.readline("=> ") {
            Ok(line) => {
                repl.add_history_entry(&line);
                let mut tokens = lexer.analyze(&line);
                for t in tokens.iter() {
                    println!("{:?}", t);
                }
                let mut parsed_tokens = parser.parse(tokens);
                for p in parsed_tokens.iter() {
                    println!("{:?}", p);
                }
                // let result: String = evaluator.evaluate(parsed_tokens);
            }
            Err(ReadlineError::Eof) => break,
            Err(ReadlineError::Interrupted) => {
                println!("Type 'exit' or press Ctrl-D to leave bspl");
                continue;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }

        }
        repl.save_history(tmp_file.path()).unwrap();
    }
}

pub fn main() {
    prelude();
    repl();
}
<commit_msg>Match parser errors<commit_after>extern crate bspl;
extern crate tempfile;
extern crate rustyline;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use tempfile::NamedTempFile;
use bspl::constants::VERSION;
use bspl::lexer::Lexer;
use bspl::parser::Parser;
use bspl::evaluator::Evaluator;
use bspl::error::ParserError;

fn prelude() {
    println!("bspl {}", VERSION);
    println!("Bit-Shift-Print Loop");
    println!("Type 'help', or 'license' for more information.");
}

fn repl() {
    let mut repl = Editor::<()>::new();
    let prompt = "=> ";
    let tmp_file = NamedTempFile::new().unwrap();
    let _ = repl.load_history(tmp_file.path());

    let mut lexer = Lexer::new();
    let mut parser = Parser::default();
    // let mut evaluator = Evaluator::new();

    loop {
        match repl.readline(prompt) {
            Ok(line) => {
                repl.add_history_entry(&line);
                match parser.parse(lexer.analyze(&line)) {
                    Ok(parsed_tokens) => {
                        println!("{:?}", parsed_tokens);
                        // let result: String = evaluator.evaluate(parsed_tokens);
                    }
                    Err(ParserError::IllegalOperator(position)) => {
                        println!("{caret:>width$}\n.. Illegal Operator",
                                 caret = "^",
                                 width = position + prompt.len() + 1);
                    }
                    Err(ParserError::MissingBracket(position)) => {
                        println!("{caret:>width$}\n.. Missing Bracket",
                                 caret = "^",
                                 width = position + prompt.len() + 1);
                    }
                    _ => break,

                }
            }
            Err(ReadlineError::Eof) => break,
            Err(ReadlineError::Interrupted) => {
                println!("Type 'exit' or press Ctrl-D to leave bspl");
                continue;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }

        }
        repl.save_history(tmp_file.path()).unwrap();
    }
}

pub fn main() {
    prelude();
    repl();
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate env_logger;
extern crate log;
extern crate shlex;
extern crate skim;
extern crate time;

use clap::{App, Arg};
use skim::{Skim, SkimOptions};
use std::env;

const VERSION: &str = env!("CARGO_PKG_VERSION");

const USAGE: &str = "
Usage: sk [options]

  Options
    -h, --help           print this help menu
    --version            print out the current version of skim

  Search
    --tac                reverse the order of input
    -t, --tiebreak [score,index,begin,end,-score,...]
                         comma seperated criteria
    -n, --nth 1,2..5     specify the fields to be matched
    --with-nth 1,2..5    specify the fields to be transformed
    -d, --delimiter \\t  specify the delimiter(in REGEX) for fields
    -e, --exact          start skim in exact mode
    --regex              use regex instead of fuzzy match

  Interface
    -b, --bind KEYBINDS  comma seperated keybindings, in KEY:ACTION
                         such as 'ctrl-j:accept,ctrl-k:kill-line'
    -m, --multi          Enable Multiple Selection
    --no-multi           Disable Multiple Selection
    -c, --cmd ag         command to invoke dynamically
    -I replstr           replace `replstr` with the selected item
    -i, --interactive    Start skim in interactive(command) mode
    --color [BASE][,COLOR:ANSI]
                         change color theme
    --no-hscroll         Disable horizontal scroll

  Layout
    --reverse            Reverse orientation
    --height=HEIGHT      Height of skim's window (--height 40%)
    --no-height          Disable height feature
    --min-height=HEIGHT  Minimum height when --height is given by percent
                         (default: 10)
    --margin=MARGIN      Screen Margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
                         e.g. (sk --margin 1,10%)
    -p, --prompt '> '    prompt string for query mode
    --cmd-prompt '> '    prompt string for command mode

  Display
    --ansi               parse ANSI color codes for input strings
    --tabstop=SPACES     Number of spaces for a tab character (default: 8)

  Preview
    --preview=COMMAND    command to preview current highlighted line ({})
                         We can specify the fields. e.g. ({1}, {..3}, {0..})
    --preview-window=OPT Preview window layout (default: right:50%)
                         [up|down|left|right][:SIZE[%]][:hidden]

  Scripting
    -q, --query \"\"       specify the initial query
    --cmd-query \"\"       specify the initial query for interactive mode
    --expect KEYS        comma seperated keys that can be used to complete skim
    --read0              Read input delimited by ASCII NUL(\\0) characters
    --print0             Print output delimited by ASCII NUL(\\0) characters
    --print-query        Print query as the first line
    --print-cmd          Print command query as the first line (after --print-query)

  Environment variables
    SKIM_DEFAULT_COMMAND Default command to use when input is tty
    SKIM_DEFAULT_OPTIONS Default options (e.g. '--ansi --regex')
                         You should not include other environment variables
                         (e.g. '-c \"$HOME/bin/ag\"')

  Reserved (not used for now)
    --extended
    --algo=TYPE
    --literal
    --no-mouse
    --cycle
    --hscroll-off=COL
    --filepath-word
    --jump-labels=CHARS
    --border
    --inline-info
    --header=STR
    --header-lines=N
    --no-bold
    --history=FILE
    --history-size=N
    --sync
    --no-sort
    --select-1
    --exit-0
    --filter
";

fn main() {
    use env_logger::LogBuilder;
    use log::{LogLevelFilter, LogRecord};

    let format = |record: &LogRecord| {
        let t = time::now();
        format!(
            "{},{:03} - {} - {}",
            time::strftime("%Y-%m-%d %H:%M:%S", &t).expect("main: time format error"),
            t.tm_nsec / 1_000_000,
            record.level(),
            record.args()
        )
    };

    let mut builder = LogBuilder::new();
    builder.format(format).filter(None, LogLevelFilter::Info);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init().expect("failed to initialize logger builder");

    let exit_code = real_main();
    std::process::exit(exit_code);
}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn real_main() -> i32 {
    let mut args = Vec::new();

    args.push(env::args().next().expect("there should be at least one arg: the application name"));
    args.extend(env::var("SKIM_DEFAULT_OPTIONS")
                .ok()
                .and_then(|val| shlex::split(&val))
                .unwrap_or_default());
    for arg in env::args().skip(1) {
        args.push(arg);
    }

    //------------------------------------------------------------------------------
    // parse options
    let opts = App::new("sk")
        .author("Jinzhou Zhang<lotabout@gmail.com")
        .arg(Arg::with_name("help").long("help").short("h"))
        .arg(Arg::with_name("version").long("version").short("v"))
        .arg(Arg::with_name("bind").long("bind").short("b").multiple(true).takes_value(true))
        .arg(Arg::with_name("multi").long("multi").short("m").multiple(true))
        .arg(Arg::with_name("no-multi").long("no-multi").multiple(true))
        .arg(Arg::with_name("prompt").long("prompt").short("p").multiple(true).takes_value(true).default_value("> "))
        .arg(Arg::with_name("cmd-prompt").long("cmd-prompt").multiple(true).takes_value(true).default_value("c> "))
        .arg(Arg::with_name("expect").long("expect").multiple(true).takes_value(true))
        .arg(Arg::with_name("tac").long("tac").multiple(true))
        .arg(Arg::with_name("tiebreak").long("tiebreak").short("t").multiple(true).takes_value(true))
        .arg(Arg::with_name("ansi").long("ansi").multiple(true))
        .arg(Arg::with_name("exact").long("exact").short("e").multiple(true))
        .arg(Arg::with_name("cmd").long("cmd").short("cmd").multiple(true).takes_value(true))
        .arg(Arg::with_name("interactive").long("interactive").short("i").multiple(true))
        .arg(Arg::with_name("query").long("query").short("q").multiple(true).takes_value(true))
        .arg(Arg::with_name("cmd-query").long("cmd-query").multiple(true).takes_value(true))
        .arg(Arg::with_name("regex").long("regex").multiple(true))
        .arg(Arg::with_name("delimiter").long("delimiter").short("d").multiple(true).takes_value(true))
        .arg(Arg::with_name("nth").long("nth").short("n").multiple(true).takes_value(true))
        .arg(Arg::with_name("with-nth").long("with-nth").multiple(true).takes_value(true))
        .arg(Arg::with_name("replstr").short("I").multiple(true).takes_value(true))
        .arg(Arg::with_name("color").long("color").multiple(true).takes_value(true))
        .arg(Arg::with_name("margin").long("margin").multiple(true).takes_value(true).default_value("0,0,0,0"))
        .arg(Arg::with_name("min-height").long("min-height").multiple(true).takes_value(true).default_value("10"))
        .arg(Arg::with_name("height").long("height").multiple(true).takes_value(true).default_value("100%"))
        .arg(Arg::with_name("no-height").long("no-height").multiple(true))
        .arg(Arg::with_name("preview").long("preview").multiple(true).takes_value(true))
        .arg(Arg::with_name("preview-window").long("preview-window").multiple(true).takes_value(true).default_value("right:50%"))
        .arg(Arg::with_name("reverse").long("reverse").multiple(true))

        .arg(Arg::with_name("algorithm").long("algo").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("literal").long("literal").multiple(true))
        .arg(Arg::with_name("no-mouse").long("no-mouse").multiple(true))
        .arg(Arg::with_name("cycle").long("cycle").multiple(true))
        .arg(Arg::with_name("no-hscroll").long("no-hscroll").multiple(true))
        .arg(Arg::with_name("hscroll-off").long("hscroll-off").multiple(true).takes_value(true).default_value("10"))
        .arg(Arg::with_name("filepath-word").long("filepath-word").multiple(true))
        .arg(Arg::with_name("jump-labels").long("jump-labels").multiple(true).takes_value(true).default_value("abcdefghijklmnopqrstuvwxyz"))
        .arg(Arg::with_name("border").long("border").multiple(true))
        .arg(Arg::with_name("inline-info").long("inline-info").multiple(true))
        .arg(Arg::with_name("header").long("header").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("header-lines").long("header-lines").multiple(true).takes_value(true).default_value("1"))
        .arg(Arg::with_name("tabstop").long("tabstop").multiple(true).takes_value(true).default_value("8"))
        .arg(Arg::with_name("no-bold").long("no-bold").multiple(true))
        .arg(Arg::with_name("history").long("history").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("history-size").long("history-size").multiple(true).takes_value(true).default_value("500"))
        .arg(Arg::with_name("print-query").long("print-query").multiple(true))
        .arg(Arg::with_name("print-cmd").long("print-cmd").multiple(true))
        .arg(Arg::with_name("read0").long("read0").multiple(true))
        .arg(Arg::with_name("print0").long("print0").multiple(true))
        .arg(Arg::with_name("sync").long("sync").multiple(true))
        .arg(Arg::with_name("extended").long("extended").short("x").multiple(true))
        .arg(Arg::with_name("no-sort").long("no-sort").multiple(true))
        .arg(Arg::with_name("select-1").long("select-1").short("1").multiple(true))
        .arg(Arg::with_name("exit-0").long("exit-0").short("0").multiple(true))
        .arg(Arg::with_name("filter").long("filter").short("f").multiple(true))
        .get_matches_from(args);

    if opts.is_present("help") {
        print!("{}", USAGE);
        return 0;
    }

    if opts.is_present("version") {
        println!("{}", VERSION);
        return 0;
    }

    let options = SkimOptions::from_options(&opts);
    let output_ending = if options.print0 {"\0"} else {"\n"};

    let output = Skim::run_with(&options, None);
    if let None = output {
        return 130;
    }

    let output = output.unwrap();

    // output query
    if options.print_query {
        print!("{}{}", output.query, output_ending);
    }

    if options.print_cmd {
        print!("{}{}", output.cmd, output_ending);
    }

    output.accept_key.map(|key| {
        print!("{}{}", key, output_ending);
    });

    for item in output.selected_items.iter() {
        print!("{}{}", item.get_output_text(), output_ending);
    }

    if output.selected_items.len() > 0 {0} else {1}
}
<commit_msg>inline-info: Update usage string.<commit_after>extern crate clap;
extern crate env_logger;
extern crate log;
extern crate shlex;
extern crate skim;
extern crate time;

use clap::{App, Arg};
use skim::{Skim, SkimOptions};
use std::env;

const VERSION: &str = env!("CARGO_PKG_VERSION");

const USAGE: &str = "
Usage: sk [options]

  Options
    -h, --help           print this help menu
    --version            print out the current version of skim

  Search
    --tac                reverse the order of input
    -t, --tiebreak [score,index,begin,end,-score,...]
                         comma seperated criteria
    -n, --nth 1,2..5     specify the fields to be matched
    --with-nth 1,2..5    specify the fields to be transformed
    -d, --delimiter \\t  specify the delimiter(in REGEX) for fields
    -e, --exact          start skim in exact mode
    --regex              use regex instead of fuzzy match

  Interface
    -b, --bind KEYBINDS  comma seperated keybindings, in KEY:ACTION
                         such as 'ctrl-j:accept,ctrl-k:kill-line'
    -m, --multi          Enable Multiple Selection
    --no-multi           Disable Multiple Selection
    -c, --cmd ag         command to invoke dynamically
    -I replstr           replace `replstr` with the selected item
    -i, --interactive    Start skim in interactive(command) mode
    --color [BASE][,COLOR:ANSI]
                         change color theme
    --no-hscroll         Disable horizontal scroll

  Layout
    --reverse            Reverse orientation
    --height=HEIGHT      Height of skim's window (--height 40%)
    --no-height          Disable height feature
    --min-height=HEIGHT  Minimum height when --height is given by percent
                         (default: 10)
    --margin=MARGIN      Screen Margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
                         e.g. (sk --margin 1,10%)
    -p, --prompt '> '    prompt string for query mode
    --cmd-prompt '> '    prompt string for command mode

  Display
    --ansi               parse ANSI color codes for input strings
    --tabstop=SPACES     Number of spaces for a tab character (default: 8)
    --inline-info        Display info next to query

  Preview
    --preview=COMMAND    command to preview current highlighted line ({})
                         We can specify the fields. e.g. ({1}, {..3}, {0..})
    --preview-window=OPT Preview window layout (default: right:50%)
                         [up|down|left|right][:SIZE[%]][:hidden]

  Scripting
    -q, --query \"\"       specify the initial query
    --cmd-query \"\"       specify the initial query for interactive mode
    --expect KEYS        comma seperated keys that can be used to complete skim
    --read0              Read input delimited by ASCII NUL(\\0) characters
    --print0             Print output delimited by ASCII NUL(\\0) characters
    --print-query        Print query as the first line
    --print-cmd          Print command query as the first line (after --print-query)

  Environment variables
    SKIM_DEFAULT_COMMAND Default command to use when input is tty
    SKIM_DEFAULT_OPTIONS Default options (e.g. '--ansi --regex')
                         You should not include other environment variables
                         (e.g. '-c \"$HOME/bin/ag\"')

  Reserved (not used for now)
    --extended
    --algo=TYPE
    --literal
    --no-mouse
    --cycle
    --hscroll-off=COL
    --filepath-word
    --jump-labels=CHARS
    --border
    --header=STR
    --header-lines=N
    --no-bold
    --history=FILE
    --history-size=N
    --sync
    --no-sort
    --select-1
    --exit-0
    --filter
";

fn main() {
    use env_logger::LogBuilder;
    use log::{LogLevelFilter, LogRecord};

    let format = |record: &LogRecord| {
        let t = time::now();
        format!(
            "{},{:03} - {} - {}",
            time::strftime("%Y-%m-%d %H:%M:%S", &t).expect("main: time format error"),
            t.tm_nsec / 1_000_000,
            record.level(),
            record.args()
        )
    };

    let mut builder = LogBuilder::new();
    builder.format(format).filter(None, LogLevelFilter::Info);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init().expect("failed to initialize logger builder");

    let exit_code = real_main();
    std::process::exit(exit_code);
}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn real_main() -> i32 {
    let mut args = Vec::new();

    args.push(env::args().next().expect("there should be at least one arg: the application name"));
    args.extend(env::var("SKIM_DEFAULT_OPTIONS")
                .ok()
                .and_then(|val| shlex::split(&val))
                .unwrap_or_default());
    for arg in env::args().skip(1) {
        args.push(arg);
    }

    //------------------------------------------------------------------------------
    // parse options
    let opts = App::new("sk")
        .author("Jinzhou Zhang<lotabout@gmail.com")
        .arg(Arg::with_name("help").long("help").short("h"))
        .arg(Arg::with_name("version").long("version").short("v"))
        .arg(Arg::with_name("bind").long("bind").short("b").multiple(true).takes_value(true))
        .arg(Arg::with_name("multi").long("multi").short("m").multiple(true))
        .arg(Arg::with_name("no-multi").long("no-multi").multiple(true))
        .arg(Arg::with_name("prompt").long("prompt").short("p").multiple(true).takes_value(true).default_value("> "))
        .arg(Arg::with_name("cmd-prompt").long("cmd-prompt").multiple(true).takes_value(true).default_value("c> "))
        .arg(Arg::with_name("expect").long("expect").multiple(true).takes_value(true))
        .arg(Arg::with_name("tac").long("tac").multiple(true))
        .arg(Arg::with_name("tiebreak").long("tiebreak").short("t").multiple(true).takes_value(true))
        .arg(Arg::with_name("ansi").long("ansi").multiple(true))
        .arg(Arg::with_name("exact").long("exact").short("e").multiple(true))
        .arg(Arg::with_name("cmd").long("cmd").short("cmd").multiple(true).takes_value(true))
        .arg(Arg::with_name("interactive").long("interactive").short("i").multiple(true))
        .arg(Arg::with_name("query").long("query").short("q").multiple(true).takes_value(true))
        .arg(Arg::with_name("cmd-query").long("cmd-query").multiple(true).takes_value(true))
        .arg(Arg::with_name("regex").long("regex").multiple(true))
        .arg(Arg::with_name("delimiter").long("delimiter").short("d").multiple(true).takes_value(true))
        .arg(Arg::with_name("nth").long("nth").short("n").multiple(true).takes_value(true))
        .arg(Arg::with_name("with-nth").long("with-nth").multiple(true).takes_value(true))
        .arg(Arg::with_name("replstr").short("I").multiple(true).takes_value(true))
        .arg(Arg::with_name("color").long("color").multiple(true).takes_value(true))
        .arg(Arg::with_name("margin").long("margin").multiple(true).takes_value(true).default_value("0,0,0,0"))
        .arg(Arg::with_name("min-height").long("min-height").multiple(true).takes_value(true).default_value("10"))
        .arg(Arg::with_name("height").long("height").multiple(true).takes_value(true).default_value("100%"))
        .arg(Arg::with_name("no-height").long("no-height").multiple(true))
        .arg(Arg::with_name("preview").long("preview").multiple(true).takes_value(true))
        .arg(Arg::with_name("preview-window").long("preview-window").multiple(true).takes_value(true).default_value("right:50%"))
        .arg(Arg::with_name("reverse").long("reverse").multiple(true))

        .arg(Arg::with_name("algorithm").long("algo").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("literal").long("literal").multiple(true))
        .arg(Arg::with_name("no-mouse").long("no-mouse").multiple(true))
        .arg(Arg::with_name("cycle").long("cycle").multiple(true))
        .arg(Arg::with_name("no-hscroll").long("no-hscroll").multiple(true))
        .arg(Arg::with_name("hscroll-off").long("hscroll-off").multiple(true).takes_value(true).default_value("10"))
        .arg(Arg::with_name("filepath-word").long("filepath-word").multiple(true))
        .arg(Arg::with_name("jump-labels").long("jump-labels").multiple(true).takes_value(true).default_value("abcdefghijklmnopqrstuvwxyz"))
        .arg(Arg::with_name("border").long("border").multiple(true))
        .arg(Arg::with_name("inline-info").long("inline-info").multiple(true))
        .arg(Arg::with_name("header").long("header").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("header-lines").long("header-lines").multiple(true).takes_value(true).default_value("1"))
        .arg(Arg::with_name("tabstop").long("tabstop").multiple(true).takes_value(true).default_value("8"))
        .arg(Arg::with_name("no-bold").long("no-bold").multiple(true))
        .arg(Arg::with_name("history").long("history").multiple(true).takes_value(true).default_value(""))
        .arg(Arg::with_name("history-size").long("history-size").multiple(true).takes_value(true).default_value("500"))
        .arg(Arg::with_name("print-query").long("print-query").multiple(true))
        .arg(Arg::with_name("print-cmd").long("print-cmd").multiple(true))
        .arg(Arg::with_name("read0").long("read0").multiple(true))
        .arg(Arg::with_name("print0").long("print0").multiple(true))
        .arg(Arg::with_name("sync").long("sync").multiple(true))
        .arg(Arg::with_name("extended").long("extended").short("x").multiple(true))
        .arg(Arg::with_name("no-sort").long("no-sort").multiple(true))
        .arg(Arg::with_name("select-1").long("select-1").short("1").multiple(true))
        .arg(Arg::with_name("exit-0").long("exit-0").short("0").multiple(true))
        .arg(Arg::with_name("filter").long("filter").short("f").multiple(true))
        .get_matches_from(args);

    if opts.is_present("help") {
        print!("{}", USAGE);
        return 0;
    }

    if opts.is_present("version") {
        println!("{}", VERSION);
        return 0;
    }

    let options = SkimOptions::from_options(&opts);
    let output_ending = if options.print0 {"\0"} else {"\n"};

    let output = Skim::run_with(&options, None);
    if let None = output {
        return 130;
    }

    let output = output.unwrap();

    // output query
    if options.print_query {
        print!("{}{}", output.query, output_ending);
    }

    if options.print_cmd {
        print!("{}{}", output.cmd, output_ending);
    }

    output.accept_key.map(|key| {
        print!("{}{}", key, output_ending);
    });

    for item in output.selected_items.iter() {
        print!("{}{}", item.get_output_text(), output_ending);
    }

    if output.selected_items.len() > 0 {0} else {1}
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ptr;
use std::ops::Drop;

use libc::{uint32_t, uint8_t, c_void, size_t};

type Byte = u8;

#[link(name = "DXGCap")]
extern {
	fn init();

	fn create_dxgi_manager() -> *mut c_void;

	fn delete_dxgi_manager(dxgi_manager: *mut c_void);

	fn get_output_dimensions(dxgi_manager: *const c_void, width: *mut size_t,
		height: *mut size_t);

	fn get_frame_bytes(dxgi_manager: *mut c_void, o_size: *mut size_t,
		o_bytes: *mut *mut uint8_t) -> bool;
}

struct Capturer {
	dxgi_manager: *mut c_void,
	current_frame: Vec<Byte>,
}

impl Capturer {
	fn new() -> Result<Capturer, ()> {
		let manager = unsafe { create_dxgi_manager() };
		if manager.is_null() {
			Err(())
		} else {
			Ok(Capturer{
				dxgi_manager: manager,
				current_frame: Vec::new() })
		}
	}

	fn dimensions(&self) -> (usize, usize) {
		let (mut width, mut height): (size_t, size_t) = (0, 0);
		unsafe { get_output_dimensions(self.dxgi_manager, &mut width, &mut height); }
		(width as usize, height as usize)
	}

	fn get_frame(&mut self) -> Result<&mut [Byte], ()> {
		let mut buffer_size: size_t = 0;
		let mut buffer = ptr::null_mut::<Byte>();
		if unsafe { get_frame_bytes(self.dxgi_manager, &mut buffer_size, &mut buffer) } {
			if buffer_size == 0 {
				Ok(self.current_frame.as_mut_slice())
			} else {
				let buffer_size = buffer_size as usize;
				if buffer.is_null() {
					Err(())
				} else {
					self.current_frame = unsafe {
						Vec::from_raw_parts(buffer, buffer_size, buffer_size) };
					Ok(self.current_frame.as_mut_slice())
				}
			}
		} else {
			Err(())
		}
	}
}

fn init_dxgi() {
	unsafe { init(); }
}

impl Drop for Capturer {
	fn drop(&mut self) {
		unsafe { delete_dxgi_manager(self.dxgi_manager); }
	}
}

fn main() {
	init_dxgi();
	{
		let mut capturer = Capturer::new().unwrap();

		let (width, height) = capturer.dimensions();
		println!("{} x {}", width, height);

		for i in 0..60u8 {
			println!("null frame: {}", capturer.get_frame().unwrap().iter().all(|b| *b == 0));
		}
		println!("Done1");
	}
	println!("Done2");

}
<commit_msg>It runs, but bad performance<commit_after>extern crate libc;

use std::ptr;
use std::mem;
use std::ops::Drop;

use libc::{uint32_t, uint8_t, c_void, size_t};

// B8G8R8A8 pixel size in bytes
static PIXEL_SIZE: u8 = 4;

#[link(name = "DXGCap")]
extern {
	fn init();

	fn create_dxgi_manager() -> *mut c_void;

	fn delete_dxgi_manager(dxgi_manager: *mut c_void);

	fn get_output_dimensions(dxgi_manager: *const c_void, width: *mut size_t,
		height: *mut size_t);

	fn get_frame_bytes(dxgi_manager: *mut c_void, o_size: *mut size_t,
		o_bytes: *mut *mut uint8_t) -> bool;
}

struct Capturer {
	dxgi_manager: *mut c_void,
	current_frame: Vec<u8>,
}

impl Capturer {
	fn new() -> Result<Capturer, ()> {
		let manager = unsafe { create_dxgi_manager() };
		if manager.is_null() {
			Err(())
		} else {
			Ok(Capturer{
				dxgi_manager: manager,
				current_frame: Vec::new() })
		}
	}

	fn dimensions(&self) -> (usize, usize) {
		let (mut width, mut height): (size_t, size_t) = (0, 0);
		unsafe { get_output_dimensions(self.dxgi_manager, &mut width, &mut height); }
		(width as usize, height as usize)
	}

	fn get_frame(&mut self) -> Result<&mut [u8], ()> {
		let mut buffer_size: size_t = 0;
		let mut buffer = ptr::null_mut::<u8>();
		if unsafe { get_frame_bytes(self.dxgi_manager, &mut buffer_size, &mut buffer) } {
			if buffer_size == 0 {
				Ok(self.current_frame.as_mut_slice())
			} else {
				let buffer_size = buffer_size as usize;
				if buffer.is_null() {
					Err(())
				} else {
					self.current_frame = unsafe {
						Vec::from_raw_parts(buffer, buffer_size, buffer_size) };
					Ok(self.current_frame.as_mut_slice())
				}
			}
		} else {
			Err(())
		}
	}
}

impl Drop for Capturer {
	fn drop(&mut self) {
		unsafe {
			let v = mem::replace(&mut self.current_frame, Vec::new());
			mem::forget(v);
			delete_dxgi_manager(self.dxgi_manager);
		}
	}
}

fn average_color(pixels_bytes: &[u8]) -> (u64, u64, u64) {
	let n_pixels = pixels_bytes.len() as u64 / PIXEL_SIZE as u64;
	let (mut r_sum, mut b_sum, mut g_sum) = (0u64, 0u64, 0u64);
	for n in (0..n_pixels) {
		let i = n as usize * PIXEL_SIZE as usize;
		let (b, g, r) = (pixels_bytes[i], pixels_bytes[i+1], pixels_bytes[i+2]);
		r_sum += r as u64;
		b_sum += b as u64;
		g_sum += g as u64;
	}
	(r_sum/n_pixels, b_sum/n_pixels, g_sum/n_pixels)
}

fn init_dxgi() {
	unsafe { init(); }
}

fn main() {
	init_dxgi();
	let mut capturer = Capturer::new().unwrap();

	let (width, height) = capturer.dimensions();
	println!("{} x {}", width, height);

	for i in 0..240u16 {
		let frame = capturer.get_frame().unwrap();
		// println!("null frame: {}", frame.iter().all(|b| *b == 0));
		let avs = average_color(frame);
		println!("Avs: {} {} {}", avs.0, avs.1, avs.2);
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Alex Crawford
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate clap;
extern crate hyper;
extern crate hyper_rustls;
extern crate pulldown_cmark;
extern crate rayon;
extern crate url;
extern crate walkdir;

mod document;
mod error;

use clap::{Arg, App};
use document::{Document, Error, Event};
use error::{DocumentError, DocumentLocation, LinkError, LocatedDocumentError};
use hyper::client::Client;
use hyper::header::UserAgent;
use hyper::net::HttpsConnector;
use hyper::status::StatusCode;
use hyper_rustls::TlsClient;
use rayon::prelude::*;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::process::exit;
use std::sync::Arc;
use url::{ParseError, Url};
use walkdir::WalkDir;

macro_rules! fail {
    ($($print:expr),+) => {
        {
            eprintln!($($print),+);
            exit(1);
        }
    };
}

macro_rules! printerror {
    ($error:expr, $flag:expr) => {
        {
            println!("{}", $error);
            $flag = true;
        }
    };
}

struct LinkContext {
    target: String,
    text: String,
    line: usize,
    file: PathBuf,
}

impl LinkContext {
    fn new_error(self, error: LinkError) -> LocatedDocumentError {
        LocatedDocumentError {
            location: DocumentLocation {
                path: self.file,
                line: self.line,
            },
            error: DocumentError::Link {
                text: self.text,
                target: self.target,
                error: error,
            },
        }
    }
}

fn main() {
    let matches = App::new("Marker")
        .version(crate_version!())
        .arg(
            Arg::with_name("root")
                .short("r")
                .long("root")
                .help("The path to the root of the documentation to be checked")
                .takes_value(true),
        )
        .arg(Arg::with_name("skip-http").long("skip-http").help(
            "Skip validation of HTTP[S] URLs",
        ))
        .get_matches();

    let skip_http = matches.is_present("skip-http");
    let root = Path::new(matches.value_of("root").unwrap_or("."));
    let mut links = Vec::new();
    let mut found_error = false;

    for entry in WalkDir::new(root).into_iter().filter_map(|entry| {
        let entry = entry.unwrap_or_else(|error| {
            fail!("Failed to walk directory: {}", error);
        });
        if entry.file_type().is_file() && entry.path().extension() == Some(OsStr::new("md")) {
            Some(entry)
        } else {
            None
        }
    })
    {
        let contents = {
            let mut file = File::open(entry.path()).unwrap_or_else(|error| {
                fail!(
                    "Failed to open file ({}): {}",
                    entry.path().display(),
                    error
                );
            });
            let mut text = String::new();
            if let Err(error) = file.read_to_string(&mut text) {
                fail!(
                    "Failed to read file ({}): {}",
                    entry.path().display(),
                    error
                );
            };
            text
        };

        for event in Document::new(&contents) {
            match event.event {
                Event::Link { target, text } => {
                    links.push(LinkContext {
                        target: target,
                        text: text,
                        line: event.line,
                        file: entry.path().to_path_buf(),
                    })
                }
                Event::Error(Error::ReferenceBroken { target, text }) => {
                    printerror!(
                        LinkContext {
                            target: target,
                            text: text,
                            line: event.line,
                            file: entry.path().to_path_buf(),
                        }.new_error(LinkError::ReferenceBroken),
                        found_error
                    )
                }
            }
        }
    }

    let mut urls = HashMap::new();
    for link in links {
        match Url::parse(&link.target) {
            Ok(_) if skip_http => {}
            Ok(mut url) => {
                url.set_fragment(None);
                urls.entry(url).or_insert(Vec::new()).push(link)
            }
            Err(ParseError::RelativeUrlWithoutBase) => {
                if let Err(error) = check_path(&link.target, &link.file) {
                    printerror!(link.new_error(error), found_error)
                }
            }
            Err(error) => printerror!(link.new_error(LinkError::UrlMalformed(error)), found_error),
        }
    }

    for (result, links) in urls.into_par_iter()
        .map(|(url, links)| (check_url(url), links))
        .collect::<Vec<_>>()
    {
        if let Err(error) = result {
            for link in links {
                printerror!(link.new_error(error.clone()), found_error)
            }
        }
    }

    if found_error {
        exit(1)
    }
}

fn check_url(url: Url) -> Result<(), LinkError> {
    if url.scheme() != "http" && url.scheme() != "https" {
        return Ok(());
    }

    let client = Client::with_connector(HttpsConnector::new(TlsClient::new()));
    let agent = UserAgent(format!("marker/{}", crate_version!()));

    let res = client
        .head(url.clone())
        .header(agent.clone())
        .send()
        .and_then(|resp| if resp.status == StatusCode::MethodNotAllowed {
            client.get(url.clone()).header(agent.clone()).send()
        } else {
            Ok(resp)
        });
    match res {
        Ok(resp) => {
            match resp.status {
                StatusCode::Ok => Ok(()),
                status => Err(LinkError::HttpStatus(status)),
            }
        }
        Err(error) => Err(LinkError::HttpError(Arc::new(error))),
    }
}

fn check_path(target: &str, file: &Path) -> Result<(), LinkError> {
    let path = Path::new(OsStr::new(target.split('#').next().expect("string")));
    if path.is_absolute() {
        Err(LinkError::PathAbsolute)
    } else if !file.parent()
               .expect("non-root file path")
               .join(path)
               .exists()
    {
        Err(LinkError::PathNonExistant)
    } else {
        Ok(())
    }
}
<commit_msg>main: set a default value for the root flag<commit_after>// Copyright 2016 Alex Crawford
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate clap;
extern crate hyper;
extern crate hyper_rustls;
extern crate pulldown_cmark;
extern crate rayon;
extern crate url;
extern crate walkdir;

mod document;
mod error;

use clap::{Arg, App};
use document::{Document, Error, Event};
use error::{DocumentError, DocumentLocation, LinkError, LocatedDocumentError};
use hyper::client::Client;
use hyper::header::UserAgent;
use hyper::net::HttpsConnector;
use hyper::status::StatusCode;
use hyper_rustls::TlsClient;
use rayon::prelude::*;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::process::exit;
use std::sync::Arc;
use url::{ParseError, Url};
use walkdir::WalkDir;

macro_rules! fail {
    ($($print:expr),+) => {
        {
            eprintln!($($print),+);
            exit(1);
        }
    };
}

macro_rules! printerror {
    ($error:expr, $flag:expr) => {
        {
            println!("{}", $error);
            $flag = true;
        }
    };
}

struct LinkContext {
    target: String,
    text: String,
    line: usize,
    file: PathBuf,
}

impl LinkContext {
    fn new_error(self, error: LinkError) -> LocatedDocumentError {
        LocatedDocumentError {
            location: DocumentLocation {
                path: self.file,
                line: self.line,
            },
            error: DocumentError::Link {
                text: self.text,
                target: self.target,
                error: error,
            },
        }
    }
}

fn main() {
    let matches = App::new("Marker")
        .version(crate_version!())
        .arg(
            Arg::with_name("root")
                .short("r")
                .long("root")
                .help("The path to the root of the documentation to be checked")
                .takes_value(true)
                .default_value("."),
        )
        .arg(Arg::with_name("skip-http").long("skip-http").help(
            "Skip validation of HTTP[S] URLs",
        ))
        .get_matches();

    let skip_http = matches.is_present("skip-http");
    let root = Path::new(matches.value_of("root").expect("default root"));
    let mut links = Vec::new();
    let mut found_error = false;

    for entry in WalkDir::new(root).into_iter().filter_map(|entry| {
        let entry = entry.unwrap_or_else(|error| {
            fail!("Failed to walk directory: {}", error);
        });
        if entry.file_type().is_file() && entry.path().extension() == Some(OsStr::new("md")) {
            Some(entry)
        } else {
            None
        }
    })
    {
        let contents = {
            let mut file = File::open(entry.path()).unwrap_or_else(|error| {
                fail!(
                    "Failed to open file ({}): {}",
                    entry.path().display(),
                    error
                );
            });
            let mut text = String::new();
            if let Err(error) = file.read_to_string(&mut text) {
                fail!(
                    "Failed to read file ({}): {}",
                    entry.path().display(),
                    error
                );
            };
            text
        };

        for event in Document::new(&contents) {
            match event.event {
                Event::Link { target, text } => {
                    links.push(LinkContext {
                        target: target,
                        text: text,
                        line: event.line,
                        file: entry.path().to_path_buf(),
                    })
                }
                Event::Error(Error::ReferenceBroken { target, text }) => {
                    printerror!(
                        LinkContext {
                            target: target,
                            text: text,
                            line: event.line,
                            file: entry.path().to_path_buf(),
                        }.new_error(LinkError::ReferenceBroken),
                        found_error
                    )
                }
            }
        }
    }

    let mut urls = HashMap::new();
    for link in links {
        match Url::parse(&link.target) {
            Ok(_) if skip_http => {}
            Ok(mut url) => {
                url.set_fragment(None);
                urls.entry(url).or_insert(Vec::new()).push(link)
            }
            Err(ParseError::RelativeUrlWithoutBase) => {
                if let Err(error) = check_path(&link.target, &link.file) {
                    printerror!(link.new_error(error), found_error)
                }
            }
            Err(error) => printerror!(link.new_error(LinkError::UrlMalformed(error)), found_error),
        }
    }

    for (result, links) in urls.into_par_iter()
        .map(|(url, links)| (check_url(url), links))
        .collect::<Vec<_>>()
    {
        if let Err(error) = result {
            for link in links {
                printerror!(link.new_error(error.clone()), found_error)
            }
        }
    }

    if found_error {
        exit(1)
    }
}

fn check_url(url: Url) -> Result<(), LinkError> {
    if url.scheme() != "http" && url.scheme() != "https" {
        return Ok(());
    }

    let client = Client::with_connector(HttpsConnector::new(TlsClient::new()));
    let agent = UserAgent(format!("marker/{}", crate_version!()));

    let res = client
        .head(url.clone())
        .header(agent.clone())
        .send()
        .and_then(|resp| if resp.status == StatusCode::MethodNotAllowed {
            client.get(url.clone()).header(agent.clone()).send()
        } else {
            Ok(resp)
        });
    match res {
        Ok(resp) => {
            match resp.status {
                StatusCode::Ok => Ok(()),
                status => Err(LinkError::HttpStatus(status)),
            }
        }
        Err(error) => Err(LinkError::HttpError(Arc::new(error))),
    }
}

fn check_path(target: &str, file: &Path) -> Result<(), LinkError> {
    let path = Path::new(OsStr::new(target.split('#').next().expect("string")));
    if path.is_absolute() {
        Err(LinkError::PathAbsolute)
    } else if !file.parent()
               .expect("non-root file path")
               .join(path)
               .exists()
    {
        Err(LinkError::PathNonExistant)
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate reqwest;
extern crate rocket;
extern crate toml;

use std::fmt::{Display, Formatter, self};
use std::fs::{File, self};
use std::io::Read;
use std::io::Write;
use std::process;

enum Status {
    Unknown,
    OutOfDate,
    UpToDate
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate")
        }
    }
}

#[get("/<owner>/<name>")]
fn index(owner: &str, name: &str) -> File {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = get_deps_status(owner, name, "dev-dependencies");
    File::open(format!("public/img/status/{}.png", status)).unwrap()
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> Status {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml", owner, name);

    if let Ok(mut resp) = reqwest::get(&*cargo_url) {
        match resp.status() {
            &reqwest::StatusCode::Ok => {
                let mut body = String::new();
                resp.read_to_string(&mut body).ok();
                deps_status_from_cargo(owner, name, body, deps_type)
            },
            _ => Status::Unknown
        }
    } else {
        Status::Unknown
    }
}

fn deps_status_from_cargo(owner: &str, name: &str, cargo: String, deps_type: &str) -> Status {

    let root = match toml::Parser::new(&*cargo).parse() {
        Some(root) => root,
        None => return Status::Unknown
    };

    let dependencies = match root.get(deps_type)
        .and_then(|val| val.as_table()) {
            Some(dependencies) => dependencies,
            None => return Status::UpToDate
        };

    // TODO:
    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
    let tmp_dir = format!("/tmp/{}/{}", owner, name);
    let tmp_manifest = format!("{}/Cargo.toml", tmp_dir);
    let tmp_src_dir = format!("{}/src", tmp_dir);
    let tmp_src_lib = format!("{}/lib.rs", tmp_src_dir);

    if let Err(_) = fs::create_dir_all(tmp_src_dir.as_str())
        .and_then(|_| File::create(tmp_manifest.as_str()))
            .and_then(|mut file| file.write_all(cargo.as_bytes()))
            .and_then(|_| File::create(tmp_src_lib.as_str())) {
                return Status::Unknown;
            }
    // 3- `cargo update --manifest-path /tmp/owner/name/Cargo.toml`
    if let Err(_) = process::Command::new("cargo")
        .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.as_str())
            .output() {
                return Status::Unknown;
            }
    // 4- Parse the /tmp/owner/name/Cargo.lock generated
    // 5- Compare each deps with semver
    dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version)| {
        println!("{:?}", dep);
        println!("{:?}", version);
        Status::OutOfDate
    })
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
<commit_msg>Implement parsing for step 4<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate reqwest;
extern crate rocket;
extern crate toml;

use std::fmt::{Display, Formatter, self};
use std::fs::{File, self};
use std::io::Read;
use std::io::Write;
use std::process;

enum Status {
    Unknown,
    OutOfDate,
    UpToDate
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            Status::Unknown => write!(f, "unknown"),
            Status::OutOfDate => write!(f, "outofdate"),
            Status::UpToDate => write!(f, "uptodate")
        }
    }
}

#[get("/<owner>/<name>")]
fn index(owner: &str, name: &str) -> File {
    // TODO: HEADER 'Cache-Control': 'no-cache, no-store, must-revalidate',
    // TODO: HEADER 'Expires': new Date().toUTCString()
    let status = get_deps_status(owner, name, "dev-dependencies");
    File::open(format!("public/img/status/{}.png", status)).unwrap()
}

fn get_deps_status(owner: &str, name: &str, deps_type: &str) -> Status {
    let cargo_url = format!("https://raw.githubusercontent.com/{}/{}/master/Cargo.toml", owner, name);

    if let Ok(mut resp) = reqwest::get(&*cargo_url) {
        match resp.status() {
            &reqwest::StatusCode::Ok => {
                let mut body = String::new();
                resp.read_to_string(&mut body).ok();
                deps_status_from_cargo(owner, name, body, deps_type)
            },
            _ => Status::Unknown
        }
    } else {
        Status::Unknown
    }
}

fn deps_status_from_cargo(owner: &str, name: &str, cargo: String, deps_type: &str) -> Status {

    let root = match toml::Parser::new(&*cargo).parse() {
        Some(root) => root,
        None => return Status::Unknown
    };

    let dependencies = match root.get(deps_type)
        .and_then(|val| val.as_table()) {
            Some(dependencies) => dependencies,
            None => return Status::UpToDate
        };

    // TODO:
    // 1- Download the Cargo.toml of the project into /tmp/owner/name/Cargo.toml
    // 2- Create a dummy /tmp/owner/name/src/lib.rs (avoid `cargo update` complaint)
    let tmp_dir = format!("/tmp/{}/{}", owner, name);
    let tmp_manifest = format!("{}/Cargo.toml", tmp_dir);
    let tmp_lockfile = format!("{}/Cargo.lock", tmp_dir);
    let tmp_src_dir = format!("{}/src", tmp_dir);
    let tmp_src_lib = format!("{}/lib.rs", tmp_src_dir);

    if let Err(_) = fs::create_dir_all(tmp_src_dir.as_str())
        .and_then(|_| File::create(tmp_manifest.as_str()))
            .and_then(|mut file| file.write_all(cargo.as_bytes()))
            .and_then(|_| File::create(tmp_src_lib.as_str())) {
                return Status::Unknown;
            }
    // 3- `cargo update --manifest-path /tmp/owner/name/Cargo.toml`
    if let Err(_) = process::Command::new("cargo")
        .arg("update")
            .arg("--manifest-path")
            .arg(tmp_manifest.as_str())
            .output() {
                return Status::Unknown;
            }
    // 4- Parse the /tmp/owner/name/Cargo.lock generated
    let mut buffer = String::new();
    if let Err(_) = File::open(tmp_lockfile)
        .and_then(|mut f| f.read_to_string(&mut buffer)) {
            return Status::Unknown;
        }

    //let updated_raw_deps = match toml::Parser::new(buffer.as_str()).parse()
    //    .and_then(|cargo_lockfile | cargo_lockfile.get("root"))
    //    .and_then(|root| root.lookup("dependencies")) {
    //        Some(&toml::Value::Array(ref raw_deps)) => raw_deps,
    //        Some(_) => unreachable!(),
    //        None => return Status::Unknown
    //    };

    let tmp_root_lockfile = match toml::Parser::new(buffer.as_str()).parse() {
        Some(root) => root,
        None => return Status::Unknown
    };

    let tmp_root_table = match tmp_root_lockfile.get("root") {
        Some(root) => root,
        None => return Status::Unknown
    };

    let updated_raw_deps = match tmp_root_table.lookup("dependencies") {
        Some(&toml::Value::Array(ref raw_deps)) => raw_deps,
        Some(_) => unreachable!(),
        None => return Status::Unknown
    };

    // 5- Compare each deps with semver
    dependencies.iter().fold(Status::UpToDate, |oldest, (dep, version)| {
        println!("{:?}", dep);
        println!("{:?}", version);
        Status::OutOfDate
    })
}

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


<commit_before>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::os::linux::fs::MetadataExt;

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

#[derive(Default)]
struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(Arg::with_name("noempty").short("n").long("noempty").help(
            "Exclude zero length files",
        ))
        .arg(Arg::with_name("summary").short("s").long("summary").help(
            "Print out summary information after duplicates",
        ))
        .get_matches()
}

fn collect_paths(path: &str, noempty: bool, stats: &mut Stats) -> HashMap<u64, Vec<PathBuf>> {

    let mut length_paths = HashMap::new();
    let spinner = ["|", "/", "-", "\\"];

    for (idx, entry) in WalkDir::new(path).into_iter().enumerate() {
        eprint!("\rBuilding file list {} ", spinner[idx % spinner.len()]);
        let entry = match entry {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = match entry.metadata() {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if noempty && metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        length_paths
            .entry(metadata.len())
            .or_insert(Vec::new())
            .push(path);
    }
    eprint!("\r{:40}", " ");

    length_paths
}

fn main() {
    let matches = parse_args();

    let mut stats: Stats = Default::default();

    let files = collect_paths(
        matches.value_of("DIR").unwrap(),
        matches.is_present("noempty"),
        &mut stats,
    );

    let file_count = files.len();

    let mut len_hash_path = HashMap::new();

    for (idx, (len, paths)) in files.iter().enumerate() {

        eprint!(
            "\rProgress [{}/{}] {:.0}%",
            idx,
            file_count,
            100.0 * idx as f64 / file_count as f64
        );

        if paths.len() < 2 {
            continue;
        }

        let mut inode_paths = HashMap::new();

        for path in paths {
            let metadata = match path.metadata() {
                Ok(m) => m,
                Err(err) => {
                    eprintln!("dupr: {}", err);
                    continue;
                }
            };

            let dev_inode = (metadata.st_dev(), metadata.st_ino());

            inode_paths.entry(dev_inode).or_insert(Vec::new()).push(
                path,
            );
        }

        if inode_paths.len() > 1 {
            for paths in inode_paths.values() {
                len_hash_path
                    .entry((len, hash_file(paths[0])))
                    .or_insert(Vec::new())
                    .push(paths[0]);
            }
        }
    }
    eprint!("\r{:40}\r", " ");

    for paths in len_hash_path.values().filter(|p| p.len() > 1) {
        for path in paths {
            println!("{}", path.display());
        }
        println!();
    }

    if matches.is_present("summary") {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<commit_msg>Stabalize output ordering.<commit_after>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::collections::BTreeSet;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::os::linux::fs::MetadataExt;

use clap::{App, Arg, ArgMatches};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

#[derive(Default)]
struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn parse_args<'a>() -> ArgMatches<'a> {
    App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(Arg::with_name("noempty").short("n").long("noempty").help(
            "Exclude zero length files",
        ))
        .arg(Arg::with_name("summary").short("s").long("summary").help(
            "Print out summary information after duplicates",
        ))
        .get_matches()
}

fn collect_paths(path: &str, noempty: bool, stats: &mut Stats) -> HashMap<u64, Vec<PathBuf>> {

    let mut length_paths = HashMap::new();
    let spinner = ["|", "/", "-", "\\"];

    for (idx, entry) in WalkDir::new(path).into_iter().enumerate() {
        eprint!("\rBuilding file list {} ", spinner[idx % spinner.len()]);
        let entry = match entry {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = match entry.metadata() {
            Ok(e) => e,
            Err(err) => {
                eprintln!("dupr: {}", err);
                continue;
            }
        };

        if noempty && metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        length_paths
            .entry(metadata.len())
            .or_insert(Vec::new())
            .push(path);
    }
    eprint!("\r{:40}", " ");

    length_paths
}

fn main() {
    let matches = parse_args();

    let mut stats: Stats = Default::default();

    let files = collect_paths(
        matches.value_of("DIR").unwrap(),
        matches.is_present("noempty"),
        &mut stats,
    );

    let file_count = files.len();

    let mut len_hash_path = HashMap::new();

    for (idx, (len, paths)) in files.iter().enumerate() {

        eprint!(
            "\rProgress [{}/{}] {:.0}%",
            idx,
            file_count,
            100.0 * idx as f64 / file_count as f64
        );

        if paths.len() < 2 {
            continue;
        }

        let mut inode_paths = HashMap::new();

        for path in paths {
            let metadata = match path.metadata() {
                Ok(m) => m,
                Err(err) => {
                    eprintln!("dupr: {}", err);
                    continue;
                }
            };

            let dev_inode = (metadata.st_dev(), metadata.st_ino());

            inode_paths.entry(dev_inode).or_insert(Vec::new()).push(
                path,
            );
        }

        if inode_paths.len() > 1 {
            for paths in inode_paths.values() {
                len_hash_path
                    .entry((len, hash_file(paths[0])))
                    .or_insert(BTreeSet::new())
                    .insert(paths[0]);
            }
        }
    }
    eprint!("\r{:40}\r", " ");

    let mut keys:Vec<_> = len_hash_path.iter().filter(|&(_,v)| v.len() > 1).collect();
    keys.sort();

    for (_, paths) in keys {
        for path in paths {
            println!("{}", path.display());
        }
        println!();
    }

    if matches.is_present("summary") {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate gitjournal;
extern crate term;

use std::env;
use std::fmt;
use std::fs;
use std::process::exit;

use clap::{App, Shell};
use gitjournal::GitJournal;

fn print_colored(string: &str, prefix: &str, color: term::color::Color) -> Result<(), term::Error> {
    let mut t = try!(term::stderr().ok_or(term::Error::NotSupported));
    try!(t.fg(term::color::YELLOW));
    try!(write!(t, "[git-journal] "));
    try!(t.fg(color));
    try!(write!(t, "[{}] ", prefix));
    try!(t.reset());
    try!(writeln!(t, "{}", string));
    Ok(())
}

fn print_ok(string: &str) -> Result<(), term::Error> {
    try!(print_colored(string, "OKAY", term::color::GREEN));
    Ok(())
}

fn print_err_exit(string: &str, error: Error) -> Result<(), term::Error> {
    let format_string = format!("{}: {}", string, error);
    try!(print_colored(&format_string, "ERROR", term::color::RED));
    exit(1);
}

enum Error {
    Cli,
    ParseInt(std::num::ParseIntError),
    Term(term::Error),
    GitJournal(gitjournal::Error),
}

impl From<gitjournal::Error> for Error {
    fn from(err: gitjournal::Error) -> Error {
        Error::GitJournal(err)
    }
}

impl From<term::Error> for Error {
    fn from(err: term::Error) -> Error {
        Error::Term(err)
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Cli => write!(f, "Cli argument parsing"),
            Error::ParseInt(ref err) => write!(f, "ParseInt: {}", err),
            Error::Term(ref err) => write!(f, "Term: {}", err),
            Error::GitJournal(ref err) => write!(f, "GitJournal: {}", err),
        }
    }
}

fn is_program_in_path(program: &str) -> bool {
    if let Ok(path) = env::var("PATH") {
        for p in path.split(':') {
            let p_str = format!("{}/{}", p, program);
            if fs::metadata(p_str).is_ok() {
                return true;
            }
        }
    }
    false
}

fn main() {
    if let Err(error) = run() {
        print_err_exit("Main", error).expect("Cannot print error message");
    }
}

fn run() -> Result<(), Error> {
    // Load the CLI parameters from the yaml file
    let yaml = load_yaml!("cli.yaml");
    let mut app = App::from_yaml(yaml).version(crate_version!());
    let matches = app.clone().get_matches();
    let path = try!(matches.value_of("path").ok_or(Error::Cli));

    // Create the journal
    let mut journal = try!(GitJournal::new(path));

    // Check for the subcommand
    match matches.subcommand_name() {
        Some("prepare") => {
            // Prepare a commit message before editing by the user
            if let Some(sub_matches) = matches.subcommand_matches("prepare") {
                match journal.prepare(try!(sub_matches.value_of("message").ok_or(Error::Cli)),
                                      sub_matches.value_of("type")) {
                    Ok(()) => try!(print_ok("Commit message prepared.")),
                    Err(error) => {
                        try!(print_err_exit("Commit message preparation failed",
                                            Error::GitJournal(error)))
                    }
                }
            }
        }
        Some("setup") => {
            // Do the setup procedure
            try!(journal.setup());

            // Generate completions if necessary
            if is_program_in_path("bash") {
                app.gen_completions("git-journal", Shell::Bash, env!("PWD"));
                try!(print_ok("Installed bash completions to your current working path."));
            }
            if is_program_in_path("fish") {
                app.gen_completions("git-journal", Shell::Fish, env!("PWD"));
                try!(print_ok("Installed fish completions to your current working path."));
            }
        }
        Some("verify") => {
            // Verify a commit message
            if let Some(sub_matches) = matches.subcommand_matches("verify") {
                match journal.verify(try!(sub_matches.value_of("message").ok_or(Error::Cli))) {
                    Ok(()) => try!(print_ok("Commit message valid.")),
                    Err(error) => try!(print_err_exit("Commit message invalid", Error::GitJournal(error))),
                }
            }
        }
        _ => {
            // Get all values of the given CLI parameters with default values
            let revision_range = try!(matches.value_of("revision_range").ok_or(Error::Cli));
            let tag_skip_pattern = try!(matches.value_of("tag_skip_pattern").ok_or(Error::Cli));
            let tags_count = try!(matches.value_of("tags_count").ok_or(Error::Cli));
            let max_tags = try!(tags_count.parse::<u32>());

            // Parse the log
            if let Err(error) = journal.parse_log(revision_range,
                                                  tag_skip_pattern,
                                                  &max_tags,
                                                  &matches.is_present("all"),
                                                  &matches.is_present("skip_unreleased")) {
                try!(print_err_exit("Log parsing error", Error::GitJournal(error)));
            }
            try!(journal.print_log(matches.is_present("short"),
                                   matches.value_of("template"),
                                   matches.value_of("output")));
        }
    };
    Ok(())
}
<commit_msg>Changed bash/fish completions path to the repository path during setup<commit_after>#[macro_use]
extern crate clap;
extern crate gitjournal;
extern crate term;

use std::env;
use std::fmt;
use std::fs;
use std::process::exit;

use clap::{App, Shell};
use gitjournal::GitJournal;

fn print_colored(string: &str, prefix: &str, color: term::color::Color) -> Result<(), term::Error> {
    let mut t = try!(term::stderr().ok_or(term::Error::NotSupported));
    try!(t.fg(term::color::YELLOW));
    try!(write!(t, "[git-journal] "));
    try!(t.fg(color));
    try!(write!(t, "[{}] ", prefix));
    try!(t.reset());
    try!(writeln!(t, "{}", string));
    Ok(())
}

fn print_ok(string: &str) -> Result<(), term::Error> {
    try!(print_colored(string, "OKAY", term::color::GREEN));
    Ok(())
}

fn print_err_exit(string: &str, error: Error) -> Result<(), term::Error> {
    let format_string = format!("{}: {}", string, error);
    try!(print_colored(&format_string, "ERROR", term::color::RED));
    exit(1);
}

enum Error {
    Cli,
    ParseInt(std::num::ParseIntError),
    Term(term::Error),
    GitJournal(gitjournal::Error),
}

impl From<gitjournal::Error> for Error {
    fn from(err: gitjournal::Error) -> Error {
        Error::GitJournal(err)
    }
}

impl From<term::Error> for Error {
    fn from(err: term::Error) -> Error {
        Error::Term(err)
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Cli => write!(f, "Cli argument parsing"),
            Error::ParseInt(ref err) => write!(f, "ParseInt: {}", err),
            Error::Term(ref err) => write!(f, "Term: {}", err),
            Error::GitJournal(ref err) => write!(f, "GitJournal: {}", err),
        }
    }
}

fn is_program_in_path(program: &str) -> bool {
    if let Ok(path) = env::var("PATH") {
        for p in path.split(':') {
            let p_str = format!("{}/{}", p, program);
            if fs::metadata(p_str).is_ok() {
                return true;
            }
        }
    }
    false
}

fn main() {
    if let Err(error) = run() {
        print_err_exit("Main", error).expect("Cannot print error message");
    }
}

fn run() -> Result<(), Error> {
    // Load the CLI parameters from the yaml file
    let yaml = load_yaml!("cli.yaml");
    let mut app = App::from_yaml(yaml).version(crate_version!());
    let matches = app.clone().get_matches();
    let path = try!(matches.value_of("path").ok_or(Error::Cli));

    // Create the journal
    let mut journal = try!(GitJournal::new(path));

    // Check for the subcommand
    match matches.subcommand_name() {
        Some("prepare") => {
            // Prepare a commit message before editing by the user
            if let Some(sub_matches) = matches.subcommand_matches("prepare") {
                match journal.prepare(try!(sub_matches.value_of("message").ok_or(Error::Cli)),
                                      sub_matches.value_of("type")) {
                    Ok(()) => try!(print_ok("Commit message prepared.")),
                    Err(error) => {
                        try!(print_err_exit("Commit message preparation failed",
                                            Error::GitJournal(error)))
                    }
                }
            }
        }
        Some("setup") => {
            // Do the setup procedure
            try!(journal.setup());

            // Generate completions if necessary
            if is_program_in_path("bash") {
                app.gen_completions("git-journal", Shell::Bash, path);
                try!(print_ok("Installed bash completions to the path."));
            }
            if is_program_in_path("fish") {
                app.gen_completions("git-journal", Shell::Fish, path);
                try!(print_ok("Installed fish completions to the path."));
            }
        }
        Some("verify") => {
            // Verify a commit message
            if let Some(sub_matches) = matches.subcommand_matches("verify") {
                match journal.verify(try!(sub_matches.value_of("message").ok_or(Error::Cli))) {
                    Ok(()) => try!(print_ok("Commit message valid.")),
                    Err(error) => try!(print_err_exit("Commit message invalid", Error::GitJournal(error))),
                }
            }
        }
        _ => {
            // Get all values of the given CLI parameters with default values
            let revision_range = try!(matches.value_of("revision_range").ok_or(Error::Cli));
            let tag_skip_pattern = try!(matches.value_of("tag_skip_pattern").ok_or(Error::Cli));
            let tags_count = try!(matches.value_of("tags_count").ok_or(Error::Cli));
            let max_tags = try!(tags_count.parse::<u32>());

            // Parse the log
            if let Err(error) = journal.parse_log(revision_range,
                                                  tag_skip_pattern,
                                                  &max_tags,
                                                  &matches.is_present("all"),
                                                  &matches.is_present("skip_unreleased")) {
                try!(print_err_exit("Log parsing error", Error::GitJournal(error)));
            }
            try!(journal.print_log(matches.is_present("short"),
                                   matches.value_of("template"),
                                   matches.value_of("output")));
        }
    };
    Ok(())
}
<|endoftext|>