Can GNU Stow use a stow directory that is a symbolic link

stowsymlink

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.

Best Answer

For now, there's no way.

Internally, stow find absolute canonical path of given path by using chdir to move into the path, then use getcwd() function from POSIX module, which is the Perl interface for POSIX getcwd(), to get the absolute path name.

As POSIX specified, the path name shall contain no components that are . or .., or are symbolic links.