¿Puede GNU Stow usar un directorio de almacenamiento que es un enlace simbólico?

10

Considera este guión.

#! /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

La salida es

mylink: symbolic link to mydir
LINK: file => ../mydir/package/file
target/file: symbolic link to ../mydir/package/file

Antes de correr stow, se ve así:

.
├── mydir
│   └── package
│       └── file
├── mylink -> mydir
└── target

Después de correr stow, mylinkesperaba que se viera así:

.
├── mydir
│   └── package
│       └── file
├── mylink -> mydir
└── target
    └── file -> ../mylink/package/file

Sin embargo, en cambio se ve así:

.
├── mydir
│   └── package
│       └── file
├── mylink -> mydir
└── target
    └── file -> ../mydir/package/file

Parece que el stowcomando resuelve la ruta real del directorio del paquete, por lo que en lugar de señalarlo ../mylink/package/file, apunta ../mydir/package/file.

Esto tiene sentido para evitar demasiada indirección, pero ocurre en silencio y puede no ser siempre deseable. ¿Hay alguna forma de evitar este comportamiento?

Editar: según la solicitud, describiré un caso de uso de ejemplo donde resolver la ruta real es inconveniente.

Los enlaces simbólicos a veces se usan por compatibilidad . Debian incluso habla de esto en la política oficial . A menudo, el destino es un solo archivo, pero a veces es un directorio . Resulta que tengo unos pocos cientos en mi sistema /usr/share/doc/solo:

$ find /usr/share/doc -xtype d -type l | wc -l
325

El comportamiento predeterminado de stowestá bien siempre que el objetivo del enlace simbólico no se mueva. Pero a veces el directorio deseado deseado se mueve. Por ejemplo, en Debian, el vim-runtimepaquete instala archivos en / usr / share / vim / en un directorio que depende de la versión, como la /usr/share/vim/vim64versión 6.4. Sin embargo, el paquete también podría actualizar un enlace simbólico al /usr/share/vim/vimcurrentque apuntaban a la versión actual. Esto significa que un enlace simbólico que apunta a, digamos

/usr/share/vim/vim64/doc/cmdline.txt

se rompería cuando la próxima versión de Debian lo actualizara a

/usr/share/vim/vim70/doc/cmdline.txt

pero un enlace simbólico a

/usr/share/vim/vimcurrent/doc/cmdline.txt

funcionaría en ambas versiones.

Como stowusa la ruta canónica absoluta del directorio de almacenamiento, una invocación como

stow --dir=/usr/share/vim/vimcurrent --target=./my-vim-docs doc

daría lugar a enlaces simbólicos como, por ejemplo, esto:

$ file cmdline.txt
cmdline.txt: symbolic link to ../../../../../usr/share/vim/vim64/doc/cmdline.txt

así no:

$ file cmdline.txt
cmdline.txt: symbolic link to ../../../../../usr/share/vim/vimcurrent/doc/cmdline.txt

(La motivación para usar stowon vimcurrent/docs es poder mezclar mis propias notas vim junto con enlaces simbólicos a la documentación actual). Tenga en cuenta que el vimcurrentenlace simbólico de compatibilidad ya no está presente en las distribuciones actuales de Debian , aunque puede estar en otros como Arch Linux ; No estoy seguro. En cualquier caso, aquí hay un script que da la idea general de la documentación de vim:

#! /usr/bin/env bash
mkdir -p target
ln --symbolic /usr/share/vim/vim80 vimcurrent
stow --verbose --dir=./vimcurrent --target=./target pack
file target/dist

Salida es:

LINK: dist => ../../../../../usr/share/vim/vim80/pack/dist
target/dist: symbolic link to ../../../../../usr/share/vim/vim80/pack/dist

Hipotéticamente, stowpodría tener una bandera llamada, por ejemplo --no-realpath, para que la salida se vea así:

LINK: dist => ./vimcurrent/pack/dist
target/dist: symbolic link to ./vimcurrent/pack/dist

Para otros ejemplos de enlaces simbólicos de compatibilidad que cambian con cada versión, aquí hay dos más que conozco en mi computadora portátil:

$ 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

Para abordar el caso de symlink-points-to-symlink:

#! /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

produce:

f: mylink2
 l mylink2 -> mylink
   l mylink -> mydir
     d mydir

y entonces:

$ stow --verbose --dir=./mylink2 --target=./target package
$ file target/file

produce:

LINK: file => ../mydir/package/file
target/file: symbolic link to ../mydir/package/file

mientras

$ stow --no-realpath --verbose --dir=./mylink2 --target=./target package
$ file target/file

produciría esto:

LINK: file => ../mylink2/package/file
target/file: symbolic link to ../mylink2/package/file

Entonces, en el --no-realpathcomportamiento hipotético , trataría el directorio de almacenamiento como un directorio regular.

Esta característica sería aplicable en un escenario donde

1) el directorio de almacenamiento tiene que ser un enlace simbólico, y

2) es deseable preservar ese enlace en los enlaces simbólicos generados.

Si bien no considero que la falta de esta característica sea una gran deficiencia stow, espero que este ejemplo aclare la utilidad potencial de no siempre resolver caminos canónicos.

Nathaniel M. Beaver
fuente
¿Podría dar un ejemplo de caso de uso en el que sería útil evitar esta indirección? ¿Qué pasa si en mylinklugar de un enlace simbólico al mylink2que a su vez se vinculó mydir? ¿Cómo debe Stow decidir si se debe crear enlaces simbólicos que apuntan a ../mylink/package/fileo ../mylink2/package/fileo ../mydir/package/file?
Adam Spires
@ AdamSpiers Espero que ayude un poco. También podría poner esto en el rastreador de problemas de Github, si lo prefiere.
Nathaniel M. Beaver
Gracias @Nathaniel ¡Sí, por favor, eso sería útil!
Adam Spires
1
@AdamSpiers Hecho! github.com/aspiers/stow/issues/11#issuecomment-507073811
Nathaniel M. Beaver

Respuestas:

7

Por ahora, no hay forma.

Internamente, stowencuentre la ruta canónica absoluta de la ruta dada usando chdir para moverse hacia la ruta, luego use la función getcwd () del módulo POSIX, que es la interfaz Perl para POSIX getcwd () , para obtener el nombre de ruta absoluta.

Como POSIX especificó, el nombre de la ruta no contendrá componentes que sean .o .., o sean enlaces simbólicos.

Cuonglm
fuente
1
Las sugerencias sobre cómo solucionar la implementación para manejar esto correctamente son bienvenidas. ¡Las solicitudes de extracción son aún más bienvenidas! :-) Como referencia, el problema se ha informado aquí: github.com/aspiers/stow/issues/11
Adam Spires