<commit_before>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Remote, Workspace};
use core::url::build_url;
use util::{self, process};
use vcs::{self, Vcs};

/// Toplevel application
pub enum Command<'a> {
  Add(AddCommand<'a>),
  Refresh(RefreshCommand<'a>),
  New(NewCommand<'a>),
  Clone(CloneCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(RefreshCommand::make_app(SubCommand::with_name("refresh")))
       .subcommand(NewCommand::make_app(SubCommand::with_name("new")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("add", Some(m)) => Command::Add(m.into()),
      ("refresh", Some(m)) => Command::Refresh(m.into()),
      ("new", Some(m)) => Command::New(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Refresh(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::New(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
    }
  }
}

/// subcommand `add`
pub struct AddCommand<'a> {
  path: Option<Vec<&'a Path>>,
  verbose: bool,
  import: bool,
  depth: Option<usize>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repositories into management")
       .arg_from_usage("[path]...       'Location of local repositories'")
       .arg_from_usage("-v, --verbose   'Use verbose output'")
       .arg_from_usage("-i, --import    'Use import mode'")
       .arg_from_usage("--depth=[depth] 'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand {
      path: m.values_of("path").map(|s| s.map(Path::new).collect()),
      verbose: m.is_present("verbose"),
      import: m.is_present("import"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    if self.import {
      if let Some(roots) = self.path {
        for root in roots {
          workspace.scan_repositories(root, self.verbose, self.depth)?;
        }
      } else {
        workspace.scan_repositories_default(self.verbose, self.depth)?;
      }
    } else {
      let paths: Vec<Cow<Path>> = if let Some(ref path) =
        self.path {
        path.into_iter().map(|&path| path.into()).collect()
      } else {
        vec![env::current_dir()?.into()]
      };
      for path in paths {
        if vcs::detect_from_path(&path).is_none() {
          println!("Ignored: {} is not a repository", path.display());
          continue;
        }
        if self.verbose {
          println!("Added: {}", util::canonicalize_pretty(&path)?.display());
        }
        let repo = Repository::from_path(path)?;
        workspace.add_repository(repo, false);
      }
    }

    workspace.save_cache()?;
    Ok(())
  }
}

/// Subommand `refresh`
pub struct RefreshCommand<'a> {
  verbose: bool,
  sort: bool,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for RefreshCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan repository list and drop if it is not existed or matches exclude pattern.")
       .arg_from_usage("-v, --verbose 'Use verbose output'")
       .arg_from_usage("-s, --sort    'Sort by path string'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for RefreshCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> RefreshCommand<'a> {
    RefreshCommand {
      verbose: m.is_present("verbose"),
      sort: m.is_present("sort"),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for RefreshCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.drop_invalid_repositories(self.verbose);
    if self.sort {
      workspace.sort_repositories();
    }
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `new`
pub struct NewCommand<'a> {
  path: &'a str,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
  dry_run: bool,
}

impl<'a> ClapApp for NewCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new repository and add it into management")
       .arg_from_usage("<path>                'Path of target repository, or URL-like pattern'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
       .arg_from_usage("-n, --dry-run         'Do not actually perform commands'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for NewCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> NewCommand<'a> {
    NewCommand {
      path: m.value_of("path").unwrap(),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for NewCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    let path: Cow<Path> = if let Ok(query) = self.path.parse::<Query>() {
      let host = query.host().unwrap_or("github.com");
      let path = query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    } else {
      Path::new(self.path).into()
    };
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    let posthook = self.posthook.and_then(|s| shlex::split(s));

    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();

    if !self.dry_run {
      vcs.do_init(&path)?;
      if let Some(posthook) = posthook {
        if posthook.len() >= 1 {
          let command = posthook[0].clone();
          let args: Vec<_> = posthook.into_iter().skip(1).collect();
          process::inherit(&command).args(args)
            .current_dir(&path)
            .status()?;
        }
      }
      let repo = Repository::from_path(path)?;
      workspace.add_repository(repo, false);

      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  dest: Option<&'a Path>,
  root: Option<&'a Path>,
  ssh: bool,
  arg: Option<&'a str>,
  vcs: Option<Vcs>,
  dry_run: bool,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories, and then add it under management")
       .arg_from_usage("<query>         'an URL or a string to determine the URL of remote repository'")
       .arg_from_usage("[dest]          'Destination directory of cloned repository'")
       .arg_from_usage("--root=[root]   'Path to determine the destination directory of cloned repository'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for VCS command'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
       .arg_from_usage("-n, --dry-run   'Do not actually execute VCS command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      dest: m.value_of("dest").map(Path::new),
      root: m.value_of("root").map(Path::new),
      ssh: m.is_present("ssh"),
      arg: m.value_of("arg"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest: Cow<Path> = if let Some(dest) = self.dest {
      dest.into()
    } else {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone from {} into {} by using {:?} (with arguments: {})",
             url,
             dest.display(),
             vcs,
             util::join_str(&args),
    );

    if !self.dry_run {
      vcs.do_clone(&dest, &url, &args)?;
      let remote = Remote::new(url);
      let repo = Repository::from_path_with_remote(dest, remote)?;
      workspace.add_repository(repo, false);

      workspace.save_cache()?;
    }

    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<commit_msg>remove option '--dry-run' from 'rhq new' and 'rhq clone'<commit_after>use std::borrow::{Borrow, Cow};
use std::env;
use std::marker::PhantomData;
use std::path::Path;
use clap::{self, Arg, SubCommand};
use shlex;

use app::{ClapApp, ClapRun};
use core::{Query, Repository, Remote, Workspace};
use core::url::build_url;
use util;
use vcs::{self, Vcs};

/// Toplevel application
pub enum Command<'a> {
  Add(AddCommand<'a>),
  Refresh(RefreshCommand<'a>),
  New(NewCommand<'a>),
  Clone(CloneCommand<'a>),
  List(ListCommand<'a>),
  Foreach(ForeachCommand<'a>),
}

impl<'a> ClapApp for Command<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.subcommand(AddCommand::make_app(SubCommand::with_name("add")))
       .subcommand(RefreshCommand::make_app(SubCommand::with_name("refresh")))
       .subcommand(NewCommand::make_app(SubCommand::with_name("new")))
       .subcommand(CloneCommand::make_app(SubCommand::with_name("clone")))
       .subcommand(ListCommand::make_app(SubCommand::with_name("list")))
       .subcommand(ForeachCommand::make_app(SubCommand::with_name("foreach")))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for Command<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> Command<'a> {
    match m.subcommand() {
      ("add", Some(m)) => Command::Add(m.into()),
      ("refresh", Some(m)) => Command::Refresh(m.into()),
      ("new", Some(m)) => Command::New(m.into()),
      ("clone", Some(m)) => Command::Clone(m.into()),
      ("list", Some(m)) => Command::List(m.into()),
      ("foreach", Some(m)) => Command::Foreach(m.into()),
      _ => unreachable!(),
    }
  }
}

impl<'a> Command<'a> {
  pub fn run(self) -> ::Result<()> {
    match self {
      Command::Refresh(m) => m.run(),
      Command::Add(m) => m.run(),
      Command::New(m) => m.run(),
      Command::Clone(m) => m.run(),
      Command::List(m) => m.run(),
      Command::Foreach(m) => m.run(),
    }
  }
}

/// subcommand `add`
pub struct AddCommand<'a> {
  path: Option<Vec<&'a Path>>,
  verbose: bool,
  import: bool,
  depth: Option<usize>,
}

impl<'a> ClapApp for AddCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Add existed repositories into management")
       .arg_from_usage("[path]...       'Location of local repositories'")
       .arg_from_usage("-v, --verbose   'Use verbose output'")
       .arg_from_usage("-i, --import    'Use import mode'")
       .arg_from_usage("--depth=[depth] 'Maximal depth of entries for each base directory'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for AddCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> AddCommand<'a> {
    AddCommand {
      path: m.values_of("path").map(|s| s.map(Path::new).collect()),
      verbose: m.is_present("verbose"),
      import: m.is_present("import"),
      depth: m.value_of("depth").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for AddCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    if self.import {
      if let Some(roots) = self.path {
        for root in roots {
          workspace.scan_repositories(root, self.verbose, self.depth)?;
        }
      } else {
        workspace.scan_repositories_default(self.verbose, self.depth)?;
      }
    } else {
      let paths: Vec<Cow<Path>> = if let Some(ref path) =
        self.path {
        path.into_iter().map(|&path| path.into()).collect()
      } else {
        vec![env::current_dir()?.into()]
      };
      for path in paths {
        if vcs::detect_from_path(&path).is_none() {
          println!("Ignored: {} is not a repository", path.display());
          continue;
        }
        if self.verbose {
          println!("Added: {}", util::canonicalize_pretty(&path)?.display());
        }
        let repo = Repository::from_path(path)?;
        workspace.add_repository(repo, false);
      }
    }

    workspace.save_cache()?;
    Ok(())
  }
}

/// Subommand `refresh`
pub struct RefreshCommand<'a> {
  verbose: bool,
  sort: bool,
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for RefreshCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Scan repository list and drop if it is not existed or matches exclude pattern.")
       .arg_from_usage("-v, --verbose 'Use verbose output'")
       .arg_from_usage("-s, --sort    'Sort by path string'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for RefreshCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> RefreshCommand<'a> {
    RefreshCommand {
      verbose: m.is_present("verbose"),
      sort: m.is_present("sort"),
      marker: PhantomData,
    }
  }
}

impl<'a> ClapRun for RefreshCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;
    workspace.drop_invalid_repositories(self.verbose);
    if self.sort {
      workspace.sort_repositories();
    }
    workspace.save_cache()?;
    Ok(())
  }
}

/// Subcommand `new`
pub struct NewCommand<'a> {
  path: &'a str,
  vcs: Option<Vcs>,
  posthook: Option<&'a str>,
}

impl<'a> ClapApp for NewCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Create a new repository and add it into management")
       .arg_from_usage("<path>                'Path of target repository, or URL-like pattern'")
       .arg(Arg::from_usage("--vcs=[vcs]      'Used Version Control System'")
              .possible_values(Vcs::possible_values()))
       .arg_from_usage("--posthook=[posthook] 'Post hook after initialization'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for NewCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> NewCommand<'a> {
    NewCommand {
      path: m.value_of("path").unwrap(),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
      posthook: m.value_of("posthook"),
    }
  }
}

impl<'a> ClapRun for NewCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(None)?;

    let posthook = self.posthook.and_then(|s| shlex::split(s));
    let vcs = self.vcs.unwrap_or(Vcs::Git);
    let path: Cow<Path> = if let Ok(query) = self.path.parse::<Query>() {
      let host = query.host().unwrap_or("github.com");
      let path = query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    } else {
      Path::new(self.path).into()
    };

    // init
    if vcs::detect_from_path(&path).is_some() {
      println!("The repository {} has already existed.", path.display());
      return Ok(());
    }
    print!("Creating an empty repository at \"{}\"", path.display());
    print!(" (VCS: {:?})", vcs);
    println!();
    vcs.do_init(&path)?;
    let repo: Repository = Repository::from_path(path)?;

    // hook
    if let Some(posthook) = posthook {
      if posthook.len() >= 1 {
        repo.run_command(&posthook[0], &posthook[1..])?;
      }
    }

    workspace.add_repository(repo, false);
    workspace.save_cache()?;

    Ok(())
  }
}

/// Subcommand `clone`
pub struct CloneCommand<'a> {
  query: Query,
  dest: Option<&'a Path>,
  root: Option<&'a Path>,
  ssh: bool,
  arg: Option<&'a str>,
  vcs: Option<Vcs>,
}

impl<'a> ClapApp for CloneCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Clone remote repositories, and then add it under management")
       .arg_from_usage("<query>         'an URL or a string to determine the URL of remote repository'")
       .arg_from_usage("[dest]          'Destination directory of cloned repository'")
       .arg_from_usage("--root=[root]   'Path to determine the destination directory of cloned repository'")
       .arg_from_usage("-s, --ssh       'Use SSH protocol'")
       .arg_from_usage("--arg=[arg]     'Supplemental arguments for VCS command'")
       .arg(Arg::from_usage("--vcs=[vcs] 'Used Version Control System'").possible_values(Vcs::possible_values()))
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for CloneCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> CloneCommand<'a> {
    CloneCommand {
      query: m.value_of("query")
              .and_then(|s| s.parse().ok())
              .unwrap(),
      dest: m.value_of("dest").map(Path::new),
      root: m.value_of("root").map(Path::new),
      ssh: m.is_present("ssh"),
      arg: m.value_of("arg"),
      vcs: m.value_of("vcs").and_then(|s| s.parse().ok()),
    }
  }
}

impl<'a> ClapRun for CloneCommand<'a> {
  fn run(self) -> ::Result<()> {
    let mut workspace = Workspace::new(self.root)?;

    let dest: Cow<Path> = if let Some(dest) = self.dest {
      dest.into()
    } else {
      let host = self.query.host().unwrap_or("github.com");
      let path = self.query.path();
      workspace.root_dir()
               .ok_or("Unknown root directory")?
               .join(host)
               .join(path.borrow() as &str)
               .into()
    };
    if vcs::detect_from_path(&dest).is_some() {
      println!("The repository {} has already existed.", dest.display());
      return Ok(());
    }

    let url = build_url(&self.query, self.ssh)?;

    let args = self.arg
                   .and_then(|s| shlex::split(s))
                   .unwrap_or_default();

    let vcs = self.vcs.unwrap_or(Vcs::Git);

    println!("Clone from {} into {} by using {:?} (with arguments: {})",
             url,
             dest.display(),
             vcs,
             util::join_str(&args),
    );
    vcs.do_clone(&dest, &url, &args)?;
    let remote = Remote::new(url);
    let repo = Repository::from_path_with_remote(dest, remote)?;

    workspace.add_repository(repo, false);

    workspace.save_cache()?;

    Ok(())
  }
}

/// Subcommand `list`
pub struct ListCommand<'a> {
  marker: PhantomData<&'a usize>,
}

impl<'a> ClapApp for ListCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("List local repositories managed by rhq")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ListCommand<'a> {
  fn from(_: &'b clap::ArgMatches<'a>) -> ListCommand<'a> {
    ListCommand { marker: PhantomData }
  }
}

impl<'a> ClapRun for ListCommand<'a> {
  fn run(self) -> ::Result<()> {
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      println!("{}", repo.path_string());
    }
    Ok(())
  }
}

/// Subcommand `foreach`
pub struct ForeachCommand<'a> {
  command: &'a str,
  args: Option<clap::Values<'a>>,
  dry_run: bool,
}

impl<'a> ClapApp for ForeachCommand<'a> {
  fn make_app<'b, 'c: 'b>(app: clap::App<'b, 'c>) -> clap::App<'b, 'c> {
    app.about("Execute command into each repositories")
       .arg_from_usage("<command>       'Command name'")
       .arg_from_usage("[args]...       'Arguments of command'")
       .arg_from_usage("-n, --dry-run   'Do not actually execute command'")
  }
}

impl<'a, 'b: 'a> From<&'b clap::ArgMatches<'a>> for ForeachCommand<'a> {
  fn from(m: &'b clap::ArgMatches<'a>) -> ForeachCommand<'a> {
    ForeachCommand {
      command: m.value_of("command").unwrap(),
      args: m.values_of("args"),
      dry_run: m.is_present("dry-run"),
    }
  }
}

