<commit_before>#![allow(dead_code)]

extern crate num;
extern crate lazycell;
extern crate colored;
#[macro_use]
extern crate lazy_static;
extern crate getopts;

mod util;
mod syntax;
mod source;
mod number;
mod printer;
mod elaborate;

use std::fs::File;
use std::io::prelude::*;

use source::{SrcMgr, Source, DiagMgr, Severity};
use printer::PrettyPrint;

// use lexer::TokenKind;
use std::rc::Rc;

fn print_help(opts: &getopts::Options, program: &str) {
    let brief = format!("Usage: {} [options] FILES", program);
    eprint!("{}", opts.usage(&brief));
}

fn main() {
    //
    // Argument parsing
    //
    let args: Vec<String> = std::env::args().collect();

    let mut opts = getopts::Options::new();
    opts.optopt("o", "", "set output file name", "FILE");
    opts.optopt("t", "", "set toplevel module name", "MODULE");
    opts.optflag("", "parse", "parse only, do not elaborate");
    opts.optflag("h", "help", "print this help message");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => {
            eprintln!("{}", f.to_string());
            return print_help(&opts, &args[0])
        }
    };

    if matches.opt_present("h") {
        return print_help(&opts, &args[0])
    }

    let mut out: Box<dyn Write> = match matches.opt_str("o") {
        None => Box::new(std::io::stdout()),
        Some(v) => Box::new(File::create(v).unwrap()),
    };

    // Initailise source manager and diagnostic manager first
    let src_mgr = Rc::new(SrcMgr::new());
    let diag_mgr = DiagMgr::new(src_mgr.clone());

    if matches.free.is_empty() {
        diag_mgr.report_span(Severity::Fatal, "no input files specified", source::Span::none());
        return;
    }

    // Register a new panic handler. If the panic is caused by throwing fatal error, we mute
    // Rust's built-in error message and stack trace.
    {
        let hook = std::panic::take_hook();
        std::panic::set_hook(Box::new(move |info| {
            if info.payload().downcast_ref::<Severity>().is_none() {
                hook(info)
            }
        }));
    }

    // Parse all files together
    let mut files = Vec::new();
    'outer: for filename in &matches.free {
        let mut infile = File::open(filename).unwrap();
        let mut contents = String::new();
        infile.read_to_string(&mut contents).unwrap();

        let src = Rc::new(Source::new((*filename).to_owned(), contents));
        src_mgr.add_source(src.clone());

        let list = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            let tokens = syntax::lex(&src_mgr, &diag_mgr, &src);
            let list = syntax::parse(&diag_mgr, tokens);
            list
        })) {
            Ok(v) => v,
            Err(info) => {
                if info.downcast_ref::<Severity>().is_some() {
                    continue
                } else {
                    return;
                }
            }
        };

        files.push(list);
    }

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    elaborate::resolve(&diag_mgr, &mut files);

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    if matches.opt_present("parse") {
        let mut printer = PrettyPrint::new();
        for list in &files {
            for i in list {
                printer.print_item(&i);
                printer.append("\n");
            }
        }
        println!("{}", printer.take());
        return;
    }

    let elaborated = elaborate::elaborate(&diag_mgr, &files, match matches.opt_str("t") {
        None => "chip_top",
        Some(ref v) => v,
    });

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    let files = elaborate::reconstruct(&elaborated);

    {
        let list = files.first().unwrap();
        writeln!(out, "/* packages */");
        let mut printer = PrettyPrint::new();
        for i in list {
            printer.print_item(&i);
            printer.append("\n");
        }
        writeln!(out, "{}", printer.take());
    }

    for (list, name) in files.iter().skip(1).zip(matches.free.iter()) {
        writeln!(out, "/* file: {} */", name);
        if list.is_empty() {

        } else {
            let mut printer = PrettyPrint::new();
            for i in list {
                printer.print_item(&i);
                printer.append("\n");
            }
            writeln!(out, "{}", printer.take());
        }
    }
}
<commit_msg>Do not create file if elaboration failed<commit_after>#![allow(dead_code)]

extern crate num;
extern crate lazycell;
extern crate colored;
#[macro_use]
extern crate lazy_static;
extern crate getopts;

mod util;
mod syntax;
mod source;
mod number;
mod printer;
mod elaborate;

use std::fs::File;
use std::io::prelude::*;

use source::{SrcMgr, Source, DiagMgr, Severity};
use printer::PrettyPrint;

// use lexer::TokenKind;
use std::rc::Rc;

fn print_help(opts: &getopts::Options, program: &str) {
    let brief = format!("Usage: {} [options] FILES", program);
    eprint!("{}", opts.usage(&brief));
}

fn main() {
    //
    // Argument parsing
    //
    let args: Vec<String> = std::env::args().collect();

    let mut opts = getopts::Options::new();
    opts.optopt("o", "", "set output file name", "FILE");
    opts.optopt("t", "", "set toplevel module name", "MODULE");
    opts.optflag("", "parse", "parse only, do not elaborate");
    opts.optflag("h", "help", "print this help message");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => {
            eprintln!("{}", f.to_string());
            return print_help(&opts, &args[0])
        }
    };

    if matches.opt_present("h") {
        return print_help(&opts, &args[0])
    }

    // Initailise source manager and diagnostic manager first
    let src_mgr = Rc::new(SrcMgr::new());
    let diag_mgr = DiagMgr::new(src_mgr.clone());

    if matches.free.is_empty() {
        diag_mgr.report_span(Severity::Fatal, "no input files specified", source::Span::none());
        return;
    }

    // Register a new panic handler. If the panic is caused by throwing fatal error, we mute
    // Rust's built-in error message and stack trace.
    {
        let hook = std::panic::take_hook();
        std::panic::set_hook(Box::new(move |info| {
            if info.payload().downcast_ref::<Severity>().is_none() {
                hook(info)
            }
        }));
    }

    // Parse all files together
    let mut files = Vec::new();
    'outer: for filename in &matches.free {
        let mut infile = File::open(filename).unwrap();
        let mut contents = String::new();
        infile.read_to_string(&mut contents).unwrap();

        let src = Rc::new(Source::new((*filename).to_owned(), contents));
        src_mgr.add_source(src.clone());

        let list = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            let tokens = syntax::lex(&src_mgr, &diag_mgr, &src);
            let list = syntax::parse(&diag_mgr, tokens);
            list
        })) {
            Ok(v) => v,
            Err(info) => {
                if info.downcast_ref::<Severity>().is_some() {
                    continue
                } else {
                    return;
                }
            }
        };

        files.push(list);
    }

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    elaborate::resolve(&diag_mgr, &mut files);

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    if matches.opt_present("parse") {
        let mut out: Box<dyn Write> = match matches.opt_str("o") {
            None => Box::new(std::io::stdout()),
            Some(v) => Box::new(File::create(v).unwrap()),
        };

        let mut printer = PrettyPrint::new();
        for list in &files {
            for i in list {
                printer.print_item(&i);
                printer.append("\n");
            }
        }
        writeln!(out, "{}", printer.take()).unwrap();
        return;
    }

    let elaborated = elaborate::elaborate(&diag_mgr, &files, match matches.opt_str("t") {
        None => "chip_top",
        Some(ref v) => v,
    });

    // Abort elaboration when there are syntax errors.
    if diag_mgr.has_error() { return; }

    let files = elaborate::reconstruct(&elaborated);

    let mut out: Box<dyn Write> = match matches.opt_str("o") {
        None => Box::new(std::io::stdout()),
        Some(v) => Box::new(File::create(v).unwrap()),
    };

    {
        let list = files.first().unwrap();
        writeln!(out, "/* packages */").unwrap();
        let mut printer = PrettyPrint::new();
        for i in list {
            printer.print_item(&i);
            printer.append("\n");
        }
        writeln!(out, "{}", printer.take()).unwrap();
    }

    for (list, name) in files.iter().skip(1).zip(matches.free.iter()) {
        writeln!(out, "/* file: {} */", name).unwrap();
        if list.is_empty() {

        } else {
            let mut printer = PrettyPrint::new();
            for i in list {
                printer.print_item(&i);
                printer.append("\n");
            }
            writeln!(out, "{}", printer.take()).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>// fs.rs
use std::env; // env::home_dir()
use std::fs; // fs::read_dir()
//use std::path::Path;
use std::path::PathBuf;

enum ItemType {
   Dir,
   File,
   Other,
}

struct FoundItem {
   item_type: ItemType,
   item_path: PathBuf,
}

fn main() {
   //let mut idg_dir_path = PathBuf::from("~/Files/Doom/idgames");
   // create an empty PathBuf
   let mut idg_dir = PathBuf::new();
   // call `home_dir()` and act on what it returns
   match env::home_dir() {
      //Some(idg_dir) => println!("{}", idg_dir.display()),
      // home_dir() returned something
      Some(home_dir) => idg_dir = home_dir,
      // home_dir() returned nothing
      None => println!("Can't obtain home directory path!"),
   }

   // append more directories on to idg_dir
   idg_dir.push("Files");
   idg_dir.push("Doom");
   idg_dir.push("idgames");

/*
// doesn't work, try!() won't handle _Result_ objects
   for entry in try!(fs::read_dir(idg_dir)) {
       let dir = try!(entry);
       println!("{:?}", dir.path());
   }
*/

/*
   // try and read the contents of idg_dir/
   // - doesn't work, try!() won't handle _Result_ objects
   for entry in try!(fs::read_dir(idg_dir)) {
      let dir = try!(entry);
      // 'entry' is still a _Result_, so this is broken
      let metadata = try!(entry.metadata());
      // 'dir' is still a _DirEntry_
      if dir.is_dir() {
         println!("d {:?}", dir.path());
      } else {
         println!("! {:?}", dir.path());
      }
   }
*/

/*
   if let Ok(entries) = fs::read_dir(idg_dir) {
      for entry in entries {
         // 'item' is a Result, unwrap it to get access to Metadata
         if let Ok(entry) = entry {
               if let Ok(metadata) = entry.metadata() {};
               // entry.path() returns a _Result_
               if let Ok(path) = entry.path() {};
               // 'entry' is a _DirEntry_, and doesn't have an 'is_dir()'
               // method
               if entry.is_dir() {
                  println!("d {:?} {:?}",
                     // 'metadata' isn't available here
                     metadata.file_type(),
                     // the compiler doesn't know what 'path' is here
                     path);
            }
         }
      }
   }
*/

/*
   // working example
   println!("Updated іdgames/ path: {}", idg_dir.display());
   // read the contents of idg_dir/
   match fs::read_dir(idg_dir) {
      Err(why) => println!("! {:?}", why.kind()),
      Ok(paths) => for path in paths {
         println!("> {:?}", path.unwrap().path());
      }
   }
*/

   // working example from:
   // https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.file_name
   if let Ok(entries) = fs::read_dir(idg_dir) {
      for dir_entry in entries {
         if let Ok(dir_entry) = dir_entry {
            //let path = dir_entry.path();
            // get the metadata object for this DirEntry
            if let Ok(metadata) = dir_entry.metadata() {
               // below, `dir_entry` is a `DirEntry`.
               if metadata.is_file() {
                  println!("f {:?}", dir_entry.file_name());
                  let item = FoundItem {
                     item_type: ItemType::File,
                     item_path: dir_entry.path()
                  };
               }
               else if metadata.is_dir() {
                  println!("d {:?}", dir_entry.file_name());
                  let item = FoundItem {
                     item_type: ItemType::Dir,
                     item_path: dir_entry.path()
                  };
               }
            }
         }
      }
   }
}
<commit_msg>src/main.rs: moved working code above commented code<commit_after>// fs.rs
use std::env; // env::home_dir()
use std::fs; // fs::read_dir()
//use std::path::Path;
use std::path::PathBuf;

enum ItemType {
   Dir,
   File,
   Other,
}

struct FoundItem {
   item_type: ItemType,
   item_path: PathBuf,
}

fn main() {
   //let mut idg_dir_path = PathBuf::from("~/Files/Doom/idgames");
   // create an empty PathBuf
   let mut idg_dir = PathBuf::new();
   // call `home_dir()` and act on what it returns
   match env::home_dir() {
      //Some(idg_dir) => println!("{}", idg_dir.display()),
      // home_dir() returned something
      Some(home_dir) => idg_dir = home_dir,
      // home_dir() returned nothing
      None => println!("Can't obtain home directory path!"),
   }

   // append more directories on to idg_dir
   idg_dir.push("Files");
   idg_dir.push("Doom");
   idg_dir.push("idgames");

   // working example from:
   // https://doc.rust-lang.org/std/fs/struct.DirEntry.html#method.file_name
   if let Ok(entries) = fs::read_dir(idg_dir) {
      for dir_entry in entries {
         if let Ok(dir_entry) = dir_entry {
            //let path = dir_entry.path();
            // get the metadata object for this DirEntry
            if let Ok(metadata) = dir_entry.metadata() {
               // below, `dir_entry` is a `DirEntry`.
               if metadata.is_file() {
                  println!("f {:?}", dir_entry.file_name());
                  let item = FoundItem {
                     item_type: ItemType::File,
                     item_path: dir_entry.path()
                  };
               }
               else if metadata.is_dir() {
                  println!("d {:?}", dir_entry.file_name());
                  let item = FoundItem {
                     item_type: ItemType::Dir,
                     item_path: dir_entry.path()
                  };
               }
            }
         }
      }
   }

/*
// doesn't work, try!() won't handle _Result_ objects
   for entry in try!(fs::read_dir(idg_dir)) {
       let dir = try!(entry);
       println!("{:?}", dir.path());
   }
*/

/*
   // try and read the contents of idg_dir/
   // - doesn't work, try!() won't handle _Result_ objects
   for entry in try!(fs::read_dir(idg_dir)) {
      let dir = try!(entry);
      // 'entry' is still a _Result_, so this is broken
      let metadata = try!(entry.metadata());
      // 'dir' is still a _DirEntry_
      if dir.is_dir() {
         println!("d {:?}", dir.path());
      } else {
         println!("! {:?}", dir.path());
      }
   }
*/

/*
   if let Ok(entries) = fs::read_dir(idg_dir) {
      for entry in entries {
         // 'item' is a Result, unwrap it to get access to Metadata
         if let Ok(entry) = entry {
               if let Ok(metadata) = entry.metadata() {};
               // entry.path() returns a _Result_
               if let Ok(path) = entry.path() {};
               // 'entry' is a _DirEntry_, and doesn't have an 'is_dir()'
               // method
               if entry.is_dir() {
                  println!("d {:?} {:?}",
                     // 'metadata' isn't available here
                     metadata.file_type(),
                     // the compiler doesn't know what 'path' is here
                     path);
            }
         }
      }
   }
*/

/*
   // working example
   println!("Updated іdgames/ path: {}", idg_dir.display());
   // read the contents of idg_dir/
   match fs::read_dir(idg_dir) {
      Err(why) => println!("! {:?}", why.kind()),
      Ok(paths) => for path in paths {
         println!("> {:?}", path.unwrap().path());
      }
   }
*/

}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate rustc;

fn main() {
    println!("Hello, world!");
}
<commit_msg>Add get_sysroot function.<commit_after>#![feature(rustc_private)]

#[macro_use]
extern crate log;

extern crate rustc;

use std::path::PathBuf;
use std::process::Command;
use std::str::from_utf8;

fn main() {
    println!("Hello, world!");
}

/// Runs `rustc` to ask for its sysroot path.
fn get_sysroot() -> PathBuf {
    let rustc = if cfg!(windows) { "rustc.exe" } else { "rustc" };

    let output = match Command::new(rustc).args(&["--print", "sysroot"]).output() {
        Ok(output) => output.stdout,
        Err(e) => panic!("failed to run rustc: {}", e),
    };

    let path = from_utf8(&output)
        .ok().expect("sysroot is not valid UTF-8").trim_right_matches(
            |c| c == '\r' || c == '\n');

    debug!("using sysroot: {:?}", path);

    PathBuf::from(path)
}
<|endoftext|>


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

extern crate docopt;

#[macro_use]
extern crate standard_error;

use docopt::Docopt;
use standard_error::StandardResult as Result;
use std::rc::Rc;

mod git;
mod author;
mod pair;
mod config;
mod concat;

use author::Author;
use pair::Pair;
use config::Config;
use std::borrow::Cow;

const CONFIG_PATH: &'static str = "./partners.cfg";
const CFG: git::Config = git::Config::File(CONFIG_PATH);

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: partners current
       partners list
       partners add --nick=<nick> --name=<name> [--email=<email>]
       partners add
       partners set <nick>...
       partners (--help | --version)

Options:
    -h, --help      Show help
    --version       Show version information
";

trait AuthorInformation {
    fn get_nick(&self) -> Cow<str>;
    fn get_name(&self) -> Cow<str>;
    fn get_email(&self) -> Cow<str>;
}

fn print_author_list(list: &[Author]) {
    for item in list.iter() {
        println!("{}:", item.nick);
        println!("  Name:  {}", item.name);
        println!("  Email: {}", item.get_email());
    }
}

fn parse_author_line(config: Rc<Config>, line: &str) -> Result<Author> {
    let mut parts = line.splitn(1, ' ');
    let nick = parts.next().unwrap().split('.').nth(1).unwrap().to_string();
    let name = parts.next().unwrap().to_string();
    let email = CFG.get(&format!("author.{}.email", nick)).ok();

    Ok(Author { config: config, nick: nick, name: name, email: email })
}

fn get_authors(config: Rc<Config>) -> Result<Vec<Author>> {
    let lines = try!(CFG.list("author.\\w+.name"));
    lines.iter().map(|line| parse_author_line(config.clone(), line)).collect()
}

fn write_author(author: &Author) -> Result<()> {
    try!(CFG.set(&format!("author.{}.name", author.nick), &author.name));
    if let Some(ref email) = author.email {
        try!(CFG.set(&format!("author.{}.email", author.nick), email));
    }
    Ok(())
}

fn print_current() {
    if let Ok(nick) = git::Config::None.get("partners.current") {
        println!("Nick:  {}", nick);
    }
    if let Ok(name) = git::Config::None.get("user.name") {
        println!("Name:  {}", name);
    }
    if let Ok(email) = git::Config::None.get("user.email") {
        println!("Email: {}", email);
    }
}

fn filter_authors<'a>(authors: &'a [Author], nicks: &[&str]) -> std::result::Result<Vec<&'a Author>, String> {
    nicks.iter().map(|n| authors.iter().find(|a| &a.nick == n).ok_or_else(|| n.to_string())).collect()
}

