Add implementation plan for collect CLI tool
This commit is contained in:
parent
8f8b374aeb
commit
216461fa96
1 changed files with 101 additions and 0 deletions
101
plan.md
Normal file
101
plan.md
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Implementation Plan for Collect CLI Tool
|
||||
|
||||
## Overview
|
||||
A CLI tool that collects files recursively matching specific criteria, maintains their file structure, and archives them for backup purposes.
|
||||
|
||||
## Language Choice: Go
|
||||
- Single binary distribution
|
||||
- Built-in archive support (tar/gzip and zip)
|
||||
- Excellent file system traversal capabilities
|
||||
- Cross-platform compatibility
|
||||
- No runtime dependencies
|
||||
|
||||
## Behavior Specifications
|
||||
|
||||
### CLI Interface
|
||||
```
|
||||
collect [--name <filename> | --match <pattern>] <source-dir> <output-archive>
|
||||
```
|
||||
|
||||
### Flags
|
||||
- `--name`: Match exact filename (e.g., `--name .mise.toml`)
|
||||
- `--match`: Match directory pattern, collect all files within (e.g., `--match aet-*/`)
|
||||
- Flags are mutually exclusive
|
||||
|
||||
### File Collection
|
||||
- **Name matching**: Find all files with exact filename match anywhere in tree
|
||||
- **Pattern matching**: Find directories matching glob pattern, then collect all files recursively within those directories
|
||||
- Symlinks are ignored
|
||||
- Preserve relative paths from source directory in archive
|
||||
|
||||
### Archive Format
|
||||
- Determined by output file extension
|
||||
- Supported: `.tar.gz`, `.tgz`, `.zip`
|
||||
|
||||
### Error Handling
|
||||
- Permission errors: Log warning to stderr, skip file, continue
|
||||
- No files found: Exit with code 1 and error message
|
||||
- Archive creation failure: Exit with code 2
|
||||
- Invalid arguments: Exit with code 3
|
||||
- All errors reported to stderr
|
||||
|
||||
## Architecture
|
||||
|
||||
### Package Structure
|
||||
```
|
||||
collect/
|
||||
├── main.go # CLI entry point and argument parsing
|
||||
├── collector/
|
||||
│ ├── collector.go # Core collection logic
|
||||
│ └── matcher.go # File/directory matching logic
|
||||
├── archiver/
|
||||
│ ├── archiver.go # Archive interface
|
||||
│ ├── tar.go # Tar/gzip implementation
|
||||
│ └── zip.go # Zip implementation
|
||||
└── go.mod # Go module definition
|
||||
```
|
||||
|
||||
### Core Interfaces
|
||||
|
||||
#### Collector
|
||||
```go
|
||||
type Collector interface {
|
||||
Collect(sourceDir string) ([]FileEntry, error)
|
||||
}
|
||||
|
||||
type FileEntry struct {
|
||||
Path string // Relative path from sourceDir
|
||||
FullPath string // Absolute path for reading
|
||||
}
|
||||
```
|
||||
|
||||
#### Matcher
|
||||
```go
|
||||
type Matcher interface {
|
||||
ShouldInclude(path string, info os.FileInfo) bool
|
||||
}
|
||||
```
|
||||
|
||||
#### Archiver
|
||||
```go
|
||||
type Archiver interface {
|
||||
Create(outputPath string, files []FileEntry) error
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation Flow
|
||||
1. Parse and validate CLI arguments
|
||||
2. Create appropriate matcher (NameMatcher or PatternMatcher)
|
||||
3. Create collector with matcher
|
||||
4. Walk directory tree and collect matching files
|
||||
5. Check if any files were found (error if empty)
|
||||
6. Create appropriate archiver based on file extension
|
||||
7. Build archive with collected files
|
||||
8. Report any errors to stderr
|
||||
|
||||
### Key Decisions
|
||||
- Use `filepath.WalkDir` for efficient directory traversal
|
||||
- Clean all paths to ensure consistent relative paths
|
||||
- Use buffered I/O for archive operations
|
||||
- Pattern matching uses Go's `filepath.Match` function
|
||||
- Archive paths are relative to the search directory root
|
Loading…
Add table
Reference in a new issue