impl<'a> ClapRun for ForeachCommand<'a> {
  fn run(self) -> ::Result<()> {
    let args: Vec<_> = self.args.map(|s| s.collect()).unwrap_or_default();
    let workspace = Workspace::new(None)?;
    let repos = workspace.repositories()
                         .ok_or("The cache has not initialized yet")?;
    for repo in repos {
      if self.dry_run {
        println!("+ {} {}", self.command, util::join_str(&args));
      } else {
        repo.run_command(self.command, &args)?;
      }
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>pub struct Runner;

impl Runner {
    pub fn run() {
        println!("Hello rustie");
    }
}
<commit_msg>basic Runner::run() implementation<commit_after>pub struct Runner;

impl Runner {
    pub fn run(path: &str) {
        println!("Generating site in {}", path);

        let documents = Runner::parse_documents(path.to_string() + "/_posts");
    }

    fn parse_documents(document_path: &str) {
        println!("{}", document_path);
    }
}
<|endoftext|>


<commit_before>use {FswEventFlag, FswFilterType, FswMonitorType};
use libc::{c_int, c_uint, c_void, c_double, c_char, time_t};

#[link(name = "fswatch")]
extern "C" {
  pub fn fsw_init_library() -> FSW_STATUS;

  pub fn fsw_init_session(monitor_type: FswMonitorType) -> FSW_HANDLE;

  pub fn fsw_add_path(handle: FSW_HANDLE, path: *const c_char) -> FSW_STATUS;

  pub fn fsw_add_property(handle: FSW_HANDLE, name: *const c_char, value: *const c_char) -> FSW_STATUS;

  pub fn fsw_set_allow_overflow(handle: FSW_HANDLE, allow_overflow: bool) -> FSW_STATUS;

  pub fn fsw_set_callback(handle: FSW_HANDLE, callback: FSW_CEVENT_CALLBACK, data: *const c_void) -> FSW_STATUS;

  pub fn fsw_set_latency(handle: FSW_HANDLE, latency: c_double) -> FSW_STATUS;

  pub fn fsw_set_recursive(handle: FSW_HANDLE, recursive: bool) -> FSW_STATUS;

  pub fn fsw_set_directory_only(handle: FSW_HANDLE, directory_only: bool) -> FSW_STATUS;

  pub fn fsw_set_follow_symlinks(handle: FSW_HANDLE, follow_symlinks: bool) -> FSW_STATUS;

  pub fn fsw_add_event_type_filter(handle: FSW_HANDLE, event_type: fsw_event_type_filter) -> FSW_STATUS;

  pub fn fsw_add_filter(handle: FSW_HANDLE, filter: fsw_cmonitor_filter) -> FSW_STATUS;

  pub fn fsw_start_monitor(handle: FSW_HANDLE) -> FSW_STATUS;

  pub fn fsw_destroy_session(handle: FSW_HANDLE) -> FSW_STATUS;

  pub fn fsw_last_error() -> FSW_STATUS;

  pub fn fsw_is_verbose() -> bool;

  pub fn fsw_set_verbose(verbose: bool);
}

pub type FSW_STATUS = c_int;
// type FSW_HANDLE = c_uint;
// Fun story here. FSW_HANDLE is defined as an unsigned int, but it can return a signed int,
// FSW_INVALID_HANDLE, which is -1. So, we're calling FSW_HANDLE c_int, not c_unit.
pub type FSW_HANDLE = c_int;
pub type FSW_CEVENT_CALLBACK = extern fn(events: *const fsw_cevent, event_num: c_uint, data: *mut c_void);

pub const FSW_INVALID_HANDLE: FSW_HANDLE = -1;

pub const FSW_OK: FSW_STATUS = 0;
pub const FSW_ERR_UNKNOWN_ERROR: FSW_STATUS = (1 << 0);
pub const FSW_ERR_SESSION_UNKNOWN: FSW_STATUS = (1 << 1);
pub const FSW_ERR_MONITOR_ALREADY_EXISTS: FSW_STATUS = (1 << 2);
pub const FSW_ERR_MEMORY: FSW_STATUS = (1 << 3);
pub const FSW_ERR_UNKNOWN_MONITOR_TYPE: FSW_STATUS = (1 << 4);
pub const FSW_ERR_CALLBACK_NOT_SET: FSW_STATUS = (1 << 5);
pub const FSW_ERR_PATHS_NOT_SET: FSW_STATUS = (1 << 6);
pub const FSW_ERR_MISSING_CONTEXT: FSW_STATUS = (1 << 7);
pub const FSW_ERR_INVALID_PATH: FSW_STATUS = (1 << 8);
pub const FSW_ERR_INVALID_CALLBACK: FSW_STATUS = (1 << 9);
pub const FSW_ERR_INVALID_LATENCY: FSW_STATUS = (1 << 10);
pub const FSW_ERR_INVALID_REGEX: FSW_STATUS = (1 << 11);
pub const FSW_ERR_MONITOR_ALREADY_RUNNING: FSW_STATUS = (1 << 12);
pub const FSW_ERR_UNKNOWN_VALUE: FSW_STATUS = (1 << 13);
pub const FSW_ERR_INVALID_PROPERTY: FSW_STATUS = (1 << 14);

#[derive(Debug)]
#[repr(C)]
pub struct fsw_event_type_filter {
  pub flag: FswEventFlag
}

#[derive(Debug)]
#[repr(C)]
pub struct fsw_cmonitor_filter {
  pub text: *const c_char,
  pub filter_type: FswFilterType,
  pub case_sensitive: bool,
  pub extended: bool
}

#[derive(Debug)]
#[repr(C)]
pub struct fsw_cevent {
  pub path: *const c_char,
  pub evt_time: time_t,
  pub flags: *const FswEventFlag,
  pub flags_num: c_uint
}
<commit_msg>docs: fix typo<commit_after>use {FswEventFlag, FswFilterType, FswMonitorType};
use libc::{c_int, c_uint, c_void, c_double, c_char, time_t};

#[link(name = "fswatch")]
extern "C" {
  pub fn fsw_init_library() -> FSW_STATUS;

  pub fn fsw_init_session(monitor_type: FswMonitorType) -> FSW_HANDLE;

  pub fn fsw_add_path(handle: FSW_HANDLE, path: *const c_char) -> FSW_STATUS;

  pub fn fsw_add_property(handle: FSW_HANDLE, name: *const c_char, value: *const c_char) -> FSW_STATUS;

  pub fn fsw_set_allow_overflow(handle: FSW_HANDLE, allow_overflow: bool) -> FSW_STATUS;

  pub fn fsw_set_callback(handle: FSW_HANDLE, callback: FSW_CEVENT_CALLBACK, data: *const c_void) -> FSW_STATUS;

  pub fn fsw_set_latency(handle: FSW_HANDLE, latency: c_double) -> FSW_STATUS;

  pub fn fsw_set_recursive(handle: FSW_HANDLE, recursive: bool) -> FSW_STATUS;

  pub fn fsw_set_directory_only(handle: FSW_HANDLE, directory_only: bool) -> FSW_STATUS;

  pub fn fsw_set_follow_symlinks(handle: FSW_HANDLE, follow_symlinks: bool) -> FSW_STATUS;

  pub fn fsw_add_event_type_filter(handle: FSW_HANDLE, event_type: fsw_event_type_filter) -> FSW_STATUS;

  pub fn fsw_add_filter(handle: FSW_HANDLE, filter: fsw_cmonitor_filter) -> FSW_STATUS;

  pub fn fsw_start_monitor(handle: FSW_HANDLE) -> FSW_STATUS;

  pub fn fsw_destroy_session(handle: FSW_HANDLE) -> FSW_STATUS;

  pub fn fsw_last_error() -> FSW_STATUS;

  pub fn fsw_is_verbose() -> bool;

  pub fn fsw_set_verbose(verbose: bool);
}

pub type FSW_STATUS = c_int;
// type FSW_HANDLE = c_uint;
// Fun story here. FSW_HANDLE is defined as an unsigned int, but it can return a signed int,
// FSW_INVALID_HANDLE, which is -1. So, we're calling FSW_HANDLE c_int, not c_uint.
pub type FSW_HANDLE = c_int;
pub type FSW_CEVENT_CALLBACK = extern fn(events: *const fsw_cevent, event_num: c_uint, data: *mut c_void);

pub const FSW_INVALID_HANDLE: FSW_HANDLE = -1;

pub const FSW_OK: FSW_STATUS = 0;
pub const FSW_ERR_UNKNOWN_ERROR: FSW_STATUS = (1 << 0);
pub const FSW_ERR_SESSION_UNKNOWN: FSW_STATUS = (1 << 1);
pub const FSW_ERR_MONITOR_ALREADY_EXISTS: FSW_STATUS = (1 << 2);
pub const FSW_ERR_MEMORY: FSW_STATUS = (1 << 3);
pub const FSW_ERR_UNKNOWN_MONITOR_TYPE: FSW_STATUS = (1 << 4);
pub const FSW_ERR_CALLBACK_NOT_SET: FSW_STATUS = (1 << 5);
pub const FSW_ERR_PATHS_NOT_SET: FSW_STATUS = (1 << 6);
pub const FSW_ERR_MISSING_CONTEXT: FSW_STATUS = (1 << 7);
pub const FSW_ERR_INVALID_PATH: FSW_STATUS = (1 << 8);
pub const FSW_ERR_INVALID_CALLBACK: FSW_STATUS = (1 << 9);
pub const FSW_ERR_INVALID_LATENCY: FSW_STATUS = (1 << 10);
pub const FSW_ERR_INVALID_REGEX: FSW_STATUS = (1 << 11);
pub const FSW_ERR_MONITOR_ALREADY_RUNNING: FSW_STATUS = (1 << 12);
pub const FSW_ERR_UNKNOWN_VALUE: FSW_STATUS = (1 << 13);
pub const FSW_ERR_INVALID_PROPERTY: FSW_STATUS = (1 << 14);

#[derive(Debug)]
#[repr(C)]
pub struct fsw_event_type_filter {
  pub flag: FswEventFlag
}

#[derive(Debug)]
#[repr(C)]
pub struct fsw_cmonitor_filter {
  pub text: *const c_char,
  pub filter_type: FswFilterType,
  pub case_sensitive: bool,
  pub extended: bool
}

#[derive(Debug)]
#[repr(C)]
pub struct fsw_cevent {
  pub path: *const c_char,
  pub evt_time: time_t,
  pub flags: *const FswEventFlag,
  pub flags_num: c_uint
}
<|endoftext|>


<commit_before>use libc::{c_int, c_char};

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
}
<commit_msg>Added some constants from libcpuid_constants.h<commit_after>use libc::{c_int, c_char};

pub static MAX_CPUID_LEVEL: uint = 32u;
pub static MAX_EXT_CPUID_LEVEL: uint = 32u;
pub static MAX_INTELFN4_LEVEL: uint = 4u;
pub static MAX_INTELFN11_LEVEL: uint = 4u;

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
}
<|endoftext|>


<commit_before>use std::io;
use std::ptr;
use std::sync::mpsc::{channel, Sender, Receiver, TryIter};
use std::thread;

use super::iokit::*;
use core_foundation_sys::base::*;
use core_foundation_sys::runloop::*;
use runloop::RunLoop;

extern crate libc;
use libc::c_void;

extern crate mach;
use mach::kern_return::KERN_SUCCESS;

pub struct IOHIDDeviceID {
    pub device_id: u64 // TODO: Does this work on non-64-bit systems?
}

impl IOHIDDeviceID {
    pub fn from_ref(device_ref: IOHIDDeviceRef) -> IOHIDDeviceID {
        IOHIDDeviceID{ device_id: device_ref as u64 }
    }

