Skip to content

Allow a package to opt out of tree folding for a specific directory #29

Description

@arecarn

Problem

dploy folds a fully-owned directory into a single symlink. That is the right default, but it is wrong whenever the target directory is also written to at runtime by the program being configured.

Concrete case. A stow package ships config for a tool that keeps both config and runtime state in one directory:

pkg/.pi/agent/AGENTS.md
pkg/.pi/agent/settings.json

If ~/.pi does not already exist, stowing folds at the top:

~/.pi -> <repo>/pkg/.pi

The tool then writes its runtime state — installed package payloads, per-project trust decisions, session history — to ~/.pi/agent/, which now resolves inside the repo working tree. For a public dotfiles repo that means local paths and session data land one careless git add -A away from being pushed. git clean will also happily delete the tool's installed state, since from git's point of view it is untracked junk in the tree.

Nothing in dploy currently expresses "link the files here, but leave this directory real."

Current workaround

Pre-create the directory as a real directory before calling stow, so folding can only happen at the leaf:

for d in (home / ".pi", home / ".pi/agent"):
    d.mkdir(parents=True, exist_ok=True)
dploy.stow(packages, home)

This works, but it lives in the consumer rather than the package, and it is invisible to anyone reading the package directory. I am already carrying a second instance of the same workaround for an unrelated directory, which is what suggests the tool should express it.

The workaround also silently no-ops on an existing symlink (mkdir(exist_ok=True) does not replace one), so a machine stowed before the workaround was added does not self-heal.

Proposal

A per-directory marker file that suppresses folding for the directory containing it, e.g. .dploynofold:

pkg/.pi/agent/.dploynofold
pkg/.pi/agent/AGENTS.md
pkg/.pi/agent/settings.json

Stowing that package would create ~/.pi/ and ~/.pi/agent/ as real directories and link only AGENTS.md and settings.json.

Why a marker rather than only a flag:

  • The requirement is genuinely local. It is a property of this directory (the tool writes state here), not of the invocation. A global switch would also change how every other package in the same run is stowed.
  • It is discoverable. Someone reading the package sees why the directory is special, without knowing what the calling code does.
  • It mirrors the existing precedent — .dploystowignore already establishes per-package control files, so the concept and the lookup path exist.

A --no-folding flag (as GNU stow has) would be a reasonable complement for the all-or-nothing case, but on its own it does not cover this, since the need is per-directory.

Notes

  • Marker files should be excluded from being linked into the destination, the way .dploystowignore excludes itself.
  • Unstow would need to treat a pre-created real directory as removable when it ends up empty, or deliberately leave it — worth deciding explicitly, since the runtime state that motivated the marker often means the directory is not empty and must survive.
  • Observed against dploy 0.1.3.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions