Bisakah GNU Stow menggunakan direktori penyimpanan yang merupakan tautan simbolik?

10

Pertimbangkan skrip ini.

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

Outputnya adalah

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

Sebelum berjalan stow, tampilannya seperti ini:

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

Setelah berjalan stow, aktif mylink, saya berharap akan terlihat seperti ini:

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

Namun, sebaliknya terlihat seperti ini:

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

Tampaknya stowperintah tersebut menyelesaikan realpath dari direktori paket, jadi alih-alih menunjuk ke ../mylink/package/filesana menunjuk ke ../mydir/package/file.

Ini masuk akal untuk menghindari terlalu banyak tipuan, tetapi itu terjadi secara diam-diam dan mungkin tidak selalu diinginkan. Apakah ada cara untuk mengatasi perilaku ini?

Sunting: Sesuai permintaan, saya akan menjelaskan contoh kasus penggunaan di mana penyelesaian realpath tidak nyaman.

Tautan simbolik terkadang digunakan untuk kompatibilitas . Debian bahkan membicarakan hal ini dalam kebijakan resmi . Seringkali targetnya adalah file tunggal, tetapi terkadang itu adalah direktori . Saya kebetulan memiliki beberapa ratus di sistem saya /usr/share/doc/sendiri:

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

Perilaku default stowbaik-baik saja selama target symlink tidak dipindahkan. Tapi kadang-kadang direktori yang diinginkan tidak dipindahkan. Misalnya, pada Debian, vim-runtimepaket menginstal file di bawah / usr / share / vim / di direktori yang tergantung pada versi, seperti /usr/share/vim/vim64untuk versi 6.4. Namun, paket itu juga akan memperbarui symlink pada saat /usr/share/vim/vimcurrentitu menunjuk ke versi saat ini. Ini berarti bahwa symlink menunjuk ke, katakanlah

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

akan rusak ketika rilis berikutnya dari Debian ditingkatkan ke

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

tetapi sebuah symlink ke

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

akan bekerja di kedua versi.

Karena stowmenggunakan jalur kanonik absolut dari direktori penyimpanan, doa seperti

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

akan menghasilkan tautan simbolis seperti, misalnya ini:

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

tidak seperti ini:

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

(Motivasi untuk menggunakan stowon vimcurrent/docs adalah untuk dapat memadukan catatan vim saya sendiri di samping symlink ke dokumentasi saat ini.) Perhatikan bahwa vimcurrentsymlink kompatibilitas tidak lagi hadir dalam distribusi Debian saat ini , meskipun mungkin di yang lain seperti Arch Linux ; Saya tidak yakin. Bagaimanapun, inilah skrip yang memberikan ide umum untuk dokumentasi 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

Output adalah:

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

Hipotetis, stowdapat memiliki bendera yang disebut, katakanlah --no-realpath, sehingga output akan terlihat seperti ini sebagai gantinya:

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

Untuk contoh lain dari symlink kompatibilitas yang berubah dengan setiap versi, berikut adalah dua lagi yang saya ketahui di laptop saya:

$ 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

Untuk mengatasi kasus 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

menghasilkan:

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

lalu:

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

menghasilkan:

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

sedangkan

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

akan menghasilkan ini:

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

Jadi dalam --no-realpathperilaku hipotetis itu akan memperlakukan direktori penyimpanan sebagai direktori biasa.

Fitur ini akan berlaku dalam skenario di mana

1) direktori penyimpanan harus symlink, dan

2) diinginkan untuk menjaga tautan itu di symlink yang dihasilkan.

Meskipun saya tidak menganggap kekurangan fitur ini sebagai kekurangan yang besar stow, saya berharap contoh ini mengklarifikasi kegunaan potensial dari tidak selalu menyelesaikan jalur kanonik.

Nathaniel M. Beaver
sumber
Tolong bisakah Anda memberikan contoh kasus penggunaan di mana menghindari tipuan ini akan membantu? Bagaimana jika mylinksebaliknya disinkronkan dengan mylink2yang pada gilirannya disinkronkan mydir? Bagaimana seharusnya Stow memutuskan apakah harus membuat symlink menunjuk ke ../mylink/package/fileatau ../mylink2/package/fileatau ../mydir/package/file?
Adam Spires
@AdamSpiers Saya harap itu membantu. Saya bisa meletakkan ini di pelacak masalah Github, juga, jika Anda mau.
Nathaniel M. Beaver
Terima kasih @Nathaniel. Ya tolong itu akan sangat membantu!
Adam Spires
1
@AdamSpiers Selesai! github.com/aspiers/stow/issues/11#issuecomment-507073811
Nathaniel M. Beaver

Jawaban:

7

Untuk saat ini, tidak mungkin.

Secara internal, stowtemukan jalur kanonik absolut dari jalur yang diberikan dengan menggunakan chdir untuk pindah ke jalur, kemudian gunakan fungsi getcwd () dari modul POSIX, yang merupakan antarmuka Perl untuk POSIX getcwd () , untuk mendapatkan nama path absolut.

Seperti yang ditentukan POSIX, nama jalur tidak boleh mengandung komponen yang .atau .., atau tautan simbolis.

cuonglm
sumber
1
Saran tentang cara memperbaiki implementasi untuk menangani hal ini dengan benar sangat disambut. Permintaan tarik bahkan lebih disambut! :-) Untuk referensi, masalah ini telah dilaporkan di sini: github.com/aspiers/stow/issues/11
Adam Spires