From 1138579bf4783deda4115683277a4e95d0c2f12b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 16 Jan 2015 17:19:41 -0500 Subject: [PATCH] Add regression test for #20797. Fixes #20797. --- src/test/run-pass/issue-20797.rs | 91 ++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/test/run-pass/issue-20797.rs diff --git a/src/test/run-pass/issue-20797.rs b/src/test/run-pass/issue-20797.rs new file mode 100644 index 0000000000000..c4f3c33f26983 --- /dev/null +++ b/src/test/run-pass/issue-20797.rs @@ -0,0 +1,91 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #20797. + +use std::default::Default; +use std::io::IoResult; +use std::io::fs; +use std::io::fs::PathExtensions; + +/// A strategy for acquiring more subpaths to walk. +pub trait Strategy { + type P: PathExtensions; + /// Get additional subpaths from a given path. + fn get_more(&self, item: &Self::P) -> IoResult>; + /// Determine whether a path should be walked further. + /// This is run against each item from `get_more()`. + fn prune(&self, p: &Self::P) -> bool; +} + +/// The basic fully-recursive strategy. Nothing is pruned. +#[derive(Copy, Default)] +pub struct Recursive; + +impl Strategy for Recursive { + type P = Path; + fn get_more(&self, p: &Path) -> IoResult> { fs::readdir(p) } + + fn prune(&self, _: &Path) -> bool { false } +} + +/// A directory walker of `P` using strategy `S`. +pub struct Subpaths { + stack: Vec, + strategy: S, +} + +impl Subpaths { + /// Create a directory walker with a root path and strategy. + pub fn new(p: &S::P, strategy: S) -> IoResult> { + let stack = try!(strategy.get_more(p)); + Ok(Subpaths { stack: stack, strategy: strategy }) + } +} + +impl Subpaths { + /// Create a directory walker with a root path and a default strategy. + pub fn walk(p: &S::P) -> IoResult> { + Subpaths::new(p, Default::default()) + } +} + +impl Default for Subpaths { + fn default() -> Subpaths { + Subpaths { stack: Vec::new(), strategy: Default::default() } + } +} + +impl Iterator for Subpaths { + type Item = S::P; + fn next (&mut self) -> Option { + let mut opt_path = self.stack.pop(); + while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { + opt_path = self.stack.pop(); + } + match opt_path { + Some(path) => { + if PathExtensions::is_dir(&path) { + let result = self.strategy.get_more(&path); + match result { + Ok(dirs) => { self.stack.extend(dirs.into_iter()); }, + Err(..) => { } + } + } + Some(path) + } + None => None, + } + } +} + +fn main() { + let mut walker: Subpaths = Subpaths::walk(&Path::new("/home")).unwrap(); +}