    pub fn as_ref(&self) -> IOHIDDeviceRef {
        self.device_id as IOHIDDeviceRef
    }
}

pub enum Event {
    Add { device_id: IOHIDDeviceID },
    Remove { device_id: IOHIDDeviceID },
}

pub struct Monitor {
    // Receive events from the thread.
    rx: Receiver<Event>,
    // Handle to the thread loop.
    thread: RunLoop
}

impl Monitor {
    pub fn new() -> io::Result<Self> {
        let (tx, rx) = channel();

        let thread = RunLoop::new(move |alive| {
            let (removal_tx, removal_rx) = channel::<IOHIDDeviceRef>();
            let (added_tx, added_rx) = channel::<IOHIDDeviceRef>();

            let hid_manager = unsafe {
                let hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
                IOHIDManagerSetDeviceMatching(hid_manager, ptr::null());
                if IOHIDManagerOpen(hid_manager, kIOHIDManagerOptionNone) != KERN_SUCCESS {
                    panic!("Couldn't open a HID Manager");
                }
                hid_manager
            };

            let boxed_added_tx = Box::new(added_tx);
            let added_tx_ptr = Box::into_raw(boxed_added_tx) as *mut libc::c_void;
            let boxed_removal_tx = Box::new(removal_tx);
            let removal_tx_ptr = Box::into_raw(boxed_removal_tx) as *mut libc::c_void;

            unsafe {
                IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, device_register_cb, removal_tx_ptr);
                IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, device_register_cb, added_tx_ptr);
                IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
            }

            // Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input reports into the
            // various call
            while alive() {
                println!("Run loop running, handle={:?}", thread::current());

                for device_ref in added_rx.try_iter() {
                    tx.send(Event::Add { device_id: IOHIDDeviceID::from_ref(device_ref) });
                }
                for device_ref in removal_rx.try_iter() {
                    tx.send(Event::Remove { device_id: IOHIDDeviceID::from_ref(device_ref) });
                }

                #[allow(non_upper_case_globals)]
                match unsafe { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, 0) } {
                    kCFRunLoopRunStopped => {
                        println!("Device stopped.");
                        // TODO: drop the removal_tx_ptr
                        break;
                    },
                    _ => {},
                }
            }

            if unsafe { IOHIDManagerClose(hid_manager, kIOHIDManagerOptionNone) } != KERN_SUCCESS {
                panic!("Couldn't close the HID Manager");
            }

            Ok(())
        }, 0 /* no timeout */)?;

        Ok(Self { rx, thread })
    }

    pub fn events<'a>(&'a self) -> TryIter<'a, Event> {
        self.rx.try_iter()
    }

    // This might block.
    pub fn stop(&mut self) {
        self.thread.cancel();
    }
}

// This is called from the RunLoop thread
extern "C" fn device_register_cb(context: *mut c_void,
                                 result: IOReturn,
                                 _: *mut c_void,
                                 device: IOHIDDeviceRef) {
    unsafe {
        let tx: &mut Sender<IOHIDDeviceRef> = &mut *(context as *mut Sender<IOHIDDeviceRef>);

        // context contains a Device which we populate as the out variable
        // let device: &mut Device = &mut *(context as *mut Device);

        // let device_ref = void_ref as IOHIDDeviceRef;
        println!("{:?} device_register_cb context={:?} result={:?} device_ref={:?}",
                 thread::current(), context, result, device);

        if let Err(e) = tx.send(device) {
            // TOOD: This happens when the channel closes before this thread
            // does. This is pretty common, but let's deal with stopping
            // properly later.
            println!("Problem returning device_register_cb data for thread: {}", e);
        };
    }
}
<commit_msg>Small cleanup for the macOS device monitor<commit_after>use std::io;
use std::ptr;
use std::sync::mpsc::{channel, Sender, Receiver, TryIter};
use std::thread;

use super::iokit::*;
use core_foundation_sys::base::*;
use core_foundation_sys::runloop::*;
use runloop::RunLoop;

extern crate libc;
use libc::c_void;

extern crate mach;
use mach::kern_return::KERN_SUCCESS;

pub struct IOHIDDeviceID {
    pub device_id: u64 // TODO: Does this work on non-64-bit systems?
}

impl IOHIDDeviceID {
    pub fn from_ref(device_ref: IOHIDDeviceRef) -> IOHIDDeviceID {
        IOHIDDeviceID{ device_id: device_ref as u64 }
    }

    pub fn as_ref(&self) -> IOHIDDeviceRef {
        self.device_id as IOHIDDeviceRef
    }
}

pub enum Event {
    Add { device_id: IOHIDDeviceID },
    Remove { device_id: IOHIDDeviceID },
}

pub struct Monitor {
    // Receive events from the thread.
    rx: Receiver<Event>,
    // Handle to the thread loop.
    thread: RunLoop
}

impl Monitor {
    pub fn new() -> io::Result<Self> {
        let (tx, rx) = channel();

        let thread = RunLoop::new(move |alive| {
            let (removal_tx, removal_rx) = channel::<IOHIDDeviceRef>();
            let (added_tx, added_rx) = channel::<IOHIDDeviceRef>();

            let hid_manager = unsafe {
                let hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone);
                IOHIDManagerSetDeviceMatching(hid_manager, ptr::null());
                if IOHIDManagerOpen(hid_manager, kIOHIDManagerOptionNone) != KERN_SUCCESS {
                    panic!("Couldn't open a HID Manager");
                }
                hid_manager
            };

            let boxed_added_tx = Box::new(added_tx);
            let added_tx_ptr = Box::into_raw(boxed_added_tx) as *mut libc::c_void;
            let boxed_removal_tx = Box::new(removal_tx);
            let removal_tx_ptr = Box::into_raw(boxed_removal_tx) as *mut libc::c_void;

            unsafe {
                IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, device_register_cb, removal_tx_ptr);
                IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, device_register_cb, added_tx_ptr);
                IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
            }

            // Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input reports into the
            // various call
            while alive() {
                println!("Run loop running, handle={:?}", thread::current());

                for device_ref in added_rx.try_iter() {
                    tx.send(Event::Add { device_id: IOHIDDeviceID::from_ref(device_ref) }).unwrap();
                }
                for device_ref in removal_rx.try_iter() {
                    tx.send(Event::Remove { device_id: IOHIDDeviceID::from_ref(device_ref) }).unwrap();
                }

                if unsafe { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, 0) } == kCFRunLoopRunStopped {
                    println!("Device stopped.");
                    // TODO: drop the removal_tx_ptr
                    break;
                }
            }

            if unsafe { IOHIDManagerClose(hid_manager, kIOHIDManagerOptionNone) } != KERN_SUCCESS {
                panic!("Couldn't close the HID Manager");
            }

            Ok(())
        }, 0 /* no timeout */)?;

        Ok(Self { rx, thread })
    }

    pub fn events<'a>(&'a self) -> TryIter<'a, Event> {
        self.rx.try_iter()
    }

    // This might block.
    pub fn stop(&mut self) {
        self.thread.cancel();
    }
}

