From 6e93e76083bc949625cfdebb4299157f288e77ae Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 11 Sep 2023 13:51:58 +0200 Subject: [PATCH] New command tramp-revert-buffer-with-sudo * doc/misc/tramp.texi (Ad-hoc multi-hops): Document tramp-file-name-with-method and tramp-revert-buffer-with-sudo. * etc/NEWS: New command tramp-revert-buffer-with-sudo. * lisp/net/tramp-cmds.el (dired-advertise, dired-unadvertise): Declare. (tramp-dired-buffer-p, tramp-remote-process-p): Rename. (tramp-file-name-with-method): New defcustom. (tramp-file-name-with-sudo, tramp-revert-buffer-with-sudo): New defuns. --- doc/misc/tramp.texi | 30 ++++++++++++++++ etc/NEWS | 15 +++++--- lisp/net/tramp-cmds.el | 81 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 78b47f779cf..ea3bf8570b7 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -3716,6 +3716,36 @@ containers on the remote host. @end lisp @end defopt +A common use case for ad-hoc specifications is to visit a file or a +directory with proper permissions, for example with the @option{sudo} +method. The command @code{tramp-revert-buffer-with-sudo} supports +this. + +@deffn Command tramp-revert-buffer-with-sudo +This command shows the current buffer with @option{sudo} permissions. +The buffer must either visit a file, or a directory +(@code{dired-mode}). +@end deffn + +@defopt tramp-file-name-with-method +The method @code{tramp-revert-buffer-with-sudo} shows an alternate +buffer. It defaults to @code{sudo}, other valid methods are +@code{su}, @code{doas}, and @code{ksu}. + +@lisp +(customize-set-variable 'tramp-file-name-with-method "doas") +@end lisp +@end defopt + +These methods apply the user @samp{root} as default. If another user +shall be taken, add a proper rule to the user option +@code{tramp-default-user-alist} (@pxref{Default User}): + +@lisp +(add-to-list 'tramp-default-user-alist '("sudo" "remotehost" "admin")) +@end lisp + + @node Home directories @section Expanding @file{~} to home directory diff --git a/etc/NEWS b/etc/NEWS index 5e6ce716117..29d44a622cb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -483,6 +483,13 @@ be attempted at the end of a multi-hop chain. This allows completion candidates to include a list of, for example, containers running on a remote docker host. ++++ +*** New command 'tramp-revert-buffer-with-sudo'. +It reverts the current buffer to visit with "sudo" permissions. The +buffer must either visit a file, or it must run 'dired-mode'. Another +method but "sudo" can be configured with user option +'tramp-file-name-with-method'. + ** EWW +++ @@ -748,7 +755,7 @@ This can help avoid some awkward skip conditions. For example '(skip-unless (not noninteractive))' can be changed to the easier to read '(skip-when noninteractive)'. -** checkdoc +** Checkdoc --- *** New checkdock warning if not using lexical-binding. @@ -756,7 +763,7 @@ Checkdoc now warns if the first line of an Emacs Lisp file does not end with a "-*- lexical-binding: t -*-" cookie. Customize the user option 'checkdoc-lexical-binding-flag' to nil to disable this warning. -** url +** URL +++ *** 'url-gateway-broken-resolution' is now obsolete. @@ -787,7 +794,7 @@ files. +++ ** New global minor mode 'minibuffer-regexp-mode'. This is a minor mode for editing regular expressions in the minibuffer. -It highlight parens via ‘show-paren-mode’ and ‘blink-matching-paren’ in +It highlights parens via ‘show-paren-mode’ and ‘blink-matching-paren’ in a user-friendly way, avoids reporting alleged paren mismatches and makes sexp navigation more intuitive. @@ -915,7 +922,7 @@ See the "(elisp) Porting Old Advice" node for help converting them to use 'advice-add' or 'define-advice' instead. ** 'cl-old-struct-compat-mode' is marked as obsolete. -You may need to recompile our code if it was compiled with Emacs<24.3. +You may need to recompile our code if it was compiled with Emacs < 24.3. +++ ** New macro 'static-if' for conditional evaluation of code. diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 8d95adb597c..22fb7eee8f3 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -31,6 +31,8 @@ (require 'tramp) ;; Pacify byte-compiler. +(declare-function dired-advertise "dired") +(declare-function dired-unadvertise "dired") (declare-function mml-mode "mml") (declare-function mml-insert-empty-tag "mml") (declare-function reporter-dump-variable "reporter") @@ -75,6 +77,8 @@ SYNTAX can be one of the symbols `default' (default), (when (tramp-tramp-file-p (tramp-get-default-directory x)) x)) (buffer-list)))) +;;; Cleanup + ;;;###tramp-autoload (defvar tramp-cleanup-connection-hook nil "List of functions to be called after Tramp connection is cleaned up. @@ -221,13 +225,13 @@ functions are called with `current-buffer' set." (add-hook 'tramp-cleanup-some-buffers-hook #'buffer-file-name) -(defun tramp-cleanup-dired-buffer-p () +(defun tramp-dired-buffer-p () "Return t if current buffer runs `dired-mode'." (declare (tramp-suppress-trace t)) (derived-mode-p 'dired-mode)) (add-hook 'tramp-cleanup-some-buffers-hook - #'tramp-cleanup-dired-buffer-p) + #'tramp-dired-buffer-p) (defvar tramp-tainted-remote-process-buffers nil "List of process buffers to be cleaned up.") @@ -256,12 +260,12 @@ functions are called with `current-buffer' set." (remove-hook 'kill-buffer-hook #'tramp-delete-tainted-remote-process-buffer-function))) -(defun tramp-cleanup-remote-process-p () +(defun tramp-remote-process-p () "Return t if current buffer belongs to a remote process." (memq (current-buffer) tramp-tainted-remote-process-buffers)) (add-hook 'tramp-cleanup-some-buffers-hook - #'tramp-cleanup-remote-process-p) + #'tramp-remote-process-p) ;;;###tramp-autoload (defun tramp-cleanup-some-buffers () @@ -288,6 +292,8 @@ non-nil." (let ((tramp-cleanup-some-buffers-hook '(tramp-compat-always))) (tramp-cleanup-some-buffers))) +;;; Rename + (defcustom tramp-default-rename-alist nil "Default target for renaming remote buffer file names. This is an alist of cons cells (SOURCE . TARGET). The first @@ -552,6 +558,73 @@ For details, see `tramp-rename-files'." (function-put #'tramp-rename-these-files 'completion-predicate #'tramp-command-completion-p) +;;; Run as sudo + +(defcustom tramp-file-name-with-method "sudo" + "Which method to be used in `tramp-file-name-with-sudo'." + :group 'tramp + :version "30.1" + :type '(choice (const "su") + (const "sudo") + (const "doas") + (const "ksu"))) + +(defun tramp-file-name-with-sudo (filename) + "Convert FILENAME into a multi-hop file name with \"sudo\". +An alternative method could be chosen with `tramp-file-name-with-method'." + (setq filename (expand-file-name filename)) + (if (tramp-tramp-file-p filename) + (with-parsed-tramp-file-name filename nil + (cond + ;; Remote file with proper method. + ((string-equal method tramp-file-name-with-method) + filename) + ;; Remote file on the local host. + ((and + (stringp tramp-local-host-regexp) (stringp host) + (string-match-p tramp-local-host-regexp host)) + (tramp-make-tramp-file-name + (make-tramp-file-name + :method tramp-file-name-with-method :localname localname))) + ;; Remote file with multi-hop capable method.. + ((tramp-multi-hop-p v) + (tramp-make-tramp-file-name + (make-tramp-file-name + :method (tramp-find-method tramp-file-name-with-method nil host) + :user (tramp-find-user tramp-file-name-with-method nil host) + :host (tramp-find-host tramp-file-name-with-method nil host) + :localname localname :hop (tramp-make-tramp-hop-name v)))) + ;; Other remote file. + (t (tramp-user-error v "Multi-hop with `%s' not applicable" method)))) + ;; Local file. + (tramp-make-tramp-file-name + (make-tramp-file-name + :method tramp-file-name-with-method :localname filename)))) + +;;;###tramp-autoload +(defun tramp-revert-buffer-with-sudo () + "Revert current buffer to visit with \"sudo\" permissions. +An alternative method could be chosen with `tramp-file-name-with-method'. +If the buffer visits a file, the file is replaced. +If the buffer runs `dired', the buffer is reverted." + (interactive) + (cond + ((buffer-file-name) + (find-alternate-file (tramp-file-name-with-sudo (buffer-name)))) + ((tramp-dired-buffer-p) + (dired-unadvertise (expand-file-name default-directory)) + (setq default-directory (tramp-file-name-with-sudo default-directory) + list-buffers-directory + (tramp-file-name-with-sudo list-buffers-directory)) + (if (consp dired-directory) + (setcar + dired-directory (tramp-file-name-with-sudo (car dired-directory))) + (setq dired-directory (tramp-file-name-with-sudo dired-directory))) + (dired-advertise) + (revert-buffer)))) + +;;; Recompile on ELPA + ;; This function takes action since Emacs 28.1, when ;; `read-extended-command-predicate' is set to ;; `command-completion-default-include-p'. -- 2.39.5