]> git.eshelyaron.com Git - emacs.git/commitdiff
Tramp: Cache also `file-executable-p' in `file-name-all-completions'
authorMichael Albinus <michael.albinus@gmx.de>
Sun, 22 Jun 2025 15:29:52 +0000 (17:29 +0200)
committerEshel Yaron <me@eshelyaron.com>
Tue, 24 Jun 2025 06:30:57 +0000 (08:30 +0200)
* lisp/net/tramp-archive.el (tramp-archive-autoload-file-name-regexp):
Fix comment.

* lisp/net/tramp-sh.el (tramp-perl-file-name-all-completions):
Cache also `file-executable-p'.  Suggested by <mail@knazarov.com>.
(tramp-shell-file-name-all-completions): New script.
(tramp-bundle-read-file-names): Fix for special characters.  Cache
also `file-executable-p'.
(tramp-sh-handle-file-name-all-completions): Unify different cases.

* lisp/net/tramp.el (with-tramp-suspended-timers, without-remote-files):
Fix debug spec.

(cherry picked from commit 87fc539a0b4d7f84d1697e8479158b30c09b4e49)

lisp/net/tramp-archive.el
lisp/net/tramp-sh.el
lisp/net/tramp.el

index 9df2b657e91ddea4a78dcb0d66daffd3813c0d08..0a1c44d36730c9ef276386a761570fdbec3f8a11 100644 (file)
@@ -176,8 +176,8 @@ It must be supported by libarchive(3).")
 It must be supported by libarchive(3).")
 
 ;; The definition of `tramp-archive-file-name-regexp' contains calls
-;; to `regexp-opt', which cannot be autoloaded while loading
-;; loaddefs.el.  So we use a macro, which is evaluated only when needed.
+;; to `rx', which cannot be autoloaded while loading loaddefs.el.  So
+;; we use a macro, which is evaluated only when needed.
 ;;;###autoload
 (progn (defmacro tramp-archive-autoload-file-name-regexp ()
   "Regular expression matching archive file names."
index 7ef6cb3de95c25cf7a119ddce4a4f284d6459287..1be2c1628eeff5724884b7d6ca729fbcb60c7ee6 100644 (file)
@@ -731,18 +731,31 @@ print \"(\\n\";
 foreach $f (@files) {
   ($p = $f) =~ s/\\\"/\\\\\\\"/g;
   ($q = \"$dir/$f\") =~ s/\\\"/\\\\\\\"/g;
-  print \"(\",
-    ((-d \"$q\") ? \"\\\"$p/\\\" \\\"$q\\\" t\" : \"\\\"$p\\\" \\\"$q\\\" nil\"),
+  print \"(\\\"$q\\\"\",
     ((-e \"$q\") ? \" t\" : \" nil\"),
     ((-r \"$q\") ? \" t\" : \" nil\"),
+    ((-d \"$q\") ? \" t\" : \" nil\"),
+    ((-x \"$q\") ? \" t\" : \" nil\"),
     \")\\n\";
 }
 print \")\\n\";
 ' \"$1\" %n"
   "Perl script to produce output suitable for use with
-`file-name-all-completions' on the remote file system.
-Format specifiers are replaced by `tramp-expand-script', percent
-characters need to be doubled.")
+`file-name-all-completions' on the remote file system.  It returns the
+same format as `tramp-bundle-read-file-names'.  Format specifiers are
+replaced by `tramp-expand-script', percent characters need to be
+doubled.")
+
+(defconst tramp-shell-file-name-all-completions
+  "cd \"$1\" 2>&1; %l -a %n | while IFS= read file; do
+    quoted=`echo \"$1/$file\" | sed -e \"s#//#/#g\" -e \"s/\\\"/\\\\\\\\\\\\\\\\\\\"/g\"`
+    printf \"%%b\n\" \"$quoted\"
+  done | tramp_bundle_read_file_names"
+   "Shell script to produce output suitable for use with
+`file-name-all-completions' on the remote file system.  It returns the
+same format as `tramp-bundle-read-file-names'.  Format specifiers are
+replaced by `tramp-expand-script', percent characters need to be
+doubled.")
 
 ;; Perl script to implement `file-attributes' in a Lisp `read'able
 ;; output.  If you are hacking on this, note that you get *no* output
@@ -1172,21 +1185,22 @@ characters need to be doubled.")
 
 (defconst tramp-bundle-read-file-names
   "echo \"(\"
-while read file; do
-  quoted=`echo \"$file\" | sed -e \"s/\\\"/\\\\\\\\\\\\\\\\\\\"/\"`
+while IFS= read file; do
+  quoted=`echo \"$file\" | sed -e \"s/\\\"/\\\\\\\\\\\\\\\\\\\"/g\"`
   printf \"(%%b\" \"\\\"$quoted\\\"\"
   if %q \"$file\"; then printf \" %%b\" t; else printf \" %%b\" nil; fi
   if %m -r \"$file\"; then printf \" %%b\" t; else printf \" %%b\" nil; fi
-  if %m -d \"$file\"; then printf \" %%b)\n\" t; else printf \" %%b)\n\" nil; fi
+  if %m -d \"$file\"; then printf \" %%b\" t; else printf \" %%b\" nil; fi
+  if %m -x \"$file\"; then printf \" %%b)\n\" t; else printf \" %%b)\n\" nil; fi
 done
 echo \")\""
-  "Script to check file attributes of a bundle of files.
-It must be sent formatted with three strings; the tests for file
-existence, file readability, and file directory.  Input shall be
-read via here-document, otherwise the command could exceed
-maximum length of command line.
-Format specifiers \"%s\" are replaced before the script is used,
-percent characters need to be doubled.")
+  "Shell script to check file attributes of a bundle of files.
+For every file, it returns a list with the absolute file name, and the
+tests for file existence, file readability, file directory, and file
+executable.  Input shall be read via here-document, otherwise the
+command could exceed maximum length of command line.  Format specifiers
+\"%s\" are replaced before the script is used, percent characters need
+to be doubled.")
 
 ;; New handlers should be added here.
 ;;;###tramp-autoload
@@ -1947,47 +1961,40 @@ ID-FORMAT valid values are `string' and `integer'."
               ;; reliably tagging the directories with a trailing "/".
               ;; Because I rock.  --daniel@danann.net
               (if (tramp-get-remote-perl v)
-                  (progn
-                    (tramp-maybe-send-script
-                     v tramp-perl-file-name-all-completions
-                     "tramp_perl_file_name_all_completions")
-                    (setq result
-                          (tramp-send-command-and-read
-                           v (format "tramp_perl_file_name_all_completions %s"
-                                     (tramp-shell-quote-argument localname))
-                           'noerror))
-                    ;; Cached values.
-                    (dolist (elt result)
-                      (tramp-set-file-property
-                       v (cadr elt) "file-directory-p" (nth 2 elt))
-                      (tramp-set-file-property
-                       v (cadr elt) "file-exists-p" (nth 3 elt))
-                      (tramp-set-file-property
-                       v (cadr elt) "file-readable-p" (nth 4 elt)))
-                    ;; Result.
-                    (mapcar #'car result))
-
-                ;; Do it with ls.
-                (when (tramp-send-command-and-check
-                       v (format (concat
-                                  "cd %s 2>&1 && %s -a 2>%s"
-                                  " | while IFS= read f; do"
-                                  " if %s -d \"$f\" 2>%s;"
-                                  " then echo \"$f/\"; else echo \"$f\"; fi;"
-                                  " done")
-                                 (tramp-shell-quote-argument localname)
-                                 (tramp-get-ls-command v)
-                                 (tramp-get-remote-null-device v)
-                                 (tramp-get-test-command v)
-                                 (tramp-get-remote-null-device v)))
-
-                  ;; Now grab the output.
-                  (with-current-buffer (tramp-get-buffer v)
-                    (goto-char (point-max))
-                    (while (zerop (forward-line -1))
-                      (push
-                       (buffer-substring (point) (line-end-position)) result)))
-                  result))))))))))
+                  (tramp-maybe-send-script
+                   v tramp-perl-file-name-all-completions
+                   "tramp_perl_file_name_all_completions")
+                ;; Used in `tramp-shell-file-name-all-completions'.
+                (tramp-maybe-send-script
+                 v tramp-bundle-read-file-names "tramp_bundle_read_file_names")
+                (tramp-maybe-send-script
+                 v tramp-shell-file-name-all-completions
+                 "tramp_shell_file_name_all_completions"))
+
+              (dolist
+                  (elt
+                   (tramp-send-command-and-read
+                    v (format
+                       "%s %s"
+                       (if (tramp-get-remote-perl v)
+                           "tramp_perl_file_name_all_completions"
+                         "tramp_shell_file_name_all_completions")
+                       (tramp-shell-quote-argument localname))
+                    'noerror)
+                   result)
+                ;; Don't cache "." and "..".
+                (when (string-match-p
+                       directory-files-no-dot-files-regexp
+                       (file-name-nondirectory (car elt)))
+                  (tramp-set-file-property v (car elt) "file-exists-p" (nth 1 elt))
+                  (tramp-set-file-property v (car elt) "file-readable-p" (nth 2 elt))
+                  (tramp-set-file-property v (car elt) "file-directory-p" (nth 3 elt))
+                  (tramp-set-file-property v (car elt) "file-executable-p" (nth 4 elt)))
+
+                (push
+                 (concat
+                  (file-name-nondirectory (car elt)) (and (nth 3 elt) "/"))
+                 result))))))))))
 
 (defun tramp-sh-handle-file-name-completion-annotation (filename)
   "Like `file-name-completion-annotation' for Tramp files."
