Consider this script.
#! /usr/bin/env bash
mkdir -p target
mkdir -p mydir/package/
touch mydir/package/file
ln --symbolic mydir mylink
file mylink
stow --verbose --dir=./mylink --target=./target package
file target/file
The output is
mylink: symbolic link to mydir
LINK: file => ../mydir/package/file
target/file: symbolic link to ../mydir/package/file
Before running stow
, it looks like this:
.
├── mydir
│ └── package
│ └── file
├── mylink -> mydir
└── target
After running stow
, on mylink
, I expected it to look like this:
.
├── mydir
│ └── package
│ └── file
├── mylink -> mydir
└── target
└── file -> ../mylink/package/file
However, instead it looks like this:
.
├── mydir
│ └── package
│ └── file
├── mylink -> mydir
└── target
└── file -> ../mydir/package/file
It seems that the stow
command resolves the realpath of the package directory, so instead of pointing to ../mylink/package/file
it points to ../mydir/package/file
.
This makes sense for avoiding too much indirection, but it happens silently and may not always be desirable. Is there a way to work around this behavior?
Edit: As per request, I will describe an example use case where resolving the realpath is inconvenient.
Symbolic links are sometimes used for compatibility.
Debian even talks about this in official policy.
Often the target is a single file,
but sometimes it is a directory
.
I happen to have a few hundred on my system in /usr/share/doc/
alone:
$ find /usr/share/doc -xtype d -type l | wc -l
325
The default behavior of stow
is fine
as long as the symlink target doesn't get moved.
But sometimes the desired targeted directory does get moved.
For example, on Debian, the vim-runtime
package
installs files under /usr/share/vim/
in a directory that depends on the version,
such as /usr/share/vim/vim64
for version 6.4.
However, the package would also update a symlink
at /usr/share/vim/vimcurrent
that pointed to the current version.
This means that a symlink pointing to, say
/usr/share/vim/vim64/doc/cmdline.txt
would break when the next release of Debian upgraded it to
/usr/share/vim/vim70/doc/cmdline.txt
but a symlink to
/usr/share/vim/vimcurrent/doc/cmdline.txt
would work in both versions.
Since stow
uses the absolute canonical path of the stow directory,
an invocation like
stow --dir=/usr/share/vim/vimcurrent --target=./my-vim-docs doc
would result in symbolic links like, e.g. this:
$ file cmdline.txt
cmdline.txt: symbolic link to ../../../../../usr/share/vim/vim64/doc/cmdline.txt
not like this:
$ file cmdline.txt
cmdline.txt: symbolic link to ../../../../../usr/share/vim/vimcurrent/doc/cmdline.txt
(The motivation for using stow
on vimcurrent/docs
is to be able to mingle my own vim notes alongside symlinks to the current documentation.)
Note that the vimcurrent
compatibility symlink is
no longer present in current Debian distributions,
though it may be in others like Arch Linux;
I'm not sure.
In any case, here's a script that gives the general idea for vim documentation:
#! /usr/bin/env bash
mkdir -p target
ln --symbolic /usr/share/vim/vim80 vimcurrent
stow --verbose --dir=./vimcurrent --target=./target pack
file target/dist
Output is:
LINK: dist => ../../../../../usr/share/vim/vim80/pack/dist
target/dist: symbolic link to ../../../../../usr/share/vim/vim80/pack/dist
Hypothetically, stow
could have a flag called, say, --no-realpath
,
so the output would look something like this instead:
LINK: dist => ./vimcurrent/pack/dist
target/dist: symbolic link to ./vimcurrent/pack/dist
For other examples of compatibility symlinks that change with each version, here are two more I know of on my laptop:
$ file /usr/share/go
/usr/share/go: symbolic link to go-1.10
$ file /usr/share/mscore
/usr/share/mscore: symbolic link to mscore-2.1
To address the symlink-points-to-symlink case:
#! /usr/bin/env bash
mkdir -p target
mkdir -p mydir/package/
touch mydir/package/file
ln --symbolic mydir mylink
ln --symbolic mylink mylink2
namei mylink2
produces:
f: mylink2
l mylink2 -> mylink
l mylink -> mydir
d mydir
and then:
$ stow --verbose --dir=./mylink2 --target=./target package
$ file target/file
produces:
LINK: file => ../mydir/package/file
target/file: symbolic link to ../mydir/package/file
whereas
$ stow --no-realpath --verbose --dir=./mylink2 --target=./target package
$ file target/file
would produce this:
LINK: file => ../mylink2/package/file
target/file: symbolic link to ../mylink2/package/file
So in the hypothetical --no-realpath
behavior it would treat the stow directory as a regular directory.
This feature would be applicable in a scenario where
1) the stow directory has to be a symlink, and
2) it is desirable to preserve that link in the generated symlinks.
While I don't consider the lack of this feature a great deficiency of stow
,
I hope that this example clarifies the potential usefulness
of not always resolving canonical paths.
mylink
instead symlinked tomylink2
which in turn symlinked tomydir
? How should Stow decide whether it should create symlinks pointing to../mylink/package/file
or../mylink2/package/file
or../mydir/package/file
?