<commit_before>use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use rustc_serialize::hex::ToHex;
use rustc_serialize::json;

use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use sources::PathSource;
use util::{CargoResult, human, ChainError, Config, Sha256};
use util::paths;

pub struct DirectorySource<'cfg> {
    source_id: SourceId,
    root: PathBuf,
    packages: HashMap<PackageId, (Package, Checksum)>,
    config: &'cfg Config,
}

#[derive(RustcDecodable)]
struct Checksum {
    package: String,
    files: HashMap<String, String>,
}

impl<'cfg> DirectorySource<'cfg> {
    pub fn new(path: &Path, id: &SourceId, config: &'cfg Config)
               -> DirectorySource<'cfg> {
        DirectorySource {
            source_id: id.clone(),
            root: path.to_path_buf(),
            config: config,
            packages: HashMap::new(),
        }
    }
}

impl<'cfg> Debug for DirectorySource<'cfg> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "DirectorySource {{ root: {:?} }}", self.root)
    }
}

impl<'cfg> Registry for DirectorySource<'cfg> {
    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
        let packages = self.packages.values().map(|p| &p.0);
        let matches = packages.filter(|pkg| dep.matches(pkg.summary()));
        let summaries = matches.map(|pkg| pkg.summary().clone());
        Ok(summaries.collect())
    }

    fn supports_checksums(&self) -> bool {
        true
    }
}

impl<'cfg> Source for DirectorySource<'cfg> {
    fn source_id(&self) -> &SourceId {
        &self.source_id
    }

    fn update(&mut self) -> CargoResult<()> {
        self.packages.clear();
        let entries = self.root.read_dir().chain_error(|| {
            human(format!("failed to read root of directory source: {}",
                          self.root.display()))
        })?;

        for entry in entries {
            let entry = entry?;
            let path = entry.path();
            let mut src = PathSource::new(&path, &self.source_id, self.config);
            src.update()?;
            let pkg = src.root_package()?;

            let cksum_file = path.join(".cargo-checksum.json");<commit_msg>Auto merge of #3417 - alexcrichton:fix-svn, r=brson<commit_after>use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use rustc_serialize::hex::ToHex;
use rustc_serialize::json;

use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use sources::PathSource;
use util::{CargoResult, human, ChainError, Config, Sha256};
use util::paths;

pub struct DirectorySource<'cfg> {
    source_id: SourceId,
    root: PathBuf,
    packages: HashMap<PackageId, (Package, Checksum)>,
    config: &'cfg Config,
}

#[derive(RustcDecodable)]
struct Checksum {
    package: String,
    files: HashMap<String, String>,
}

impl<'cfg> DirectorySource<'cfg> {
    pub fn new(path: &Path, id: &SourceId, config: &'cfg Config)
               -> DirectorySource<'cfg> {
        DirectorySource {
            source_id: id.clone(),
            root: path.to_path_buf(),
            config: config,
            packages: HashMap::new(),
        }
    }
}

impl<'cfg> Debug for DirectorySource<'cfg> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "DirectorySource {{ root: {:?} }}", self.root)
    }
}

impl<'cfg> Registry for DirectorySource<'cfg> {
    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
        let packages = self.packages.values().map(|p| &p.0);
        let matches = packages.filter(|pkg| dep.matches(pkg.summary()));
        let summaries = matches.map(|pkg| pkg.summary().clone());
        Ok(summaries.collect())
    }

    fn supports_checksums(&self) -> bool {
        true
    }
}

impl<'cfg> Source for DirectorySource<'cfg> {
    fn source_id(&self) -> &SourceId {
        &self.source_id
    }

    fn update(&mut self) -> CargoResult<()> {
        self.packages.clear();
        let entries = self.root.read_dir().chain_error(|| {
            human(format!("failed to read root of directory source: {}",
                          self.root.display()))
        })?;

        for entry in entries {
            let entry = entry?;
            let path = entry.path();

            // Ignore hidden/dot directories as they typically don't contain
            // crates and otherwise may conflict with a VCS
            // (rust-lang/cargo#3414).
            if let Some(s) = path.file_name().and_then(|s| s.to_str()) {
                if s.starts_with(".") {
                    continue
                }
            }

            let mut src = PathSource::new(&path, &self.source_id, self.config);
            src.update()?;
            let pkg = src.root_package()?;

            let cksum_file = path.join(".cargo-checksum.json");
{'fraction_non_alphanumeric': 0.15387689848121502, 'fraction_numerical': 0.0031974420463629096, 'mean_word_length': 2.624185372918175, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4714869', 'n_tokens_mistral': 1558, 'n_tokens_neox': 1556, 'n_words': 361}