<commit_before>#![crate_id="cargo-git-checkout"]

extern crate cargo;
extern crate serialize;
extern crate hammer;
extern crate url;

use hammer::FlagConfig;
use cargo::{execute_main_without_stdin,CLIResult,CLIError,ToResult};
use cargo::sources::git::{GitRemote,GitCheckout};
use url::Url;

#[deriving(Eq,Clone,Decodable)]
struct Options {
    database_path: String,
    checkout_path: String,
    url: String,
    reference: String,
    verbose: bool
}

impl FlagConfig for Options {}

fn main() {
    execute_main_without_stdin(execute);
}

fn execute(options: Options) -> CLIResult<Option<GitCheckout>> {
    let Options { database_path, checkout_path, url, reference, verbose } = options;

    let url: Url = try!(from_str(url.as_slice()).to_result(|_|
        CLIError::new(format!("The URL `{}` you passed was not a valid URL", url), None::<&str>, 1)));

    let repo = GitRemote::new(url, verbose);
    let local = try!(repo.checkout(&Path::new(database_path)).map_err(|e|
        CLIError::new(format!("Couldn't check out repository: {}", e), None::<&str>, 1)));

    let checkout = try!(local.copy_to(reference, &Path::new(checkout_path)).map_err(|e|
        CLIError::new(format!("Couldn't copy repository: {}", e), None::<&str>, 1)));

    Ok(Some(checkout))
}
<commit_msg>Use GitSource in the stub executable<commit_after>#![crate_id="cargo-git-checkout"]

extern crate cargo;
extern crate serialize;
extern crate hammer;
extern crate url;

use hammer::FlagConfig;
use cargo::{execute_main_without_stdin,CLIResult,CLIError,ToResult};
use cargo::core::source::Source;
use cargo::sources::git::{GitSource,GitRemote};
use url::Url;

#[deriving(Eq,Clone,Decodable)]
struct Options {
    database_path: String,
    checkout_path: String,
    url: String,
    reference: String,
    verbose: bool
}

impl FlagConfig for Options {}

fn main() {
    execute_main_without_stdin(execute);
}

fn execute(options: Options) -> CLIResult<Option<()>> {
    let Options { database_path, checkout_path, url, reference, verbose } = options;

    let url: Url = try!(from_str(url.as_slice()).to_result(|_|
        CLIError::new(format!("The URL `{}` you passed was not a valid URL", url), None::<&str>, 1)));

    let remote = GitRemote::new(url, verbose);
    let source = GitSource::new(remote, reference, Path::new(database_path), Path::new(checkout_path), verbose);
    try!(source.update().map_err(|e| {
        CLIError::new(format!("Couldn't update {}: {}", source, e), None::<&str>, 1)
    }));

    Ok(None)
}
<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::io::{Read, Write};
use std::collections::HashSet;
use std::env;
use std::rc::Rc;
use std::cell::RefCell;

use tempdir::TempDir;
use toml::Value;
use toml::value::Table;
use cargo::util::errors::CargoResultExt;
use cargo::core::{PackageId, Workspace};
use cargo::util::{CargoError, CargoErrorKind, CargoResult, Config};
use cargo::ops::{update_lockfile, UpdateOptions};

use Options;
use super::{ElaborateWorkspace, Manifest};

/// A temporary project
pub struct TempProject<'tmp> {
    pub workspace: Rc<RefCell<Option<Workspace<'tmp>>>>,
    pub temp_dir: TempDir,
    manifest_paths: Vec<PathBuf>,
    config: Config,
    relative_manifest: String,
}

impl<'tmp> TempProject<'tmp> {
    /// Copy needed manifest and lock files from an existing workspace
    pub fn from_workspace(
        orig_workspace: &ElaborateWorkspace,
        orig_manifest: &str,
        options: &Options,
    ) -> CargoResult<TempProject<'tmp>> {
        // e.g. /path/to/project
        let workspace_root = orig_workspace.workspace.root().to_str().ok_or_else(|| {
            CargoError::from_kind(CargoErrorKind::Msg(format!(
                "Invalid character found in path {}",
                orig_workspace.workspace.root().to_string_lossy()
            )))
        })?;

        let temp_dir = TempDir::new("cargo-outdated")?;
        let manifest_paths = manifest_paths(orig_workspace)?;
        let mut tmp_manifest_paths = vec![];
        for from in &manifest_paths {
            // e.g. /path/to/project/src/sub
            let mut from_dir = from.clone();
            from_dir.pop();
            let from_dir = from_dir.to_string_lossy();
            // e.g. /tmp/cargo.xxx/src/sub
            let mut dest = PathBuf::from(format!(
                "{}/{}",
                temp_dir.path().to_string_lossy(),
                &from_dir[workspace_root.len()..]
            ));
            fs::create_dir_all(&dest)?;
            // e.g. /tmp/cargo.xxx/src/sub/Cargo.toml
            dest.push("Cargo.toml");
            tmp_manifest_paths.push(dest.clone());
            fs::copy(from, &dest)?;
            let lockfile = PathBuf::from(format!("{}/Cargo.lock", from_dir));
            if lockfile.is_file() {
                dest.pop();
                dest.push("Cargo.lock");
                fs::copy(lockfile, dest)?;
            }
        }
        Self::write_manifest_semver_with_paths(&tmp_manifest_paths)?;

        // virtual root
        let mut virtual_root = PathBuf::from(format!("{}/Cargo.toml", workspace_root));
        if !manifest_paths.contains(&virtual_root) && virtual_root.is_file() {
            fs::copy(
                &virtual_root,
                format!("{}/Cargo.toml", temp_dir.path().to_string_lossy()),
            )?;
            virtual_root.pop();
            virtual_root.push("Cargo.lock");
            if virtual_root.is_file() {
                fs::copy(
                    &virtual_root,
                    format!("{}/Cargo.lock", temp_dir.path().to_string_lossy()),
                )?;
            }
        }