fn set_current<T>(current: T) -> Result<()> where T: AuthorInformation {
    try!(git::Config::Global.set("partners.current", &current.get_nick()));
    try!(git::Config::Global.set("user.name", &current.get_name()));
    try!(git::Config::Global.set("user.email", &current.get_email()));
    Ok(())
}

fn main() {
    let docopt = Docopt::new(USAGE).unwrap().help(true).version(Some(env!("CARGO_PKG_VERSION").to_string()));
    let args = docopt.parse().unwrap_or_else(|e| e.exit());

    let config = Rc::new(Config {
        domain: CFG.get("config.domain").unwrap_or_else(|_| "example.com".to_string()),
        prefix: CFG.get("config.prefix").unwrap_or_else(|_| "dev".to_string()),
        separator: CFG.get("config.separator").unwrap_or_else(|_| "+".to_string()),
    });

    if args.get_bool("list") {
        let authors = get_authors(config).unwrap();
        print_author_list(&authors);
    } else if args.get_bool("add") {
        let email = args.get_str("--email");
        let nick = args.get_str("--nick");
        let name = args.get_str("--name");

        let email = if email.is_empty() { None } else { Some(email.to_string()) };

        let author = Author { config: config.clone(), nick: nick.to_string(), name: name.to_string(), email: email };
        write_author(&author).unwrap();
    } else if args.get_bool("current") {
        print_current();
    } else if args.get_bool("set") {
        let nicks = args.get_vec("<nick>");
        let authors = get_authors(config.clone()).unwrap();
        match filter_authors(&authors, &nicks) {
            Ok(filtered_authors) => {
                println!("{:?}", filtered_authors);
                match filtered_authors.len() {
                    0 => println!("no author specified"),
                    1 => set_current(filtered_authors[0]).unwrap(),
                    _ => {
                        let pair = Pair { config: config.clone(), authors: filtered_authors.as_slice() };
                        set_current(&pair).unwrap()
                    }
                }
                print_current();
            },
            Err(nick) => {
                println!("couldn't find author '{}'", nick);
            }
        }

        // match get_authors(config).unwrap().iter().find(|a| a.nick == nick) {
        //     Some(author) => {
        //     }
        //     None => {
        //         println!("no such author");
        //     }
        // }
    }
}
<commit_msg>remove comments<commit_after>#![feature(core)]
#![feature(process)]

extern crate docopt;

#[macro_use]
extern crate standard_error;

use docopt::Docopt;
use standard_error::StandardResult as Result;
use std::rc::Rc;

mod git;
mod author;
mod pair;
mod config;
mod concat;

use author::Author;
use pair::Pair;
use config::Config;
use std::borrow::Cow;

const CONFIG_PATH: &'static str = "./partners.cfg";
const CFG: git::Config = git::Config::File(CONFIG_PATH);

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: partners current
       partners list
       partners add --nick=<nick> --name=<name> [--email=<email>]
       partners add
       partners set <nick>...
       partners (--help | --version)

Options:
    -h, --help      Show help
    --version       Show version information
";

trait AuthorInformation {
    fn get_nick(&self) -> Cow<str>;
    fn get_name(&self) -> Cow<str>;
    fn get_email(&self) -> Cow<str>;
}

fn print_author_list(list: &[Author]) {
    for item in list.iter() {
        println!("{}:", item.nick);
        println!("  Name:  {}", item.name);
        println!("  Email: {}", item.get_email());
    }
}

fn parse_author_line(config: Rc<Config>, line: &str) -> Result<Author> {
    let mut parts = line.splitn(1, ' ');
    let nick = parts.next().unwrap().split('.').nth(1).unwrap().to_string();
    let name = parts.next().unwrap().to_string();
    let email = CFG.get(&format!("author.{}.email", nick)).ok();

    Ok(Author { config: config, nick: nick, name: name, email: email })
}

fn get_authors(config: Rc<Config>) -> Result<Vec<Author>> {
    let lines = try!(CFG.list("author.\\w+.name"));
    lines.iter().map(|line| parse_author_line(config.clone(), line)).collect()
}

fn write_author(author: &Author) -> Result<()> {
    try!(CFG.set(&format!("author.{}.name", author.nick), &author.name));
    if let Some(ref email) = author.email {
        try!(CFG.set(&format!("author.{}.email", author.nick), email));
    }
    Ok(())
}

fn print_current() {
    if let Ok(nick) = git::Config::None.get("partners.current") {
        println!("Nick:  {}", nick);
    }
    if let Ok(name) = git::Config::None.get("user.name") {
        println!("Name:  {}", name);
    }
    if let Ok(email) = git::Config::None.get("user.email") {
        println!("Email: {}", email);
    }
}

fn filter_authors<'a>(authors: &'a [Author], nicks: &[&str]) -> std::result::Result<Vec<&'a Author>, String> {
    nicks.iter().map(|n| authors.iter().find(|a| &a.nick == n).ok_or_else(|| n.to_string())).collect()
}

fn set_current<T>(current: T) -> Result<()> where T: AuthorInformation {
    try!(git::Config::Global.set("partners.current", &current.get_nick()));
    try!(git::Config::Global.set("user.name", &current.get_name()));
    try!(git::Config::Global.set("user.email", &current.get_email()));
    Ok(())
}

