Skip to content

Add --dotfiles to stow and unstow - #44

Merged
arecarn merged 4 commits into
masterfrom
dotfiles
Oct 9, 2026
Merged

arecarn merged 4 commits into
masterfrom
dotfiles

Conversation

@arecarn

@arecarn arecarn commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Adds --dotfiles: a package entry named dot-foo is stowed as .foo, like GNU stow. Builds on #16 by @menghuu.

  • stow accepts the flag. Names that would resolve outside the destination (dot-, dot-., dot-.., dot-.hidden) are left as they are, as GNU stow does.
  • unstow finds links by what they point at, so it removes them whether they are named dot-foo or .foo. It does not need the flag, and still accepts it.
  • Folding after an unstow unlinks the links it found instead of looking them up again by name.
  • The README documents the flag, and the changelog has an entry.

Closes #30.

@arecarn
arecarn force-pushed the dotfiles branch 2 times, most recently from 5e7f848 to 98db0f8 Compare October 5, 2026 03:59
@harkabeeparolus

Copy link
Copy Markdown
Contributor

I love that you're tackling this problem! ☺️
I think there may be some correctness issues with this branch in its current state, though. I'll suggest some improvements shortly.

@harkabeeparolus

harkabeeparolus commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Matching links by what they point at (follow-up idea)

The fixes I'm proposing all patch the same underlying thing. unstow finds a link by predicting its name from the package entry: dot-foo becomes .foo with --dotfiles and stays dot-foo without it. So a stow and an unstow have to agree on the flag, and each way they can disagree needs its own guard. The existing warning covers one direction and the new one covers the other, and the fold path had to stop re-deriving names because it crashed on a link whose name it could not predict. Some cases are still unguarded. A stow without the flag followed by a stow with it leaves two links to the same file, dot-bbb and .bbb, and neither form of unstow removes both. Unfolding another package's folded directory renames that package's links to whatever convention the current run is using.

One rule could cover all of these. Instead of predicting a single name, unstow could look at both candidate names for an entry, the literal one and the translated one, and unlink whichever is a symlink that resolves into the package entry. If a link points into the package, a stow made it, whatever it is called. clean already works this way, which is why the README can say it is unaffected by the flag.

With that rule, --dotfiles is no longer needed on unstow, though it could stay accepted for symmetry with stow and with GNU Stow. DotfilesMismatch and _is_linked_into go away, and so does the README's "pass the flag to unstow as well" caveat. The double-link case and the unfold renaming need no extra code, because the link still points into the package no matter what it ended up being called.

GNU Stow 2.4.1 requires the flag on stow -D and silently leaves links behind in both mismatch directions, exiting 0. So the warnings already put dploy ahead of Stow here, and matching by target would be another step in the same direction. Stow's own --compat mode walks the destination instead of the package for a related reason.

The cost is a larger change to _collect_actions. It would need a hook that returns one candidate for stow and two for unstow, and already unlinked would have to pick a name to print when neither candidate exists. The tests for the warnings would turn into tests that the links are removed.

I'd suggest landing the guard-based fixes here, since they are small and keep the design of this PR, and opening a follow-up issue for the target-based approach. I'm happy to prototype it if that would help.

A package entry named 'dot-foo' is linked as '.foo', like GNU stow's
--dotfiles. A name whose prefix is followed by nothing or by a dot ('dot-',
'dot-.', 'dot-..', 'dot-.hidden') is left untranslated, so a link can never
resolve outside the destination.

Unstow matches links by what they point at instead of predicting their name
from the flag. For each package entry it checks both 'dot-foo' and '.foo'
(and the same inside unfolded directories) and removes whichever links into
the package, so it does not need the flag and a package stowed with either
setting, or both, is removed by one unstow. Only links into the package are
touched under the name the flag does not predict, so an unrelated file there
is never a conflict. Folding after an unstow unlinks the links it found
rather than looking them up again by name.

Adds a changelog entry and documents the flag in the README.

Co-authored-by: Fredrik Mellström <11281108+harkabeeparolus@users.noreply.github.com>
Co-authored-by: Ryan Carney <arecarn@gmail.com>
@arecarn

arecarn commented Oct 9, 2026

Copy link
Copy Markdown
Owner Author

Thank you for the review and the follow-up PR.

Your fixes from #45 are in 488a13d. I also used your target-matching idea: unstow now removes links by what they point at, so it no longer needs --dotfiles, and the mismatch warnings are gone.

When both 'dot-foo' and '.foo' are real directories holding links, unstow
removed a link under one name and then printed "already unlinked" for the
same entry under the other. Entries whose link was queued under the name the
flag does not predict are now skipped by the already-unlinked report.
'dot-a' in one package and '.a' in another map to the same destination name
with --dotfiles, so stowing both must report a conflict.
Defines dotfile translation, literal name, translated name and matching by
target, and says unstow recognises links by their target.
@arecarn
arecarn merged commit 016b7ec into master Oct 9, 2026
15 checks passed
@arecarn

arecarn commented Oct 9, 2026

Copy link
Copy Markdown
Owner Author

Merged. Thank you @menghuu for the original --dotfiles work in #16. Your commit is the base of this change, and you are the author of the merged commit. Thank you also @harkabeeparolus for the review and the fixes in #45, which are included.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Finish integrating --dotfiles from #16

3 participants