        let relative_manifest = String::from(
            &orig_manifest[orig_workspace.workspace.root().to_string_lossy().len()..],
        );
        let config = Self::generate_config(
            &temp_dir.path().to_string_lossy(),
            &relative_manifest,
            options,
        )?;
        Ok(TempProject {
            // workspace: Workspace::new(Path::new(&root_manifest), config)?,
            workspace: Rc::new(RefCell::new(None)),
            temp_dir: temp_dir,
            manifest_paths: tmp_manifest_paths,
            config: config,
            relative_manifest: relative_manifest,
        })
    }

    fn generate_config(
        root: &str,
        relative_manifest: &str,
        options: &Options,
    ) -> CargoResult<Config> {
        let shell = ::cargo::core::Shell::new();
        let cwd = env::current_dir()
            .chain_err(|| "Cargo couldn't get the current directory of the process")?;

        let homedir = ::cargo::util::homedir(&cwd).ok_or_else(|| {
            "Cargo couldn't find your home directory. \
             This probably means that $HOME was not set."
        })?;
        let mut cwd = PathBuf::from(format!("{}/{}", root, relative_manifest));
        cwd.pop();
        let config = Config::new(shell, cwd, homedir);
        config.configure(
            0,
            if options.flag_verbose > 0 {
                None
            } else {
                Some(true)
            },
            &options.flag_color,
            options.flag_frozen,
            options.flag_locked,
        )?;
        Ok(config)
    }

    /// Run `cargo update` against the temporary project
    pub fn cargo_update(&self) -> CargoResult<()> {
        let update_opts = UpdateOptions {
            aggressive: false,
            precise: None,
            to_update: &[],
            config: &self.config,
        };
        update_lockfile(self.workspace.borrow().as_ref().unwrap(), &update_opts)?;
        Ok(())
    }

    fn write_manifest<P: AsRef<Path>>(manifest: &Manifest, path: P) -> CargoResult<()> {
        let mut file = try!(File::create(path));
        let serialized = ::toml::to_string(manifest).expect("Failed to serialized Cargo.toml");
        try!(write!(file, "{}", serialized));
        Ok(())
    }

    /// Write manifests with SemVer requirements
    pub fn write_manifest_semver(&'tmp self) -> CargoResult<()> {
        Self::write_manifest_semver_with_paths(&self.manifest_paths)?;
        let root_manifest = format!(
            "{}/{}",
            self.temp_dir.path().to_string_lossy(),
            self.relative_manifest
        );
        *self.workspace.borrow_mut() =
            Some(Workspace::new(Path::new(&root_manifest), &self.config)?);
        Ok(())
    }

    fn write_manifest_semver_with_paths(manifest_paths: &[PathBuf]) -> CargoResult<()> {
        let bin = {
            let mut bin = Table::new();
            bin.insert("name".to_owned(), Value::String("test".to_owned()));
            bin.insert("path".to_owned(), Value::String("test.rs".to_owned()));
            bin
        };
        for manifest_path in manifest_paths {
            let mut manifest: Manifest = {
                let mut buf = String::new();
                let mut file = File::open(manifest_path)?;
                file.read_to_string(&mut buf)?;
                ::toml::from_str(&buf)?
            };
            manifest.bin = Some(vec![bin.clone()]);
            // provide lib.path
            manifest.lib.as_mut().map(|lib| {
                lib.insert("path".to_owned(), Value::String("test_lib.rs".to_owned()));
            });
            Self::write_manifest(&manifest, manifest_path)?;
        }

        Ok(())
    }

    /// Write manifests with wildcard requirements
    pub fn write_manifest_latest(&'tmp self) -> CargoResult<()> {
        let bin = {
            let mut bin = Table::new();
            bin.insert("name".to_owned(), Value::String("test".to_owned()));
            bin.insert("path".to_owned(), Value::String("test.rs".to_owned()));
            bin
        };
        for manifest_path in &self.manifest_paths {
            let mut manifest: Manifest = {
                let mut buf = String::new();
                let mut file = File::open(manifest_path)?;
                file.read_to_string(&mut buf)?;
                ::toml::from_str(&buf)?
            };
            manifest.bin = Some(vec![bin.clone()]);

            // provide lib.path
            manifest.lib.as_mut().map(|lib| {
                lib.insert("path".to_owned(), Value::String("test_lib.rs".to_owned()));
            });

            // replace versions of direct dependencies
            manifest
                .dependencies
                .as_mut()
                .map(Self::replace_version_with_wildcard);
            manifest
                .dev_dependencies
                .as_mut()
                .map(Self::replace_version_with_wildcard);
            manifest
                .build_dependencies
                .as_mut()
                .map(Self::replace_version_with_wildcard);

            // replace target-specific dependencies
            manifest
                .target
                .as_mut()
                .map(|ref mut t| for target in t.values_mut() {
                    if let Value::Table(ref mut target) = *target {
                        for dependency_tables in
                            &["dependencies", "dev-dependencies", "build-dependencies"]
                        {
                            target.get_mut(*dependency_tables).map(|dep_table| {
                                if let Value::Table(ref mut dep_table) = *dep_table {
                                    Self::replace_version_with_wildcard(dep_table);
                                }
                            });
                        }
                    }
                });
            Self::write_manifest(&manifest, manifest_path)?;
        }

        let root_manifest = format!(
            "{}/{}",
            self.temp_dir.path().to_string_lossy(),
            self.relative_manifest
        );
        *self.workspace.borrow_mut() =
            Some(Workspace::new(Path::new(&root_manifest), &self.config)?);
        Ok(())
    }

    fn replace_version_with_wildcard(dependencies: &mut Table) {
        let dep_names: Vec<_> = dependencies.keys().cloned().collect();
        for name in dep_names {
            let original = dependencies.get(&name).cloned().unwrap();
            match original {
                Value::String(_) => {
                    dependencies.insert(name, Value::String("*".to_owned()));
                }
                Value::Table(ref t) => {
                    if t.contains_key("path") {
                        continue;
                    }
                    let mut replaced = t.clone();
                    if replaced.contains_key("version") {
                        replaced.insert("version".to_owned(), Value::String("*".to_owned()));
                    }
                    dependencies.insert(name, Value::Table(replaced));
                }
                _ => panic!("Dependency spec is neither a string nor a table {}", name),
            }
        }
    }
}

fn manifest_paths(elab: &ElaborateWorkspace) -> CargoResult<Vec<PathBuf>> {
    let mut visited: HashSet<PackageId> = HashSet::new();
    let mut manifest_paths = vec![];
    let workspace_members: HashSet<_> = elab.workspace
        .members()
        .map(|pkg| pkg.package_id())
        .collect();
    for member in &workspace_members {
        manifest_paths.push(elab.pkgs[member].manifest_path().to_owned());
    }
    let root_pkg = elab.workspace.current()?.package_id();
    // e.g. /path/to/project
    let workspace_path = elab.workspace.current()?.root().to_string_lossy();

    fn manifest_paths_recursive(
        pkg_id: &PackageId,
        elab: &ElaborateWorkspace,
        workspace_path: &str,
        members: &HashSet<&PackageId>,
        visited: &mut HashSet<PackageId>,
        manifest_paths: &mut Vec<PathBuf>,
    ) -> CargoResult<()> {
        if visited.contains(pkg_id) {
            return Ok(());
        }
        visited.insert(pkg_id.clone());
        if !members.contains(pkg_id) {
            let pkg = &elab.pkgs[pkg_id];
            let pkg_path = pkg.root().to_string_lossy();
            if pkg_path.len() >= workspace_path.len() &&
                &pkg_path[..workspace_path.len()] == workspace_path
            {
                manifest_paths.push(pkg.manifest_path().to_owned());
            }
        }

        for dep in elab.pkg_deps[pkg_id].keys() {
            manifest_paths_recursive(dep, elab, workspace_path, members, visited, manifest_paths)?;
        }

        Ok(())
    };
    manifest_paths_recursive(
        root_pkg,
        elab,
        &workspace_path,
        &workspace_members,
        &mut visited,
        &mut manifest_paths,
    )?;

    Ok(manifest_paths)
}
<commit_msg>fix: relative path handling<commit_after>use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::io::{Read, Write};
use std::collections::HashSet;
use std::env;
use std::rc::Rc;
use std::cell::RefCell;

use tempdir::TempDir;
use toml::Value;
use toml::value::Table;
use cargo::util::errors::CargoResultExt;
use cargo::core::{PackageId, Workspace};
use cargo::util::{CargoError, CargoErrorKind, CargoResult, Config};
use cargo::ops::{update_lockfile, UpdateOptions};

use Options;
use super::{ElaborateWorkspace, Manifest};

/// A temporary project
pub struct TempProject<'tmp> {
    pub workspace: Rc<RefCell<Option<Workspace<'tmp>>>>,
    pub temp_dir: TempDir,
    manifest_paths: Vec<PathBuf>,
    config: Config,
    relative_manifest: String,
}

impl<'tmp> TempProject<'tmp> {
    /// Copy needed manifest and lock files from an existing workspace
    pub fn from_workspace(
        orig_workspace: &ElaborateWorkspace,
        orig_manifest: &str,
        options: &Options,
    ) -> CargoResult<TempProject<'tmp>> {
        // e.g. /path/to/project
        let workspace_root = orig_workspace.workspace.root().to_str().ok_or_else(|| {
            CargoError::from_kind(CargoErrorKind::Msg(format!(
                "Invalid character found in path {}",
                orig_workspace.workspace.root().to_string_lossy()
            )))
        })?;

        let temp_dir = TempDir::new("cargo-outdated")?;
        let manifest_paths = manifest_paths(orig_workspace)?;
        let mut tmp_manifest_paths = vec![];
        for from in &manifest_paths {
            // e.g. /path/to/project/src/sub
            let mut from_dir = from.clone();
            from_dir.pop();
            let from_dir = from_dir.to_string_lossy();
            // e.g. /tmp/cargo.xxx/src/sub
            let mut dest = PathBuf::from(format!(
                "{}/{}",
                temp_dir.path().to_string_lossy(),
                &from_dir[workspace_root.len()..]
            ));
            fs::create_dir_all(&dest)?;
            // e.g. /tmp/cargo.xxx/src/sub/Cargo.toml
            dest.push("Cargo.toml");
            tmp_manifest_paths.push(dest.clone());
            fs::copy(from, &dest)?;
            let lockfile = PathBuf::from(format!("{}/Cargo.lock", from_dir));
            if lockfile.is_file() {
                dest.pop();
                dest.push("Cargo.lock");
                fs::copy(lockfile, dest)?;
            }
        }
        Self::write_manifest_semver_with_paths(
            &tmp_manifest_paths,
            workspace_root,
            &temp_dir.path().to_string_lossy(),
        )?;

        // virtual root
        let mut virtual_root = PathBuf::from(format!("{}/Cargo.toml", workspace_root));
        if !manifest_paths.contains(&virtual_root) && virtual_root.is_file() {
            fs::copy(
                &virtual_root,
                format!("{}/Cargo.toml", temp_dir.path().to_string_lossy()),
            )?;
            virtual_root.pop();
            virtual_root.push("Cargo.lock");
            if virtual_root.is_file() {
                fs::copy(
                    &virtual_root,
                    format!("{}/Cargo.lock", temp_dir.path().to_string_lossy()),
                )?;
            }
        }

        let relative_manifest = String::from(
            &orig_manifest[orig_workspace.workspace.root().to_string_lossy().len()..],
        );
        let config = Self::generate_config(
            &temp_dir.path().to_string_lossy(),
            &relative_manifest,
            options,
        )?;
        Ok(TempProject {
            // workspace: Workspace::new(Path::new(&root_manifest), config)?,
            workspace: Rc::new(RefCell::new(None)),
            temp_dir: temp_dir,
            manifest_paths: tmp_manifest_paths,
            config: config,
            relative_manifest: relative_manifest,
        })
    }

    fn generate_config(
        root: &str,
        relative_manifest: &str,
        options: &Options,
    ) -> CargoResult<Config> {
        let shell = ::cargo::core::Shell::new();
        let cwd = env::current_dir()
            .chain_err(|| "Cargo couldn't get the current directory of the process")?;

        let homedir = ::cargo::util::homedir(&cwd).ok_or_else(|| {
            "Cargo couldn't find your home directory. \
             This probably means that $HOME was not set."
        })?;
        let mut cwd = PathBuf::from(format!("{}/{}", root, relative_manifest));
        cwd.pop();
        let config = Config::new(shell, cwd, homedir);
        config.configure(
            0,
            if options.flag_verbose > 0 {
                None
            } else {
                Some(true)
            },
            &options.flag_color,
            options.flag_frozen,
            options.flag_locked,
        )?;
        Ok(config)
    }

    /// Run `cargo update` against the temporary project
    pub fn cargo_update(&self) -> CargoResult<()> {
        let update_opts = UpdateOptions {
            aggressive: false,
            precise: None,
            to_update: &[],
            config: &self.config,
        };
        update_lockfile(self.workspace.borrow().as_ref().unwrap(), &update_opts)?;
        Ok(())
    }

    fn write_manifest<P: AsRef<Path>>(manifest: &Manifest, path: P) -> CargoResult<()> {
        let mut file = try!(File::create(path));
        let serialized = ::toml::to_string(manifest).expect("Failed to serialized Cargo.toml");
        try!(write!(file, "{}", serialized));
        Ok(())
    }

    fn manipulate_dependencies(manifest: &mut Manifest, f: &Fn(&mut Table)) {
        manifest.dependencies.as_mut().map(f);
        manifest.dev_dependencies.as_mut().map(f);
        manifest.build_dependencies.as_mut().map(f);
        manifest
            .target
            .as_mut()
            .map(|ref mut t| for target in t.values_mut() {
                if let Value::Table(ref mut target) = *target {
                    for dependency_tables in
                        &["dependencies", "dev-dependencies", "build-dependencies"]
                    {
                        target.get_mut(*dependency_tables).map(|dep_table| {
                            if let Value::Table(ref mut dep_table) = *dep_table {
                                f(dep_table);
                            }
                        });
                    }
                }
            });
    }

    /// Write manifests with SemVer requirements
    pub fn write_manifest_semver(&'tmp self) -> CargoResult<()> {
        let root_manifest = format!(
            "{}/{}",
            self.temp_dir.path().to_string_lossy(),
            self.relative_manifest
        );
        *self.workspace.borrow_mut() =
            Some(Workspace::new(Path::new(&root_manifest), &self.config)?);
        Ok(())
    }

    fn write_manifest_semver_with_paths<P: AsRef<Path>>(
        manifest_paths: &[PathBuf],
        orig_root: P,
        tmp_root: P,
    ) -> CargoResult<()> {
        let bin = {
            let mut bin = Table::new();
            bin.insert("name".to_owned(), Value::String("test".to_owned()));
            bin.insert("path".to_owned(), Value::String("test.rs".to_owned()));
            bin
        };
        for manifest_path in manifest_paths {
            let mut manifest: Manifest = {
                let mut buf = String::new();
                let mut file = File::open(manifest_path)?;
                file.read_to_string(&mut buf)?;
                ::toml::from_str(&buf)?
            };
            manifest.bin = Some(vec![bin.clone()]);
            // provide lib.path
            manifest.lib.as_mut().map(|lib| {
                lib.insert("path".to_owned(), Value::String("test_lib.rs".to_owned()));
            });
            Self::manipulate_dependencies(&mut manifest, &|deps| {
                Self::replace_path_with_absolute(
                    deps,
                    orig_root.as_ref(),
                    tmp_root.as_ref(),
                    manifest_path,
                )
            });
            Self::write_manifest(&manifest, manifest_path)?;
        }

        Ok(())
    }

    /// Write manifests with wildcard requirements
    pub fn write_manifest_latest(&'tmp self) -> CargoResult<()> {
        let bin = {
            let mut bin = Table::new();
            bin.insert("name".to_owned(), Value::String("test".to_owned()));
            bin.insert("path".to_owned(), Value::String("test.rs".to_owned()));
            bin
        };
        for manifest_path in &self.manifest_paths {
            let mut manifest: Manifest = {
                let mut buf = String::new();
                let mut file = File::open(manifest_path)?;
                file.read_to_string(&mut buf)?;
                ::toml::from_str(&buf)?
            };
            manifest.bin = Some(vec![bin.clone()]);
            // provide lib.path
            manifest.lib.as_mut().map(|lib| {
                lib.insert("path".to_owned(), Value::String("test_lib.rs".to_owned()));
            });
            Self::manipulate_dependencies(&mut manifest, &Self::replace_version_with_wildcard);
            Self::write_manifest(&manifest, manifest_path)?;
        }

        let root_manifest = format!(
            "{}/{}",
            self.temp_dir.path().to_string_lossy(),
            self.relative_manifest
        );
        *self.workspace.borrow_mut() =
            Some(Workspace::new(Path::new(&root_manifest), &self.config)?);
        Ok(())
    }

    fn replace_version_with_wildcard(dependencies: &mut Table) {
        let dep_names: Vec<_> = dependencies.keys().cloned().collect();
        for name in dep_names {
            let original = dependencies.get(&name).cloned().unwrap();
            match original {
                Value::String(_) => {
                    dependencies.insert(name, Value::String("*".to_owned()));
                }
                Value::Table(ref t) => {
                    if t.contains_key("path") {
                        continue;
                    }
                    let mut replaced = t.clone();
                    if replaced.contains_key("version") {
                        replaced.insert("version".to_owned(), Value::String("*".to_owned()));
                    }
                    dependencies.insert(name, Value::Table(replaced));
                }
                _ => panic!("Dependency spec is neither a string nor a table {}", name),
            }
        }
    }

    fn replace_path_with_absolute(
        dependencies: &mut Table,
        orig_root: &Path,
        tmp_root: &Path,
        tmp_manifest: &Path,
    ) {
        let dep_names: Vec<_> = dependencies.keys().cloned().collect();
        for name in dep_names {
            let original = dependencies.get(&name).cloned().unwrap();
            match original {
                Value::Table(ref t) if t.contains_key("path") => {
                    if let Value::String(ref orig_path) = t["path"] {
                        let orig_path = Path::new(orig_path);
                        if orig_path.is_relative() {
                            let relative = {
                                let delimiter: &[_] = &['/', '\\'];
                                let relative = &tmp_manifest.to_string_lossy()
                                    [tmp_root.to_string_lossy().len()..];
                                let mut relative =
                                    PathBuf::from(relative.trim_left_matches(delimiter));
                                relative.pop();
                                relative.join(orig_path)
                            };
                            if !tmp_root.join(&relative).join("Cargo.toml").exists() {
                                let mut replaced = t.clone();
                                replaced.insert(
                                    "path".to_owned(),
                                    Value::String(
                                        fs::canonicalize(orig_root.join(relative))
                                            .unwrap()
                                            .to_string_lossy()
                                            .to_string(),
                                    ),
                                );
                                dependencies.insert(name, Value::Table(replaced));
                            }
                        }
                    }
                }
                _ => {}
            }
        }
    }
}

fn manifest_paths(elab: &ElaborateWorkspace) -> CargoResult<Vec<PathBuf>> {
    let mut visited: HashSet<PackageId> = HashSet::new();
    let mut manifest_paths = vec![];
    let workspace_members: HashSet<_> = elab.workspace
        .members()
        .map(|pkg| pkg.package_id())
        .collect();
    for member in &workspace_members {
        manifest_paths.push(elab.pkgs[member].manifest_path().to_owned());
    }
    let root_pkg = elab.workspace.current()?.package_id();
    // e.g. /path/to/project
    let workspace_path = elab.workspace.current()?.root().to_string_lossy();

    fn manifest_paths_recursive(
        pkg_id: &PackageId,
        elab: &ElaborateWorkspace,
        workspace_path: &str,
        members: &HashSet<&PackageId>,
        visited: &mut HashSet<PackageId>,
        manifest_paths: &mut Vec<PathBuf>,
    ) -> CargoResult<()> {
        if visited.contains(pkg_id) {
            return Ok(());
        }
        visited.insert(pkg_id.clone());
        if !members.contains(pkg_id) {
            let pkg = &elab.pkgs[pkg_id];
            let pkg_path = pkg.root().to_string_lossy();
            if pkg_path.starts_with(workspace_path) {
                manifest_paths.push(pkg.manifest_path().to_owned());
            }
        }

        for dep in elab.pkg_deps[pkg_id].keys() {
            manifest_paths_recursive(dep, elab, workspace_path, members, visited, manifest_paths)?;
        }

        Ok(())
    };
    manifest_paths_recursive(
        root_pkg,
        elab,
        &workspace_path,
        &workspace_members,
        &mut visited,
        &mut manifest_paths,
    )?;

    Ok(manifest_paths)
}
<|endoftext|>


<commit_before>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```
//! # #[allow(unused_extern_crates)]
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```
//! # #[allow(unused_imports)]
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
//!   traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//!   reasons, but shouldn't have to exist. It provides a few useful methods on
//!   slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/first-edition/closures.html
//! [book-dtor]: ../../book/first-edition/drop.html
//! [book-enums]: ../../book/first-edition/enums.html
//! [book-iter]: ../../book/first-edition/iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Rollup merge of #57683 - xfix:patch-15, r=QuietMisdreavus<commit_after>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! On a technical level, Rust inserts
//!
//! ```
//! # #[allow(unused_extern_crates)]
//! extern crate std;
//! ```
//!
//! into the crate root of every crate, and
//!
//! ```
//! # #[allow(unused_imports)]
//! use std::prelude::v1::*;
//! ```
//!
//! into every module.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::slice`]::[`SliceConcatExt`], a trait that exists for technical
//!   reasons, but shouldn't have to exist. It provides a few useful methods on
//!   slices.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/first-edition/closures.html
//! [book-dtor]: ../../book/first-edition/drop.html
//! [book-enums]: ../../book/first-edition/enums.html
//! [book-iter]: ../../book/first-edition/iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! A collection of handlers for the HTTP server's router

use std::result;
use std::sync::{Arc, Mutex};

use bodyparser;
use hab_net;
use hab_net::routing::Broker;
use hab_net::oauth::github::GitHubClient;
use iron::prelude::*;
use iron::status;
use iron::headers::{Authorization, Bearer};
use protobuf;
use protocol::jobsrv::{Job, JobCreate, JobGet};
use protocol::sessionsrv::{OAuthProvider, Session, SessionCreate, SessionGet};
use protocol::vault::*;
use protocol::net::{self, NetError, ErrCode};
use router::Router;
use rustc_serialize::json::{self, ToJson};
use zmq;

pub fn authenticate(req: &mut Request,
                    ctx: &Arc<Mutex<zmq::Context>>)
                    -> result::Result<Session, Response> {
    match req.headers.get::<Authorization<Bearer>>() {
        Some(&Authorization(Bearer { ref token })) => {
            let mut conn = Broker::connect(&ctx).unwrap();
            let mut request = SessionGet::new();
            request.set_token(token.to_string());
            conn.route(&request).unwrap();
            match conn.recv() {
                Ok(rep) => {
                    match rep.get_message_id() {
                        "Session" => {
                            let session = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                            Ok(session)
                        }
                        "NetError" => {
                            let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                            Err(render_net_error(&err))
                        }

                        _ => unreachable!("unexpected msg: {:?}", rep),
                    }
                }
                Err(e) => {
                    error!("session get, err={:?}", e);
                    Err(Response::with(status::InternalServerError))
                }
            }
        }
        _ => Err(Response::with(status::Unauthorized)),
    }
}

pub fn session_create(req: &mut Request,
                      github: &GitHubClient,
                      ctx: &Arc<Mutex<zmq::Context>>)
                      -> IronResult<Response> {
    let params = req.extensions.get::<Router>().unwrap();
    let code = match params.find("code") {
        Some(code) => code,
        _ => return Ok(Response::with(status::BadRequest)),
    };
    match github.authenticate(code) {
        Ok(token) => {
            match github.user(&token) {
                Ok(user) => {
                    let mut conn = Broker::connect(&ctx).unwrap();
                    let mut request = SessionCreate::new();
                    request.set_token(token);
                    request.set_extern_id(user.id);
                    if let Some(email) = user.email {
                        request.set_email(email);
                    }
                    request.set_name(user.login);
                    request.set_provider(OAuthProvider::GitHub);
                    conn.route(&request).unwrap();
                    match conn.recv() {
                        Ok(rep) => {
                            match rep.get_message_id() {
                                "Session" => {
                                    let token: Session = protobuf::parse_from_bytes(rep.get_body())
                                        .unwrap();
                                    let encoded = json::encode(&token.to_json()).unwrap();
                                    Ok(Response::with((status::Ok, encoded)))
                                }
                                "NetError" => {
                                    let err: NetError = protobuf::parse_from_bytes(rep.get_body())
                                        .unwrap();
                                    Ok(render_net_error(&err))
                                }
                                _ => unreachable!("unexpected msg: {:?}", rep),
                            }
                        }
                        Err(e) => {
                            error!("{:?}", e);
                            Ok(Response::with(status::ServiceUnavailable))
                        }
                    }
                }
                Err(e @ hab_net::Error::JsonDecode(_)) => {
                    debug!("github user get, err={:?}", e);
                    let err = net::err(ErrCode::BAD_REMOTE_REPLY, "rg:auth:1");
                    Ok(render_net_error(&err))
                }
                Err(e) => {
                    debug!("github user get, err={:?}", e);
                    let err = net::err(ErrCode::BUG, "ss:auth:2");
                    Ok(render_net_error(&err))
                }
            }
        }
        Err(hab_net::Error::Auth(e)) => {
            debug!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::REMOTE_REJECTED, e.error);
            Ok(render_net_error(&err))
        }
        Err(e @ hab_net::Error::JsonDecode(_)) => {
            debug!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::BAD_REMOTE_REPLY, "ss:auth:1");
            Ok(render_net_error(&err))
        }
        Err(e) => {
            error!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::BUG, "ss:auth:0");
            Ok(render_net_error(&err))
        }
    }
}

