fs_tools is a filesystem utilities crate providing temporary directory path management via the TempDir structure and Unix shell-style glob pattern matching via re-export of the glob crate. It serves as a foundation for filesystem operations within the wTools workspace.
Version: 0.1.0 Status: Experimental (Early Development) Category: Utilities (Filesystem) Dependents: Unknown (likely testing utilities)
Provide filesystem manipulation utilities, currently limited to temporary directory path management through the TempDir structure, with plans for future expansion to general file and directory operations.
-
TempDir Structure
- Path management for temporary directories
- Three configurable path components: base, prefix, postfix
- Simple constructor
new()with empty defaults - Public field access for all path components
- RAII cleanup for directories created via
create()/create_all()
-
Path Components
base_path: PathBuf- Base directory pathprefix_path: PathBuf- Prefix path componentpostfix_path: PathBuf- Postfix path component
-
Directory Operations
TempDir::new()- Create instance with empty pathsfull_path()- Construct full path from componentscreate()- Create directory (parent must exist)create_all()- Create directory and all parents- Automatic cleanup on Drop for created directories
-
Feature Gating
enabled- Master switch (default)glob- Re-exports glob crate (requires enabled)full- Enables all features including glob- Requires
not(no_std)for TempDir functionality - Only TempDir requires std library; glob works in std mode
-
Glob Pattern Matching (via re-export)
glob::glob()- Find files matching a patternglob::glob_with()- Pattern matching with optionsglob::Pattern- Compiled glob patternglob::MatchOptions- Matching configuration- Error types:
GlobError,PatternError - Iterator type:
Paths
-
Traditional Module Organization
- Nested
fsmodule structure - Standard namespaces: own, orphan, exposed, prelude
- Not using mod_interface! (utility crate)
- Nested
-
Optional Dependencies
globcrate (optional, viaglobfeature)- Uses std::path::PathBuf for TempDir
- Minimal core implementation
-
NOT File Operations
- No file reading/writing
- No file manipulation
- Rationale: Future enhancement
-
NOT Path Validation
- Does not validate paths exist
- Does not check permissions
- Rationale: Simple data structure only
-
NOT Temporary File Management
- Only directory paths, not files
- No temporary file creation
- Rationale: Focused on directories
-
NOT Cross-Platform Abstractions
- No platform-specific path handling
- Relies on std::path::PathBuf semantics
- Rationale: std provides cross-platform support
-
NOT Atomic Operations
- No atomic file operations
- No locking mechanisms
- Rationale: Out of scope for current implementation
-
NOT Recursive Operations
- No recursive directory traversal
- No recursive deletion
- Rationale: Not yet implemented
- fs_tools vs std::fs: fs_tools currently minimal wrapper; std::fs provides actual filesystem operations
- fs_tools vs tempfile: fs_tools is path container; tempfile creates actual temp directories with RAII
- fs_tools vs test utilities: fs_tools provides structure; test utilities like assert_fs provide testing facilities
fs_tools (utilities)
├── Optional Dependencies
│ └── glob (workspace, optional via glob feature)
├── Internal Dependencies
│ └── (none - foundational utility)
└── Dev Dependencies
└── test_tools (workspace, testing)
Note: Core functionality has zero dependencies; glob is optional.
fs_tools
├── src/fs/lib.rs (top-level wrapper)
├── src/fs/fs.rs (implementation)
│ └── TempDir struct
└── Standard namespaces: own, orphan, exposed, prelude
Pattern: Nested fs module with traditional namespace organization
enabled (master switch, default)
├── Requires not(no_std) for TempDir
├── Provides TempDir
│
glob (pattern matching)
├── Requires enabled
├── Re-exports glob crate
├── Provides glob(), glob_with(), Pattern, MatchOptions
│
full (all features)
├── enabled
└── glob
│
no_std (minimal mode)
└── use_alloc (unused, would enable allocation in no_std)
Default Features: enabled
Full Features: enabled, glob
Note: TempDir disabled in no_std mode; glob requires enabled feature
TempDir {
base_path: PathBuf (public, empty by default)
prefix_path: PathBuf (public, empty by default)
postfix_path: PathBuf (public, empty by default)
created_path: Option<PathBuf> (private, tracks RAII cleanup)
}
Usage Flow:
TempDir::new()
↓
Set base_path, prefix_path, postfix_path
↓
Call full_path() to construct: base / prefix / postfix
↓
Call create() or create_all() to make directory
↓
Automatic cleanup on Drop (only for create()-created directories)
Design Decision: RAII cleanup only applies to directories created via create() or create_all(). Manually set paths don't trigger cleanup on Drop.
The glob module is a clean re-export of the external glob crate:
fs_tools::glob (when feature = "glob")
├── glob() - Find files matching pattern
├── glob_with() - Find files with options
├── Pattern - Compiled glob pattern
├── MatchOptions - Matching configuration
├── Paths - Iterator over matching paths
├── GlobError - Error during iteration
└── PatternError - Invalid pattern error
Access Patterns:
fs_tools::glob::glob()- Primary accessfs_tools::dependency::glob::*- Via dependency namespace
/// Temporary directory management with RAII cleanup.
#[cfg(all(feature = "enabled", not(feature = "no_std")))]
#[derive(Debug)]
pub struct TempDir {
/// Base directory path
pub base_path: PathBuf,
/// Prefix path component
pub prefix_path: PathBuf,
/// Postfix path component
pub postfix_path: PathBuf,
// Private: tracks path created by create()/create_all() for RAII cleanup
created_path: Option<PathBuf>,
}impl TempDir {
/// Creates a new TempDir with empty paths.
/// No automatic cleanup is enabled until create()/create_all() is called.
pub fn new() -> Self
/// Returns full path by joining base, prefix, and postfix components.
/// Empty components are skipped during joining.
pub fn full_path( &self ) -> PathBuf
/// Creates the directory at full_path().
/// Parent directory must exist. Enables RAII cleanup on Drop.
pub fn create( &mut self ) -> io::Result<PathBuf>
/// Creates the directory at full_path() and all parent directories.
/// Enables RAII cleanup on Drop.
pub fn create_all( &mut self ) -> io::Result<PathBuf>
}
impl Drop for TempDir {
/// Removes directory if created by create()/create_all().
/// Errors during removal are silently ignored.
fn drop( &mut self )
}/// Re-export of glob crate for pattern matching
#[cfg(feature = "glob")]
pub use ::glob;
// Key types accessible via fs_tools::glob::
// - glob() - Find files matching a pattern
// - glob_with() - Find files with MatchOptions
// - Pattern - Compiled glob pattern for matching
// - MatchOptions - Configuration for matching behavior
// - Paths - Iterator over matched paths
// - GlobError - Error during path iteration
// - PatternError - Invalid pattern syntax erroruse fs_tools::TempDir;
let temp_dir = TempDir::new();
assert!(temp_dir.base_path.as_os_str().is_empty());
assert!(temp_dir.prefix_path.as_os_str().is_empty());
assert!(temp_dir.postfix_path.as_os_str().is_empty());use fs_tools::TempDir;
use std::path::PathBuf;
let mut temp_dir = TempDir::new();
temp_dir.base_path = PathBuf::from("/tmp");
temp_dir.prefix_path = PathBuf::from("test");
temp_dir.postfix_path = PathBuf::from("run_1");
// Full path would be: /tmp/test/run_1
// (but directory is not created automatically)use fs_tools::TempDir;
use std::path::PathBuf;
let mut temp_dir = TempDir::new();
temp_dir.base_path = PathBuf::from("/tmp");
// Access fields directly
let base = &temp_dir.base_path;
let prefix = &temp_dir.prefix_path;
let postfix = &temp_dir.postfix_path;
println!("Base: {:?}", base);use fs_tools::TempDir;
use std::path::PathBuf;
let mut temp_dir = TempDir::new();
temp_dir.base_path = std::env::temp_dir();
temp_dir.prefix_path = PathBuf::from( "my_app" );
temp_dir.postfix_path = PathBuf::from( "session_1" );
// Create directory (enables RAII cleanup)
let path = temp_dir.create_all().expect( "failed to create" );
assert!( path.is_dir() );
// Use the directory...
// Directory is automatically removed when temp_dir goes out of scopeuse fs_tools::TempDir;
use std::path::PathBuf;
let mut temp_dir = TempDir::new();
temp_dir.base_path = std::env::temp_dir();
temp_dir.postfix_path = PathBuf::from( format!( "test_{}", std::process::id() ) );
// create() requires parent to exist (use create_all() for nested paths)
let path = temp_dir.create().expect( "failed to create" );
assert!( path.is_dir() );
// Automatically cleaned up on dropuse fs_tools::TempDir;
use std::path::PathBuf;
let mut temp_dir = TempDir::new();
temp_dir.base_path = PathBuf::from( "/tmp" );
temp_dir.prefix_path = PathBuf::from( "test" );
temp_dir.postfix_path = PathBuf::from( "run_1" );
// Get composed path without creating directory
let full = temp_dir.full_path();
assert_eq!( full, PathBuf::from( "/tmp/test/run_1" ) );
// No cleanup on drop (create() was never called)#[ cfg( feature = "glob" ) ]
{
use fs_tools::glob::glob;
// Find all Rust files in current directory
for entry in glob( "*.rs" ).expect( "valid pattern" )
{
if let Ok( path ) = entry
{
println!( "{:?}", path );
}
}
}#[ cfg( feature = "glob" ) ]
{
use fs_tools::glob::glob;
// Find all Rust files recursively
for entry in glob( "src/**/*.rs" ).expect( "valid pattern" )
{
if let Ok( path ) = entry
{
println!( "{:?}", path );
}
}
}#[ cfg( feature = "glob" ) ]
{
use fs_tools::glob::Pattern;
let pattern = Pattern::new( "*.rs" ).expect( "valid pattern" );
assert!( pattern.matches( "lib.rs" ) );
assert!( pattern.matches( "main.rs" ) );
assert!( !pattern.matches( "Cargo.toml" ) );
}#[ cfg( feature = "glob" ) ]
{
use fs_tools::glob::{ glob_with, MatchOptions };
let options = MatchOptions
{
case_sensitive : true,
require_literal_separator : false,
require_literal_leading_dot : false,
};
for entry in glob_with( "/tmp/*.txt", options ).expect( "valid pattern" )
{
if let Ok( path ) = entry
{
println!( "{:?}", path );
}
}
}Production (optional):
glob(workspace, optional viaglobfeature) - Pattern matching
Dev:
test_tools(workspace) - Testing utilities
Likely used by:
- Test utilities
- Build tools
- Temporary file management in workspace tools
Usage Pattern: Currently very limited due to minimal functionality. Consumers likely use TempDir as a path container, managing actual directory creation/deletion themselves.
TempDir only stores paths without creating directories:
Current State: Minimal implementation Rationale:
- Early Development: Crate is v0.1.0, experimental status
- Foundation: Establishes structure for future features
- Simplicity: No dependencies or complex logic yet
Future Enhancement: Will likely add directory creation, cleanup, RAII
All TempDir fields are public:
Benefits:
- Simplicity: Easy to set and read
- Flexibility: No builder pattern overhead
- Transparency: Clear what the structure contains
Tradeoff: No encapsulation, but acceptable for simple data container
Uses base/prefix/postfix instead of single path:
Intended Design:
- base_path: Shared temp root (e.g., /tmp)
- prefix_path: Test-specific prefix (e.g., test_name)
- postfix_path: Unique identifier (e.g., timestamp, UUID)
Benefit: Composable paths for test isolation
Current Issue: No method to join these paths automatically
No Drop implementation for cleanup:
Rationale:
- Not Implemented: Early development stage
- Safety Concerns: Need careful handling of filesystem errors
- Future Work: Likely to be added in later versions
Current Workaround: Users must manually call fs::remove_dir_all
Disabled in no_std mode:
Rationale:
- PathBuf Requirement: std::path::PathBuf not available in no_std
- Filesystem Operations: Would require std::fs for directory creation
- Future Design: Could add no_std path management with alloc
Limitation: Cannot use in embedded environments
Only provides new() constructor:
Rationale:
- Early Stage: Crate is experimental, v0.1.0
- Iteration: API will evolve based on usage
- No Premature Complexity: Avoid overdesign
Future: Will likely add builder pattern, path joining, creation methods
test_tools Available:
- Can use test_tools for testing
- 24 tests total (with
--features full):- 3 basic TempDir tests
- 10 TempDir create/RAII tests
- 9 glob re-export tests
- 2 smoke tests
tests/
├── inc/
│ ├── basic_test.rs - TempDir basic tests (3 tests)
│ ├── tempdir_test.rs - TempDir create/RAII tests (11 tests)
│ ├── glob_test.rs - Glob re-export tests (9 tests, requires glob feature)
│ └── mod.rs - Test module organization
├── smoke_test.rs - Smoke tests
└── tests.rs - Test aggregator
Test Matrix (from tests/inc/basic_test.rs):
| ID | Aspect Tested | Expected Behavior |
|---|---|---|
| T1.1 | TempDir creation | TempDir::new() returns valid instance |
| T1.2 | Path access | Can access base_path field |
| T1.3 | Default values | Fields initialize to empty PathBuf |
Test Matrix (from tests/inc/glob_test.rs):
| ID | Aspect Tested | Expected Behavior |
|---|---|---|
| G1.1 | Module accessible | glob module accessible via fs_tools |
| G1.2 | Types accessible | Pattern, MatchOptions, errors are usable |
| G2.1 | Traversal works | glob() finds files matching pattern |
| G2.2 | Glob with options | glob_with() accepts MatchOptions |
| G2.3 | Pattern matching | Pattern::matches() validates strings |
| G2.4 | Pattern with options | matches_with() respects MatchOptions |
| G2.5 | Pattern escape | Pattern::escape() escapes special chars |
| G2.6 | Recursive pattern | **/*.rs finds files in subdirectories |
| G3.1 | Dependency namespace | glob accessible via dependency::glob |
Test Matrix (from tests/inc/tempdir_test.rs):
| ID | Aspect Tested | Expected Behavior |
|---|---|---|
| T2.1 | full_path joins components | base/prefix/postfix joined correctly |
| T2.2 | full_path handles empty | Empty components skipped during join |
| T2.3 | full_path postfix only | Works with only postfix set |
| T3.1 | create creates directory | Directory exists after create() |
| T3.2 | create fails without parent | Returns error if parent missing |
| T4.1 | create_all nested directories | Creates all parent directories |
| T4.2 | create_all idempotent | Succeeds even if directory exists |
| T5.1 | Drop cleans up created directory | Directory removed after drop |
| T5.2 | Drop ignores manual paths | Manually set paths not removed |
| T5.3 | Drop handles already deleted | No panic if directory already removed |
- No Cross-Platform Tests: Doesn't verify Windows/Unix behavior differences
- No Permission Tests: Doesn't test permission denied scenarios
- No Concurrent Access Tests: Doesn't test race conditions
-
Directory Creation✅ IMPLEMENTEDcreate()- Create directory (parent must exist)create_all()- Create directory with all parents
-
Automatic Cleanup (RAII)✅ IMPLEMENTED- Drop implementation removes created directories
- Only affects directories created via create()/create_all()
-
Path Construction✅ IMPLEMENTEDfull_path()- Join base/prefix/postfix into single path
-
Builder Pattern (Future)
TempDir::builder() .base("/tmp") .prefix("test") .create()?
-
UUID/Timestamp Generation
impl TempDir { pub fn with_timestamp() -> Self pub fn with_uuid() -> Self }
-
File Operations
- Read/write files within temp directory
- Copy files in/out
- List contents
- Make Fields Private: Encapsulate with getters/setters
- Require Creation: Make
new()private, only allow viacreate() - Result Return: Make constructor fallible
- Rename: More specific name like
TempDirPathto clarify it's path-only
- No Path Validation: Doesn't check if paths are valid before creation
- No Platform Handling: Doesn't handle Windows vs Unix differences explicitly
- No Uniqueness: Doesn't generate unique paths automatically (user must provide)
- No File Operations: Only handles directories, not files within them
- No Permission Handling: Errors on permission denied, no retry/workaround
Current Recommendation: SUITABLE FOR BASIC USE
The crate now provides functional temporary directory management:
- TempDir with RAII cleanup
- Directory creation (
create(),create_all()) - Path composition (
full_path()) - Glob pattern matching (via re-export)
Consider alternatives for:
- tempfile: More mature, production-proven temp directory handling
- assert_fs: Testing-focused filesystem utilities
- std::fs: General filesystem operations beyond temp directories
Good for:
- Test fixtures requiring temporary directories
- Internal wTools utilities
- Simple temporary workspace needs
Good Candidates (when implemented):
- Test fixtures requiring temporary directories
- Build tools needing temporary workspaces
- CLI tools with temporary file storage
- Isolated test environments
Poor Candidates:
- Production temporary file management (use tempfile)
- Complex filesystem operations (use walkdir, fs_extra)
- no_std environments (requires std)
// Current (working):
let mut td = TempDir::new();
td.base_path = std::env::temp_dir();
td.prefix_path = PathBuf::from( "test" );
td.postfix_path = PathBuf::from( "run_1" );
let path = td.create_all()?;
// ... use path ...
// Automatic cleanup on drop
// Future (with builder pattern):
let td = TempDir::builder()
.base( std::env::temp_dir() )
.prefix( "test" )
.postfix( "run_1" )
.create()?;
// ... use td.full_path() ...
// Automatic cleanup on drop- glob (re-exported): Unix shell-style pattern matching
- tempfile: Full-featured temporary file/directory management (recommended alternative)
- assert_fs: Filesystem testing utilities
- std::fs: Standard library filesystem operations
- fs_extra: Extended filesystem operations (copy, move, etc.)
- walkdir: Directory traversal
- API Documentation
- Repository
- readme.md
- glob crate - Re-exported pattern matching crate
- tempfile crate - Recommended alternative for actual temp directory management
- std::fs - Standard library filesystem operations
Status: This crate is in development (v0.1.0, experimental status). Current functionality includes:
- TempDir: Directory creation with RAII cleanup (
create(),create_all(),full_path()) - glob: Full re-export of the glob crate for pattern matching (via
globfeature)
The specification documents both current state and anticipated future enhancements.
For production use cases requiring advanced features (unique path generation, cross-platform handling, permission management), consider the tempfile crate. For basic temporary directory needs within the wTools ecosystem, fs_tools is now functional.