// This is called from the RunLoop thread
extern "C" fn device_register_cb(context: *mut c_void,
                                 result: IOReturn,
                                 _: *mut c_void,
                                 device: IOHIDDeviceRef) {
    unsafe {
        let tx: &mut Sender<IOHIDDeviceRef> = &mut *(context as *mut Sender<IOHIDDeviceRef>);

        // context contains a Device which we populate as the out variable
        // let device: &mut Device = &mut *(context as *mut Device);

        // let device_ref = void_ref as IOHIDDeviceRef;
        println!("{:?} device_register_cb context={:?} result={:?} device_ref={:?}",
                 thread::current(), context, result, device);

        if let Err(e) = tx.send(device) {
            // TOOD: This happens when the channel closes before this thread
            // does. This is pretty common, but let's deal with stopping
            // properly later.
            println!("Problem returning device_register_cb data for thread: {}", e);
        };
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;

macro_rules! dispatch {
    ($m0:expr => $h0:expr, $($m1:expr => $h1:expr,)*) => {{
        if $m0 { $h0 } $( else if $m1 { $h1 } )*
    }}
}

trait ToResponse {
    fn status(&self) -> StatusCode {
        StatusCode::Ok
    }

    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(0)
    }

    fn content(&self) -> &[u8] {
        &[]
    }

    fn make_response(&self, mut response: Response) {
        response.headers_mut().set(self.content_type());
        response.headers_mut().set(self.content_length());
        response.start().unwrap().write(self.content()).unwrap();
    }
}

impl ToResponse for StatusCode {
    fn status(&self) -> StatusCode {
        *self
    }
}

impl ToResponse for String {
    fn content_type(&self) -> ContentType {
        ContentType::html()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.as_bytes().len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.as_bytes()
    }
}

pub fn get(request: Request, response: Response) {
    println!("** Handling GET {}", request.uri);
    println!("** Incoming headers {:?}", request.headers);
    if let RequestUri::AbsolutePath(ref path) = request.uri {
        dispatch![
            path == "/" => index(&request).make_response(response),
            path == "/ip" => origin(&request).make_response(response),
            path.starts_with("/status/") => status(path).make_response(response),
            path.starts_with("/test") => test(&request).make_response(response),
            true => notfound404().make_response(response),
        ];
    }
}

fn notfound404() -> String {
    String::from("<!DOCTYPE html>

            <title>404 Not Found</title>

Not Found

The requested URL was not found on the server.
        If you entered the URL manually please check your spelling and try again.

    ")
}

fn index(request: &Request) -> String {
    String::from("<!DOCTYPE html>

            <link
                rel=\"icon\"
                href=\"http://investorintel.com/wp-content/uploads/2014/03/tin-can.jpg\"/>
            <title>HTTPTIN</title>

HTTPTIN - HTTP tester in Rust and Rocket

    ")
}

fn status(path: &str) -> StatusCode {
    // /status/xx
    // 0123456789
    let (_, param) = path.split_at(8);
    match param.parse::<u16>() {
        Ok(status) => StatusCode::from_u16(status),
        Err(_) => StatusCode::BadRequest,
    }
}

fn origin(request: &Request) -> String {
    format!("origin: {}", request.remote_addr)
}

fn test(request: &Request) -> String {
    format!("<!DOCTYPE html>

            <title>HTTPTIN TEST</title>

            Remote Address: {}

            Method: {}

            HTTPVersion: {}

            Headers: {}

            URI: {}

    ",
            request.remote_addr,
            request.method,
            request.version,
            request.headers,
            request.uri)
}
<commit_msg>Add Text type for trivial plaintext responses<commit_after>use std::io::Write;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri;

macro_rules! dispatch {
    ($m0:expr => $h0:expr, $($m1:expr => $h1:expr,)*) => {{
        if $m0 { $h0 } $( else if $m1 { $h1 } )*
    }}
}

trait ToResponse {
    fn status(&self) -> StatusCode {
        StatusCode::Ok
    }

    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(0)
    }

    fn content(&self) -> &[u8] {
        &[]
    }

    fn make_response(&self, mut response: Response) {
        response.headers_mut().set(self.content_type());
        response.headers_mut().set(self.content_length());
        response.start().unwrap().write(self.content()).unwrap();
    }
}

impl ToResponse for StatusCode {
    fn status(&self) -> StatusCode {
        *self
    }
}

impl ToResponse for String {
    fn content_type(&self) -> ContentType {
        ContentType::html()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.as_bytes().len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.as_bytes()
    }
}

pub fn get(request: Request, response: Response) {
    println!("** Handling GET {}", request.uri);
    println!("** Incoming headers {:?}", request.headers);
    if let RequestUri::AbsolutePath(ref path) = request.uri {
        dispatch![
            path == "/" => index(&request).make_response(response),
            path == "/ip" => origin(&request).make_response(response),
            path.starts_with("/status/") => status(path).make_response(response),
            path.starts_with("/test") => test(&request).make_response(response),
            true => notfound404().make_response(response),
        ];
    }
}

struct Text(String);

impl ToResponse for Text {
    fn content_type(&self) -> ContentType {
        ContentType::plaintext()
    }

    fn content_length(&self) -> ContentLength {
        ContentLength(self.0.as_bytes().len() as u64)
    }

    fn content(&self) -> &[u8] {
        self.0.as_bytes()
    }
}

fn notfound404() -> String {
    String::from("<!DOCTYPE html>

            <title>404 Not Found</title>

Not Found

The requested URL was not found on the server.
        If you entered the URL manually please check your spelling and try again.

    ")
}

fn index(request: &Request) -> String {
    String::from("<!DOCTYPE html>

            <link
                rel=\"icon\"
                href=\"http://investorintel.com/wp-content/uploads/2014/03/tin-can.jpg\"/>
            <title>HTTPTIN</title>

HTTPTIN - HTTP tester in Rust and Rocket

    ")
}

fn status(path: &str) -> StatusCode {
    // /status/xx
    // 0123456789
    let (_, param) = path.split_at(8);
    match param.parse::<u16>() {
        Ok(status) => StatusCode::from_u16(status),
        Err(_) => StatusCode::BadRequest,
    }
}

fn origin(request: &Request) -> Text {
    Text(format!("origin: {}", request.remote_addr))
}

fn test(request: &Request) -> String {
    format!("<!DOCTYPE html>

            <title>HTTPTIN TEST</title>

            Remote Address: {}

            Method: {}

            HTTPVersion: {}

            Headers: {}

            URI: {}

    ",
            request.remote_addr,
            request.method,
            request.version,
            request.headers,
            request.uri)
}
<|endoftext|>


<commit_before>extern crate git2;
extern crate regex;
use super::Result;

use git2::build::RepoBuilder;
use std::path::Path;
use regex::Regex;

#[derive(Debug)]
pub enum Url {
    Local(String),
    Github(String, String),
    Remote(String)
}

impl Url {
    /// supports two types git of repository urls
    /// local repositories that start with file://
    /// and github repositories ower/repo
    pub fn from_str(txt: &str) -> Option<Url> {
        lazy_static! {
            static ref LOCAL: Regex = Regex::new(r#"^file://(\S+)$""#).unwrap();
            static ref GH: Regex = Regex::new(r#"^([^\s/]+)/([^\s/]+?)$"#).unwrap();
            static ref REMOTE: Regex = Regex::new(
                r#"^(git[@|://].*)|(https://.*)|(http://.*)|(ssh://.*)$"#
            ).unwrap();
        }
        LOCAL.captures(txt)
            .map(|caps| Url::Local(caps.get(1).unwrap().as_str().to_owned()))
            .or_else(|| {
                if REMOTE.is_match(txt) {
                    Some(Url::Remote(txt.to_string()))
                } else {
                    None
                }
            }).or_else(|| {
                GH.captures(txt)
                    .map(|caps| {
                        Url::Github(caps.get(1).unwrap().as_str().to_owned(),
                                    caps.get(2).unwrap().as_str().to_owned())
                    })
            })
    }
}

/// clone a repository at a rev to a directory
/// a best attempt effort is made to authenticate
/// requests when required to support private
/// git repositories
pub fn clone<P>(repo: Url, dir: P, rev: &str) -> Result<()>
    where P: AsRef<Path>
{
    let mut cb = git2::RemoteCallbacks::new();
    let mut tried_sshkey = false;
    cb.credentials(move |url, username, cred_type| {
        if cred_type.contains(git2::USER_PASS_PLAINTEXT) {
            let cfg = git2::Config::open_default().unwrap();
            return git2::Cred::credential_helper(&cfg, url, username);
        }
        if cred_type.contains(git2::SSH_KEY) && !tried_sshkey {

            // If ssh-agent authentication fails, libgit2 will keep
            // calling this callback asking for other authentication
            // methods to try. Make sure we only try ssh-agent once,
            // to avoid looping forever.
            tried_sshkey = true;
            let username = username.unwrap();
            return git2::Cred::ssh_key_from_agent(&username);
        }
        Err(git2::Error::from_str("no authentication available"))
    });

    let mut fo = git2::FetchOptions::new();
    fo.remote_callbacks(cb).download_tags(git2::AutotagOption::All);
    let url = match repo {
        Url::Github(ref owner, ref repo) => format!("git://github.com/{}/{}.git", owner, repo),
        Url::Local(ref path) => path.to_owned(),
        Url::Remote(ref remote) => remote.to_owned()
    };
    RepoBuilder::new()
        .branch(rev)
        .fetch_options(fo)
        .clone(&url, dir.as_ref())?;

    debug!("cloned {:?} to {:?}", repo, dir.as_ref());
    Ok(())
}
<commit_msg>more generic<commit_after>extern crate git2;
extern crate regex;
use super::Result;

use git2::build::RepoBuilder;
use std::path::Path;
use regex::Regex;

#[derive(Debug)]
pub enum Url {
    Local(String),
    Github(String, String),
    Remote(String)
}

impl Url {
    /// supports two types git of repository urls
    /// local repositories that start with file://
    /// and github repositories ower/repo
    pub fn from_str(txt: &str) -> Option<Url> {
        lazy_static! {
            static ref LOCAL: Regex = Regex::new(r#"^file://(\S+)$""#).unwrap();
            static ref GH: Regex = Regex::new(r#"^([^\s/]+)/([^\s/]+?)$"#).unwrap();
            static ref REMOTE: Regex = Regex::new(
                r#"^(git[@|://].*)|(https://.*)|(http://.*)|(ssh://.*)$"#
            ).unwrap();
        }
        LOCAL.captures(txt)
            .map(|caps| Url::Local(caps.get(1).unwrap().as_str().to_owned()))
            .or_else(|| {
                if REMOTE.is_match(txt) {
                    Some(Url::Remote(txt.to_string()))
                } else {
                    None
                }
            }).or_else(|| {
                GH.captures(txt)
                    .map(|caps| {
                        Url::Github(caps.get(1).unwrap().as_str().to_owned(),
                                    caps.get(2).unwrap().as_str().to_owned())
                    })
            })
    }
}

/// clone a repository at a rev to a directory
/// a best attempt effort is made to authenticate
/// requests when required to support private
/// git repositories
pub fn clone<P, R>(repo: Url, dir: P, rev: R) -> Result<()>
    where P: AsRef<Path>, R: Into<String>
{
    let mut cb = git2::RemoteCallbacks::new();
    let mut tried_sshkey = false;
    cb.credentials(move |url, username, cred_type| {
        if cred_type.contains(git2::USER_PASS_PLAINTEXT) {
            let cfg = git2::Config::open_default().unwrap();
            return git2::Cred::credential_helper(&cfg, url, username);
        }
        if cred_type.contains(git2::SSH_KEY) && !tried_sshkey {

            // If ssh-agent authentication fails, libgit2 will keep
            // calling this callback asking for other authentication
            // methods to try. Make sure we only try ssh-agent once,
            // to avoid looping forever.
            tried_sshkey = true;
            let username = username.unwrap();
            return git2::Cred::ssh_key_from_agent(&username);
        }
        Err(git2::Error::from_str("no authentication available"))
    });

    let mut fo = git2::FetchOptions::new();
    fo.remote_callbacks(cb).download_tags(git2::AutotagOption::All);
    let url = match repo {
        Url::Github(ref owner, ref repo) => format!("git://github.com/{}/{}.git", owner, repo),
        Url::Local(ref path) => path.to_owned(),
        Url::Remote(ref remote) => remote.to_owned()
    };
    RepoBuilder::new()
        .branch(&rev.into())
        .fetch_options(fo)
        .clone(&url, dir.as_ref())?;

    debug!("cloned {:?} to {:?}", repo, dir.as_ref());
    Ok(())
}
<|endoftext|>


<commit_before>use meta::enums::Enum;
use meta::sum::Sum;

pub trait ContinuationSet {
    type Emit;
    type Continue: State;
    type Suspend: ContinuationSet;
}

impl ContinuationSet for ! {
    type Emit = !;
    type Continue = !;
    type Suspend = !;
}

impl<Enumeration, Y, C> ContinuationSet for Enumeration
    where C: State,
          Enumeration: Enum<Head = (Y, C)>,
          Enumeration::Tail: ContinuationSet
{
    type Emit = Y;
    type Continue = C;
    type Suspend = Enumeration::Tail;
}

pub trait State: Sized {
    type Input;
    type Exit;
    type Next: ContinuationSet;
    type Transition: Sum<Left = Self::Next, Right = Self::Exit>;

    fn send(self, i: Self::Input) -> Self::Transition;
}

impl State for ! {
    type Input = !;
    type Exit = !;
    type Next = !;
    type Transition = !;

    fn send(self, _: Self::Input) -> Self::Transition {
        unreachable!()
    }
}

#[cfg(test)]
mod tests {

    #![macro_use]

    use super::{State, ContinuationSet};
    use meta::matches::Match::*;
    use meta::matches::Match;
    use meta::sum::Sum;
    use std::fmt;

    pub enum Transition<Next, Exit>
        where Next: ContinuationSet
    {
        Next(Next),
        Exit(Exit),
    }

    impl<Next, Exit> Sum for Transition<Next, Exit>
        where Next: ContinuationSet
    {
        type Left = Next;
        type Right = Exit;

        fn to_canonical(self) -> Match<Self::Left, Self::Right> {
            match self {
                Transition::Next(next) => Match::Variant(next),
                Transition::Exit(exit) => Match::Next(exit),
            }
        }
    }

    struct TooSmall;

    impl fmt::Display for TooSmall {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Too small!")
        }
    }

    struct TooBig;

    impl fmt::Display for TooBig {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Too big!")
        }
    }

    struct Correct;

    impl fmt::Display for Correct {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "You guessed it!")
        }
    }

    struct Guess(i64);

    impl State for Guess {
        type Input = i64;
        type Exit = Correct;

        type Next = enums![(TooSmall, Guess), (TooBig, Guess)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, i: Self::Input) -> Self::Transition {
            if self.0 == i {
                Transition::Exit(Correct {})
            } else if i < self.0 {
                Transition::Next(Variant((TooSmall {}, self)))
            } else {
                Transition::Next(Next(Variant((TooBig {}, self))))
            }
        }
    }

    struct Game;

    impl State for Game {
        type Input = i64;
        type Exit = !;

        type Next = enums![((), Guess)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, secret: Self::Input) -> Self::Transition {
            Transition::Next(Variant(((), Guess(secret))))
        }
    }

    struct Quit;

    impl fmt::Display for Quit {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "I quit!")
        }
    }

    struct Maverick;

    impl State for Maverick {
        type Input = (i64, i64);
        type Exit = Quit;

        type Next = enums![(i64, Strategist)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, range: Self::Input) -> Self::Transition {
            if range.0 > range.1 {
                Transition::Exit(Quit {})
            } else {
                let guess = (range.0 + range.1) / 2;
                Transition::Next(Variant((guess, Strategist(range.0, guess, range.1))))
            }
        }
    }

    struct Strategist(i64, i64, i64);

    impl State for Strategist {
        type Input = enums![TooSmall, TooBig];
        type Exit = Quit;

        type Next = enums![(i64, Strategist)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, result: Self::Input) -> Self::Transition {
            let mav = Maverick {};
            let range = match result {
                Variant(TooSmall) => (self.1 + 1, self.2),
                Next(Variant(TooBig)) => (self.0, self.1 - 1),
            };
            mav.send(range)
        }
    }

    /*
    fn play_guess(secret: i64) {
        guess = yield;
        loop {
            guess = if guess == secret {
                return Correct;
            } else if guess < secret {
                yield TooSmall;
            } else {
                yield TooBig;
            }
        }
    }

    fn player(lo: i64, hi: i64) {
        while lo >= hi {
            let med = (lo + hi) / 2;
            let res = yield med;
            match res {
                TooBig => hi = med - 1,
                TooSmall => lo = med + 1
            }
        }
        return Quit;
    }
    */

    #[test]
    fn guess() {
        let game = Game {};

        let game = match game.send(16) {
            Transition::Next(Variant(((), game))) => game,
        };

        let suspend = match game.send(10) {
            Transition::Next(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Variant((msg, guess_again)) => {
                assert_eq!(msg.to_string(), "Too small!");
                guess_again
            }
            _ => panic!("The number was clearly too small! Why do you not see this?"),
        };

        let suspend = match game.send(19) {
            Transition::Next(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Next(Variant((msg, guess_again))) => {
                assert_eq!(msg.to_string(), "Too big!");
                guess_again
            }
            _ => panic!("The number was clearly too big! Why do you not see this?"),
        };

        match game.send(16) {
            Transition::Exit(msg) => assert_eq!(msg.to_string(), "You guessed it!"),
            _ => panic!("The answer was correct! The coroutine should return."),
        }
    }

    enum Finish<G, P> {
        GameWon(G),
        PlayerGaveUp(P),
    }

    fn play(secret: i64, lo: i64, hi: i64) -> Finish<Correct, Quit> {
        let (_, mut game) = match (Game {}.send(secret)) {
            Transition::Next(Variant(s)) => s,
        };

        let player = Maverick {};

        let (mut guess, mut player) = match player.send((lo, hi)) {
            Transition::Next(Variant(x)) => x,
            Transition::Exit(_) => panic!("The range is valid, why did you return?"),
        };

        loop {
            let (result, game_) = match game.send(guess) {
                Transition::Next(Variant((r, g))) => (Variant(r), g),
                Transition::Next(Next(Variant((r, g)))) => (Next(Variant(r)), g),
                Transition::Exit(r) => break Finish::GameWon(r),
            };
            game = game_;
            let (guess_, player_) = match player.send(result) {
                Transition::Next(Variant(s)) => s,
                Transition::Exit(r) => break Finish::PlayerGaveUp(r),
            };
            guess = guess_;
            player = player_;
        }
    }

    #[test]
    fn solo() {
        let msg = match play(75, 10, 100) {
            Finish::GameWon(e) => e.to_string(),
            Finish::PlayerGaveUp(q) => q.to_string(),
        };
        assert_eq!(msg, "You guessed it!");

        let msg = match play(5, 10, 100) {
            Finish::GameWon(e) => e.to_string(),
            Finish::PlayerGaveUp(q) => q.to_string(),
        };
        assert_eq!(msg, "I quit!");
    }
}
<commit_msg>Remove unnecessary Sized constraint from State<commit_after>use meta::enums::Enum;
use meta::sum::Sum;

pub trait ContinuationSet {
    type Emit;
    type Continue: State;
    type Suspend: ContinuationSet;
}

impl ContinuationSet for ! {
    type Emit = !;
    type Continue = !;
    type Suspend = !;
}

impl<Enumeration, Y, C> ContinuationSet for Enumeration
    where C: State,
          Enumeration: Enum<Head = (Y, C)>,
          Enumeration::Tail: ContinuationSet
{
    type Emit = Y;
    type Continue = C;
    type Suspend = Enumeration::Tail;
}

pub trait State {
    type Input;
    type Exit;
    type Next: ContinuationSet;
    type Transition: Sum<Left = Self::Next, Right = Self::Exit>;

    fn send(self, i: Self::Input) -> Self::Transition;
}

impl State for ! {
    type Input = !;
    type Exit = !;
    type Next = !;
    type Transition = !;

    fn send(self, _: Self::Input) -> Self::Transition {
        unreachable!()
    }
}

#[cfg(test)]
mod tests {

    #![macro_use]

    use super::{State, ContinuationSet};
    use meta::matches::Match::*;
    use meta::matches::Match;
    use meta::sum::Sum;
    use std::fmt;

    pub enum Transition<Next, Exit>
        where Next: ContinuationSet
    {
        Next(Next),
        Exit(Exit),
    }

    impl<Next, Exit> Sum for Transition<Next, Exit>
        where Next: ContinuationSet
    {
        type Left = Next;
        type Right = Exit;

        fn to_canonical(self) -> Match<Self::Left, Self::Right> {
            match self {
                Transition::Next(next) => Match::Variant(next),
                Transition::Exit(exit) => Match::Next(exit),
            }
        }
    }

    struct TooSmall;

    impl fmt::Display for TooSmall {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Too small!")
        }
    }

    struct TooBig;

    impl fmt::Display for TooBig {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "Too big!")
        }
    }

    struct Correct;

    impl fmt::Display for Correct {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "You guessed it!")
        }
    }

    struct Guess(i64);

    impl State for Guess {
        type Input = i64;
        type Exit = Correct;

        type Next = enums![(TooSmall, Guess), (TooBig, Guess)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, i: Self::Input) -> Self::Transition {
            if self.0 == i {
                Transition::Exit(Correct {})
            } else if i < self.0 {
                Transition::Next(Variant((TooSmall {}, self)))
            } else {
                Transition::Next(Next(Variant((TooBig {}, self))))
            }
        }
    }

    struct Game;

    impl State for Game {
        type Input = i64;
        type Exit = !;

        type Next = enums![((), Guess)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, secret: Self::Input) -> Self::Transition {
            Transition::Next(Variant(((), Guess(secret))))
        }
    }

    struct Quit;

    impl fmt::Display for Quit {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "I quit!")
        }
    }

    struct Maverick;

    impl State for Maverick {
        type Input = (i64, i64);
        type Exit = Quit;

        type Next = enums![(i64, Strategist)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, range: Self::Input) -> Self::Transition {
            if range.0 > range.1 {
                Transition::Exit(Quit {})
            } else {
                let guess = (range.0 + range.1) / 2;
                Transition::Next(Variant((guess, Strategist(range.0, guess, range.1))))
            }
        }
    }

    struct Strategist(i64, i64, i64);

    impl State for Strategist {
        type Input = enums![TooSmall, TooBig];
        type Exit = Quit;

        type Next = enums![(i64, Strategist)];
        type Transition = Transition<Self::Next, Self::Exit>;

        fn send(self, result: Self::Input) -> Self::Transition {
            let mav = Maverick {};
            let range = match result {
                Variant(TooSmall) => (self.1 + 1, self.2),
                Next(Variant(TooBig)) => (self.0, self.1 - 1),
            };
            mav.send(range)
        }
    }

    /*
    fn play_guess(secret: i64) {
        guess = yield;
        loop {
            guess = if guess == secret {
                return Correct;
            } else if guess < secret {
                yield TooSmall;
            } else {
                yield TooBig;
            }
        }
    }

    fn player(lo: i64, hi: i64) {
        while lo >= hi {
            let med = (lo + hi) / 2;
            let res = yield med;
            match res {
                TooBig => hi = med - 1,
                TooSmall => lo = med + 1
            }
        }
        return Quit;
    }
    */

    #[test]
    fn guess() {
        let game = Game {};

        let game = match game.send(16) {
            Transition::Next(Variant(((), game))) => game,
        };

        let suspend = match game.send(10) {
            Transition::Next(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Variant((msg, guess_again)) => {
                assert_eq!(msg.to_string(), "Too small!");
                guess_again
            }
            _ => panic!("The number was clearly too small! Why do you not see this?"),
        };

        let suspend = match game.send(19) {
            Transition::Next(suspend) => suspend,
            _ => panic!("We didn't guess the number, so the coroutine should not return yet!"),
        };

        let game = match suspend {
            Next(Variant((msg, guess_again))) => {
                assert_eq!(msg.to_string(), "Too big!");
                guess_again
            }
            _ => panic!("The number was clearly too big! Why do you not see this?"),
        };

        match game.send(16) {
            Transition::Exit(msg) => assert_eq!(msg.to_string(), "You guessed it!"),
            _ => panic!("The answer was correct! The coroutine should return."),
        }
    }

    enum Finish<G, P> {
        GameWon(G),
        PlayerGaveUp(P),
    }

    fn play(secret: i64, lo: i64, hi: i64) -> Finish<Correct, Quit> {
        let (_, mut game) = match (Game {}.send(secret)) {
            Transition::Next(Variant(s)) => s,
        };

        let player = Maverick {};

        let (mut guess, mut player) = match player.send((lo, hi)) {
            Transition::Next(Variant(x)) => x,
            Transition::Exit(_) => panic!("The range is valid, why did you return?"),
        };

        loop {
            let (result, game_) = match game.send(guess) {
                Transition::Next(Variant((r, g))) => (Variant(r), g),
                Transition::Next(Next(Variant((r, g)))) => (Next(Variant(r)), g),
                Transition::Exit(r) => break Finish::GameWon(r),
            };
            game = game_;
            let (guess_, player_) = match player.send(result) {
                Transition::Next(Variant(s)) => s,
                Transition::Exit(r) => break Finish::PlayerGaveUp(r),
            };
            guess = guess_;
            player = player_;
        }
    }

    #[test]
    fn solo() {
        let msg = match play(75, 10, 100) {
            Finish::GameWon(e) => e.to_string(),
            Finish::PlayerGaveUp(q) => q.to_string(),
        };
        assert_eq!(msg, "You guessed it!");

        let msg = match play(5, 10, 100) {
            Finish::GameWon(e) => e.to_string(),
            Finish::PlayerGaveUp(q) => q.to_string(),
        };
        assert_eq!(msg, "I quit!");
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// 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.

//! Utilities for collecting metrics.

use std::time::SystemTime;

/// Adds given metric with given value.
///
/// Metric name should be in the following format: `module_name.metric_name`, where `module_name`
/// is a high level name. For example `storage` or `node` (not `storage_proof_list_index`).
///
/// Value is a string and can be formatted similar to the `println!`. See `std::fmt` and example
/// for details.
///
/// Metrics output direction is determined by the corresponding `metrics-...` feature. If
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate exonum;
/// # fn main() {
/// let val = 10;
/// metric!("mod_name.metric_name", val);
/// # }
/// ```
#[macro_export]
macro_rules! metric {
    ($name:expr, $value:expr) => ({
        $crate::helpers::metrics::add_metric($name, $value as i64);
    })
}

// Do not use directly, use `metric!` macro instead.
#[doc(hidden)]
#[allow(unused_variables)]
pub fn add_metric(metric_name: &str, value: i64) {
    // TODO: Convert time to some meaningful format.
    let time = format!("{:?}", SystemTime::now());

    #[cfg(feature = "metrics-log")]
    {
        trace!("{} {} {}", metric_name, value, time);
    }
}
<commit_msg>Replace SystemTime::now() with Utc::now() (#620)<commit_after>// Copyright 2018 The Exonum Team
//
// 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.

//! Utilities for collecting metrics.

use chrono::offset::Utc;

/// Adds given metric with given value.
///
/// Metric name should be in the following format: `module_name.metric_name`, where `module_name`
/// is a high level name. For example `storage` or `node` (not `storage_proof_list_index`).
///
/// Value is a string and can be formatted similar to the `println!`. See `std::fmt` and example
/// for details.
///
/// Metrics output direction is determined by the corresponding `metrics-...` feature. If
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate exonum;
/// # fn main() {
/// let val = 10;
/// metric!("mod_name.metric_name", val);
/// # }
/// ```
#[macro_export]
macro_rules! metric {
    ($name:expr, $value:expr) => ({
        $crate::helpers::metrics::add_metric($name, $value as i64);
    })
}

// Do not use directly, use `metric!` macro instead.
#[doc(hidden)]
#[allow(unused_variables)]
pub fn add_metric(metric_name: &str, value: i64) {
    // TODO: Convert time to some meaningful format.
    let time = format!("{:?}", Utc::now());

    #[cfg(feature = "metrics-log")]
    {
        trace!("{} {} {}", metric_name, value, time);
    }
}
<|endoftext|>


<commit_before>mod token;

pub fn compile(sass: String, style: &str) -> String {
    let mut sp = SassParser::new(sass); // SassTokenizer::new(sass);
    let parsed = sp.parse();
    match style {
        "nested"     => nested(parsed),
        "compressed" => compressed(parsed),
        "expanded"   => expanded(parsed),
        "compact"    => compact(parsed),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}

#[derive(Debug)]
struct SassRuleSet {
    pub rules: Vec<SassRule>,
}

#[derive(Debug)]
struct SassRule {
    pub selectors: Vec<token::Range>,
    pub props_and_values: Vec<PropertyValueSet>,
}

#[derive(Debug)]
struct PropertyValueSet {
    pub property: token::Range,
    pub value: token::Range,
}

#[derive(Debug)]
struct SassParser {
    pub curr: Option<token::Range>,
    pub peek_range: token::Range,
    pub tok: SassTokenizer,
}

impl SassParser {
    pub fn new(str: String) -> SassParser {
        let mut sp = SassParser {
            tok: SassTokenizer::new(str),
            curr: None,
            peek_range: token::Range { start_pos: 0, end_pos: 0, token: token::Eof },
        };
        sp.advance_token();
        sp.bump();
        sp
    }

    pub fn bump(&mut self) {
        if self.peek_range.token == token::Eof {
            self.curr = None;
        } else {
            self.curr = Some(self.peek_range.clone());
            self.advance_token();
        }
    }

    pub fn advance_token(&mut self) {
        match self.tok.scan_whitespace() {
            Some(whitespace) => {
                self.peek_range = whitespace;
            },
            None => {
                if self.tok.is_eof() {
                    self.peek_range = token::Range { start_pos: self.tok.pos + 1, end_pos: self.tok.pos + 1, token: token::Eof };
                } else {
                    self.peek_range = self.tok.next_token_inner();
                }
            },
        }
    }

    pub fn parse(&mut self) -> String {
        println!("{:?}", self.parse_rules());
        self.tok.sass.clone()
    }

    fn parse_rules(&mut self) -> Result<SassRuleSet, &'static str> {
        let mut rules = vec![];
        while let Some(rule) = try!(self.parse_rule()) {
            rules.push(rule);
        }
        Ok(SassRuleSet { rules: rules })
    }

    fn parse_rule(&mut self) -> Result<Option<SassRule>, &'static str> {
        let c = match self.curr.clone() {
            Some(c) => c,
            None => return Ok(None),
        };

        let mut selectors = vec![];
        while let Some(selector) = try!(self.parse_selector()) {
            selectors.push(selector);
        }
        if selectors.len() == 0 {
            panic!("Empty selector!")
        }

        let mut props_and_values = vec![];
        while let Some(property_value_set) = try!(self.parse_property_value_set()) {
            props_and_values.push(property_value_set);
        }

        // A rule without properties and values isn't *wrong*, per se...
        Ok(Some(SassRule { selectors: selectors, props_and_values: props_and_values }))
    }

    fn parse_selector(&mut self) -> Result<Option<token::Range>, &'static str> {
        let c = match self.curr.clone() {
            Some(c) => c,
            None => return Ok(None),
        };

        if c.token == token::Text {
            self.bump();
            return Ok(Some(c))
        }

        match &c.token {
            &token::Eof => Ok(None),
            &token::OpenDelim(token::Brace) => {
                self.bump(); // for the delim
                self.bump(); // whitespace
                Ok(None)
            },
            &token::Comma => {
                self.bump();
                self.parse_selector()
            },
            &token::Whitespace => { // wrong but temporarily so
                self.bump();
                self.parse_selector()
            },
            _ => Err("Unexpected token where we expected selectors"),
        }
    }

    fn parse_property_value_set(&mut self) -> Result<Option<PropertyValueSet>, &'static str> {
        let p = match self.curr.clone() {
            Some(p) => p,
            None => return Ok(None),
        };

        match p.token {
            token::Text => {
                self.bump(); // should be colon
                self.bump(); // optional whitespace required for now
                self.bump(); // now val

                let v = match self.curr.clone() {
                    Some(v) => v,
                    None => panic!("Expected a value here, instead got EOF!"),
                };

                if v.token == token::Text {
                    self.bump(); // semicolon
                    self.bump(); // whitespace
                    return Ok(Some(PropertyValueSet { property: p, value: v }))
                } else {
                    panic!("Expected a value here, instead got who knows what!");
                }
            },
            token::CloseDelim(token::Brace) => {
                self.bump();
                Ok(None)
            },
            token::Whitespace => {
                self.bump();
                self.parse_property_value_set()
            },
            _ => Err("Unexpected token where we expected properties and values"),
        }
    }
}

#[derive(Debug)]
struct SassTokenizer {
    pub pos: u32,
    pub last_pos: u32,
    pub curr: Option<char>,
    sass: String,
}

impl SassTokenizer {
    pub fn new(str: String) -> SassTokenizer {
        let mut sr = SassTokenizer {
            pos: 0,
            last_pos: 0,
            curr: Some('\n'),
            sass: str,
        };
        sr.bump();
        sr
    }

    pub fn bump(&mut self) {
        self.last_pos = self.pos;
        let current_pos = self.pos as usize;
        if current_pos < self.sass.len() {
            let ch = char_at(&self.sass, current_pos);

            self.pos = self.pos + (ch.len_utf8() as u32);
            self.curr = Some(ch);
        } else {
            self.curr = None;
        }
    }

    fn next_token_inner(&mut self) -> token::Range {
        let c = match self.curr {
            Some(c) => c,
            None => return token::Range { start_pos: self.pos + 1, end_pos: self.pos + 1, token: token::Eof },
        };

        if c >= 'a' && c <= 'z' {
            let start = self.last_pos;
            while !self.curr.is_none() && self.curr.unwrap() >= 'a' && self.curr.unwrap() <= 'z' {
                self.bump();
            }
            return token::Range { start_pos: start, end_pos: self.last_pos, token: token::Text }
        }

        match c {
            ';' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Semi }; },
            ':' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Colon }; },
            ',' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Comma }; },
            '{' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::OpenDelim(token::Brace) }; },
            '}' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::CloseDelim(token::Brace) }; },
            _   => { return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Unknown} },
        }
    }

    fn real_token(&mut self) -> token::Range {
        let mut t = self.next_token_inner();
        loop {
            match t.token {
                token::Whitespace => {
                    t = self.next_token_inner();
                },
                _ => break,
            }
        }
        t
    }

    fn scan_whitespace(&mut self) -> Option<token::Range> {
        match self.curr.unwrap_or('\0') {
            c if is_whitespace(Some(c)) => {
                let start = self.last_pos;
                while is_whitespace(self.curr) { self.bump(); }
                Some(token::Range { start_pos: start, end_pos: self.last_pos, token: token::Whitespace })
            },
            _ => None
        }
    }

    fn is_eof(&self) -> bool {
        self.curr.is_none()
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_whitespace(c: Option<char>) -> bool {
    match c.unwrap_or('\x00') { // None can be null for now... it's not whitespace
        ' ' | '\n' | '\t' | '\r' => true,
        _ => false
    }
}
<commit_msg>Fix off-by-one weirdnesses, for this example at least<commit_after>mod token;

pub fn compile(sass: String, style: &str) -> String {
    let mut sp = SassParser::new(sass); // SassTokenizer::new(sass);
    let parsed = sp.parse();
    match style {
        "nested"     => nested(parsed),
        "compressed" => compressed(parsed),
        "expanded"   => expanded(parsed),
        "compact"    => compact(parsed),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}

#[derive(Debug)]
struct SassRuleSet {
    pub rules: Vec<SassRule>,
}

#[derive(Debug)]
struct SassRule {
    pub selectors: Vec<token::Range>,
    pub props_and_values: Vec<PropertyValueSet>,
}

#[derive(Debug)]
struct PropertyValueSet {
    pub property: token::Range,
    pub value: token::Range,
}

#[derive(Debug)]
struct SassParser {
    pub token: token::Range,
    pub last_token: token::Range,
    pub tokenizer: SassTokenizer,
}

impl SassParser {
    pub fn new(str: String) -> SassParser {
        let mut tokenizer = SassTokenizer::new(str);
        let initial_token = tokenizer.real_token();
        SassParser {
            token: initial_token.clone(),
            last_token: initial_token.clone(),
            tokenizer: tokenizer,
        }
    }

    pub fn bump(&mut self) {
        self.last_token = self.token.clone();
        self.token = self.tokenizer.real_token();
    }

    pub fn parse(&mut self) -> String {
        println!("{:?}", self.parse_rules());
        self.tokenizer.sass.clone()
    }

    fn parse_rules(&mut self) -> Result<SassRuleSet, &'static str> {
        let mut rules = vec![];
        while let Some(rule) = try!(self.parse_rule()) {
            rules.push(rule);
        }
        Ok(SassRuleSet { rules: rules })
    }

    fn parse_rule(&mut self) -> Result<Option<SassRule>, &'static str> {
        if self.token.token == token::Eof {
            return Ok(None)
        }

        let mut selectors = vec![];
        while let Some(selector) = try!(self.parse_selector()) {
            selectors.push(selector);
        }
        if selectors.len() == 0 {
            panic!("Empty selector!")
        }

        let mut props_and_values = vec![];
        while let Some(property_value_set) = try!(self.parse_property_value_set()) {
            props_and_values.push(property_value_set);
        }

        // A rule without properties and values isn't *wrong*, per se...
        Ok(Some(SassRule { selectors: selectors, props_and_values: props_and_values }))
    }

    fn parse_selector(&mut self) -> Result<Option<token::Range>, &'static str> {
        if self.token.token == token::Eof {
            return Ok(None)
        }

        if self.token.token == token::Text {
            self.bump();
            return Ok(Some(self.last_token.clone()))
        }

        match &self.token.token {
            &token::Eof => Ok(None),
            &token::OpenDelim(token::Brace) => {
                self.bump();
                Ok(None)
            },
            &token::Comma => {
                self.bump();
                self.parse_selector()
            },
            &token::Whitespace => { // wrong but temporarily so
                self.bump();
                self.parse_selector()
            },
            _ => Err("Unexpected token where we expected selectors"),
        }
    }

    fn parse_property_value_set(&mut self) -> Result<Option<PropertyValueSet>, &'static str> {
        if self.token.token == token::Eof {
            return Ok(None)
        }

        if self.token.token == token::CloseDelim(token::Brace) {
            self.bump();
            return Ok(None)
        }

        let p = self.token.clone();

        match p.token {
            token::Text => {
                self.bump(); // should be colon
                self.bump(); // optional whitespace required for now

                let v = self.token.clone();

                if v.token == token::Text {
                    self.bump(); // semicolon
                    self.bump(); // whitespace
                    return Ok(Some(PropertyValueSet { property: p, value: v }))
                } else {
                    panic!("Expected a value here, instead got who knows what!");
                }
            },
            token::CloseDelim(token::Brace) => {
                self.bump();
                Ok(None)
            },
            token::Whitespace => {
                self.bump();
                self.parse_property_value_set()
            },
            _ => Err("Unexpected token where we expected properties and values"),
        }
    }
}

