Skip to content

Instantly share code, notes, and snippets.

@halo
Created August 19, 2025 13:26
Show Gist options
  • Select an option

  • Save halo/e6aff8bda1f656cce11a663ecdff437e to your computer and use it in GitHub Desktop.

Select an option

Save halo/e6aff8bda1f656cce11a663ecdff437e to your computer and use it in GitHub Desktop.
Playground for experimenting with different GNU stow scenarios
# You need stow on your system for this demonstration.
# E.g. `brew install stow`
# Then run this file with `ruby stow.rb`
require 'fileutils'
# Up here are just helper methods for readability
def cleanup
FileUtils.rm_rf('/tmp/home')
FileUtils.mkdir_p('/tmp/home')
Dir.chdir("/tmp/home")
end
def touch(relative_path)
path = "/tmp/home/#{relative_path}"
FileUtils.mkdir_p(File.dirname(path))
FileUtils.touch(path)
end
def stow(args = nil)
`cd stow; stow #{args}`
end
def assert(condition)
raise unless condition
end
# Now for the playground
# File names are never modified. They always start with a dot.
cleanup
touch 'stow/package/.gitconfig'
stow 'package'
assert File.readlink('/tmp/home/.gitconfig') == 'stow/package/.gitconfig' # Works well
# This is how the `--dotfiles` flag works with a single file
cleanup
touch 'stow/package/dot-alpha'
stow 'package --dotfiles'
assert File.readlink('/tmp/home/.alpha') == 'stow/package/dot-alpha' # Weird but works
# This is how the `--dotfiles` flag works with subdirectories
cleanup
touch 'stow/package/dot-alpha/dot-beta'
stow 'package --dotfiles'
assert File.readlink('/tmp/home/.alpha') == 'stow/package/dot-alpha' # Expected
assert File.exist?('/tmp/home/.alpha/dot-beta') # Maybe unexpected?
# Smart folding can lead to bad consequences
cleanup
touch 'stow/package/.config/alpha.toml'
touch 'stow/package/.config/beta.toml'
stow 'package'
touch '.config/cache' # Adding a file
assert File.exist?('/tmp/home/stow/package/.config/cache') # Not good
# Conflict with symlink resolves automatically if override-- is used
cleanup
touch 'stow/alpha/.config'
touch 'stow/beta/.config'
stow 'alpha'
stow 'beta --override=".*"'
assert File.readlink('/tmp/home/.config') == 'stow/beta/.config'
# Conflicting by empty directory
cleanup
touch 'stow/package/.config'
FileUtils.mkdir_p('/tmp/home/.config') # Conflicting directory
stow 'package' # Refuses to run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment