branch: externals/tramp-hlo
commit a7daa1217cad0135e933a3dc88cf6a7e2ef548a4
Author: Joe Sadusk <[email protected]>
Commit: Joe Sadusk <[email protected]>

    Address review comments. Add full docstrings, add macro for advice function 
setup, remove unnecessary group
---
 tramp-hlo.el | 200 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 128 insertions(+), 72 deletions(-)

diff --git a/tramp-hlo.el b/tramp-hlo.el
index 6f1fe35841..d330007876 100644
--- a/tramp-hlo.el
+++ b/tramp-hlo.el
@@ -12,10 +12,6 @@
 
 ;;; Code
 
-(defgroup tramp-hlo nil
-  "High level operations as tramp handlers"
-  :group 'tools)
-
 (require 'tramp-sh)
 
 (defconst tramp-hlo-test-files-in-dir-script
@@ -36,7 +32,7 @@ else
     echo \\)
 fi
 "
-  "Script to check for dir-locals in a remote dir"
+  "Script to check for `dir-locals' in a remote dir."
   )
 
 (defconst tramp-hlo-list-parents-script
@@ -114,99 +110,148 @@ echo \\)
   "Script to find several dominating files on a remote host"
 )
 
+(defmacro tramp-hlo-advice (file fallback &rest body)
+  "Setup macro for tramp-hlo advice functions.
+Creates a scaffold to make an advice function to add a tramp implementation to
+a high level function. FILE is a filename that might be a remote file with a
+tramp-sh backend. If so, execute the BODY of the macro, otherwise run the
+FALLBACK expression. If executing BODY, the dissected FILE will be in scope as
+`vec'."
+  `(if-let* ((non-essential t)
+             (vec (ignore-errors
+                    (tramp-dissect-file-name ,file)))
+             ((tramp-sh-file-name-handler-p vec)))
+
+       (progn ,@body)
+     (,@fallback)
+     )
+  )
+
+
 (defun tramp-hlo-dir-locals--all-files (orig-fun directory &optional 
base-el-only)
-  "Tramp version of dir-locals--all-files"
-  (let ((connection (file-remote-p directory)))
-    (if connection
-        (let* ((localdir (directory-file-name (file-local-name directory)))    
-               (file-1 dir-locals-file)
-               (file-2 (when (string-match "\\.el\\'" file-1)
-                         (replace-match "-2.el" t nil file-1)))
-               (vec (tramp-dissect-file-name directory))
+  "Tramp optimized version of dir-locals--all-files.
+Return a list of all readable dir-locals files in the directory
+represented by VEC.
+The returned list is sorted by increasing priority.  That is,
+values specified in the last file should take precedence over
+those in the first.
+
+The optional argument BASE-EL-ONLY will only consider the base dir locals file.
+This is intended as an advice function, with ORIG-FUN as the fallback 
function."
+  (tramp-hlo-advice directory
+    (funcall orig-fun directory)
+    (let* ((localdir (directory-file-name (tramp-file-name-localname vec)))
+           (file-1 dir-locals-file)
+           (file-2 (when (string-match "\\.el\\'" file-1)
+                     (replace-match "-2.el" t nil file-1)))
+           )
+      (tramp-maybe-send-script vec tramp-hlo-test-files-in-dir-script 
"test_files_in_dir")
+      (mapcar (lambda (name) (tramp-make-tramp-file-name vec name))
+              (tramp-send-command-and-read
+               vec
+               (if base-el-only
+                   (format "test_files_in_dir %s %s"
+                           localdir file-1)
+                 (format "test_files_in_dir %s %s %s"
+                         localdir file-1 file-2)
+                 )
                )
-          (tramp-maybe-send-script vec tramp-hlo-test-files-in-dir-script 
"test_files_in_dir")
-          (mapcar (lambda (name) (concat connection name))
-                  (tramp-send-command-and-read
-                   vec
-                   (if base-el-only
-                       (format "test_files_in_dir %s %s"
-                               localdir file-1)
-                       (format "test_files_in_dir %s %s %s"
-                               localdir file-1 file-2)
-                       )
-                   )
-                  )
-          )
-      (funcall orig-fun directory)
+              )
       )
     )
   )
 
-(defun tramp-hlo-locate-dominating-file-pred (connection vec file pred)
-  "Implementation of tramp-hlo-locate-dominating-file for a name predicate"
+(defun tramp-hlo-locate-dominating-file-pred (vec pred)
+  "Implementation of tramp-hlo-locate-dominating-file for a name predicate.
+Starting at the file represented by VEC, look up directory hierarchy for
+directory identified by PRED.
+Stop at the first parent directory matched, and return the directory. Return 
nil
+if not found.
+PRED takes one argument, a directory, and returns a non-nil value if that
+directory is the one for which we're looking."
   (tramp-maybe-send-script vec tramp-hlo-list-parents-script "list_parents")
   (let* ((command (format "list_parents %s" (nth 6 vec)))
          (parents (tramp-send-command-and-read vec command))
          )
-    (while (and parents (not (funcall pred (concat connection (car parents)))))
+    (while (and parents (not (funcall pred (tramp-make-tramp-file-name vec 
(car parents)))))
       (pop parents)
       )
     (if parents
-        (concat connection (car parents))
+        (tramp-make-tramp-file-name vec (car parents))
       nil)
     )
   )
 
-(defun tramp-hlo-locate-dominating-file-list (connection vec file names)
-  "Implementation of tramp-hlo-locate-dominating-file for a list of names"
+(defun tramp-hlo-locate-dominating-file-list (vec names)
+  "Implementation of tramp-hlo-locate-dominating-file for a list of names.
+Starting at the file represented by VEC, look up directory hierarchy for
+directory containing any files in list NAMES.
+Stop at the first parent directory matched, and return the directory. Return 
nil
+if not found."
   (tramp-maybe-send-script vec tramp-hlo-locate-dominating-file-multi-script 
"locate_dominating_file_multi")
   (let* ((localfile (nth 6 vec))
          (quoted-names (mapcar (lambda (name) (format "\"%s\"" name)) names))
          (quoted-names-str (string-join names " "))
          (command (format "locate_dominating_file_multi %s %s" localfile 
quoted-names-str))
          (local-dominating (tramp-send-command-and-read vec command)))
-    (mapcar (lambda (result) (concat connection result)) local-dominating)
+    (mapcar (lambda (result) (tramp-make-tramp-file-name vec result)) 
local-dominating)
     )
   )
 
 (defun tramp-hlo-locate-dominating-file (orig-fun file name)
-  "Tramp version of locate-dominating-file"
-  (let ((connection (file-remote-p file)))
-    (if connection
-        (let ((vec (tramp-dissect-file-name file)))
-          (if (functionp name)
-              (tramp-hlo-locate-dominating-file-pred connection vec file name)
-            (let* ((names (if (listp name) name (list name)))
-                   (file-list (tramp-hlo-locate-dominating-file-list 
connection vec file names)))
-              (if file-list
-                  (file-name-directory (car file-list))
-                nil
-                )
-              )
-            )
-          )
-      (funcall orig-fun file name)
-      )
-    )
-  )
-
-(defun tramp-hlo-find-dominating-files (file names)
-  "Tramp specific function to find multiple dominating files"
-  (let ((connection (file-remote-p file)))
-    (if connection
-        (let ((vec (tramp-dissect-file-name file)))
-          (tramp-hlo-locate-dominating-file-list connection vec file names)
-          )
-      )
-    )
+  "Tramp version of locate-dominating-file
+Starting at FILE, look up directory hierarchy for directory containing NAME.
+FILE can be a file or a directory.  If it's a file, its directory will
+serve as the starting point for searching the hierarchy of directories.
+Stop at the first parent directory containing a file NAME,
+and return the directory.  Return nil if not found.
+Instead of a string, NAME can also be a predicate taking one argument
+\(a directory) and returning a non-nil value if that directory is the one for
+which we're looking.  The predicate will be called with every file/directory
+the function needs to examine, starting with FILE.
+This is intended as an advice function, with ORIG-FUN as the fallback 
function."
+  (tramp-hlo-advice file
+   (funcall orig-fun file name)
+   (if (functionp name)
+       (tramp-hlo-locate-dominating-file-pred vec name)
+     (let* ((names (if (listp name) name (list name)))
+            (file-list (tramp-hlo-locate-dominating-file-list vec names)))
+       (if file-list
+           (file-name-directory (car file-list))
+         nil
+         )
+       )
+     )
+   )
   )
 
 (defun tramp-hlo-dir-locals-find-file (orig-fun file)
-  "Tramp implementation of dir-locals-find-file"
-  (let ((connection (file-remote-p file)))
-    (if connection
-        (let* ((locals-files (tramp-hlo-find-dominating-files 
(file-name-directory file)
-                                                   '(".dir-locals.el" 
".dir-locals-2.el")))
+  "Tramp implementation of `dir-locals-find-file'.
+Find the directory-local variables for FILE.
+This searches upward in the directory tree from FILE.
+It stops at the first directory that has been registered in
+`dir-locals-directory-cache' or contains a `dir-locals-file'.
+If it finds an entry in the cache, it checks that it is valid.
+A cache entry with no modification time element (normally, one that
+has been assigned directly using `dir-locals-set-directory-class', not
+set from a file) is always valid.
+A cache entry based on a `dir-locals-file' is valid if the modification
+time stored in the cache matches the current file modification time.
+If not, the cache entry is cleared so that the file will be re-read.
+
+This function returns either:
+  - nil (no directory local variables found),
+  - the matching entry from `dir-locals-directory-cache' (a list),
+  - or the full path to the directory (a string) containing at
+    least one `dir-locals-file' in the case of no valid cache
+    entry.
+
+This is intended as an advice function, with ORIG-FUN as the fallback 
function."
+  (tramp-hlo-advice file
+      (funcall orig-fun file)
+      (let* ((locals-files (tramp-hlo-locate-dominating-file-list
+                            vec
+                            '(".dir-locals.el" ".dir-locals-2.el")))
               (locals-dir (if locals-files (file-name-directory (car 
locals-files)) nil))
               dir-elt)
          ;; `locate-dominating-file' may have abbreviated the name.
@@ -253,15 +298,26 @@ echo \\)
                locals-dir)
            ;; No cache entry.
            locals-dir))
-      (funcall orig-fun file)
       )
-    )
   )
 
-(defun configure-tramp-hlo ()
+(defun setup-tramp-hlo ()
+  "Setup tramp high-level functions.
+Adds advice functions with tramp implementations for the following emacs
+built-in functions:
+- `dir-locals--all-files'
+- `locate-dominating-file'
+- `dir-locals-find-file'"
   (advice-add 'dir-locals--all-files :around #'tramp-hlo-dir-locals--all-files)
   (advice-add 'locate-dominating-file :around 
#'tramp-hlo-locate-dominating-file)
   (advice-add 'dir-locals-find-file :around #'tramp-hlo-dir-locals-find-file)
   )
 
-(provide 'tramp-hlo)
+(defun remove-tramp-hlo ()
+  "Remove tramp high-level functions.
+Remove tramp advice functions for high-level emacs built-in functions."
+  (advice-remove 'dir-locals--all-files #'tramp-hlo-dir-locals--all-files)
+  (advice-remove 'locate-dominating-file #'tramp-hlo-locate-dominating-file)
+  (advice-remove 'dir-locals-find-file #'tramp-hlo-dir-locals-find-file)
+  )
+

Reply via email to