#[derive(Debug)]
struct SassTokenizer {
    pub pos: u32,
    pub last_pos: u32,
    pub curr: Option<char>,
    pub peek_range: token::Range,
    sass: String,
}

impl SassTokenizer {
    pub fn new(str: String) -> SassTokenizer {
        let mut sr = SassTokenizer {
            pos: 0,
            last_pos: 0,
            curr: Some('\n'),
            peek_range: token::Range { start_pos: 0, end_pos: 0, token: token::Eof },
            sass: str,
        };
        sr.bump();
        sr.advance_token();
        sr
    }

    pub fn bump(&mut self) {
        self.last_pos = self.pos;
        let current_pos = self.pos as usize;
        if current_pos < self.sass.len() {
            let ch = char_at(&self.sass, current_pos);

            self.pos = self.pos + (ch.len_utf8() as u32);
            self.curr = Some(ch);
        } else {
            self.curr = None;
        }
    }

    fn advance_token(&mut self) {
        match self.scan_whitespace() {
            Some(whitespace) => {
                self.peek_range = whitespace;
            },
            None => {
                if self.is_eof() {
                    self.peek_range = token::Range { start_pos: self.pos + 1, end_pos: self.pos + 1, token: token::Eof };
                } else {
                    self.peek_range = self.next_token_inner();
                }
            },
        }
    }

