Skip to content

Feature Request: Intelligent Exclude File Propagation Control #1

@djdarcy

Description

@djdarcy

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:

  1. The file itself is skipped (not processed)
  2. But its parent folders are still updated
  3. 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=mtime

How It Works

  1. When encountering an excluded file (e.g., thumbs.db)
  2. Check if its mtime matches parent folders up to X levels
  3. If mtime differs from any parent in the chain:
    • Skip updating those parent folders
    • Preserve existing meaningful timestamps
  4. 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 differs
  • always: Always skip parent updates when excluded files present
  • smart: Use file-specific rules (see Advanced Configuration)

Use Cases

  1. Windows thumbs.db files: System regenerates these with current timestamps, shouldn't affect folder dates from years ago

  2. macOS .DS_Store files: Finder updates these frequently, shouldn't change meaningful folder organization dates

  3. Temporary files: Applications create .tmp, .cache files that shouldn't affect project folder dates

  4. 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_flags

Examples

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 files

Example 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 files

Example 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 files

Testing Scenarios

  1. Single excluded file: Verify parent chain updates correctly skip
  2. Multiple excluded files: Handle multiple exclusions at different levels
  3. Mixed content: Folders with both excluded and normal files
  4. Deep hierarchies: Test with 10+ level deep structures
  5. Performance: Measure impact of propagation checks
  6. Cross-platform: Test with Windows, macOS, Linux exclusion patterns

Benefits

  1. Preserves meaningful timestamps: User-organized folders keep their dates
  2. Reduces filesystem writes: Fewer unnecessary updates
  3. Smarter handling: Respects system vs user files
  4. Configurable: Users control the behavior
  5. Backward compatible: Default behavior unchanged

Potential Concerns

  1. Complexity: More complex mental model for users
  2. Performance: Additional stat() calls for checking
  3. Inconsistency: Some parents updated, others not
  4. Debugging: Harder to understand why certain folders weren't updated

Migration Path

  1. Phase 1: Implement basic --exclude-propagation-levels flag
  2. Phase 2: Add strategy options (mtime, always, off)
  3. Phase 3: Configuration file support
  4. 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:

  1. Should the default levels be 0 (current behavior) or something like 2-3?
  2. Should we support per-file-pattern rules in the first version?
  3. How should we handle symbolic links in the parent chain?
  4. Should there be a --dry-run mode to preview propagation decisions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions