-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Problem Statement
Currently, folder-datetime-fix updates all parent folders' modification times regardless of excluded files. This causes issues when system-generated files (like thumbs.db, .DS_Store, temporary files) have different modification times than their containing folders. These excluded files can trigger unnecessary parent folder updates, overwriting meaningful user-created timestamps.
Current Behavior
When an excluded file is encountered:
- The file itself is skipped (not processed)
- But its parent folders are still updated
- This happens even if the excluded file's mtime doesn't match the parent folders
Example scenario:
/photos/
├── 2024/ (mtime: 2024-12-31)
│ ├── vacation/ (mtime: 2024-07-15)
│ │ ├── IMG_001.jpg (mtime: 2024-07-15)
│ │ └── thumbs.db (mtime: 2025-01-15) ← System generated recently
Currently, even though thumbs.db is excluded, the tool would still update /photos/2024/ and /photos/ based on other files, potentially losing meaningful timestamps.
Proposed Solution
Add a new flag --exclude-propagation-control with configurable behavior:
# Check up to 3 parent levels for mtime mismatch
folder-datetime-fix --exclude-propagation-control=3
# More explicit configuration
folder-datetime-fix --exclude-propagation-levels=3 --exclude-propagation-strategy=mtimeHow It Works
- When encountering an excluded file (e.g.,
thumbs.db) - Check if its mtime matches parent folders up to X levels
- If mtime differs from any parent in the chain:
- Skip updating those parent folders
- Preserve existing meaningful timestamps
- If mtime matches all checked parents:
- Continue with normal update logic
Configuration Options
--exclude-propagation-levels=N (default: 0)
0: Current behavior (no propagation control)1-10: Check N parent levels for mtime mismatch- Example:
--exclude-propagation-levels=3
--exclude-propagation-strategy=STRATEGY (default: 'off')
off: Current behavior (no special handling)mtime: Skip parent updates if excluded file mtime differsalways: Always skip parent updates when excluded files presentsmart: Use file-specific rules (see Advanced Configuration)
Use Cases
-
Windows thumbs.db files: System regenerates these with current timestamps, shouldn't affect folder dates from years ago
-
macOS .DS_Store files: Finder updates these frequently, shouldn't change meaningful folder organization dates
-
Temporary files: Applications create
.tmp,.cachefiles that shouldn't affect project folder dates -
Backup metadata: Backup tools create metadata files that shouldn't change original folder structures
Implementation Details
Basic Implementation
class ExcludePropagationHandler:
def __init__(self, levels: int = 3, strategy: str = 'mtime'):
self.levels = levels
self.strategy = strategy
def should_update_parent_chain(self,
excluded_file: Path,
parent_chain: List[Path]) -> List[bool]:
"""
Determine which parents in the chain should be updated.
Returns: List of booleans indicating update (True) or skip (False)
"""
if self.strategy == 'off':
return [True] * len(parent_chain)
if self.strategy == 'always':
# Skip all parents when excluded file found
return [False] * len(parent_chain)
if self.strategy == 'mtime':
# Check mtime match up to specified levels
update_flags = []
excluded_mtime = excluded_file.stat().st_mtime
for i, parent in enumerate(parent_chain[:self.levels]):
parent_mtime = parent.stat().st_mtime
if abs(excluded_mtime - parent_mtime) < 1.0: # Within 1 second
# mtimes match, can update this parent
update_flags.append(True)
else:
# Mismatch found, stop propagation from here
update_flags.append(False)
# All remaining parents also skip
update_flags.extend([False] * (len(parent_chain) - i - 1))
break
# Parents beyond check levels use normal logic
if len(update_flags) < len(parent_chain):
update_flags.extend([True] * (len(parent_chain) - len(update_flags)))
return update_flagsExamples
Example 1: Photo Organization
# Protect meaningful folder dates from thumbs.db updates
folder-datetime-fix /photos --exclude-propagation-levels=2
# Result: Year and month folders keep their meaningful dates
# even if Windows regenerates thumbs.db filesExample 2: Development Project
# Protect project structure from .DS_Store changes
folder-datetime-fix ~/projects --exclude-propagation-strategy=mtime --exclude-propagation-levels=3
# Result: Project folders maintain creation/modification dates
# even when macOS updates .DS_Store filesExample 3: Backup Restoration
# Preserve original timestamps despite backup metadata
folder-datetime-fix /restored-backup --exclude-propagation-levels=5
# Result: Original folder structure dates preserved
# even with newer backup metadata filesTesting Scenarios
- Single excluded file: Verify parent chain updates correctly skip
- Multiple excluded files: Handle multiple exclusions at different levels
- Mixed content: Folders with both excluded and normal files
- Deep hierarchies: Test with 10+ level deep structures
- Performance: Measure impact of propagation checks
- Cross-platform: Test with Windows, macOS, Linux exclusion patterns
Benefits
- Preserves meaningful timestamps: User-organized folders keep their dates
- Reduces filesystem writes: Fewer unnecessary updates
- Smarter handling: Respects system vs user files
- Configurable: Users control the behavior
- Backward compatible: Default behavior unchanged
Potential Concerns
- Complexity: More complex mental model for users
- Performance: Additional stat() calls for checking
- Inconsistency: Some parents updated, others not
- Debugging: Harder to understand why certain folders weren't updated
Migration Path
- Phase 1: Implement basic
--exclude-propagation-levelsflag - Phase 2: Add strategy options (mtime, always, off)
- Phase 3: Configuration file support
- Phase 4: Smart per-file rules
Related Issues
- Connects with DazzleTreeLib Issue #20 (cache improvements)
- Enhances existing exclude file functionality
- Part of making the tool more intelligent about system vs user files
Request for Comments
Questions for discussion:
- Should the default levels be 0 (current behavior) or something like 2-3?
- Should we support per-file-pattern rules in the first version?
- How should we handle symbolic links in the parent chain?
- Should there be a
--dry-runmode to preview propagation decisions?