>From bc56c17082ea3ff2a76308f14310908853e3a2d1 Mon Sep 17 00:00:00 2001 From: Ruijie Yu Date: Thu, 9 Feb 2023 00:45:19 +0800 Subject: [PATCH] lisp/arc-mode.el Work around zip's filename limitations on extension [DRAFT PATCH] Fixes 61326. The "zip" executable requires that the named archive must have an extension, else it attaches ".zip" to the supplied file name, causing incorrect behaviors. This patch looks for such scenarios and temporarily rename extension-less archives so that "zip" would function correctly. TODO: 1. Make sure other write operations, in addition to zip-write-member, are fixed. 2. Tests? (I might need some pointers as to where existing tests are and how to write them.) --- lisp/arc-mode.el | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 6f3e922880d..cd7f4ca1134 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -1350,14 +1350,23 @@ archive-write-file-member (setq last-coding-system-used archive-member-coding-system)) t) -(defun archive-*-write-file-member (archive descr command) +(defun archive-*-write-file-member + (archive descr command &optional ensure-extension) (let* ((archive (expand-file-name archive)) + (real-archive archive) + (archive (if ensure-extension + (make-temp-name + (expand-file-name (concat archive "_tmp."))) + archive)) (ename (archive--file-desc-ext-file-name descr)) (tmpfile (expand-file-name ename archive-tmpdir)) (top (directory-file-name (file-name-as-directory archive-tmpdir))) (default-directory (file-name-as-directory top))) (unwind-protect - (progn + (cl-flet ((maybe-rename (newname) + (when ensure-extension + (with-current-buffer archive-superior-buffer + (rename-visited-file newname))))) (make-directory (file-name-directory tmpfile) t) ;; If the member is itself an archive, write it without ;; the dired-like listing we created. @@ -1376,16 +1385,20 @@ archive-*-write-file-member (setq ename (encode-coding-string ename archive-file-name-coding-system)) (let* ((coding-system-for-write 'no-conversion) - (default-directory (file-name-as-directory archive-tmpdir)) - (exitcode (apply #'call-process - (car command) - nil - nil - nil + (default-directory (file-name-as-directory archive-tmpdir))) + (unwind-protect + (progn + (maybe-rename archive) + (let ((exitcode + (apply #'call-process (car command) + nil nil nil (append (cdr command) (list archive ename))))) (or (zerop exitcode) (error "Updating was unsuccessful (%S)" exitcode)))) + (progn (maybe-rename real-archive) + (with-current-buffer archive-superior-buffer + (revert-buffer nil t)))))) (archive-delete-local tmpfile)))) (defun archive-write-file (&optional file) @@ -2048,12 +2061,19 @@ archive--file-desc-case-fiddled (not (eq (archive--file-desc-int-file-name fd) (archive--file-desc-ext-file-name fd)))) +(defun archive--file-name-zip-extless-p (fname) + ;; zip's rule: if the filename contains "." anywhere in the name + ;; (including obscure names like ".foo" and "bar."), then this + ;; filename is considered to have an extension. + (not (seq-contains-p (file-name-nondirectory fname) ?. #'eq))) + (defun archive-zip-write-file-member (archive descr) (archive-*-write-file-member archive descr (if (archive--file-desc-case-fiddled descr) - archive-zip-update-case archive-zip-update))) + archive-zip-update-case archive-zip-update) + (archive--file-name-zip-extless-p archive))) (defun archive-zip-chmod-entry (newmode files) (save-restriction -- 2.39.1