'symlinks' test fails when /tmp is on a different filesystem to /home
1 test failed
symlinks
Rejected promise returned by test. Reason:
Error {
code: 'ENOENT',
dest: '/home/alan-sysop/.local/share/Trash/files/689b96e0-ef36-4532-9f56-30c86009afec',
errno: -2,
path: '/tmp/10fa99e2-c8ea-4643-ab3e-8b0f10156755/ccc',
syscall: 'copyfile',
message: 'ENOENT: no such file or directory, copyfile \'/tmp/10fa99e2-c8ea-4643-ab3e-8b0f10156755/ccc\' -> \'/home/alan-sysop/.local/share/Trash/files/689b96e0-ef36-4532-9f56-30c86009afec\'',
}
Analysis
-
fs.copyFile()fails because it tries to copy the target of the symbolic link being trashed. And in this test,cccis a symlink to a non-existent file (ddd). -
We never want copyFile to be copying the target of a symbolic link. This is a bug in
move-file.move-fileshould use something other than copyFile. (copyFile does not have aNOFOLLOWoption that we could use). -
It should be surprising that
move-fileneeded to fall back to copyFile at all. Linux does add a number ofEXDEVcases - overlayfs copy-up, crossing btrfs volumes, or on bcachefs if the new parent directory has different storage options. However none of these applies in my case. The surprise is a deficiency inxdg-trashdir, partly caused bymount-point. (Here is a test case which shows the inconsistency in xdg-trashdir). -
mount-pointdoes not do what we want for symlinks - it is dereferencing them.mount-pointrelies on@sindresorhus/df, which literally runs thedfcommand, which always dereferences symbolic links.mount-pointtries to follow this dangling symbolic link, so it fails. The failure causesxdg-trashdirto fall back to/home/alan-sysop/.local/share/Trash.
Side notes
-
You might still hit
EXDEVe.g. from the cross-btrfs-subvolume case, and need to fall back to copying. Currently,move-fileis not suitable for this. It does not support copying symbolic links or directories. -
Trashing a regular file in
/tmpwill use/tmp/.Trash-1000, avoiding any problems with cross-filesystem renames. This does not seem very desirable.trashcurrently relies entirely on other implementations to provide the critical "un-trash" feature :-). The Gnome file browser does not support trashing files in/tmp, at least if it is on a different filesystem, and nor does it not any trashed files from/tmp/.Trash-1000.
Possible solutions
-
To solve side note 1, maybe use
move-concurrently. On the plus side, it's fairly widely used, well written, and small. There are several alternatives, which vary in how suitable they are.fs-extrashould work fine as well, but it's bigger, and the fact that it's coupled to graceful-fs is weirding me out: https://softwarerecs.stackexchange.com/questions/65653/node-js-library-package-to-move-a-file-directory-or-symlink/ -
Addressing side note 1 would make the test pass. However, on its own, this would ignore side note 2 and the inconsistency in
xdg-trashdir. This problem is pretty tricky! But IMO we've already been doing weird things when crossing filesystems. The simplest thing that could work would be to drop support for creating.Trash-$UID. It would be possible to followup later, with a closer emulation of what the Gnome file manager does (this might involve queryingudisksusingdbusmethod calls).
Thanks for your thorough analysis. 🙌
(I must have missed the notification for this)
fs.copyFile() fails because it tries to copy the target of the symbolic link being trashed. And in this test, ccc is a symlink to a non-existent file (ddd).
That is surprising behavior to me. The Node.js docs says nothing about how symlinks are treated. https://nodejs.org/api/fs.html#fs_fs_copyfile_src_dest_flags_callback
I think you should open an issue on Node.js to clarify how symlinks are handled and also add an option to not follow symlinks (should IMHO be on by default).
mount-point does not do what we want for symlinks - it is dereferencing them. mount-point relies on @sindresorhus/df, which literally runs the df command, which always dereferences symbolic links. mount-point tries to follow this dangling symbolic link, so it fails. The failure causes xdg-trashdir to fall back to /home/alan-sysop/.local/share/Trash.
I'm happy to consider solutions. I don't use Linux and the Linux parts of the trash codebase was not written by me. So what I'm saying is that PRs are welcome and I will review, but I won't be working on any of this.
To solve side note 1, maybe use move-concurrently. On the plus side, it's fairly widely used, well written, and small.
I'm vary of using packages under the npm GitHub org. They are very often buggy and badly maintained. I've been burned by that many times in the past. For example, https://github.com/npm/write-file-atomic/issues