pub fn origin_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let params = req.extensions.get::<Router>().unwrap();
    let origin = match params.find("origin") {
        Some(origin) => origin.to_string(),
        _ => return Ok(Response::with(status::BadRequest)),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = OriginGet::new();
    request.set_name(origin);
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Origin" => {
                    let origin: Origin = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&origin.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn origin_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };
    let mut request = OriginCreate::new();
    request.set_owner_id(session.get_id());
    match req.get::<bodyparser::Json>() {
        Ok(Some(body)) => {
            match body.find("name") {
                Some(origin) => request.set_name(origin.as_string().unwrap().to_owned()),
                _ => return Ok(Response::with(status::BadRequest)),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Origin" => {
                    let origin: Origin = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&origin.to_json()).unwrap();
                    Ok(Response::with((status::Created, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn job_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = JobCreate::new();
    request.set_owner_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Job" => {
                    let job: Job = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&job.to_json()).unwrap();
                    Ok(Response::with((status::Created, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn job_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let params = req.extensions.get::<Router>().unwrap();
    let id = match params.find("id") {
        Some(id) => {
            match id.parse() {
                Ok(id) => id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = JobGet::new();
    request.set_id(id);
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Job" => {
                    let job: Job = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&job.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

/// Endpoint for determining availability of builder-api components.
///
/// Returns a status 200 on success. Any non-200 responses are an outage or a partial outage.
pub fn status(_req: &mut Request) -> IronResult<Response> {
    Ok(Response::with(status::Ok))
}

/// Return an IronResult containing the body of a NetError and the appropriate HTTP response status
/// for the corresponding NetError.
///
/// For example, a NetError::ENTITY_NOT_FOUND will result in an HTTP response containing the body
/// of the NetError with an HTTP status of 404.
///
/// # Panics
///
/// * The given encoded message was not a NetError
/// * The given messsage could not be decoded
/// * The NetError could not be encoded to JSON
fn render_net_error(err: &NetError) -> Response {
    let encoded = json::encode(&err.to_json()).unwrap();
    let status = match err.get_code() {
        ErrCode::ENTITY_NOT_FOUND => status::NotFound,
        ErrCode::NO_SHARD => status::ServiceUnavailable,
        ErrCode::TIMEOUT => status::RequestTimeout,
        ErrCode::BAD_REMOTE_REPLY => status::BadGateway,
        ErrCode::SESSION_EXPIRED => status::Unauthorized,
        _ => status::InternalServerError,
    };
    Response::with((status, encoded))
}

pub fn list_account_invitations(req: &mut Request,
                                ctx: &Arc<Mutex<zmq::Context>>)
                                -> IronResult<Response> {
    debug!("list_account_invitations");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };

    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = AccountInvitationListRequest::new();
    request.set_account_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "AccountInvitationListResponse" => {
                    let invites: AccountInvitationListResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&invites.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn list_user_origins(req: &mut Request,
                         ctx: &Arc<Mutex<zmq::Context>>)
                         -> IronResult<Response> {
    debug!("list_user_origins");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };

    let mut conn = Broker::connect(&ctx).unwrap();

    let mut request = AccountOriginListRequest::new();
    request.set_account_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "AccountOriginListResponse" => {
                    let invites: AccountOriginListResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&invites.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn accept_invitation(req: &mut Request,
                         ctx: &Arc<Mutex<zmq::Context>>)
                         -> IronResult<Response> {
    debug!("accept_invitation");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };
    let params = &req.extensions.get::<Router>().unwrap();

    let invitation_id = match params.find("invitation_id") {
        Some(ref invitation_id) => {
            match invitation_id.parse::<u64>() {
                Ok(v) => v,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };

    // TODO: read the body to determine "ignore"
    let ignore_val = false;

    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = OriginInvitationAcceptRequest::new();

    // make sure we're not trying to accept someone else's request
    request.set_account_accepting_request(session.get_id());
    request.set_invite_id(invitation_id);
    request.set_ignore(ignore_val);

    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "OriginInvitationAcceptResponse" => {
                    let _invites: OriginInvitationAcceptResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    // empty response
                    Ok(Response::with(status::Ok))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}
<commit_msg>remove unused code paths & fix log messages<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! A collection of handlers for the HTTP server's router

use std::result;
use std::sync::{Arc, Mutex};

use hab_net;
use hab_net::routing::Broker;
use hab_net::oauth::github::GitHubClient;
use iron::prelude::*;
use iron::status;
use iron::headers::{Authorization, Bearer};
use protobuf;
use protocol::jobsrv::{Job, JobCreate, JobGet};
use protocol::sessionsrv::{OAuthProvider, Session, SessionCreate, SessionGet};
use protocol::vault::*;
use protocol::net::{self, NetError, ErrCode};
use router::Router;
use rustc_serialize::json::{self, ToJson};
use zmq;

pub fn authenticate(req: &mut Request,
                    ctx: &Arc<Mutex<zmq::Context>>)
                    -> result::Result<Session, Response> {
    match req.headers.get::<Authorization<Bearer>>() {
        Some(&Authorization(Bearer { ref token })) => {
            let mut conn = Broker::connect(&ctx).unwrap();
            let mut request = SessionGet::new();
            request.set_token(token.to_string());
            conn.route(&request).unwrap();
            match conn.recv() {
                Ok(rep) => {
                    match rep.get_message_id() {
                        "Session" => {
                            let session = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                            Ok(session)
                        }
                        "NetError" => {
                            let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                            Err(render_net_error(&err))
                        }

                        _ => unreachable!("unexpected msg: {:?}", rep),
                    }
                }
                Err(e) => {
                    error!("session get, err={:?}", e);
                    Err(Response::with(status::InternalServerError))
                }
            }
        }
        _ => Err(Response::with(status::Unauthorized)),
    }
}

pub fn session_create(req: &mut Request,
                      github: &GitHubClient,
                      ctx: &Arc<Mutex<zmq::Context>>)
                      -> IronResult<Response> {
    let params = req.extensions.get::<Router>().unwrap();
    let code = match params.find("code") {
        Some(code) => code,
        _ => return Ok(Response::with(status::BadRequest)),
    };
    match github.authenticate(code) {
        Ok(token) => {
            match github.user(&token) {
                Ok(user) => {
                    let mut conn = Broker::connect(&ctx).unwrap();
                    let mut request = SessionCreate::new();
                    request.set_token(token);
                    request.set_extern_id(user.id);
                    if let Some(email) = user.email {
                        request.set_email(email);
                    }
                    request.set_name(user.login);
                    request.set_provider(OAuthProvider::GitHub);
                    conn.route(&request).unwrap();
                    match conn.recv() {
                        Ok(rep) => {
                            match rep.get_message_id() {
                                "Session" => {
                                    let token: Session = protobuf::parse_from_bytes(rep.get_body())
                                        .unwrap();
                                    let encoded = json::encode(&token.to_json()).unwrap();
                                    Ok(Response::with((status::Ok, encoded)))
                                }
                                "NetError" => {
                                    let err: NetError = protobuf::parse_from_bytes(rep.get_body())
                                        .unwrap();
                                    Ok(render_net_error(&err))
                                }
                                _ => unreachable!("unexpected msg: {:?}", rep),
                            }
                        }
                        Err(e) => {
                            error!("{:?}", e);
                            Ok(Response::with(status::ServiceUnavailable))
                        }
                    }
                }
                Err(e @ hab_net::Error::JsonDecode(_)) => {
                    debug!("github user get, err={:?}", e);
                    let err = net::err(ErrCode::BAD_REMOTE_REPLY, "rg:auth:1");
                    Ok(render_net_error(&err))
                }
                Err(e) => {
                    debug!("github user get, err={:?}", e);
                    let err = net::err(ErrCode::BUG, "rg:auth:2");
                    Ok(render_net_error(&err))
                }
            }
        }
        Err(hab_net::Error::Auth(e)) => {
            debug!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::REMOTE_REJECTED, e.error);
            Ok(render_net_error(&err))
        }
        Err(e @ hab_net::Error::JsonDecode(_)) => {
            debug!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::BAD_REMOTE_REPLY, "rg:auth:1");
            Ok(render_net_error(&err))
        }
        Err(e) => {
            error!("github authentication, err={:?}", e);
            let err = net::err(ErrCode::BUG, "rg:auth:0");
            Ok(render_net_error(&err))
        }
    }
}

pub fn job_create(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = JobCreate::new();
    request.set_owner_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Job" => {
                    let job: Job = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&job.to_json()).unwrap();
                    Ok(Response::with((status::Created, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn job_show(req: &mut Request, ctx: &Arc<Mutex<zmq::Context>>) -> IronResult<Response> {
    let params = req.extensions.get::<Router>().unwrap();
    let id = match params.find("id") {
        Some(id) => {
            match id.parse() {
                Ok(id) => id,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        _ => return Ok(Response::with(status::BadRequest)),
    };
    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = JobGet::new();
    request.set_id(id);
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "Job" => {
                    let job: Job = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&job.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

/// Endpoint for determining availability of builder-api components.
///
/// Returns a status 200 on success. Any non-200 responses are an outage or a partial outage.
pub fn status(_req: &mut Request) -> IronResult<Response> {
    Ok(Response::with(status::Ok))
}

/// Return an IronResult containing the body of a NetError and the appropriate HTTP response status
/// for the corresponding NetError.
///
/// For example, a NetError::ENTITY_NOT_FOUND will result in an HTTP response containing the body
/// of the NetError with an HTTP status of 404.
///
/// # Panics
///
/// * The given encoded message was not a NetError
/// * The given messsage could not be decoded
/// * The NetError could not be encoded to JSON
fn render_net_error(err: &NetError) -> Response {
    let encoded = json::encode(&err.to_json()).unwrap();
    let status = match err.get_code() {
        ErrCode::ENTITY_NOT_FOUND => status::NotFound,
        ErrCode::NO_SHARD => status::ServiceUnavailable,
        ErrCode::TIMEOUT => status::RequestTimeout,
        ErrCode::BAD_REMOTE_REPLY => status::BadGateway,
        ErrCode::SESSION_EXPIRED => status::Unauthorized,
        _ => status::InternalServerError,
    };
    Response::with((status, encoded))
}

pub fn list_account_invitations(req: &mut Request,
                                ctx: &Arc<Mutex<zmq::Context>>)
                                -> IronResult<Response> {
    debug!("list_account_invitations");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };

    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = AccountInvitationListRequest::new();
    request.set_account_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "AccountInvitationListResponse" => {
                    let invites: AccountInvitationListResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&invites.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn list_user_origins(req: &mut Request,
                         ctx: &Arc<Mutex<zmq::Context>>)
                         -> IronResult<Response> {
    debug!("list_user_origins");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };

    let mut conn = Broker::connect(&ctx).unwrap();

    let mut request = AccountOriginListRequest::new();
    request.set_account_id(session.get_id());
    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "AccountOriginListResponse" => {
                    let invites: AccountOriginListResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    let encoded = json::encode(&invites.to_json()).unwrap();
                    Ok(Response::with((status::Ok, encoded)))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}

pub fn accept_invitation(req: &mut Request,
                         ctx: &Arc<Mutex<zmq::Context>>)
                         -> IronResult<Response> {
    debug!("accept_invitation");
    let session = match authenticate(req, ctx) {
        Ok(session) => session,
        Err(response) => return Ok(response),
    };
    let params = &req.extensions.get::<Router>().unwrap();

    let invitation_id = match params.find("invitation_id") {
        Some(ref invitation_id) => {
            match invitation_id.parse::<u64>() {
                Ok(v) => v,
                Err(_) => return Ok(Response::with(status::BadRequest)),
            }
        }
        None => return Ok(Response::with(status::BadRequest)),
    };

    // TODO: read the body to determine "ignore"
    let ignore_val = false;

    let mut conn = Broker::connect(&ctx).unwrap();
    let mut request = OriginInvitationAcceptRequest::new();

    // make sure we're not trying to accept someone else's request
    request.set_account_accepting_request(session.get_id());
    request.set_invite_id(invitation_id);
    request.set_ignore(ignore_val);

    conn.route(&request).unwrap();
    match conn.recv() {
        Ok(rep) => {
            match rep.get_message_id() {
                "OriginInvitationAcceptResponse" => {
                    let _invites: OriginInvitationAcceptResponse =
                        protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    // empty response
                    Ok(Response::with(status::Ok))
                }
                "NetError" => {
                    let err: NetError = protobuf::parse_from_bytes(rep.get_body()).unwrap();
                    Ok(render_net_error(&err))
                }
                _ => unreachable!("unexpected msg: {:?}", rep),
            }
        }
        Err(e) => {
            error!("{:?}", e);
            Ok(Response::with(status::ServiceUnavailable))
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    if env::var_os("CARGO_FEATURE_CLI_ADMIN").is_some() {
        let schema_path = out_path.join("graphql-schema.json");

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "--path", src_dir.as_ref(),
                "--bin", "turingarena-graphql-schema",
                "--root", out_path.to_str().unwrap(),
                "--force",
                "--debug",
                "--offline",
                "--no-default-features",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
            .status()
            .unwrap();

        let schema_file = File::create(&schema_path).unwrap();

        Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
            .stdout(schema_file)
            .status()
            .unwrap();

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "graphql_client_cli",
                "--root", out_path.to_str().unwrap(),
                "--force",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
            .status()
            .unwrap();

        Command::new(out_path.join("bin").join("graphql-client"))
            .args(&[
                "generate",
                "--output-directory", out_path.to_str().unwrap(),
                "--schema-path", schema_path.to_str().unwrap(),
                src_path.join("src").join("operations.graphql").to_str().unwrap(),
            ])
            .status()
            .unwrap();
    }

}
<commit_msg>contest: call cargo verbosely in build script<commit_after>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    if env::var_os("CARGO_FEATURE_CLI_ADMIN").is_some() {
        let schema_path = out_path.join("graphql-schema.json");

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "--path", src_dir.as_ref(),
                "--bin", "turingarena-graphql-schema",
                "--root", out_path.to_str().unwrap(),
                "--force",
                "--debug",
                "--offline",
                "--no-default-features",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
            .status()
            .unwrap();

        let schema_file = File::create(&schema_path).unwrap();

        Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
            .stdout(schema_file)
            .status()
            .unwrap();

        Command::new(env::var("CARGO").unwrap())
            .args(&[
                "install",
                "-vv",
                "graphql_client_cli",
                "--root", out_path.to_str().unwrap(),
                "--force",
            ])
            .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
            .status()
            .unwrap();

        Command::new(out_path.join("bin").join("graphql-client"))
            .args(&[
                "generate",
                "--output-directory", out_path.to_str().unwrap(),
                "--schema-path", schema_path.to_str().unwrap(),
                src_path.join("src").join("operations.graphql").to_str().unwrap(),
            ])
            .status()
            .unwrap();
    }

}
<|endoftext|>


<commit_before>pub static LITERAL_EXPRESSION : &'static str = "LiteralExpression";

mod literal;
mod not;
mod and;
mod char_class;
mod dot;
mod option;
// mod star;
// mod plus;
// mod parens;
// mod or;
// mod sequence;
mod unicode;
mod unescape;
mod test_utils;

#[deriving(Show, Eq)]
enum NodeContents<'a> {
  Data( &'a [u8] ),
  Children( ~[ Node<'a> ] ),
  Empty
}

#[deriving(Show, Eq)]
struct Node<'a> {
  name: &'static str,
  start: uint,
  end: uint,
  contents: NodeContents<'a>
}

impl<'a> Node<'a> {
  // fn matchedData( &self ) -> ~[u8] {
  //   match self.contents {
  //     Empty => ~"",
  //     Data( ref x ) => x.to_owned(),
  //
  //     // TODO: recurse through children and collect all text
  //     Children( _ ) => ~"foo"
  //   }
  // }

  // TODO: methods in_order/pre_order/post_order that yield
  // iterators for walking the node tree structure

  fn predicate( name: &'static str ) -> Node {
    Node { name: name, start: 0, end: 0, contents: Empty }
  }
}

#[deriving(Show, Clone, Eq)]
struct ParseState<'a> {
  input: &'a [u8],  // Unconsumed input from "main" slice.
  offset: uint  // Offset of 'input' from start of "main" slice.
}

impl<'a> ParseState<'a> {
  fn advanceTo( &self, new_offset: uint ) -> ParseState<'a> {
    let mut clone = self.clone();
    clone.input = clone.input.slice_from( new_offset - clone.offset );
    clone.offset = new_offset;
    clone
  }

  fn sliceTo( &self, new_offset: uint ) -> &'a [u8] {
    self.input.slice_to( new_offset - self.offset )
  }

  fn nameAndOffsetToResult( &self, node_name: &'static str, new_offset: uint )
      -> Option< ParseResult<'a> > {
    Some( ParseResult::oneNode(
        Node { name: node_name,
               start: self.offset,
               end: new_offset,
               contents: Data( self.sliceTo( new_offset ) ) },
        self.advanceTo( new_offset ) ) )
  }
}

struct ParseResult<'a> {
  nodes: ~[ Node<'a> ],
  parse_state: ParseState<'a>
}

impl<'a> ParseResult<'a> {
  fn oneNode<'a>( node: Node<'a>, parse_state: ParseState<'a> )
      -> ParseResult<'a> {
    ParseResult { nodes: ~[ node ], parse_state: parse_state }
  }

  fn manyNodes<'a>( nodes: ~[ Node<'a> ], parse_state: ParseState<'a> )
      -> ParseResult<'a> {
    ParseResult { nodes: nodes, parse_state: parse_state }
  }
}

trait Expression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> >;
}

// TODO: We should pass around the lifetime of 'input' to other functions and
// thus avoild allocating Data and stuff
pub fn parseBytes<'a>( input: &'a [u8] ) -> Node<'a> {
  Node { name: LITERAL_EXPRESSION,
         start: 0,
         end: 3,
         contents: Data( input ) }
}

<commit_msg>Not duplicating the LITERAL_EXPRESSION anymore<commit_after>use parser::literal::LITERAL_EXPRESSION;

mod literal;
mod not;
mod and;
mod char_class;
mod dot;
mod option;
// mod star;
// mod plus;
// mod parens;
// mod or;
// mod sequence;
mod unicode;
mod unescape;
mod test_utils;

#[deriving(Show, Eq)]
enum NodeContents<'a> {
  Data( &'a [u8] ),
  Children( ~[ Node<'a> ] ),
  Empty
}

#[deriving(Show, Eq)]
struct Node<'a> {
  name: &'static str,
  start: uint,
  end: uint,
  contents: NodeContents<'a>
}

impl<'a> Node<'a> {
  // fn matchedData( &self ) -> ~[u8] {
  //   match self.contents {
  //     Empty => ~"",
  //     Data( ref x ) => x.to_owned(),
  //
  //     // TODO: recurse through children and collect all text
  //     Children( _ ) => ~"foo"
  //   }
  // }

  // TODO: methods in_order/pre_order/post_order that yield
  // iterators for walking the node tree structure

  fn predicate( name: &'static str ) -> Node {
    Node { name: name, start: 0, end: 0, contents: Empty }
  }
}

#[deriving(Show, Clone, Eq)]
struct ParseState<'a> {
  input: &'a [u8],  // Unconsumed input from "main" slice.
  offset: uint  // Offset of 'input' from start of "main" slice.
}

impl<'a> ParseState<'a> {
  fn advanceTo( &self, new_offset: uint ) -> ParseState<'a> {
    let mut clone = self.clone();
    clone.input = clone.input.slice_from( new_offset - clone.offset );
    clone.offset = new_offset;
    clone
  }

  fn sliceTo( &self, new_offset: uint ) -> &'a [u8] {
    self.input.slice_to( new_offset - self.offset )
  }

  fn nameAndOffsetToResult( &self, node_name: &'static str, new_offset: uint )
      -> Option< ParseResult<'a> > {
    Some( ParseResult::oneNode(
        Node { name: node_name,
               start: self.offset,
               end: new_offset,
               contents: Data( self.sliceTo( new_offset ) ) },
        self.advanceTo( new_offset ) ) )
  }
}

struct ParseResult<'a> {
  nodes: ~[ Node<'a> ],
  parse_state: ParseState<'a>
}

impl<'a> ParseResult<'a> {
  fn oneNode<'a>( node: Node<'a>, parse_state: ParseState<'a> )
      -> ParseResult<'a> {
    ParseResult { nodes: ~[ node ], parse_state: parse_state }
  }

  fn manyNodes<'a>( nodes: ~[ Node<'a> ], parse_state: ParseState<'a> )
      -> ParseResult<'a> {
    ParseResult { nodes: nodes, parse_state: parse_state }
  }
}

trait Expression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> >;
}

// TODO: We should pass around the lifetime of 'input' to other functions and
// thus avoild allocating Data and stuff
pub fn parseBytes<'a>( input: &'a [u8] ) -> Node<'a> {
  Node { name: LITERAL_EXPRESSION,
         start: 0,
         end: 3,
         contents: Data( input ) }
}

<|endoftext|>


<commit_before>use flowgger::config::Config;
use openssl::bn::BigNum;
use openssl::dh::DH;
use openssl::ssl::*;
use openssl::x509::X509FileType;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use openssl::x509::X509;

pub mod tls_input;
#[cfg(feature = "coroutines")]
pub mod tlsco_input;

pub use super::Input;

const DEFAULT_CERT: &'static str = "flowgger.pem";
const DEFAULT_CIPHERS: &'static str = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
const DEFAULT_COMPRESSION: bool = false;
const DEFAULT_FRAMING: &'static str = "line";
const DEFAULT_KEY: &'static str = "flowgger.pem";
const DEFAULT_LISTEN: &'static str = "0.0.0.0:6514";
#[cfg(feature = "coroutines")]
const DEFAULT_THREADS: usize = 1;
const DEFAULT_TIMEOUT: u64 = 3600;
const DEFAULT_TLS_METHOD: &'static str = "any";
const DEFAULT_VERIFY_PEER: bool = false;
const TLS_VERIFY_DEPTH: u32 = 6;

#[derive(Clone)]
pub struct TlsConfig {
    framing: String,
    threads: usize,
    arc_ctx: Arc<SslContext>
}

#[cfg(feature = "ecdh")]
fn set_ecdh(ctx: &mut SslContext) {
    ctx.set_ecdh_auto(true).unwrap();
}

#[cfg(not(feature = "ecdh"))]
fn set_ecdh(ctx: &mut SslContext) {
    let _ = ctx;
}

fn set_fs(ctx: &mut SslContext) {
    let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap();
    let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap();
    let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap();
    let dh = DH::from_params(p, g, q).unwrap();
    ctx.set_tmp_dh(dh).unwrap();
    set_ecdh(ctx);
}

#[cfg(feature = "coroutines")]
fn get_default_threads(config: &Config) -> usize {
    config.lookup("input.tls_threads").map_or(DEFAULT_THREADS, |x| x.as_integer().
        expect("input.tls_threads must be an unsigned integer") as usize)
}

#[cfg(not(feature = "coroutines"))]
fn get_default_threads(_config: &Config) -> usize {
    1
}

pub fn config_parse(config: &Config) -> (TlsConfig, String, u64) {
    let listen = config.lookup("input.listen").map_or(DEFAULT_LISTEN, |x| x.as_str().
        expect("input.listen must be an ip:port string")).to_owned();
    let threads = get_default_threads(&config);
    let cert = config.lookup("input.tls_cert").map_or(DEFAULT_CERT, |x| x.as_str().
        expect("input.tls_cert must be a path to a .pem file")).to_owned();
    let key = config.lookup("input.tls_key").map_or(DEFAULT_KEY, |x| x.as_str().
        expect("input.tls_key must be a path to a .pem file")).to_owned();
    let ciphers = config.lookup("input.tls_ciphers").map_or(DEFAULT_CIPHERS, |x| x.as_str().
        expect("input.tls_ciphers must be a string with a cipher suite")).to_owned();
    let tls_method = match config.lookup("input.tls_method").map_or(DEFAULT_TLS_METHOD, |x| x.as_str().
        expect("input.tls_method must be a string with the TLS method")).to_lowercase().as_ref() {
            "any" | "sslv23" => SslMethod::Sslv23,
            "tlsv1" | "tlsv1.0" => SslMethod::Tlsv1,
            "tlsv1.1" => SslMethod::Tlsv1_1,
            "tlsv1.2" => SslMethod::Tlsv1_2,
            _ => panic!(r#"TLS method must be "any", "TLSv1.0", "TLSv1.1" or "TLSv1.2""#)
    };
    let verify_peer = config.lookup("input.tls_verify_peer").map_or(DEFAULT_VERIFY_PEER, |x| x.as_bool().
        expect("input.tls_verify_peer must be a boolean"));
    let ca_file: Option<PathBuf> = config.lookup("input.tls_ca_file").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_ca_file must be a path to a file"))));
    let compression = config.lookup("input.tls_compression").map_or(DEFAULT_COMPRESSION, |x| x.as_bool().
        expect("input.tls_compression must be a boolean"));
    let cert_chain_file_path: Option<PathBuf> = config.lookup("input.tls_cert_chain").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_cert_chain must be a path to a file"))));
    let timeout = config.lookup("input.timeout").map_or(DEFAULT_TIMEOUT, |x| x.as_integer().
        expect("input.timeout must be an integer") as u64);
    let framing = if config.lookup("input.framed").map_or(false, |x| x.as_bool().
        expect("input.framed must be a boolean")) {
        "syslen"
    } else {
        DEFAULT_FRAMING
    };
    let framing = config.lookup("input.framing").map_or(framing, |x| x.as_str().
        expect(r#"input.framing must be a string set to "line", "nul" or "syslen""#)).to_owned();
    let mut ctx = SslContext::new(tls_method).unwrap();
    if verify_peer == false {
        ctx.set_verify(SSL_VERIFY_NONE, None);
    } else {
        ctx.set_verify_depth(TLS_VERIFY_DEPTH);
        ctx.set_verify(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, None);
    }
    if let Some(ca_file) = ca_file {
            ctx.set_CA_file(&ca_file).expect("Unable to read the trusted CA file");
    }
    if let Some(cert_chain_file_path) = cert_chain_file_path {
         let mut cert_chain_file = File::open(cert_chain_file_path.as_path())
             .ok()
             .expect("Failed to open the extra chain cert file");
         let cert_chain_x509 = X509::from_pem(&mut cert_chain_file).ok().expect("unable to load the provided extra chain cert");
         ctx.add_extra_chain_cert(&cert_chain_x509).expect("Unable to read the certificate chain");
    }

    let mut opts = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    if compression == false {
        opts = opts | SSL_OP_NO_COMPRESSION;
    }
    ctx.set_options(opts);
    set_fs(&mut ctx);
    ctx.set_certificate_file(&Path::new(&cert), X509FileType::PEM).
        expect("Unable to read the TLS certificate");
    ctx.set_private_key_file(&Path::new(&key), X509FileType::PEM).
        expect("Unable to read the TLS key");
    ctx.set_cipher_list(&ciphers).expect("Unsupported cipher suite");
    let arc_ctx = Arc::new(ctx);
    let tls_config = TlsConfig {
        framing: framing,
        threads: threads,
        arc_ctx: arc_ctx
    };
    (tls_config, listen, timeout)
}
<commit_msg>Revert "TLS: allow to set CA file when the user wants (to use cert chain completion feature) and variables renaming"<commit_after>use flowgger::config::Config;
use openssl::bn::BigNum;
use openssl::dh::DH;
use openssl::ssl::*;
use openssl::x509::X509FileType;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use openssl::x509::X509;

pub mod tls_input;
#[cfg(feature = "coroutines")]
pub mod tlsco_input;

pub use super::Input;

const DEFAULT_CERT: &'static str = "flowgger.pem";
const DEFAULT_CIPHERS: &'static str = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
const DEFAULT_COMPRESSION: bool = false;
const DEFAULT_FRAMING: &'static str = "line";
const DEFAULT_KEY: &'static str = "flowgger.pem";
const DEFAULT_LISTEN: &'static str = "0.0.0.0:6514";
#[cfg(feature = "coroutines")]
const DEFAULT_THREADS: usize = 1;
const DEFAULT_TIMEOUT: u64 = 3600;
const DEFAULT_TLS_METHOD: &'static str = "any";
const DEFAULT_VERIFY_PEER: bool = false;
const TLS_VERIFY_DEPTH: u32 = 6;

#[derive(Clone)]
pub struct TlsConfig {
    framing: String,
    threads: usize,
    arc_ctx: Arc<SslContext>
}

#[cfg(feature = "ecdh")]
fn set_ecdh(ctx: &mut SslContext) {
    ctx.set_ecdh_auto(true).unwrap();
}

#[cfg(not(feature = "ecdh"))]
fn set_ecdh(ctx: &mut SslContext) {
    let _ = ctx;
}

fn set_fs(ctx: &mut SslContext) {
    let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap();
    let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap();
    let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3").unwrap();
    let dh = DH::from_params(p, g, q).unwrap();
    ctx.set_tmp_dh(dh).unwrap();
    set_ecdh(ctx);
}

#[cfg(feature = "coroutines")]
fn get_default_threads(config: &Config) -> usize {
    config.lookup("input.tls_threads").map_or(DEFAULT_THREADS, |x| x.as_integer().
        expect("input.tls_threads must be an unsigned integer") as usize)
}

#[cfg(not(feature = "coroutines"))]
fn get_default_threads(_config: &Config) -> usize {
    1
}

pub fn config_parse(config: &Config) -> (TlsConfig, String, u64) {
    let listen = config.lookup("input.listen").map_or(DEFAULT_LISTEN, |x| x.as_str().
        expect("input.listen must be an ip:port string")).to_owned();
    let threads = get_default_threads(&config);
    let cert = config.lookup("input.tls_cert").map_or(DEFAULT_CERT, |x| x.as_str().
        expect("input.tls_cert must be a path to a .pem file")).to_owned();
    let key = config.lookup("input.tls_key").map_or(DEFAULT_KEY, |x| x.as_str().
        expect("input.tls_key must be a path to a .pem file")).to_owned();
    let ciphers = config.lookup("input.tls_ciphers").map_or(DEFAULT_CIPHERS, |x| x.as_str().
        expect("input.tls_ciphers must be a string with a cipher suite")).to_owned();
    let tls_method = match config.lookup("input.tls_method").map_or(DEFAULT_TLS_METHOD, |x| x.as_str().
        expect("input.tls_method must be a string with the TLS method")).to_lowercase().as_ref() {
            "any" | "sslv23" => SslMethod::Sslv23,
            "tlsv1" | "tlsv1.0" => SslMethod::Tlsv1,
            "tlsv1.1" => SslMethod::Tlsv1_1,
            "tlsv1.2" => SslMethod::Tlsv1_2,
            _ => panic!(r#"TLS method must be "any", "TLSv1.0", "TLSv1.1" or "TLSv1.2""#)
    };
    let verify_peer = config.lookup("input.tls_verify_peer").map_or(DEFAULT_VERIFY_PEER, |x| x.as_bool().
        expect("input.tls_verify_peer must be a boolean"));
    let ca_file: Option<PathBuf> = config.lookup("input.tls_ca_file").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_ca_file must be a path to a file"))));
    let compression = config.lookup("input.tls_compression").map_or(DEFAULT_COMPRESSION, |x| x.as_bool().
        expect("input.tls_compression must be a boolean"));
    let extra_chain_path: Option<PathBuf> = config.lookup("input.tls_cert_chain").map_or(None, |x|
        Some(PathBuf::from(x.as_str().expect("input.tls_extra_chain_path must be a path to a file"))));
    let timeout = config.lookup("input.timeout").map_or(DEFAULT_TIMEOUT, |x| x.as_integer().
        expect("input.timeout must be an integer") as u64);
    let framing = if config.lookup("input.framed").map_or(false, |x| x.as_bool().
        expect("input.framed must be a boolean")) {
        "syslen"
    } else {
        DEFAULT_FRAMING
    };
    let framing = config.lookup("input.framing").map_or(framing, |x| x.as_str().
        expect(r#"input.framing must be a string set to "line", "nul" or "syslen""#)).to_owned();
    let mut ctx = SslContext::new(tls_method).unwrap();
    if verify_peer == false {
        ctx.set_verify(SSL_VERIFY_NONE, None);
    } else {
        ctx.set_verify_depth(TLS_VERIFY_DEPTH);
        ctx.set_verify(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, None);
        if let Some(ca_file) = ca_file {
            ctx.set_CA_file(&ca_file).expect("Unable to read the trusted CA file");
        }
    }
    if let Some(extra_chain_path) = extra_chain_path {
         let mut extra_chain_file = File::open(extra_chain_path.as_path())
             .ok()
             .expect("Failed to open the extra chain cert file");
         let extra_chain_cert = X509::from_pem(&mut extra_chain_file).ok().expect("unable to load the provided extra chain cert");
         ctx.add_extra_chain_cert(&extra_chain_cert).expect("Unable to read the certificate chain");
    }

    let mut opts = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    if compression == false {
        opts = opts | SSL_OP_NO_COMPRESSION;
    }
    ctx.set_options(opts);
    set_fs(&mut ctx);
    ctx.set_certificate_file(&Path::new(&cert), X509FileType::PEM).
        expect("Unable to read the TLS certificate");
    ctx.set_private_key_file(&Path::new(&key), X509FileType::PEM).
        expect("Unable to read the TLS key");
    ctx.set_cipher_list(&ciphers).expect("Unsupported cipher suite");
    let arc_ctx = Arc::new(ctx);
    let tls_config = TlsConfig {
        framing: framing,
        threads: threads,
        arc_ctx: arc_ctx
    };
    (tls_config, listen, timeout)
}
<|endoftext|>