From e880aa6b8f7f3678e13b0a14e2a0646a5a399a7a Mon Sep 17 00:00:00 2001 From: Struan Robertson Date: Sat, 28 Dec 2024 16:11:59 +0000 Subject: [PATCH 1/4] Allow flymake-ruff to use Ruff config files from remote TRAMP hosts Don't pollute /tmp Fix error on directory existing Cache config and use tramp-handle-* funcitons to stop TRAMP reentrant errors --- flymake-ruff.el | 53 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/flymake-ruff.el b/flymake-ruff.el index 77f7187..ab5bbfc 100644 --- a/flymake-ruff.el +++ b/flymake-ruff.el @@ -39,6 +39,41 @@ '(".ruff.toml" "ruff.toml" "pyproject.toml") "Default configuration files supported by Ruff.") +(defun flymake-ruff--get-config () + "Look for configuration files supported by Ruff in project root. +When project is on remote host, cache config using `default-directory' as key." + (if (file-remote-p default-directory) + (let ((cache-dir (expand-file-name + (concat "ruff-config-" (sha1 default-directory)) + "/tmp"))) + (if (file-directory-p cache-dir) + ;; Return cached config if exists + (seq-find #'file-readable-p + (mapcar (lambda (f) + (expand-file-name f cache-dir)) + flymake-ruff--default-configs)) + ;; Create cache and return config path + (when-let* ((project-current (project-current)) + (config (seq-find + #'tramp-handle-file-readable-p + (mapcar (lambda (f) + (expand-file-name f (project-root project-current))) + flymake-ruff--default-configs))) + (temp-file (expand-file-name (file-name-nondirectory config) cache-dir)) + (temp-copy (tramp-handle-file-local-copy config))) + (message "first") + (make-directory cache-dir) + (copy-file temp-copy temp-file t) + (delete-file temp-copy) + temp-file))) + + ;; Local project path + (when-let ((project-current (project-current))) + (seq-find #'file-readable-p + (mapcar (lambda (f) + (expand-file-name f (project-root project-current))) + flymake-ruff--default-configs))))) + (defun flymake-ruff--check-buffer () "Generate a list of diagnostics for the current buffer." (let ((code-buffer (current-buffer)) @@ -52,14 +87,8 @@ ;; check if the current buffer belongs to a project before ;; trying to build a path using `project-current' otherwise it ;; will fail silently - (let* ((config (and (project-current) - (seq-find - #'file-readable-p - (mapcar - (lambda (f) - (expand-file-name f (project-root (project-current)))) - flymake-ruff--default-configs)))) - (args (if config + (let* ((config (flymake-ruff--get-config)) + (args (if config ;; for version > 0.5 the work "check" is ;; included so we need to extract it and put it ;; before --config argument @@ -94,6 +123,14 @@ "Load hook for the current buffer to tell flymake to run checker." (interactive) (when (derived-mode-p 'python-mode 'python-ts-mode) + ;; If cached TRAMP config file exists for current buffer, remove it so that cache can be refreshed on reverting buffer. + (when-let* ((_remote (file-remote-p default-directory)) + (cache-dir (expand-file-name + (concat "ruff-config-" (sha1 default-directory)) + "/tmp")) + (_cache_exist (file-directory-p cache-dir))) + (delete-directory cache-dir t)) + (add-hook 'flymake-diagnostic-functions #'flymake-ruff--run-checker nil t))) (defun flymake-ruff--run-checker (report-fn &rest _args) From d80cc7f1aeae2d19bd153df5ffa71636a3a6f24f Mon Sep 17 00:00:00 2001 From: Struan Robertson Date: Thu, 16 Jan 2025 12:26:03 +0000 Subject: [PATCH 2/4] Don't repeatedly search for a config file if one does not exist --- flymake-ruff.el | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/flymake-ruff.el b/flymake-ruff.el index ab5bbfc..7dd7380 100644 --- a/flymake-ruff.el +++ b/flymake-ruff.el @@ -35,6 +35,10 @@ (defvar flymake-ruff--output-regex "\\(.*\\):\\([0-9]+\\):\\([0-9]+\\): \\([A-Za-z0-9]+\\):? \\(.*\\)") +(defvar flymake-ruff--no-config-tramp-dirs + nil + "List of TRAMP directories that ruff checked for config in but found none. This prevents repeatedly looking for config files that do not exist.") + (defconst flymake-ruff--default-configs '(".ruff.toml" "ruff.toml" "pyproject.toml") "Default configuration files supported by Ruff.") @@ -42,30 +46,34 @@ (defun flymake-ruff--get-config () "Look for configuration files supported by Ruff in project root. When project is on remote host, cache config using `default-directory' as key." - (if (file-remote-p default-directory) - (let ((cache-dir (expand-file-name - (concat "ruff-config-" (sha1 default-directory)) - "/tmp"))) - (if (file-directory-p cache-dir) - ;; Return cached config if exists - (seq-find #'file-readable-p - (mapcar (lambda (f) - (expand-file-name f cache-dir)) - flymake-ruff--default-configs)) - ;; Create cache and return config path - (when-let* ((project-current (project-current)) + (if (and (tramp-handle-file-remote-p default-directory)) + (when (not (seq-contains-p flymake-ruff--no-config-tramp-dirs default-directory #'string-equal)) + (let ((cache-dir (expand-file-name + (concat "ruff-config-" (sha1 default-directory)) + "/tmp"))) + (if (file-directory-p cache-dir) + ;; Return cached config if exists + (seq-find #'file-readable-p + (mapcar (lambda (f) + (expand-file-name f cache-dir)) + flymake-ruff--default-configs)) + ;; Create cache and return config path + (if-let* ((project-current (project-current)) (config (seq-find #'tramp-handle-file-readable-p (mapcar (lambda (f) - (expand-file-name f (project-root project-current))) + (tramp-handle-expand-file-name f (project-root project-current))) flymake-ruff--default-configs))) - (temp-file (expand-file-name (file-name-nondirectory config) cache-dir)) + (temp-file (tramp-handle-expand-file-name (tramp-handle-file-name-nondirectory config) cache-dir)) (temp-copy (tramp-handle-file-local-copy config))) - (message "first") - (make-directory cache-dir) - (copy-file temp-copy temp-file t) - (delete-file temp-copy) - temp-file))) + (progn + (make-directory cache-dir) + (copy-file temp-copy temp-file t) + (delete-file temp-copy) + temp-file) + (progn + (push default-directory flymake-ruff--no-config-tramp-dirs) + nil))))) ;; Local project path (when-let ((project-current (project-current))) From d86df3065ecd5fb7004a883075a8a9a8142962ec Mon Sep 17 00:00:00 2001 From: Struan Robertson Date: Fri, 24 Jan 2025 14:43:21 +0000 Subject: [PATCH 3/4] Better handling of checking if a file is remote --- flymake-ruff.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flymake-ruff.el b/flymake-ruff.el index 7dd7380..f7b3789 100644 --- a/flymake-ruff.el +++ b/flymake-ruff.el @@ -46,7 +46,8 @@ (defun flymake-ruff--get-config () "Look for configuration files supported by Ruff in project root. When project is on remote host, cache config using `default-directory' as key." - (if (and (tramp-handle-file-remote-p default-directory)) + (if (and (tramp-handle-file-remote-p (or buffer-file-name + default-directory))) (when (not (seq-contains-p flymake-ruff--no-config-tramp-dirs default-directory #'string-equal)) (let ((cache-dir (expand-file-name (concat "ruff-config-" (sha1 default-directory)) From d4905ca4d0d85b623b55a2158bd25a4e9ad924f2 Mon Sep 17 00:00:00 2001 From: Struan Robertson Date: Mon, 17 Feb 2025 23:59:05 +0000 Subject: [PATCH 4/4] Fix syntax error Dont remove buffer-file-name --- flymake-ruff.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flymake-ruff.el b/flymake-ruff.el index f7b3789..0c8e9a8 100644 --- a/flymake-ruff.el +++ b/flymake-ruff.el @@ -46,8 +46,8 @@ (defun flymake-ruff--get-config () "Look for configuration files supported by Ruff in project root. When project is on remote host, cache config using `default-directory' as key." - (if (and (tramp-handle-file-remote-p (or buffer-file-name - default-directory))) + (if (tramp-handle-file-remote-p (or buffer-file-name + default-directory)) (when (not (seq-contains-p flymake-ruff--no-config-tramp-dirs default-directory #'string-equal)) (let ((cache-dir (expand-file-name (concat "ruff-config-" (sha1 default-directory))