Add production-ready filesystem operations to filesystem-rs example#555
Conversation
- Add write operations: write-file, create-directory, move-path, delete-file, delete-directory - Add utility operations: file-exists, get-directory-tree - Improve get-file-info with human-readable output (size formatting, timestamps) - Improve search-file with better feedback when no matches found - Add comprehensive error handling with descriptive messages - Add safety checks for delete operations - Update WIT interface with all new functions - Update README with complete documentation and usage examples - Update policy.yaml with write permission example Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
- Update Justfile to automatically inject WIT documentation into compiled component - Ensures tool descriptions and parameter schemas are properly embedded in the WASM component - Adds ensure-wit-docs-inject target to install the tool if not present Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
- Remove wit-docs-inject step that was causing multiple package-docs sections error - Update policy.yaml to use actual test paths instead of USERNAME placeholders - Component successfully builds and loads with all 11 tools Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This PR significantly enhances the filesystem-rs example by adding comprehensive write operations and improving the user experience with better error messages and metadata formatting. The changes transform it from a basic read-only demo into a production-ready filesystem toolkit.
Key changes:
- Adds 7 new filesystem operations: write-file, create-directory, move-path, delete-file, delete-directory, file-exists, and get-directory-tree
- Enhances existing operations with human-readable output (formatted file sizes, readable timestamps) and contextual error messages
- Updates documentation with detailed usage examples and security guidance
Reviewed Changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| examples/filesystem-rs/wit/world.wit | Adds WIT function definitions for 7 new operations with comprehensive documentation |
| examples/filesystem-rs/src/lib.rs | Implements new filesystem operations with safety checks, enhanced error messages, and helper functions (build_tree, format_size) |
| examples/filesystem-rs/src/bindings.rs | Auto-generated bindings updated for new WIT interface (missing required copyright header) |
| examples/filesystem-rs/policy.yaml | Updates example policy with write permissions for /tmp directory for testing |
| examples/filesystem-rs/README.md | Expands documentation with feature list, usage examples, and security features explanation |
| examples/filesystem-rs/Justfile | Minor formatting fix removing trailing whitespace |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Generated by `wit-bindgen` 0.37.0. DO NOT EDIT! | ||
| // Options used: |
There was a problem hiding this comment.
The Microsoft copyright header is missing from this file. According to the project's coding guidelines, ALL Rust files (including generated files) must include the copyright header at the top:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.This header should be placed before the "Generated by" comment, as done in other generated files like examples/fetch-rs/src/bindings.rs.
There was a problem hiding this comment.
Fixed in commit 63655e6. Added the Microsoft copyright header at the top of bindings.rs before the "Generated by" comment.
| if e.kind() == std::io::ErrorKind::Other { | ||
| Err(format!( | ||
| "Failed to delete directory '{}': Directory is not empty. \ | ||
| Remove all contents first.", | ||
| path.display() | ||
| )) |
There was a problem hiding this comment.
The error kind check for non-empty directories is incorrect. On most platforms, attempting to remove a non-empty directory with fs::remove_dir returns std::io::ErrorKind::DirectoryNotEmpty (when available) or platform-specific errors, not ErrorKind::Other.
This check will likely never match the intended condition, causing the helpful error message to not be displayed when it should be. Consider either:
- Checking for the specific error kind if targeting Rust 1.83+ where
DirectoryNotEmptyis stabilized - Checking the error message string content
- Removing this special case handling and letting the OS error message pass through
Example fix:
Err(e) => {
let error_msg = format!("Failed to delete directory '{}': {}", path.display(), e);
// Directory not empty errors often contain "not empty" in the message
if e.to_string().to_lowercase().contains("not empty") {
Err(format!("{} Remove all contents first.", error_msg))
} else {
Err(error_msg)
}
}There was a problem hiding this comment.
Fixed in commit 63655e6. Changed the error detection to check if the error message contains "not empty" instead of checking for ErrorKind::Other, which will now properly detect non-empty directory errors across platforms.
| Ok(path) => match fs::metadata(&path) { | ||
| Ok(metadata) => { | ||
| Ok(format!("{:?}", metadata)) | ||
| } | ||
| Err(e) => { | ||
| Err(format!("Failed to get metadata: {}", e)) | ||
| let file_type = if metadata.is_dir() { | ||
| "Directory" | ||
| } else if metadata.is_file() { | ||
| "File" | ||
| } else if metadata.is_symlink() { | ||
| "Symlink" |
There was a problem hiding this comment.
The symlink detection will never work correctly because fs::metadata() follows symlinks. To detect symlinks, you need to use fs::symlink_metadata() instead, which does not follow symlinks.
Change line 275 from:
Ok(path) => match fs::metadata(&path) {To:
Ok(path) => match fs::symlink_metadata(&path) {With the current implementation, metadata.is_symlink() on line 282 will always return false.
There was a problem hiding this comment.
Fixed in commit 63655e6. Changed from fs::metadata() to fs::symlink_metadata() on line 268, which now correctly detects symlinks without following them.
|
@copilot address the comments |
- Add Microsoft copyright header to bindings.rs - Fix delete_directory error detection by checking error message string instead of ErrorKind::Other - Fix symlink detection in get_file_info by using fs::symlink_metadata() instead of fs::metadata() Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Summary: Improved Filesystem Example for Production Readiness ✅
Successfully enhanced the filesystem-rs example with comprehensive production-ready features.
Completed Improvements
New Production Features (7 new tools):
write-file: Write content to files (creates or overwrites)create-directory: Create directories with parent creationmove-path: Move or rename files and directoriesdelete-file: Delete files with type safety checksdelete-directory: Delete empty directories with validationfile-exists: Check file/directory existenceget-directory-tree: Recursive directory tree visualizationEnhanced Existing Features:
get-file-info: Human-readable metadata (size, type, timestamps, read-only status) with proper symlink detectionsearch-file: Better feedback when no matches foundlist-directory: More descriptive error messagesread-file: Enhanced error contextCode Quality:
Bug Fixes (PR Review):
fs::symlink_metadata()instead offs::metadata()Testing Results ✅
Component Loading: Success
Build Verification: Success
Production Readiness Features
The filesystem example is now a comprehensive, production-ready component.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.