Kann GNU Stow ein Stow-Verzeichnis verwenden, das eine symbolische Verknüpfung darstellt?

10

Betrachten Sie dieses Skript.

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

Die Ausgabe ist

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

Vor dem Laufen stowsieht es so aus:

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

Nach dem Laufen stow, auf mylink, erwartete ich es wie folgt aussehen:

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

Stattdessen sieht es jedoch so aus:

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

Es scheint, dass der stowBefehl den Realpfad des Paketverzeichnisses auflöst, sodass er nicht darauf verweist, ../mylink/package/filesondern darauf verweist ../mydir/package/file.

Dies ist sinnvoll, um zu viel Indirektion zu vermeiden, geschieht jedoch stillschweigend und ist möglicherweise nicht immer wünschenswert. Gibt es eine Möglichkeit, dieses Verhalten zu umgehen?

Bearbeiten: Auf Anfrage beschreibe ich einen Anwendungsbeispiel, bei dem das Auflösen des Realpfads unpraktisch ist.

Aus Kompatibilitätsgründen werden manchmal symbolische Links verwendet . Debian spricht sogar in der offiziellen Politik darüber . Oft ist das Ziel eine einzelne Datei, manchmal aber auch ein Verzeichnis . Ich habe zufällig ein paar Hundert /usr/share/doc/allein auf meinem System :

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

Das Standardverhalten von stowist in Ordnung, solange das Symlink-Ziel nicht verschoben wird. Aber manchmal wird das gewünschte Zielverzeichnis verschoben. Unter Debian vim-runtimeinstalliert das Paket beispielsweise Dateien unter / usr / share / vim / in einem Verzeichnis, das von der Version abhängt, z. B. /usr/share/vim/vim64für Version 6.4. Allerdings würde das Paket auch einen Symlink aktualisieren an /usr/share/vim/vimcurrentdiesem spitzen auf die aktuelle Version. Dies bedeutet, dass ein Symlink beispielsweise auf zeigt

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

würde brechen, wenn die nächste Version von Debian es auf aktualisiert

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

aber ein Symlink zu

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

würde in beiden Versionen funktionieren.

Da stowverwendet der absolute kanonische Pfad des Stow-Verzeichnisses, ein Aufruf wie

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

würde zu symbolischen Links führen, wie zum Beispiel:

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

so nicht:

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

(Die Motivation für die Verwendung von stowon vimcurrent/docs besteht darin, meine eigenen vim-Notizen neben Symlinks zur aktuellen Dokumentation mischen zu können.) Beachten Sie, dass der vimcurrentKompatibilitätssymlink in aktuellen Debian-Distributionen nicht mehr vorhanden ist , obwohl er möglicherweise in anderen wie Arch Linux vorhanden ist . Ich bin mir nicht sicher. In jedem Fall ist hier ein Skript, das die allgemeine Idee für die vim-Dokumentation gibt:

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

Ausgabe ist:

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

Könnte hypothetisch stowein Flag haben, das beispielsweise heißt, --no-realpathalso würde die Ausgabe stattdessen ungefähr so ​​aussehen:

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

Weitere Beispiele für Kompatibilitätssymlinks, die sich mit jeder Version ändern, sind zwei weitere, die ich auf meinem Laptop kenne:

$ 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

So behandeln Sie den Fall von Symlink-Punkten zu 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

produziert:

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

und dann:

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

produziert:

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

wohingegen

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

würde dies produzieren:

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

Im hypothetischen --no-realpathVerhalten würde das Stow-Verzeichnis also als reguläres Verzeichnis behandelt.

Diese Funktion ist in einem Szenario anwendbar, in dem

1) Das Stow-Verzeichnis muss ein Symlink sein, und

2) Es ist wünschenswert, diesen Link in den generierten Symlinks beizubehalten.

Obwohl ich das Fehlen dieser Funktion nicht als großen Mangel betrachte stow, hoffe ich, dass dieses Beispiel die potenzielle Nützlichkeit der nicht immer auflösenden kanonischen Pfade verdeutlicht.

Nathaniel M. Beaver
quelle
Könnten Sie bitte einen Anwendungsbeispiel nennen, bei dem das Vermeiden dieser Indirektion hilfreich wäre? Was ist, wenn mylinkstattdessen eine Symlink-Verknüpfung zu einer mylink2Symlink-Verknüpfung besteht mydir? Wie sollte Stow entscheiden, ob Symlinks erstellt werden sollen, die auf ../mylink/package/fileoder ../mylink2/package/fileoder verweisen ../mydir/package/file?
Adam Spiers
@AdamSpiers Ich hoffe das hilft etwas. Ich könnte dies auch auf den Github Issue Tracker setzen, wenn Sie es vorziehen.
Nathaniel M. Beaver
Danke @Nathaniel. Ja bitte das wäre hilfreich!
Adam Spiers
1
@AdamSpiers Fertig! github.com/aspiers/stow/issues/11#issuecomment-507073811
Nathaniel M. Beaver

Antworten:

7

Im Moment gibt es keinen Weg.

stowSuchen Sie intern den absoluten kanonischen Pfad des angegebenen Pfads, indem Sie mit chdir in den Pfad wechseln, und verwenden Sie dann die Funktion getcwd () aus dem POSIX-Modul, der Perl-Schnittstelle für POSIX getcwd () , um den absoluten Pfadnamen abzurufen .

Wie POSIX angegeben, wird der Pfadname keine Komponenten enthalten , die sind .oder .., oder sind symbolische Links.

cuonglm
quelle
1
Vorschläge zur Behebung der Implementierung, um dies korrekt zu handhaben, sind sehr willkommen. Pull-Anfragen sind noch willkommener! :-) Als Referenz wurde das Problem hier gemeldet: github.com/aspiers/stow/issues/11
Adam Spiers