fn main() {
    let docopt = Docopt::new(USAGE).unwrap().help(true).version(Some(env!("CARGO_PKG_VERSION").to_string()));
    let args = docopt.parse().unwrap_or_else(|e| e.exit());

    let config = Rc::new(Config {
        domain: CFG.get("config.domain").unwrap_or_else(|_| "example.com".to_string()),
        prefix: CFG.get("config.prefix").unwrap_or_else(|_| "dev".to_string()),
        separator: CFG.get("config.separator").unwrap_or_else(|_| "+".to_string()),
    });

    if args.get_bool("list") {
        let authors = get_authors(config).unwrap();
        print_author_list(&authors);
    } else if args.get_bool("add") {
        let email = args.get_str("--email");
        let nick = args.get_str("--nick");
        let name = args.get_str("--name");

        let email = if email.is_empty() { None } else { Some(email.to_string()) };

        let author = Author { config: config.clone(), nick: nick.to_string(), name: name.to_string(), email: email };
        write_author(&author).unwrap();
    } else if args.get_bool("current") {
        print_current();
    } else if args.get_bool("set") {
        let nicks = args.get_vec("<nick>");
        let authors = get_authors(config.clone()).unwrap();
        match filter_authors(&authors, &nicks) {
            Ok(filtered_authors) => {
                println!("{:?}", filtered_authors);
                match filtered_authors.len() {
                    0 => println!("no author specified"),
                    1 => set_current(filtered_authors[0]).unwrap(),
                    _ => {
                        let pair = Pair { config: config.clone(), authors: filtered_authors.as_slice() };
                        set_current(&pair).unwrap()
                    }
                }
                print_current();
            },
            Err(nick) => {
                println!("couldn't find author '{}'", nick);
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;
extern crate toml;
extern crate url;

mod config;
mod crates_io;
mod errors;
mod github;
mod lockfile;

use std::env;

use crates_io::Repository;
use errors::*;

quick_main!(|| -> Result<()> {
  let home_dir = env::home_dir().expect("Cannot get home directory");

  let config = config::read(&home_dir.join(".thank-you-stars.json"))
    .chain_err(|| "Save your configuration as `.thank-you-stars.json`")?;

  let lockfile = lockfile::read(&env::current_dir()?.join("Cargo.lock"))
    .chain_err(|| "Run `cargo install` before")?;

  for dependency in lockfile.root.dependencies {
    if dependency.is_registry() {
      let krate = crates_io::get(&dependency.crate_id())
        .chain_err(|| "Cannot get crate data from crates.io")?;

      if let Repository::GitHub(repository) = krate.repository() {
        match github::star(&config.token, &repository) {
          Ok(_) => println!("Starred! https://github.com/{}", &repository),
          Err(e) => println!("{}", e),
        }
      }
    }
  }

  Ok(())
});
<commit_msg>Print errors to stderr instead of stdout<commit_after>#[macro_use]
extern crate error_chain;
extern crate reqwest;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;
extern crate toml;
extern crate url;

mod config;
mod crates_io;
mod errors;
mod github;
mod lockfile;

use std::env;

use crates_io::Repository;
use errors::*;

quick_main!(|| -> Result<()> {
  let home_dir = env::home_dir().expect("Cannot get home directory");

  let config = config::read(&home_dir.join(".thank-you-stars.json"))
    .chain_err(|| "Save your configuration as `.thank-you-stars.json`")?;

  let lockfile = lockfile::read(&env::current_dir()?.join("Cargo.lock"))
    .chain_err(|| "Run `cargo install` before")?;

  for dependency in lockfile.root.dependencies {
    if dependency.is_registry() {
      let krate = crates_io::get(&dependency.crate_id())
        .chain_err(|| "Cannot get crate data from crates.io")?;

      if let Repository::GitHub(repository) = krate.repository() {
        match github::star(&config.token, &repository) {
          Ok(_) => println!("Starred! https://github.com/{}", &repository),
          Err(e) => eprintln!("{}", e.to_string()),
        }
      }
    }
  }

  Ok(())
});
<|endoftext|>


<commit_before>extern crate csv;
#[macro_use]
extern crate lazy_static;
extern crate prettytable;
extern crate regex;
extern crate rusqlite;
extern crate rustyline;

use std::env;
use std::error::Error;

fn _normalize_col(col: &str) -> String {
    lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    return RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &Vec<String>) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _insert_row(db: &mut rusqlite::Connection, row: csv::StringRecord, insert_query: &str) {
    let mut stmt = db.prepare(insert_query).unwrap();

    let res = stmt.execute(&row);
    assert!(res.is_ok());
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: String,
) -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_path(path).unwrap();

    let normalized_cols = reader
        .headers()
        .unwrap()
        .iter()
        .map(_normalize_col)
        .collect();
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    for row in reader.records() {
        _insert_row(db, row.unwrap(), &insert_query);
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Text(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) => String::from_utf8(v.to_vec()).unwrap(),
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _print_table(conn: &mut rusqlite::Connection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.description());
            return;
        }
    };
    let mut results = stmt.query(&[] as &[&rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = prettytable::Row::new(vec![]);
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(prettytable::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize) -> Option<String> {
        return None;
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = vec![
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
    ]
    .iter()
    .map(|s| s.to_string())
    .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(line.clone());
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<commit_msg>Handle duplicate column names<commit_after>extern crate csv;
#[macro_use]
extern crate lazy_static;
extern crate prettytable;
extern crate regex;
extern crate rusqlite;
extern crate rustyline;

use std::env;
use std::error::Error;

fn _normalize_col(col: &str) -> String {
    lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    return RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &Vec<String>) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _insert_row(db: &mut rusqlite::Connection, row: csv::StringRecord, insert_query: &str) {
    let mut stmt = db.prepare(insert_query).unwrap();

    let res = stmt.execute(&row);
    assert!(res.is_ok());
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: String,
) -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_path(path).unwrap();

    let normalized_cols =
        reader
            .headers()
            .unwrap()
            .iter()
            .map(_normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                return v;
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    for row in reader.records() {
        _insert_row(db, row.unwrap(), &insert_query);
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Text(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) => String::from_utf8(v.to_vec()).unwrap(),
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _print_table(conn: &mut rusqlite::Connection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.description());
            return;
        }
    };
    let mut results = stmt.query(&[] as &[&rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = prettytable::Row::new(vec![]);
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(prettytable::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize) -> Option<String> {
        return None;
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = vec![
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
    ]
    .iter()
    .map(|s| s.to_string())
    .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(line.clone());
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate toml;

use docopt::Docopt;
use std::path::Path;
use std::fs::File;
use std::fs::metadata;
use std::io::prelude::*;
use glob::Pattern;
use rustc_serialize::Decodable;

const USAGE: &'static str = "
enforcer for code rules

Usage:
  enforcer [-g GLOB...] [-c|--clean]
  enforcer (-h | --help)
  enforcer (-v | --version)

Options:
  -g GLOB       use these glob patterns (e.g. \"**/*.h\")
  -h --help     Show this screen.
  -v --version  Show version.
  --count       only count found entries
  -c --clean    clean up trailing whitespaces
";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_count: bool,
    flag_clean: bool,
    flag_g: Vec<String>,
    flag_version: bool,
}
const HAS_TABS: u8               = 1 << 0;
const TRAILING_SPACES: u8        = 1 << 1;
const HAS_ILLEGAL_CHARACTERS: u8 = 1 << 2;

fn check_content<'a>(input: &'a str) -> std::io::Result<u8> {
    let mut result = 0;
    let mut i: u32 = 0;
    for line in input.lines_any() {
        i += 1;
        if line.ends_with(' ') {
            result |= TRAILING_SPACES;
        }
        if line.contains("\t") {
            result |= HAS_TABS;
        }
        if line.as_bytes().iter().any(|x| *x > 127) {
            println!("non ASCII line [{}]: {}", i, line);
            result |= HAS_ILLEGAL_CHARACTERS;
        }
    }
    Ok(result)
}

fn clean_string(input: &str) -> String {
    let v: Vec<&str> = input
        .lines_any()
        .map(|line| line.trim_right())
        .collect();

    if input.ends_with("\n") {
        v.join("\n") + "\n"
    }
    else {
        v.join("\n")
    }
}

fn is_dir(path: &Path) -> bool {
    if let Ok(result) = metadata(&path) {
        result.is_dir()
    } else {
        false
    }
}

fn report_offending_line(path: &Path) -> std::io::Result<()> {
    use std::io::BufReader;
    let mut i: u32 = 1;
    let f = try!(File::open(path));
    let file = BufReader::new(f);
    for line in file.lines() {
        match line.ok() {
            Some(_) => i = i + 1,
            None => println!("offending line {} in file [{}]", i, path.display()),
        }
    }
    Ok(())
}

fn check_path(path: &Path, clean: bool) -> std::io::Result<()> {
    use std::io::ErrorKind;

    let mut f = try!(File::open(path));
    let mut buffer = String::new();
    let mut check = 0;
    if let Err(e) = f.read_to_string(&mut buffer) {
        match e.kind() {
            ErrorKind::InvalidData => {
                check = check | HAS_ILLEGAL_CHARACTERS;
                let _ = report_offending_line(path);
            },
            _ => return Err(e),
        }
    }
    // only check content if we could read the file
    if check == 0 { check = try!(check_content(&buffer)); }
    if (check & HAS_TABS) > 0 {
        println!("HAS_TABS:[{}]", path.display());
    }
    if (check & TRAILING_SPACES) > 0 {
        println!("TRAILING_SPACES:[{}]", path.display());
        if clean {
            println!("cleaning trailing whitespaces");
            let res_string = clean_string(&buffer);
            let mut file = try!(File::create(path));
            try!(file.write_all(res_string.as_bytes()));
        }
    }
    Ok(())
}

#[derive(Debug, RustcDecodable, PartialEq)]
struct EnforcerCfg {
    ignore: Vec<String>,
    globs: Vec<String>,
}

fn s(x: &str) -> String { x.to_string() }

fn default_cfg() -> EnforcerCfg {
    EnforcerCfg {
        ignore: vec![s(".git"), s(".bake"), s(".repo")],
        globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
    }
}

fn is_unwanted(comp: std::path::Component, to_ignore: &Vec<String>) -> bool {
    let path_elem = comp.as_os_str()
                        .to_str()
                        .expect(&format!("illegal path component {:?}", comp)[..]);
    to_ignore.iter()
        .any(|x| Pattern::new(x)
            .ok()
            .expect(&format!("{} seems not to be a valid pattern", x)[..])
            .matches(path_elem))
}

fn load_config<'a>(input: &'a str) -> std::io::Result<EnforcerCfg> {
    use std::io::{Error, ErrorKind};
    let mut parser = toml::Parser::new(input);
    fn default_err() -> Error {
        Error::new(ErrorKind::InvalidData, "could not parse the config")
    }

    parser.parse().map_or(Err(default_err()), |toml| {
        let mut decoder = toml::Decoder::new(toml::Value::Table(toml));
        EnforcerCfg::decode(&mut decoder)
            .ok()
            .map_or(Err(default_err()), |config|
                Ok(config))
    })
}

#[allow(dead_code)]
fn main() {
    use glob::glob;
    env_logger::init().unwrap();

    fn get_cfg() -> EnforcerCfg {
        fn read_enforcer_config() -> std::io::Result<EnforcerCfg> {
            let mut cfg_file = try!(File::open(".enforcer"));
            let mut buffer = String::new();
            try!(cfg_file.read_to_string(&mut buffer));
            load_config(&buffer[..])
        }
        let enforcer_cfg = read_enforcer_config()
            .unwrap_or(default_cfg());
        println!("loaded ignores: {:?}", enforcer_cfg.ignore);
        enforcer_cfg
    }

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

    if args.flag_version {
        println!("  Version: {}", VERSION);
    }
    let enforcer_cfg = get_cfg();
    let cfg_ignores = enforcer_cfg.ignore;
    let cfg_globs = enforcer_cfg.globs;
    let pats = if args.flag_g.len() > 0 {
        args.flag_g
    } else {
        cfg_globs
    };

    fn find_matches<'a>(pat: &str, to_ignore: &Vec<String>) -> Vec<std::path::PathBuf> {
        glob(&*pat) // -> Result<Paths, PatternError>
            .ok()   // -> Option<Paths>
            .expect(&format!("glob has problems with {}", pat)[..]) // -> Paths (Iterator ofer GlobResult)
            .filter_map(Result::ok) // ignore unreadable paths -> Iterator over PathBuf
            .filter(|x| !x.components()
                        .any(|y| is_unwanted(y, to_ignore))).collect()
    }
    let paths: Vec<std::path::PathBuf> = pats.iter().flat_map(|pat| find_matches(pat, &cfg_ignores)).collect();
    for path in paths {
        if !is_dir(path.as_path()) {
            check_path(path.as_path(), args.flag_clean)
                .ok()
                .expect(&format!("check_path for {:?} should work", path));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::clean_string;
    use super::load_config;
    use super::is_unwanted;
    use super::s;
    use glob::Pattern;
    use super::EnforcerCfg;
    use std::ffi::OsStr;
    use std::path::Component::Normal;

    #[test]
    fn test_clean_does_not_remove_trailing_newline() {
        let content = "1\n2\n3\n4\n5\n";
        let cleaned = clean_string(content);
        assert!(cleaned.eq(content));
    }
    #[test]
    fn test_clean_trailing_whitespace() {
        let content = "1 \n2";
        let cleaned = clean_string(content);
        println!("{:?}", cleaned);
        assert!(cleaned.eq("1\n2"));
    }
    #[test]
    fn test_load_simple_config() {
        let c = include_str!("../samples/.enforcer");
        let cfg = load_config(c).unwrap();
        assert_eq!(cfg.ignore.len(), 2);
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert_eq!(expected.ignore, cfg.ignore);
        assert_eq!(expected, cfg);
    }
    #[test]
    fn test_load_broken_config() {
        let c = include_str!("../samples/.enforcer_broken");
        let cfg = load_config(c).unwrap();
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert!(expected.ignore != cfg.ignore);
    }
    #[test]
    fn test_glob() {
        assert!(Pattern::new("build_*").unwrap().matches("build_Debug"));
    }
    #[test]
    fn test_is_unwanted() {
        let cfg = EnforcerCfg { ignore: vec![s("build_*"), s(".git")], globs: vec![]};
        assert!(is_unwanted(Normal(OsStr::new("build_Debug")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new(".git")), &cfg.ignore));
        assert!(!is_unwanted(Normal(OsStr::new("bla")), &cfg.ignore));
    }
}

<commit_msg>better diagnostics of files with illegal characters<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate rustc_serialize;
extern crate docopt;
extern crate glob;
extern crate toml;

use docopt::Docopt;
use std::path::Path;
use std::fs::File;
use std::fs::metadata;
use std::io::prelude::*;
use glob::Pattern;
use rustc_serialize::Decodable;

const USAGE: &'static str = "
enforcer for code rules

Usage:
  enforcer [-g GLOB...] [-c|--clean]
  enforcer (-h | --help)
  enforcer (-v | --version)

Options:
  -g GLOB       use these glob patterns (e.g. \"**/*.h\")
  -h --help     Show this screen.
  -v --version  Show version.
  --count       only count found entries
  -c --clean    clean up trailing whitespaces
";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_count: bool,
    flag_clean: bool,
    flag_g: Vec<String>,
    flag_version: bool,
}
const HAS_TABS: u8               = 1 << 0;
const TRAILING_SPACES: u8        = 1 << 1;
const HAS_ILLEGAL_CHARACTERS: u8 = 1 << 2;

fn check_content<'a>(input: &'a str, filename: &str) -> std::io::Result<u8> {
    let mut result = 0;
    let mut i: u32 = 0;
    for line in input.lines_any() {
        i += 1;
        if line.ends_with(' ') {
            result |= TRAILING_SPACES;
        }
        if line.contains("\t") {
            result |= HAS_TABS;
        }
        if line.as_bytes().iter().any(|x| *x > 127) {
            println!("non ASCII line [{}]: {} [{}]", i, line, filename);
            result |= HAS_ILLEGAL_CHARACTERS;
        }
    }
    Ok(result)
}

fn clean_string(input: &str) -> String {
    let v: Vec<&str> = input
        .lines_any()
        .map(|line| line.trim_right())
        .collect();

    if input.ends_with("\n") {
        v.join("\n") + "\n"
    }
    else {
        v.join("\n")
    }
}

fn is_dir(path: &Path) -> bool {
    if let Ok(result) = metadata(&path) {
        result.is_dir()
    } else {
        false
    }
}

fn report_offending_line(path: &Path) -> std::io::Result<()> {
    use std::io::BufReader;
    let mut i: u32 = 1;
    let f = try!(File::open(path));
    let file = BufReader::new(f);
    for line in file.lines() {
        match line.ok() {
            Some(_) => i = i + 1,
            None => println!("offending line {} in file [{}]", i, path.display()),
        }
    }
    Ok(())
}

fn check_path(path: &Path, clean: bool) -> std::io::Result<u8> {
    use std::io::ErrorKind;

    let mut f = try!(File::open(path));
    let mut buffer = String::new();
    let mut check = 0;
    if let Err(e) = f.read_to_string(&mut buffer) {
        match e.kind() {
            ErrorKind::InvalidData => {
                check = check | HAS_ILLEGAL_CHARACTERS;
                let _ = report_offending_line(path);
            },
            _ => return Err(e),
        }
    }
    // only check content if we could read the file
    if check == 0 { check = try!(check_content(&buffer, path.to_str().expect("not available"))); }
    if (check & HAS_TABS) > 0 {
        println!("HAS_TABS:[{}]", path.display());
    }
    if (check & TRAILING_SPACES) > 0 {
        println!("TRAILING_SPACES:[{}]", path.display());
        if clean {
            println!("cleaning trailing whitespaces");
            let res_string = clean_string(&buffer);
            let mut file = try!(File::create(path));
            try!(file.write_all(res_string.as_bytes()));
        }
    }
    Ok(check)
}

#[derive(Debug, RustcDecodable, PartialEq)]
struct EnforcerCfg {
    ignore: Vec<String>,
    globs: Vec<String>,
}

fn s(x: &str) -> String { x.to_string() }

fn default_cfg() -> EnforcerCfg {
    EnforcerCfg {
        ignore: vec![s(".git"), s(".bake"), s(".repo")],
        globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
    }
}

fn is_unwanted(comp: std::path::Component, to_ignore: &Vec<String>) -> bool {
    let path_elem = comp.as_os_str()
                        .to_str()
                        .expect(&format!("illegal path component {:?}", comp)[..]);
    to_ignore.iter()
        .any(|x| Pattern::new(x)
            .ok()
            .expect(&format!("{} seems not to be a valid pattern", x)[..])
            .matches(path_elem))
}

fn load_config<'a>(input: &'a str) -> std::io::Result<EnforcerCfg> {
    use std::io::{Error, ErrorKind};
    let mut parser = toml::Parser::new(input);
    fn default_err() -> Error {
        Error::new(ErrorKind::InvalidData, "could not parse the config")
    }

    parser.parse().map_or(Err(default_err()), |toml| {
        let mut decoder = toml::Decoder::new(toml::Value::Table(toml));
        EnforcerCfg::decode(&mut decoder)
            .ok()
            .map_or(Err(default_err()), |config|
                Ok(config))
    })
}

#[allow(dead_code)]
fn main() {
    use glob::glob;
    env_logger::init().unwrap();

    fn get_cfg() -> EnforcerCfg {
        fn read_enforcer_config() -> std::io::Result<EnforcerCfg> {
            let mut cfg_file = try!(File::open(".enforcer"));
            let mut buffer = String::new();
            try!(cfg_file.read_to_string(&mut buffer));
            load_config(&buffer[..])
        }
        let enforcer_cfg = read_enforcer_config()
            .unwrap_or(default_cfg());
        enforcer_cfg
    }

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

    if args.flag_version {
        println!("  Version: {}", VERSION);
    }
    let enforcer_cfg = get_cfg();
    let cfg_ignores = enforcer_cfg.ignore;
    let cfg_globs = enforcer_cfg.globs;
    let pats = if args.flag_g.len() > 0 {
        args.flag_g
    } else {
        cfg_globs
    };

    fn find_matches<'a>(pat: &str, to_ignore: &Vec<String>) -> Vec<std::path::PathBuf> {
        glob(&*pat) // -> Result<Paths, PatternError>
            .ok()   // -> Option<Paths>
            .expect(&format!("glob has problems with {}", pat)[..]) // -> Paths (Iterator ofer GlobResult)
            .filter_map(Result::ok) // ignore unreadable paths -> Iterator over PathBuf
            .filter(|x| !x.components()
                        .any(|y| is_unwanted(y, to_ignore))).collect()
    }
    let paths: Vec<std::path::PathBuf> = pats.iter().flat_map(|pat| find_matches(pat, &cfg_ignores)).collect();
    let mut checked_files: u32 = 0;
    let mut had_tabs: u32 = 0;
    let mut had_illegals: u32 = 0;
    for path in paths {
        if !is_dir(path.as_path()) {
            checked_files += 1;
            let r = check_path(path.as_path(), args.flag_clean)
                .ok()
                .expect(&format!("check_path for {:?} should work", path));
            if (r & HAS_TABS) > 0 { had_tabs += 1 }
            if (r & HAS_ILLEGAL_CHARACTERS) > 0 { had_illegals += 1 }
        }
    }
    println!("checked {} files! ({} had tabs, {} had illegal characters)", checked_files, had_tabs, had_illegals);
}

#[cfg(test)]
mod tests {
    use super::clean_string;
    use super::load_config;
    use super::is_unwanted;
    use super::s;
    use glob::Pattern;
    use super::EnforcerCfg;
    use std::ffi::OsStr;
    use std::path::Component::Normal;

    #[test]
    fn test_clean_does_not_remove_trailing_newline() {
        let content = "1\n2\n3\n4\n5\n";
        let cleaned = clean_string(content);
        assert!(cleaned.eq(content));
    }
    #[test]
    fn test_clean_trailing_whitespace() {
        let content = "1 \n2";
        let cleaned = clean_string(content);
        println!("{:?}", cleaned);
        assert!(cleaned.eq("1\n2"));
    }
    #[test]
    fn test_load_simple_config() {
        let c = include_str!("../samples/.enforcer");
        let cfg = load_config(c).unwrap();
        assert_eq!(cfg.ignore.len(), 2);
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert_eq!(expected.ignore, cfg.ignore);
        assert_eq!(expected, cfg);
    }
    #[test]
    fn test_load_broken_config() {
        let c = include_str!("../samples/.enforcer_broken");
        let cfg = load_config(c).unwrap();
        let expected = EnforcerCfg {
            ignore: vec![s(".git"), s(".repo")],
            globs : vec![s("**/*.c"), s("**/*.cpp"), s("**/*.h")],
        };
        assert!(expected.ignore != cfg.ignore);
    }
    #[test]
    fn test_glob() {
        assert!(Pattern::new("build_*").unwrap().matches("build_Debug"));
    }
    #[test]
    fn test_is_unwanted() {
        let cfg = EnforcerCfg { ignore: vec![s("build_*"), s(".git")], globs: vec![]};
        assert!(is_unwanted(Normal(OsStr::new("build_Debug")), &cfg.ignore));
        assert!(is_unwanted(Normal(OsStr::new(".git")), &cfg.ignore));
        assert!(!is_unwanted(Normal(OsStr::new("bla")), &cfg.ignore));
    }
}

<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn main() {
    let filen = "sample/t2.bv";
    let ok = process_file(filen);
    match ok {
        Ok(()) => println!("Ok"),
        Err(e) => println!("{}: {}", filen, e),
    }
}

fn process_file<P: AsRef<Path>>(filename: P) -> io::Result<()> {
    let s = try!(read_file(filename));
    //println!("BvFile");
    let toks = s.lex(false, false);
    //println!("tokens");
    for tok in toks {
        match tok.value {
            BvTokE::QLiteral(q) => println!("QLiteral {}", q),
            BvTokE::Whitespace(w) => println!("Whitespace {}", w.len()),
            BvTokE::Comment(c) => println!("Comment {}", c),
        }
    }
    Ok(())
}

fn read_file<P: AsRef<Path>>(filename: P) -> io::Result<BvFile> {
    let mut fr = try!(File::open(filename));
    let mut s : &mut String = &mut String::with_capacity(29);
    try!(fr.read_to_string(s));
    Ok(BvFile::new(s.to_string()))
}

struct BvFile {
    text: String,
}

// token enum list
enum BvTokE {
    QLiteral(String),  // 'string'
    Whitespace(String), //  space, newline, tab
    Comment(String), // # string\n
}

// full token // todo: add range, source, ...
struct BvToken {
    value: BvTokE,
}

enum LexState {
    White, // [start] whitespace
    Q, // single quote
    Hash, // ###
    Comment, // # text\n
    Error,
}
impl BvFile {
    fn new(s : String) -> BvFile {
        BvFile {
            text: s,
        }
    }
    fn lex(&self, pass_white: bool, pass_comment: bool) -> Vec<BvToken> {
        let mut tokens : Vec<BvToken> = vec![];
        let mut word = String::with_capacity(20);
        let mut n_hash = 0;
        // let mut hash_word = String::with_capacity(20);

        let mut state = LexState::White;
        for c in self.text.chars() {
            match state {
                LexState::White => {
                    // println!("Start {}", c);
                    if c.is_whitespace() {
                        word = word + &c.to_string();
                    }
                    else {
                        if 0 < word.len() {
                            if pass_white {
                                let toke = BvTokE::Whitespace(word.clone());
                                let tok = BvToken { value: toke };
                                tokens.push(tok);
                            }
                            word.truncate(0);
                        }
                        if c == '\'' {
                            state = LexState::Q;
                        } else if c == '#' {
                            n_hash = 1;
                            state = LexState::Hash;
                        } else {
                            state = LexState::Error;
                        }
                    }
                },
                LexState::Q => {
                    // println!("Q {}",c);
                    if c == '\'' {
                        let toke = BvTokE::QLiteral(word.clone());
                        let tok = BvToken { value: toke };
                        tokens.push(tok);
                        word.truncate(0);
                        state = LexState::White;
                    } else if c == '\n' {
                        state = LexState::Error;
                    } else {
                        word = word + &c.to_string();
                    }
                },
                LexState::Hash => {
                    //println!("Hash");
                    if c.is_whitespace() {
                        if c == '\n' { // empty comment
                            if 1 == n_hash {
                                if pass_comment {
                                    let toke = BvTokE::Comment("".to_string());
                                    let tok = BvToken{ value: toke };
                                    tokens.push(tok);
                                }
                                state = LexState::White;
                            } else {
                                // ...
                                state = LexState::Error;
                            }
                        } else {
                            if 1 == n_hash {
                                state = LexState::Comment;
                            } else {
                                // ...
                                state = LexState::Error;
                            }
                        }
                    } else if c == '#' {
                        n_hash += 1;
                    } else if c.is_alphanumeric() {
                        // ...
                        state = LexState::Error;
                    } else if "{([<`'\"|".contains(c) {
                        // ...
                        state = LexState::Error;
                    } else if "+-".contains(c) {
                        // ...
                        state = LexState::Error;
                    } else {
                        // ...
                        state = LexState::Error;
                    }
                },
                LexState::Comment => {
                    //println!("Comment");
                    if c == '\n' {
                        if pass_comment {
                            let toke = BvTokE::Comment(word.clone());
                            let tok = BvToken{ value: toke };
                            tokens.push(tok);
                        }
                        word.truncate(0);
                        state = LexState::White;
                    } else {
                        word = word + &c.to_string();
                    }
                },
                LexState::Error => {
                    println!("Error {}", c)
                    // FIXME: reset at nl
                }
            }
        }

        tokens
    }
}
<commit_msg>Refactored lexing some.  Still needs more work.<commit_after>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

fn main() {
    let filen = "sample/t2.bv";
    let ok = process_file(filen);
    match ok {
        Ok(()) => println!("Ok"),
        Err(e) => println!("{}: {}", filen, e),
    }
}

fn process_file<P: AsRef<Path>>(filename: P) -> io::Result<()> {
    let s = try!(read_file(filename));
    //println!("BvFile");
    let toks = s.lex(false, true);
    //println!("tokens");
    for tok in toks {
        match tok.value {
            BvTokE::QLiteral(q) => println!("QLiteral {}", q),
            BvTokE::Whitespace(w) => println!("Whitespace {}", w.len()),
            BvTokE::Comment(c) => println!("Comment {}", c),
            BvTokE::Error(e) => println!("Error {}", e),
        }
    }
    Ok(())
}

fn read_file<P: AsRef<Path>>(filename: P) -> io::Result<BvFile> {
    let mut fr = try!(File::open(filename));
    let mut s : &mut String = &mut String::with_capacity(29);
    try!(fr.read_to_string(s));
    Ok(BvFile::new(s.to_string()))
}

struct BvFile {
    text: String,
}

// token enum list
enum BvTokE {
    QLiteral(String),  // 'string'
    Whitespace(String), //  space, newline, tab
    Comment(String), // # string\n
    Error(String),
}

// full token // todo: add range, source, ...
struct BvToken {
    value: BvTokE,
}

fn lex_white(first_char: char, chars: &mut std::str::Chars)
    -> (Option<char>, BvTokE) {
    let mut word = String::with_capacity(20);
    word.push(first_char);
    while let Some(c) = chars.next() {
        if c.is_whitespace() {
            word.push(c);
        } else {
            return (Some(c), BvTokE::Whitespace(word));
        }
    }
    (None, BvTokE::Whitespace(word))
}

fn lex_q(chars: &mut std::str::Chars) -> BvTokE {
    let mut word = String::with_capacity(20);
    while let Some(c) = chars.next() {
        if c == '\'' {
            return BvTokE::QLiteral(word);
        } else if c == '\n' {
            return BvTokE::Error("Single quote to end of line".to_string());
        } else {
            word = word + &c.to_string();
        }
    }
    BvTokE::Error("Unreachable end of single quote".to_string())
}
fn lex_hash(chars: &mut std::str::Chars, pass_comment: bool) -> Option<BvTokE> {
    let mut n_hash = 1;
    while let Some(c) = chars.next() {
        if c.is_whitespace() {
            if c == '\n' { // empty comment
                if 1 == n_hash {
                    return if pass_comment {
                        Some(BvTokE::Comment("".to_string()))
                    } else {
                        None
                    };
                } else {
                    // ....
                    return Some(BvTokE::Error("Empty multihash NYI".to_string()))
                }
            } else {
                if 1 == n_hash {
                    let toke = lex_comment_eol(chars);
                    return if pass_comment { Some(toke) } else { None };
                } else {
                    return Some(BvTokE::Error("multihash NYI".to_string()));
                }
            };
        } else if c == '#' {
            n_hash += 1;
        } else if c.is_alphanumeric() {
            return Some(BvTokE::Error("pragma NYI".to_string()));
        } else if "{([<`'\"|".contains(c) {
            return Some(BvTokE::Error("Inline comment NYI".to_string()));
        } else if "+-".contains(c) {
            return Some(BvTokE::Error("On/off pragma NYI".to_string()));
        } else {
            return Some(BvTokE::Error("Bad char after #".to_string()));
        }
    }
    None
}
fn lex_comment_eol(chars: &mut std::str::Chars) -> BvTokE {
    let mut word = String::with_capacity(20);
    while let Some(c) = chars.next() {
        if c == '\n' {
            return BvTokE::Comment(word.clone());
        } else {
            word = word + &c.to_string();
        }
    }
    BvTokE::Error("Comment unreachable".to_string())
}

impl BvFile {
    fn new(s : String) -> BvFile {
        BvFile {
            text: s,
        }
    }

    fn lex(&self, pass_white: bool, pass_comment: bool) -> Vec<BvToken> {
        let mut tokens : Vec<BvToken> = vec![];

        let mut chars = self.text.chars();
        while let Some(sc) = chars.next() {
            let mut c = sc;
            let mut rpt = true;
            while rpt {
                rpt = false;
                if c.is_whitespace() {
                    let (oc, toke) = lex_white(c, &mut chars);
                    if pass_white {
                        let tok = BvToken { value: toke };
                        tokens.push(tok)
                    }
                    match oc {
                        None => {},
                        Some(ac) => {
                            c = ac;
                            rpt = true;
                        },
                    }
                }
                else {
                    if c == '\'' {
                        let toke = lex_q(&mut chars);
                        let tok = BvToken { value: toke };
                        tokens.push(tok);
                    } else if c == '#' {
                        let otoke = lex_hash(&mut chars, pass_comment);
                        match otoke {
                            Some(toke) => {
                                let tok = BvToken { value: toke };
                                tokens.push(tok);
                            },
                            None => {}
                        }
                    } else {
                        // TODO: read to nl
                        let toke = BvTokE::Error("Unknown character - NYI".to_string());
                        let tok = BvToken { value : toke };
                        tokens.push(tok);
                    }
                }
            }
        }

        tokens
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate urlencoded;
extern crate router;
extern crate smtp;
#[macro_use]
extern crate log;

use std::io::Read;
use std::net::TcpStream;
use std::collections::HashMap;
use iron::prelude::*;
use iron::status;
use urlencoded::UrlEncodedQuery;
use urlencoded::UrlEncodedBody;
use urlencoded::QueryMap;
use router::Router;
use smtp::sender::{Sender, SenderBuilder};
use smtp::mailer::EmailBuilder;

fn main() {
    info!("Starting up!");
    println!("Hello");
    let mut router = Router::new();

    // ?first_name=Karen&last_name=Rustad&email=karen%40aerofs.com&phone=952-210-6598&org_name=&org_size=&title=&comment=Testing

    router.get("/", hello_world);
    router.post("/sales", post_email);

    fn hello_world(_: &mut Request) -> IronResult<Response> {
        let payload = "Hi!!!!";
        Ok(Response::with((status::Ok, payload)))
    }

    // fn log_params(req: &mut Request) -> IronResult<Response> {
    //     // Extract the decoded data as hashmap, using the UrlEncodedQuery plugin.
    //     match req.get_ref::<UrlEncodedQuery>() {
    //         Ok(ref hashmap) => println!("Parsed GET request query string:\n {:?}", hashmap),
    //         Err(ref e) => println!("{:?}", e)
    //     };

    //     Ok(Response::with((status::Ok, "Hello!")))
    // }

    // fn log_post_data(req: &mut Request) -> IronResult<Response> {
    //     match req.get_ref::<UrlEncodedBody>() {
    //         Ok(ref hashmap) => println!("Parsed POST request body:\n {:?}", hashmap),
    //         Err(ref e) => println!("{:?}", e)
    //     };

    //     Ok(Response::with((status::Ok, "Hello!")))
    // }

    // Receive a message by POST and play it back.
    fn post_email(request: &mut Request) -> IronResult<Response> {
        let mut payload = String::new();
        let mut email = "form".to_string();

        match request.get_ref::<UrlEncodedQuery>() {
            Ok(ref hashmap) => {
                for (name, value) in hashmap.iter() {
                    payload.push_str(name);
                    payload.push_str(": ");
                    payload.push_str(&value[0]);
                    payload.push_str("\n");
                }
                if (hashmap.contains_key("email")) {
                    email = hashmap["email"][0].clone();
                }
            },
            Err(ref e) => println!("{:?}", e)
        };

        let mut email_builder = EmailBuilder::new();
        email_builder = email_builder.to("karen@aerofs.com");
        let email = email_builder.from("inquiryform@aerofs.com")
                        .body(&payload)
                        .subject(&format!("Inquiry from {}", email))
                        .build();
        let sb = SenderBuilder::new(("devmail.aerofs.com",25)).hello_name("localhost")
                        .enable_connection_reuse(false);

        let mut sender: Sender = sb.build();
        let result = sender.send(email);
        sender.close();

        match result {
            Ok(..) => println!("Email sent successfully"),
            Err(error) => println!("Error: {:?}", error),
        }

        return Ok(Response::with((status::Ok, "")));
    }

    Iron::new(router).http("localhost:3000").unwrap();
}<commit_msg>Moved recipient address to a config variable.<commit_after>extern crate iron;
extern crate urlencoded;
extern crate router;
extern crate smtp;
#[macro_use]
extern crate log;

use std::io::Read;
use std::net::TcpStream;
// use std::collections::HashMap;
use iron::prelude::*;
use iron::status;
use urlencoded::UrlEncodedQuery;
use urlencoded::UrlEncodedBody;
// use urlencoded::QueryMap;
use router::Router;
use smtp::sender::{Sender, SenderBuilder};
use smtp::mailer::EmailBuilder;

fn main() {
    info!("Starting up!");
    println!("Hello");
    let mut router = Router::new();

    // ?first_name=Karen&last_name=Rustad&email=karen%40aerofs.com&phone=952-210-6598&org_name=&org_size=&title=&comment=Testing

    router.get("/", hello_world);
    router.post("/sales", post_email);

    fn hello_world(_: &mut Request) -> IronResult<Response> {
        let payload = "Hi!!!!";
        Ok(Response::with((status::Ok, payload)))
    }

    // Receive a message by POST and play it back.
    fn post_email(request: &mut Request) -> IronResult<Response> {
        let mut payload = String::new();
        let mut email = "form".to_string();

        match request.get_ref::<UrlEncodedQuery>() {
            Ok(ref hashmap) => {
                for (name, value) in hashmap.iter() {
                    payload.push_str(name);
                    payload.push_str(": ");
                    payload.push_str(&value[0]);
                    payload.push_str("\n");
                }
                if hashmap.contains_key("email") {
                    email = hashmap["email"][0].clone();
                }
            },
            Err(ref e) => println!("{:?}", e)
        };

        match request.get_ref::<UrlEncodedBody>() {
            Ok(ref hashmap) => println!("Parsed POST request body:\n {:?}", hashmap),
            Err(ref e) => println!("{:?}", e)
        };

        let mut email_builder = EmailBuilder::new();
        email_builder = email_builder.to("karen@aerofs.com");
        let email = email_builder.from("inquiryform@aerofs.com")
                        .body(&payload)
                        .subject(&format!("Inquiry from {}", email))
                        .build();
        let sb = SenderBuilder::new(("devmail.aerofs.com",25)).hello_name("localhost")
                        .enable_connection_reuse(false);

        let mut sender: Sender = sb.build();
        let result = sender.send(email);
        sender.close();

        match result {
            Ok(..) => println!("Email sent successfully"),
            Err(error) => println!("Error: {:?}", error),
        }

        return Ok(Response::with((status::Ok, "")));
    }

    Iron::new(router).http("localhost:3000").unwrap();
}<|endoftext|>


<commit_before>// main.rs
// Copyright 2016 Alexander Altman
//
// 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.

use std::collections::HashMap;
use std::iter;
use std::io;
use std::io::prelude::*;
use std::fs;
use std::path::PathBuf;
use std::ffi::OsStr;

#[macro_use]
extern crate clap;
use clap::Arg;

extern crate colored;
use colored::*;

extern crate difference_engine;
use difference_engine::*;

fn main() {
  let registered_languages_raw = vec![Box::new(DefaultLanguage) as Box<Language>];
  let registered_languages: HashMap<String, Box<Language>> =
    registered_languages_raw.into_iter().map(|language| (language.name(), language)).collect();

  let arg_matches =
    clap::App::new("DEng, the Difference Engine")
      .version(crate_version!())
      .author("Alexander Altman")
      .about("An extensible language-aware diff")
      .settings(&[clap::AppSettings::ColoredHelp])
      .args(&[Arg::with_name("show languages")
                .long("show-languages")
                .short("L")
                .help("Lists all of the languages currently supported by DEng")
                .conflicts_with_all(&["language name", "old file", "new file"]),
              Arg::with_name("language name")
                .long("language")
                .short("l")
                .help("The language to use when examining the supplied files for differences.{n}If this option isn't provided, DEng \
                       will perform a naïve character-by-character diff.")
                .takes_value(true),
              Arg::with_name("old file")
                .help("The file to consider “old” for the purposes of finding differences.{n}DEng will interpret a ‘-’ here as \
                       standard input.")
                .required(true),
              Arg::with_name("new file")
                .help("The file to consider “new” for the purposes of finding differences.{n}DEng will interpret a ‘-’ here as \
                       standard input.")
                .required(true)])
      .get_matches();

  if arg_matches.is_present("show languages") {
    for language in registered_languages.values() {
      println!("{}: {}", language.name().bold(), language.description());
    }
    return;
  }

  let language_name = arg_matches.value_of("language name").unwrap_or("default");
  let language = registered_languages.get(language_name).expect("could not find language");
  let (old_file, new_file) = resolve_files(arg_matches.value_of_os("old file").unwrap(),
                                           arg_matches.value_of_os("new file").unwrap());

  let diff_result = language.diff(old_file, new_file);
}

fn resolve_files(old_file_arg: &OsStr, new_file_arg: &OsStr) -> (String, String) {
  let old_file_path = handle_stdin_notation(old_file_arg).map(canonicalize_path);
  let new_file_path = handle_stdin_notation(new_file_arg).map(canonicalize_path);
  let old_file = old_file_path.clone()
                              .map(|path| read_whole_file(fs::File::open(path).expect("error opening file")))
                              .unwrap_or_else(|| read_whole_file(io::stdin()));
  let new_file;
  if old_file_path == new_file_path.clone() {
    new_file = old_file.clone();
  } else {
    new_file = new_file_path.map(|path| read_whole_file(fs::File::open(path).expect("error opening file")))
                            .unwrap_or_else(|| read_whole_file(io::stdin()));
  }
  return (old_file, new_file);
}

fn handle_stdin_notation(arg: &OsStr) -> Option<&OsStr> {
  if arg == "-" {
    return None;
  } else {
    return Some(arg);
  }
}

fn canonicalize_path(path: &OsStr) -> PathBuf { fs::canonicalize(path).expect("error locating file") }

fn read_whole_file<F: Read>(mut file: F) -> String {
  let mut result = String::new();
  file.read_to_string(&mut result).expect("error reading file");
  return result;
}
<commit_msg>It works!  (Sort of.)<commit_after>// main.rs
// Copyright 2016 Alexander Altman
//
// 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.

use std::collections::HashMap;
use std::io;
use std::io::prelude::*;
use std::fs;
use std::path::PathBuf;
use std::ffi::OsStr;

#[macro_use]
extern crate clap;
use clap::Arg;

extern crate colored;
use colored::*;

extern crate difference_engine;
use difference_engine::*;
use difference_engine::Provenance::*;

fn main() {
  let registered_languages_raw = vec![Box::new(DefaultLanguage) as Box<Language>];
  let registered_languages: HashMap<String, Box<Language>> =
    registered_languages_raw.into_iter().map(|language| (language.name(), language)).collect();

  let arg_matches =
    clap::App::new("DEng, the Difference Engine")
      .version(crate_version!())
      .author("Alexander Altman")
      .about("An extensible language-aware diff")
      .settings(&[clap::AppSettings::ColoredHelp])
      .args(&[Arg::with_name("show languages")
                .long("show-languages")
                .short("L")
                .help("Lists all of the languages currently supported by DEng")
                .conflicts_with_all(&["language name", "old file", "new file"]),
              Arg::with_name("language name")
                .long("language")
                .short("l")
                .help("The language to use when examining the supplied files for differences.{n}If this option isn't provided, DEng \
                       will perform a naïve character-by-character diff.")
                .takes_value(true),
              Arg::with_name("old file")
                .help("The file to consider “old” for the purposes of finding differences.{n}DEng will interpret a ‘-’ here as \
                       standard input.")
                .required(true),
              Arg::with_name("new file")
                .help("The file to consider “new” for the purposes of finding differences.{n}DEng will interpret a ‘-’ here as \
                       standard input.")
                .required(true)])
      .get_matches();

  if arg_matches.is_present("show languages") {
    for language in registered_languages.values() {
      println!("{}: {}", language.name().bold(), language.description());
    }
    return;
  }

  let language_name = arg_matches.value_of("language name").unwrap_or("default");
  let language = registered_languages.get(language_name).expect("could not find language");
  let (old_file, new_file) = resolve_files(arg_matches.value_of_os("old file").unwrap(),
                                           arg_matches.value_of_os("new file").unwrap());

  for (x, sx) in language.diff(old_file, new_file) {
    print!("{}",
           match sx {
             Old => x.red(),
             Shared => x.as_str().into(),
             New => x.green(),
           });
    io::stdout().flush().expect("error when attempting to flush standard ouput");
  }
}

fn resolve_files(old_file_arg: &OsStr, new_file_arg: &OsStr) -> (String, String) {
  let old_file_path = handle_stdin_notation(old_file_arg).map(canonicalize_path);
  let new_file_path = handle_stdin_notation(new_file_arg).map(canonicalize_path);
  let old_file = old_file_path.clone()
                              .map(|path| read_whole_file(fs::File::open(path).expect("error opening file")))
                              .unwrap_or_else(|| read_whole_file(io::stdin()));
  let new_file;
  if old_file_path == new_file_path.clone() {
    new_file = old_file.clone();
  } else {
    new_file = new_file_path.map(|path| read_whole_file(fs::File::open(path).expect("error opening file")))
                            .unwrap_or_else(|| read_whole_file(io::stdin()));
  }
  return (old_file, new_file);
}

fn handle_stdin_notation(arg: &OsStr) -> Option<&OsStr> {
  if arg == "-" {
    return None;
  } else {
    return Some(arg);
  }
}

fn canonicalize_path(path: &OsStr) -> PathBuf { fs::canonicalize(path).expect("error locating file") }

fn read_whole_file<F: Read>(mut file: F) -> String {
  let mut result = String::new();
  file.read_to_string(&mut result).expect("error reading file");
  return result;
}
<|endoftext|>