@@ -3649,7 +3656,8 @@ filled are described in `tramp-bundle-read-file-names'."
 
       (tramp-set-file-property vec (car elt) "file-exists-p" (nth 1 elt))
       (tramp-set-file-property vec (car elt) "file-readable-p" (nth 2 elt))
-      (tramp-set-file-property vec (car elt) "file-directory-p" (nth 3 elt)))))
+      (tramp-set-file-property vec (car elt) "file-directory-p" (nth 3 elt))
+      (tramp-set-file-property vec (car elt) "file-executable-p" (nth 4 elt)))))
 
 (defvar tramp-vc-registered-file-names nil
   "List used to collect file names, which are checked during `vc-registered'.")
index 0f7b945f84a3767065a9405756ec4568da3f013d..0d7b157c85765d4d3e916d81334d947f7387102a 100644 (file)
@@ -2218,7 +2218,7 @@ This shouldn't be changed globally, but let-bind where needed.")
 (defmacro with-tramp-suspended-timers (&rest body)
   "Run BODY with suspended timers.
 Obey `tramp-dont-suspend-timers'."
-  (declare (indent 0) (debug ((form body) body)))
+  (declare (indent 0) (debug t))
   `(if tramp-dont-suspend-timers
        (progn ,@body)
      (let ((stimers (with-timeout-suspend))
@@ -2759,7 +2759,7 @@ whether HANDLER is to be called.  Add operations defined in
 (progn (defmacro without-remote-files (&rest body)
   "Deactivate remote file names temporarily.
 Run BODY."
-  (declare (indent 0) (debug ((form body) body)))
+  (declare (indent 0) (debug t))
   `(let ((file-name-handler-alist (copy-tree file-name-handler-alist))
          tramp-mode)
      (tramp-unload-file-name-handlers)