    fn next_token(&mut self) -> token::Range {
        let retval = self.peek_range.clone();
        self.advance_token();
        retval
    }

    fn next_token_inner(&mut self) -> token::Range {
        let c = match self.curr {
            Some(c) => c,
            None => return token::Range { start_pos: self.pos + 1, end_pos: self.pos + 1, token: token::Eof },
        };

        if c >= 'a' && c <= 'z' {
            let start = self.last_pos;
            while !self.curr.is_none() && self.curr.unwrap() >= 'a' && self.curr.unwrap() <= 'z' {
                self.bump();
            }
            return token::Range { start_pos: start, end_pos: self.last_pos, token: token::Text }
        }

        match c {
            ';' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Semi }; },
            ':' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Colon }; },
            ',' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Comma }; },
            '{' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::OpenDelim(token::Brace) }; },
            '}' => { self.bump(); return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::CloseDelim(token::Brace) }; },
            _   => { return token::Range { start_pos: self.last_pos, end_pos: self.last_pos, token: token::Unknown} },
        }
    }

    fn real_token(&mut self) -> token::Range {
        let mut t = self.next_token();
        loop {
            match t.token {
                token::Whitespace => {
                    t = self.next_token();
                },
                _ => break,
            }
        }
        t
    }

    fn scan_whitespace(&mut self) -> Option<token::Range> {
        match self.curr.unwrap_or('\0') {
            c if is_whitespace(Some(c)) => {
                let start = self.last_pos;
                while is_whitespace(self.curr) { self.bump(); }
                Some(token::Range { start_pos: start, end_pos: self.last_pos, token: token::Whitespace })
            },
            _ => None
        }
    }

    fn is_eof(&self) -> bool {
        self.curr.is_none()
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_whitespace(c: Option<char>) -> bool {
    match c.unwrap_or('\x00') { // None can be null for now... it's not whitespace
        ' ' | '\n' | '\t' | '\r' => true,
        _ => false
    }
}
<|endoftext|>