Subject: eshell/sudo with delete-by-moving-to-trash

From: кппкяып япвквкп <[email-masked]>
Date: Tue, 16 Apr 2024 13:56:31 +0300

In GNU Emacs 30.0.50 on Arch Linux, I encountered a permission issue
when trying to delete a file with elevated privileges using `eshell/rm`
in combination with `delete-by-moving-to-trash` enabled. This suggests
that the deletion process is not fully "TRAMP aware."
 
Steps to reproduce:
 
1. emacs -Q
2. ~ $ (setq delete-by-moving-to-trash t)
t
3. ~ $ (require 'em-tramp)
em-tramp
4. ~ $ eshell/sudo touch /etc/bugtestfile
5. ~ $ eshell/sudo rm /etc/bugtestfile
Cannot move /etc/bugtestfile to trash: Permission denied

Expected behavior:
 
I expect emacs to handle this situation by using /root/.local/share/Trash
instead of /home/username/.local/share/Trash.

This is the backtrace:
 
Debugger entered--Lisp error: (error "Cannot move /etc/bugtestfile to trash: Permission denied")
error("Cannot move %s to trash: Permission denied" "/etc/bugtestfile")
move-file-to-trash("/etc/bugtestfile")
delete-file("/etc/bugtestfile" t)
apply(delete-file ("/etc/bugtestfile" t))
eshell-exec-lisp(eshell-printn eshell-errorn delete-file ("/etc/bugtestfile" t) nil)
eshell-remove-entries(("/etc/bugtestfile") t)
eshell/rm("/etc/bugtestfile")
apply(eshell/rm "/etc/bugtestfile")
eshell-exec-lisp(eshell-print eshell-error eshell/rm ("/etc/bugtestfile") nil)
eshell-lisp-command(eshell/rm ("/etc/bugtestfile"))
eshell-plain-command("rm" ("/etc/bugtestfile"))
eshell-named-command("rm" ("/etc/bugtestfile"))
eval((eshell-named-command '"rm" '("/etc/bugtestfile")))
eshell-do-eval((eshell-named-command '"rm" '("/etc/bugtestfile")) nil)
#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)()
funcall(#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))
(let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)))
eval((let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))))
eshell-do-eval((let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (eshell-named-command '"rm" '("/etc/bugtestfile"))) nil)
eshell-do-eval((let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (eshell-named-command '"rm" '("/etc/bugtestfile"))) nil)
eshell-do-eval((unwind-protect (let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (eshell-named-command '"rm" '("/etc/bugtestfile"))) (mapc #'funcall eshell-this-command-hook)) nil)
#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)()
funcall(#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))
(let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)))
eval((let ((eshell-this-command-hook '(ignore))) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))))
eshell-do-eval((let ((eshell-this-command-hook '(ignore))) (unwind-protect (let ((default-directory '"/sudo:root@archlinux:/home/wurfkreuz/")) (eshell-named-command '"rm" '("/etc/bugtestfile"))) (mapc #'funcall eshell-this-command-hook))) nil)
(condition-case err (eshell-do-eval '(let ((eshell-this-command-hook '(ignore))) (unwind-protect (let ((default-directory ...)) (eshell-named-command '"rm" '...)) (mapc #'funcall eshell-this-command-hook))) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))
eval((condition-case err (eshell-do-eval '(let ((eshell-this-command-hook '...)) (unwind-protect (let (...) (eshell-named-command ... ...)) (mapc #'funcall eshell-this-command-hook))) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))
eshell-do-eval((condition-case err (eshell-do-eval '(let ((eshell-this-command-hook '...)) (unwind-protect (let (...) (eshell-named-command ... ...)) (mapc #'funcall eshell-this-command-hook))) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))) nil)
eshell-do-eval((condition-case err (eshell-do-eval '(let ((eshell-this-command-hook '...)) (unwind-protect (let (...) (eshell-named-command ... ...)) (mapc #'funcall eshell-this-command-hook))) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))) nil)
#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)()
funcall(#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))
(let ((eshell-current-handles '[nil (((t) . 2) t) (((t) . 2) t)])) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)))
eval((let ((eshell-current-handles '[nil ((... . 2) t) ((... . 2) t)])) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))))
eshell-do-eval((let ((eshell-current-handles '[nil ((... . 2) t) ((... . 2) t)])) (condition-case err (eshell-do-eval '(let ((eshell-this-command-hook ...)) (unwind-protect (let ... ...) (mapc ... eshell-this-command-hook))) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1)))) nil)
eshell-do-eval((progn (let ((eshell-current-handles '[nil (... t) (... t)])) (condition-case err (eshell-do-eval '(let (...) (unwind-protect ... ...)) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))) nil)
eshell-do-eval((unwind-protect (progn (let ((eshell-current-handles '[nil ... ...])) (condition-case err (eshell-do-eval '(let ... ...) nil) ((debug error) (eshell-errorn (error-message-string err)) (eshell-close-handles 1))))) (run-hooks 'eshell-post-command-hook)) nil)
eshell-do-eval((progn 'nil (unwind-protect (progn (let ((eshell-current-handles '...)) (condition-case err (eshell-do-eval '... nil) ((debug error) (eshell-errorn ...) (eshell-close-handles 1))))) (run-hooks 'eshell-post-command-hook))) nil)
#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)()
funcall(#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))
(let ((eshell-current-handles '[nil (((t) . 2) t) (((t) . 2) t)]) (eshell-current-subjob-p 'nil)) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>)))
eval((let ((eshell-current-handles '[nil ((... . 2) t) ((... . 2) t)]) (eshell-current-subjob-p 'nil)) (funcall '#f(compiled-function () #<bytecode -0x165b8ffb2c8bf0d6>))))
eshell-do-eval((let ((eshell-current-handles '[nil ((... . 2) t) ((... . 2) t)]) eshell-current-subjob-p) (progn 'nil (unwind-protect (progn (let ((eshell-current-handles ...)) (condition-case err (eshell-do-eval ... nil) (... ... ...)))) (run-hooks 'eshell-post-command-hook)))))
eshell-resume-eval((nil (let ((eshell-current-handles '[nil (... t) (... t)]) eshell-current-subjob-p) (progn 'nil (unwind-protect (progn (let (...) (condition-case err ... ...))) (run-hooks 'eshell-post-command-hook)))) nil))
eshell-eval-command((let ((eshell-current-handles '[nil ((... . 2) t) ((... . 2) t)]) eshell-current-subjob-p) (progn 'nil (unwind-protect (progn (let ((eshell-current-handles ...)) (condition-case err (eshell-do-eval ... nil) (... ... ...)))) (run-hooks 'eshell-post-command-hook)))) "eshell/sudo rm /etc/bugtestfile")
eshell-send-input(nil)
funcall-interactively(eshell-send-input nil)
command-execute(eshell-send-input)
recursive-edit()
debug(error (void-variable delete-by-moving-to) :backtrace-base eval-expression--debug)
eval-expression--debug((void-variable delete-by-moving-to))
eval(delete-by-moving-to nil)
elisp--eval-last-sexp(nil)
#f(compiled-function () #<bytecode 0xa85ef2ba986a>)()
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
command-execute(eval-last-sexp)

In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
3.24.41, cairo version 1.18.0) of 2024-04-14 built on archlinux
Repository revision: 7add47337b62064998a5b80f357acc39b1253e98
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12302006
System Description: Arch Linux
 
Configured using:
'configure --with-native-compilation=aot --with-tree-sitter --with-gif
--with-png --with-jpeg --with-rsvg --with-tiff --with-imagemagick
--with-x-toolkit=gtk3 --with-xwidgets
CPPFLAGS=-I/opt/homebrew/opt/jpeg/include
LDFLAGS=-L/opt/homebrew/opt/jpeg/lib'
 
Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ
IMAGEMAGICK JPEG LCMS2 LIBOTF LIBSYSTEMD LIBXML2 M17N_FLT MODULES
NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3
THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2
XPM XWIDGETS GTK3 ZLIB
 
Important settings:
value of $LANG: en_US.UTF-8
locale-coding-system: utf-8-unix
 
Major mode: Outline
 
Minor modes in effect:
goto-address-mode: t
bug-reference-mode: t
eshell-syntax-highlighting-global-mode: t
global-flycheck-mode: t
flycheck-mode: t
popper-echo-mode: t
popper-mode: t
all-the-icons-ivy-rich-mode: t
ivy-rich-mode: t
ivy-posframe-mode: t
counsel-mode: t
ivy-mode: t
override-global-mode: t
projectile-mode: t
windmove-mode: t
global-treesit-auto-mode: t
corfu-history-mode: t
corfu-echo-mode: t
global-corfu-mode: t
corfu-mode: t
yas-global-mode: t
yas-minor-mode: t
tracking-mode: t
dired-async-mode: t
general-override-mode: t
global-evil-collection-unimpaired-mode: t
evil-collection-unimpaired-mode: t
evil-commentary-mode: t
global-evil-surround-mode: t
evil-surround-mode: t
evil-mode: t
evil-local-mode: t
global-undo-tree-mode: t
undo-tree-mode: t
global-auto-revert-mode: t
pixel-scroll-precision-mode: t
save-place-mode: t
savehist-mode: t
electric-pair-mode: t
global-display-line-numbers-mode: t
display-line-numbers-mode: t
straight-use-package-mode: t
straight-package-neutering-mode: t
tooltip-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tab-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
minibuffer-regexp-mode: t
buffer-read-only: t
line-number-mode: t
auto-fill-function: #[128 \304\300\301%3#\207 [yas--auto-fill do-auto-fill :around nil apply] 5 advice]
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
view-mode: t
 
Features:
(shadow mail-extr emacsbug goto-addr bug-reference lsp-zig lsp-yang
lsp-yaml lsp-xml lsp-wgsl lsp-volar lsp-vimscript lsp-vhdl lsp-vetur
lsp-html lsp-verilog lsp-vala lsp-v lsp-typeprof lsp-ttcn3 lsp-trunk
lsp-toml lsp-tilt lsp-tex lsp-terraform lsp-svelte lsp-steep lsp-sqls
lsp-sorbet lsp-solidity lsp-solargraph lsp-semgrep lsp-rust lsp-ruff-lsp
lsp-ruby-syntax-tree lsp-ruby-lsp lsp-rubocop lsp-rf lsp-remark
lsp-racket lsp-r lsp-qml lsp-pylsp lsp-pyls lsp-pwsh lsp-purescript
lsp-pls lsp-php lsp-perlnavigator lsp-perl lsp-openscad lsp-ocaml
lsp-nushell lsp-nix lsp-nim lsp-nginx lsp-move lsp-mojo lsp-mint lsp-mdx
lsp-marksman lsp-markdown lsp-magik lsp-lua lsp-lisp lsp-kotlin lsp-json
lsp-jq lsp-javascript lsp-idris lsp-haxe lsp-hack lsp-groovy lsp-graphql
lsp-golangci-lint lsp-glsl lsp-gleam lsp-gdscript lsp-fsharp lsp-fortran
lsp-eslint lsp-erlang lsp-emmet lsp-elm lsp-elixir lsp-dockerfile
lsp-dhall lsp-d lsp-cypher lsp-cucumber lsp-css lsp-csharp lsp-crystal
lsp-credo lsp-cobol lsp-cmake lsp-clojure lsp-clangd lsp-bufls lsp-go
lsp-completion lsp-beancount lsp-bash lsp-awk lsp-autotools lsp-astro
lsp-asm lsp-ansible lsp-angular lsp-ada lsp-semantic-tokens
lsp-actionscript lsp-mode lsp-protocol tree-widget network-stream
markdown-mode ht rfc2104 tramp-cmds tramp-cache time-stamp mule-util
pcmpl-unix cursor-sensor cc-awk cc-mode cc-fonts cc-guess cc-menus
cc-cmds cc-styles cc-align cc-engine sql vc-git image-file
image-converter org-indent toc-org oc-basic ol-eww ol-rmail ol-mhe
ol-irc ol-info ol-gnus nnselect ol-docview doc-view jka-compr image-mode
exif ol-bibtex bibtex ol-bbdb ol-w3m ol-doi org-link-doi em-unix em-term
em-script em-pred em-ls em-hist em-glob em-extpipe em-cmpl em-dirs
em-basic em-banner evil-collection-eshell eshell
eshell-syntax-highlighting em-prompt em-alias esh-mode esh-var cus-start
toc-org-autoloads org-bullets org-bullets-autoloads org-tempo tempo
org-drill persist org-agenda org-drill-autoloads persist-autoloads
org-download org-attach org-download-autoloads lsp-mode-autoloads
eldoc-autoloads markdown-mode-autoloads ht-autoloads flycheck
flycheck-autoloads ansible ansible-autoloads haskell-mode haskell-cabal
haskell-utils haskell-font-lock haskell-indentation haskell-string
haskell-sort-imports haskell-lexeme haskell-align-imports
haskell-complete-module haskell-ghc-support flymake-proc flymake dabbrev
haskell-customize haskell-mode-autoloads dockerfile-mode
dockerfile-mode-autoloads terraform-mode hcl-mode
terraform-mode-autoloads hcl-mode-autoloads lua-mode lua-mode-autoloads
go-mode find-file ffap go-mode-autoloads raku-mode raku-repl raku-imenu
raku-indent raku-font-lock raku-detect raku-mode-autoloads popper-echo
popper popper-autoloads vertico-posframe vertico-multiform vertico
vertico-posframe-autoloads vertico-autoloads transpose-frame
transpose-frame-autoloads evil-terminal-cursor-changer
evil-terminal-cursor-changer-autoloads em-tramp esh-cmd esh-ext esh-opt
esh-proc esh-io esh-arg esh-module esh-groups esh-util
eshell-syntax-highlighting-autoloads hydra lv hydra-autoloads
lv-autoloads helpful cc-langs cc-vars cc-defs trace cl-print edebug
info-look f help-fns radix-tree elisp-refs s dash helpful-autoloads
elisp-refs-autoloads f-autoloads s-autoloads dash-autoloads fzf
fzf-autoloads all-the-icons-ivy-rich ivy-rich ivy-posframe posframe
counsel swiper ivy delsel ivy-faces ivy-overlay colir
all-the-icons-ivy-rich-autoloads ivy-rich-autoloads
ivy-posframe-autoloads posframe-autoloads counsel-autoloads
swiper-autoloads ivy-autoloads embark-autoloads use-package-bind-key
bind-key mentor url-scgi mentor-rpc mentor-files mentor-data xml-rpc
url-http url-auth url-gw nsm evil-collection-term term disp-table ehelp
mentor-autoloads url-scgi-autoloads xml-rpc-autoloads projectile
projectile-autoloads cider-autoloads cider cider-debug cider-browse-ns
cider-mode cider-xref-backend cider-find cider-inspector
cider-completion cider-profile cider-eval cider-jar arc-mode
archive-mode cider-repl-history cider-repl cider-resolve cider-test
cider-overlays cider-stacktrace cider-doc cider-browse-spec
cider-clojuredocs cider-eldoc cider-docstring cider-client cider-common
cider-completion-context cider-connection cider-popup sesman-browser
nrepl-client cider-util sesman nrepl-dict spinner clojure-mode align
parseedn parseclj-parser parseclj-lex parseclj-alist sesman-autoloads
spinner-autoloads parseedn-autoloads map-autoloads parseclj-autoloads
clojure-mode-autoloads zoxide-autoloads hyperbole hinit hui hui-mouse
hmouse-key imenu hsys-flymake hui-menu hyrolo-menu hui-jmenu hibtypes
hib-doc-id hyrolo sort klink hmouse-tag hsys-xref hib-kbd hui-mini
hib-debbugs hsys-www eww url-queue mm-url hib-social hypb-ert ert ewoc
debug backtrace hactypes hsys-org man hargs etags fileloop xref project
hpath bookmark hmouse-sh hsettings hui-em-but hbut hmouse-drv hui-window
pulse color hycontrol windmove view hui-select hbdata hgnus gnus-msg
gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum shr
pixel-fill kinsoku url-file svg dom gnus-group gnus-undo gnus-start
gnus-dbus dbus xml gnus-cloud nnimap nnmail mail-source utf7 nnoo
gnus-spec gnus-int gnus-range gnus-win gnus nnheader range hsmail
message sendmail yank-media rfc822 mml mml-sec epa derived epg rfc6068
epg-config gnus-util mm-decode mm-bodies mm-encode mail-parse rfc2231
rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev mail-utils
gmm-utils mailheader hmail htz cal-julian hbmap hmoccur hvar hypb
package browse-url url url-proxy url-privacy url-expand url-methods
url-history url-cookie generate-lisp-file url-domsuf mailcap
url-handlers locate hversion hload-path kotl-autoloads
hyperbole-autoloads hact set hhist paredit paredit-autoloads sudo-edit
sudo-edit-autoloads clojure-ts-mode lisp-mnt clojure-ts-mode-autoloads
treesit-auto treesit-auto-autoloads exec-path-from-shell
exec-path-from-shell-autoloads cape cape-autoloads corfu-history
corfu-echo corfu corfu-autoloads orderless orderless-autoloads yasnippet
yasnippet-autoloads circe diff-mode track-changes lui-irc-colors irc
gnutls puny lcs lui-logging url-util url-parse url-vars lui-format lui
tracking shorten flyspell ispell circe-compat circe-autoloads
xterm-color xterm-color-autoloads rg vc vc-dispatcher rg-info-hack
rg-menu rg-ibuffer rg-result wgrep-rg wgrep rg-history rg-header
ibuf-ext evil-collection-ibuffer ibuffer ibuffer-loaddefs grep compile
text-property-search cus-edit pp cus-load wid-edit rg-autoloads
wgrep-autoloads transient compat transient-autoloads compat-autoloads
seq-autoloads dired-async easy-mmode dired-aux async async-autoloads avy
avy-autoloads general general-autoloads all-the-icons-dired
evil-collection-dired dired dired-loaddefs all-the-icons-dired-autoloads
all-the-icons all-the-icons-faces data-material data-weathericons
data-octicons data-fileicons data-faicons data-alltheicons
all-the-icons-autoloads use-package-ensure rose-pine-theme
evil-collection-unimpaired evil-collection-minibuffer
evil-collection-org evil-collection annalist evil-collection-autoloads
annalist-autoloads evil-org-agenda evil-org org-element org-persist
org-id org-refile org-element-ast inline avl-tree generator
evil-org-autoloads evil-commentary evil-commentary-integration
evil-commentary-autoloads evil-surround evil-surround-autoloads pcase
evil evil-integration evil-maps evil-commands reveal evil-jumps
evil-command-window evil-types evil-search evil-ex evil-macros
evil-repeat evil-states evil-core advice evil-common thingatpt rect
evil-vars edmacro kmacro evil-autoloads goto-chg-autoloads undo-tree
diff queue undo-tree-autoloads queue-autoloads finder-inf
use-package-core diary-lib diary-loaddefs midnight autorevert filenotify
pixel-scroll cua-base saveplace tramp-sh tramp trampver
tramp-integration files-x tramp-message tramp-compat xdg shell
parse-time iso8601 auth-source eieio eieio-core password-cache json map
byte-opt tramp-loaddefs desktop frameset savehist comp comp-cstr
warnings comp-run comp-common elec-pair display-line-numbers org ob
ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-src sh-script smie
treesit executable ob-comint org-pcomplete pcomplete comint ansi-osc
ansi-color ring org-list org-footnote org-faces org-entities time-date
noutline outline icons ob-emacs-lisp ob-core ob-eval org-cycle org-table
ol rx org-fold org-fold-core org-keys oc org-loaddefs find-func cal-menu
calendar cal-loaddefs org-version org-compat org-macs format-spec
use-package-autoloads info bind-key-autoloads straight-autoloads cl-seq
cl-extra help-mode straight subr-x cl-macs gv cl-loaddefs cl-lib
bytecomp byte-compile rmc iso-transl tooltip cconv eldoc paren electric
uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-dnd touch-screen tool-bar dnd fontset
image regexp-opt fringe tabulated-list replace newcomment text-mode
lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch
easymenu timer select scroll-bar mouse jit-lock font-lock syntax
font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads xwidget-internal dbusbind
inotify lcms2 dynamic-setting system-font-setting font-render-setting
cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process native-compile emacs)
 
Memory information:
((conses 16 1164379 714909) (symbols 48 71175 188) (strings 32 271480 36908)
(string-bytes 1 9978327) (vectors 16 129996) (vector-slots 8 2968386 200544)
(floats 8 1627 7929) (intervals 56 31825 4335) (buffers 992 54))