unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Ruijie Yu via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: asjo@koldfront.dk, 61326@debbugs.gnu.org
Subject: bug#61326: [PATCH v5] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch)
Date: Thu, 20 Apr 2023 16:49:29 +0800	[thread overview]
Message-ID: <sdvjzy6ud0j.fsf@netyu.xyz> (raw)
In-Reply-To: <835y9r6lll.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]


Eli Zaretskii <eliz@gnu.org> writes:

>> From: Ruijie Yu <ruijie@netyu.xyz>
>> Cc: Eli Zaretskii <eliz@gnu.org>, asjo@koldfront.dk, 61326@debbugs.gnu.org
>> Date: Mon, 17 Apr 2023 16:48:13 +0800
>> 
>> 
>> Ruijie Yu <ruijie@netyu.xyz> writes:
>> 
>> > New iteration.  As mentioned from my last message, I have reverted the
>> > part where I tried to rewrite part of `archive-expunge' using `cl-do'.
>> >
>> > FTR, I am still waiting for the counter signature from FSF before this
>> > can be included into emacs.git.
>> >
>> 
>> Ping?
>> 
>> Removing the "DRAFT" from subject, because I think it is probably
>> complete.  Also, my FSF process should now be complete.
>
> Great, then, with these two issues out of our way, we can install this
> now.
>
> However, the patch as posted back then no longer applies.  Please
> rebase on the current master branch and re-post.
>
> Thanks.

Thanks.  I have made one change after the previous iteration: I turned
the "bug#xxx" comment in the test/lisp/arc-mode-tests.el into a
docstring.  Also, interestingly, git-rebase finishes cleanly on my end.

Here attached is a patch _without_ indentation changes.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Patch *without* indentation changes --]
[-- Type: text/x-patch, Size: 9046 bytes --]

From a98a530d7a7e73404c107e77c173d8981db811ce Mon Sep 17 00:00:00 2001
From: Ruijie Yu <ruijie+git@netyu.xyz>
Date: Mon, 6 Mar 2023 11:03:32 +0800
Subject: [PATCH] Handle modifications on extensionless zips correctly
 (Bug#61326)

* lisp/arc-mode.el
(archive-*-write-file-member) (archive-*-expunge):
Refactor to correctly modify extensionless zip archives.
(archive-expunge):
Move implementation to a separate helper function to facilitate testing.
(archive--act-files): New helper function to wrap around `call-process' calls.
(archive--need-rename-p):
New helper function to check whether a temporary rename is necessary.
(archive--ensure-extension) (archive--maybe-rename):
New helper functions to rename archive if the caller deems it necessary.
(archive--with-ensure-extension):
New helper function to handle writing an archive while ensuring extensionless
archives work correctly by temporarily renaming them.

* test/lisp/arc-mode-tests.el
(arc-mode-test-zip-ensure-ext): New regression test for bug#61326.
---
 lisp/arc-mode.el            | 76 +++++++++++++++++++++++++++----------
 test/lisp/arc-mode-tests.el | 67 ++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 20 deletions(-)

diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 5e696c091b2..0a971799746 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -645,6 +645,49 @@ archive-get-descr
       (if (not noerror)
           (error "Line does not describe a member of the archive")))))
 ;; -------------------------------------------------------------------------
+;;; Section: Helper functions for requiring filename extensions
+
+(defun archive--act-files (command files)
+  (lambda (archive)
+    (apply #'call-process (car command)
+           nil nil nil (append (cdr command) (cons archive files)))))
+
+(defun archive--need-rename-p (&optional archive)
+  (let ((archive
+         (file-name-nondirectory (or archive buffer-file-name))))
+    (cl-case archive-subtype
+      ((zip) (not (seq-contains-p archive ?. #'eq))))))
+
+(defun archive--ensure-extension (archive ensure-extension)
+  (if ensure-extension
+      (make-temp-name (expand-file-name (concat archive "_tmp.")))
+    archive))
+
+(defun archive--maybe-rename (newname need-rename-p)
+  ;; Operating with archive as current buffer, and protect
+  ;; `default-directory' from being modified in `rename-visited-file'.
+  (when need-rename-p
+    (let ((default-directory default-directory))
+      (rename-visited-file newname))))
+
+(defun archive--with-ensure-extension (archive proc-fn)
+  (let ((saved default-directory))
+    (with-current-buffer (find-buffer-visiting archive)
+      (let ((ensure-extension (archive--need-rename-p))
+            (default-directory saved))
+        (unwind-protect
+            ;; Some archive programs (like zip) expect filenames to
+            ;; have an extension, so if necessary, temporarily rename
+            ;; an extensionless file for write accesses.
+            (let ((archive (archive--ensure-extension
+                            archive ensure-extension)))
+              (archive--maybe-rename archive ensure-extension)
+              (let ((exitcode (funcall proc-fn archive)))
+                (or (zerop exitcode)
+                    (error "Updating was unsuccessful (%S)" exitcode))))
+          (progn (archive--maybe-rename archive ensure-extension)
+                 (revert-buffer nil t)))))))
+;; -------------------------------------------------------------------------
 ;;; Section: the mode definition
 
 ;;;###autoload
@@ -1378,16 +1421,9 @@ 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
-				  (append (cdr command)
-					  (list archive ename)))))
-            (or (zerop exitcode)
-		(error "Updating was unsuccessful (%S)" exitcode))))
+                 (default-directory (file-name-as-directory archive-tmpdir)))
+            (archive--with-ensure-extension
+             archive (archive--act-files command (list ename)))))
       (archive-delete-local tmpfile))))
 
 (defun archive-write-file (&optional file)
@@ -1510,9 +1546,7 @@ archive-chgrp-entry
 	  (archive-resummarize))
       (error "Setting group is not supported for this archive type"))))
 
-(defun archive-expunge ()
-  "Do the flagged deletions."
-  (interactive)
+(defun archive--expunge-maybe-force (force)
   (let (files)
     (save-excursion
       (goto-char archive-file-list-start)
@@ -1526,7 +1560,8 @@ archive-expunge
     (and files
 	 (or (not archive-read-only)
 	     (error "Archive is read-only"))
-	 (or (yes-or-no-p (format "Really delete %d member%s? "
+         (or force
+             (yes-or-no-p (format "Really delete %d member%s? "
 				  (length files)
 				  (if (null (cdr files)) "" "s")))
 	     (error "Operation aborted"))
@@ -1540,13 +1575,14 @@ archive-expunge
 	       (archive-resummarize)
 	     (revert-buffer))))))
 
+(defun archive-expunge ()
+  "Do the flagged deletions."
+  (interactive)
+  (archive--expunge-maybe-force nil))
+
 (defun archive-*-expunge (archive files command)
-  (apply #'call-process
-	 (car command)
-	 nil
-	 nil
-	 nil
-	 (append (cdr command) (cons archive files))))
+  (archive--with-ensure-extension
+   archive (archive--act-files command files)))
 
 (defun archive-rename-entry (newname)
   "Change the name associated with this entry in the archive file."
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index 32bce1b71bd..b6e06a563fe 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz
       (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer))
       (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer)))))
 
+(ert-deftest arc-mode-test-zip-ensure-ext ()
+  "Regression test for bug#61326."
+  (skip-unless (executable-find "zip"))
+  (let* ((default-directory arc-mode-tests-data-directory)
+         (base-zip-1 "base-1.zip")
+         (base-zip-2 "base-2.zip")
+         (content-1 '("1" "2"))
+         (content-2 '("3" "4"))
+         (make-file (lambda (name)
+                      (with-temp-buffer
+                        (insert name)
+                        (write-file name))))
+         (make-zip
+          (lambda (zip files)
+            (delete-file zip nil)
+            (funcall (archive--act-files '("zip") files) zip)))
+         (update-fn
+          (lambda (zip-nonempty)
+            (with-current-buffer (find-file-noselect zip-nonempty)
+              (save-excursion
+                (goto-char archive-file-list-start)
+                (save-current-buffer
+                  (archive-extract)
+                  (save-excursion
+                    (goto-char (point-max))
+                    (insert ?a)
+                    (save-buffer))
+                  (kill-buffer (current-buffer)))
+                (archive-extract)
+                ;; [2] must be ?a; [3] must be (eobp)
+                (should (eq (char-after 2) ?a))
+                (should (eq (point-max) 3))))))
+         (delete-fn
+          (lambda (zip-nonempty)
+            (with-current-buffer (find-file-noselect zip-nonempty)
+              ;; mark delete and expunge first entry
+              (save-excursion
+                (goto-char archive-file-list-start)
+                (should (length= archive-files 2))
+                (archive-flag-deleted 1)
+                (archive--expunge-maybe-force t)
+                (should (length= archive-files 1))))))
+         (test-modify
+          (lambda (zip mod-fn)
+            (let ((zip-base (concat zip ".zip"))
+                  (tag (gensym)))
+              (copy-file base-zip-1 zip t)
+              (copy-file base-zip-2 zip-base t)
+              (file-has-changed-p zip tag)
+              (file-has-changed-p zip-base tag)
+              (funcall mod-fn zip)
+              (should-not (file-has-changed-p zip-base tag))
+              (should (file-has-changed-p zip tag))))))
+    ;; setup: make two zip files with different contents
+    (mapc make-file (append content-1 content-2))
+    (mapc (lambda (args) (apply make-zip args))
+          (list (list base-zip-1 content-1)
+                (list base-zip-2 content-2)))
+    ;; test 1: with "test-update" and "test-update.zip", update
+    ;; "test-update": (1) ensure only "test-update" is modified, (2)
+    ;; ensure the contents of the new member is expected.
+    (funcall test-modify "test-update" update-fn)
+    ;; test 2: with "test-delete" and "test-delete.zip", delete entry
+    ;; from "test-delete": (1) ensure only "test-delete" is modified,
+    ;; (2) ensure the file list is reduced as expected.
+    (funcall test-modify "test-delete" delete-fn)))
+
 (provide 'arc-mode-tests)
 
 ;;; arc-mode-tests.el ends here
-- 
2.40.0


[-- Attachment #3: Type: text/plain, Size: 273 bytes --]


Here attached is a patch _with_ indentation changes (on functions which
I have touched) -- I simply re-indented these functions without tabs.
Not sure if you want this, so I provided the other patch file as an
alternative.  Please choose whichever you prefer to install.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: Patch *with* indentation changes --]
[-- Type: text/x-patch, Size: 12416 bytes --]

From 36c5f839042e39b3d49e7939543b988142103033 Mon Sep 17 00:00:00 2001
From: Ruijie Yu <ruijie+git@netyu.xyz>
Date: Mon, 6 Mar 2023 11:03:32 +0800
Subject: [PATCH] Handle modifications on extensionless zips correctly
 (Bug#61326)

* lisp/arc-mode.el
(archive-*-write-file-member) (archive-*-expunge):
Refactor to correctly modify extensionless zip archives.
(archive-expunge):
Move implementation to a separate helper function to facilitate testing.
(archive--act-files): New helper function to wrap around `call-process' calls.
(archive--need-rename-p):
New helper function to check whether a temporary rename is necessary.
(archive--ensure-extension) (archive--maybe-rename):
New helper functions to rename archive if the caller deems it necessary.
(archive--with-ensure-extension):
New helper function to handle writing an archive while ensuring extensionless
archives work correctly by temporarily renaming them.

* test/lisp/arc-mode-tests.el
(arc-mode-test-zip-ensure-ext): New regression test for bug#61326.
---
 lisp/arc-mode.el            | 144 ++++++++++++++++++++++--------------
 test/lisp/arc-mode-tests.el |  67 +++++++++++++++++
 2 files changed, 157 insertions(+), 54 deletions(-)

diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 5e696c091b2..89b3e720ed9 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -645,6 +645,49 @@ archive-get-descr
       (if (not noerror)
           (error "Line does not describe a member of the archive")))))
 ;; -------------------------------------------------------------------------
+;;; Section: Helper functions for requiring filename extensions
+
+(defun archive--act-files (command files)
+  (lambda (archive)
+    (apply #'call-process (car command)
+           nil nil nil (append (cdr command) (cons archive files)))))
+
+(defun archive--need-rename-p (&optional archive)
+  (let ((archive
+         (file-name-nondirectory (or archive buffer-file-name))))
+    (cl-case archive-subtype
+      ((zip) (not (seq-contains-p archive ?. #'eq))))))
+
+(defun archive--ensure-extension (archive ensure-extension)
+  (if ensure-extension
+      (make-temp-name (expand-file-name (concat archive "_tmp.")))
+    archive))
+
+(defun archive--maybe-rename (newname need-rename-p)
+  ;; Operating with archive as current buffer, and protect
+  ;; `default-directory' from being modified in `rename-visited-file'.
+  (when need-rename-p
+    (let ((default-directory default-directory))
+      (rename-visited-file newname))))
+
+(defun archive--with-ensure-extension (archive proc-fn)
+  (let ((saved default-directory))
+    (with-current-buffer (find-buffer-visiting archive)
+      (let ((ensure-extension (archive--need-rename-p))
+            (default-directory saved))
+        (unwind-protect
+            ;; Some archive programs (like zip) expect filenames to
+            ;; have an extension, so if necessary, temporarily rename
+            ;; an extensionless file for write accesses.
+            (let ((archive (archive--ensure-extension
+                            archive ensure-extension)))
+              (archive--maybe-rename archive ensure-extension)
+              (let ((exitcode (funcall proc-fn archive)))
+                (or (zerop exitcode)
+                    (error "Updating was unsuccessful (%S)" exitcode))))
+          (progn (archive--maybe-rename archive ensure-extension)
+                 (revert-buffer nil t)))))))
+;; -------------------------------------------------------------------------
 ;;; Section: the mode definition
 
 ;;;###autoload
@@ -1357,37 +1400,30 @@ archive-*-write-file-member
          (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)))
+         (default-directory (file-name-as-directory top)))
     (unwind-protect
         (progn
           (make-directory (file-name-directory tmpfile) t)
-	  ;; If the member is itself an archive, write it without
-	  ;; the dired-like listing we created.
-	  (if (eq major-mode 'archive-mode)
-	      (archive-write-file tmpfile)
-	    (write-region nil nil tmpfile nil 'nomessage))
-	  ;; basic-save-buffer needs last-coding-system-used to have
-	  ;; the value used to write the file, so save it before any
-	  ;; further processing clobbers it (we restore it in
-	  ;; archive-write-file-member, above).
-	  (setq archive-member-coding-system last-coding-system-used)
-	  (if (archive--file-desc-mode descr)
-	      ;; Set the file modes, but make sure we can read it.
-	      (set-file-modes tmpfile
-	                      (logior ?\400 (archive--file-desc-mode descr))))
-	  (setq ename
-		(encode-coding-string ename archive-file-name-coding-system))
+          ;; If the member is itself an archive, write it without
+          ;; the dired-like listing we created.
+          (if (eq major-mode 'archive-mode)
+              (archive-write-file tmpfile)
+            (write-region nil nil tmpfile nil 'nomessage))
+          ;; basic-save-buffer needs last-coding-system-used to have
+          ;; the value used to write the file, so save it before any
+          ;; further processing clobbers it (we restore it in
+          ;; archive-write-file-member, above).
+          (setq archive-member-coding-system last-coding-system-used)
+          (if (archive--file-desc-mode descr)
+              ;; Set the file modes, but make sure we can read it.
+              (set-file-modes tmpfile
+                              (logior ?\400 (archive--file-desc-mode descr))))
+          (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
-				  (append (cdr command)
-					  (list archive ename)))))
-            (or (zerop exitcode)
-		(error "Updating was unsuccessful (%S)" exitcode))))
+                 (default-directory (file-name-as-directory archive-tmpdir)))
+            (archive--with-ensure-extension
+             archive (archive--act-files command (list ename)))))
       (archive-delete-local tmpfile))))
 
 (defun archive-write-file (&optional file)
@@ -1510,43 +1546,43 @@ archive-chgrp-entry
 	  (archive-resummarize))
       (error "Setting group is not supported for this archive type"))))
 
-(defun archive-expunge ()
-  "Do the flagged deletions."
-  (interactive)
+(defun archive--expunge-maybe-force (force)
   (let (files)
     (save-excursion
       (goto-char archive-file-list-start)
       (while (< (point) archive-file-list-end)
         (if (= (following-char) ?D)
-	    (setq files (cons (archive--file-desc-ext-file-name
-	                       (archive-get-descr))
-	                      files)))
+            (setq files (cons (archive--file-desc-ext-file-name
+                               (archive-get-descr))
+                              files)))
         (forward-line 1)))
     (setq files (nreverse files))
     (and files
-	 (or (not archive-read-only)
-	     (error "Archive is read-only"))
-	 (or (yes-or-no-p (format "Really delete %d member%s? "
-				  (length files)
-				  (if (null (cdr files)) "" "s")))
-	     (error "Operation aborted"))
-	 (let ((archive (archive-maybe-copy (buffer-file-name)))
-	       (expunger (archive-name "expunge")))
-	   (if (fboundp expunger)
-	       (funcall expunger archive files)
-	     (archive-*-expunge archive files (symbol-value expunger)))
-	   (archive-maybe-update nil)
-	   (if archive-remote
-	       (archive-resummarize)
-	     (revert-buffer))))))
+         (or (not archive-read-only)
+             (error "Archive is read-only"))
+         (or force
+             (yes-or-no-p (format "Really delete %d member%s? "
+                                  (length files)
+                                  (if (null (cdr files)) "" "s")))
+             (error "Operation aborted"))
+         (let ((archive (archive-maybe-copy (buffer-file-name)))
+               (expunger (archive-name "expunge")))
+           (if (fboundp expunger)
+               (funcall expunger archive files)
+             (archive-*-expunge archive files (symbol-value expunger)))
+           (archive-maybe-update nil)
+           (if archive-remote
+               (archive-resummarize)
+             (revert-buffer))))))
+
+(defun archive-expunge ()
+  "Do the flagged deletions."
+  (interactive)
+  (archive--expunge-maybe-force nil))
 
 (defun archive-*-expunge (archive files command)
-  (apply #'call-process
-	 (car command)
-	 nil
-	 nil
-	 nil
-	 (append (cdr command) (cons archive files))))
+  (archive--with-ensure-extension
+   archive (archive--act-files command files)))
 
 (defun archive-rename-entry (newname)
   "Change the name associated with this entry in the archive file."
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index 32bce1b71bd..b6e06a563fe 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -46,6 +46,73 @@ arc-mode-test-zip-extract-gz
       (when (buffer-live-p zip-buffer) (kill-buffer zip-buffer))
       (when (buffer-live-p gz-buffer) (kill-buffer gz-buffer)))))
 
+(ert-deftest arc-mode-test-zip-ensure-ext ()
+  "Regression test for bug#61326."
+  (skip-unless (executable-find "zip"))
+  (let* ((default-directory arc-mode-tests-data-directory)
+         (base-zip-1 "base-1.zip")
+         (base-zip-2 "base-2.zip")
+         (content-1 '("1" "2"))
+         (content-2 '("3" "4"))
+         (make-file (lambda (name)
+                      (with-temp-buffer
+                        (insert name)
+                        (write-file name))))
+         (make-zip
+          (lambda (zip files)
+            (delete-file zip nil)
+            (funcall (archive--act-files '("zip") files) zip)))
+         (update-fn
+          (lambda (zip-nonempty)
+            (with-current-buffer (find-file-noselect zip-nonempty)
+              (save-excursion
+                (goto-char archive-file-list-start)
+                (save-current-buffer
+                  (archive-extract)
+                  (save-excursion
+                    (goto-char (point-max))
+                    (insert ?a)
+                    (save-buffer))
+                  (kill-buffer (current-buffer)))
+                (archive-extract)
+                ;; [2] must be ?a; [3] must be (eobp)
+                (should (eq (char-after 2) ?a))
+                (should (eq (point-max) 3))))))
+         (delete-fn
+          (lambda (zip-nonempty)
+            (with-current-buffer (find-file-noselect zip-nonempty)
+              ;; mark delete and expunge first entry
+              (save-excursion
+                (goto-char archive-file-list-start)
+                (should (length= archive-files 2))
+                (archive-flag-deleted 1)
+                (archive--expunge-maybe-force t)
+                (should (length= archive-files 1))))))
+         (test-modify
+          (lambda (zip mod-fn)
+            (let ((zip-base (concat zip ".zip"))
+                  (tag (gensym)))
+              (copy-file base-zip-1 zip t)
+              (copy-file base-zip-2 zip-base t)
+              (file-has-changed-p zip tag)
+              (file-has-changed-p zip-base tag)
+              (funcall mod-fn zip)
+              (should-not (file-has-changed-p zip-base tag))
+              (should (file-has-changed-p zip tag))))))
+    ;; setup: make two zip files with different contents
+    (mapc make-file (append content-1 content-2))
+    (mapc (lambda (args) (apply make-zip args))
+          (list (list base-zip-1 content-1)
+                (list base-zip-2 content-2)))
+    ;; test 1: with "test-update" and "test-update.zip", update
+    ;; "test-update": (1) ensure only "test-update" is modified, (2)
+    ;; ensure the contents of the new member is expected.
+    (funcall test-modify "test-update" update-fn)
+    ;; test 2: with "test-delete" and "test-delete.zip", delete entry
+    ;; from "test-delete": (1) ensure only "test-delete" is modified,
+    ;; (2) ensure the file list is reduced as expected.
+    (funcall test-modify "test-delete" delete-fn)))
+
 (provide 'arc-mode-tests)
 
 ;;; arc-mode-tests.el ends here
-- 
2.40.0


[-- Attachment #5: Type: text/plain, Size: 128 bytes --]


-- 
Best,


RY

[Please note that this mail might go to spam due to some
misconfiguration in my mail server -- will fix soon.]

  reply	other threads:[~2023-04-20  8:49 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-06 17:00 bug#61326: 30.0.50; Editing fil in zip file without extension save creates new file Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-06 18:04 ` Eli Zaretskii
2023-02-06 18:15   ` Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-06 18:57 ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-07  1:31   ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-07  3:27     ` Eli Zaretskii
2023-02-07 13:53       ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-07 14:54         ` Eli Zaretskii
2023-02-08 16:48         ` bug#61326: [DRAFT PATCH] Work around zip's filename extension limitation (was: Adding --no-add-suffix to zip patch) Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-08 18:02           ` Eli Zaretskii
2023-02-10  8:40             ` bug#61326: [DRAFT PATCH v2] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-13 10:35               ` bug#61326: [DRAFT PATCH v3] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-04 11:21                 ` Eli Zaretskii
2023-03-04 14:56                   ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-04 15:12                     ` Eli Zaretskii
2023-03-05 15:23                       ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-05 15:52                         ` Eli Zaretskii
2023-03-06  4:05                           ` bug#61326: [DRAFT PATCH v4] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-11  8:54                             ` Eli Zaretskii
2023-03-11  8:57                               ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-03-17  3:19                                 ` bug#61326: [DRAFT PATCH v5] " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-04-17  8:48                                   ` bug#61326: [PATCH " Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-04-20  7:47                                     ` Eli Zaretskii
2023-04-20  8:49                                       ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2023-04-20  9:29                                         ` Eli Zaretskii
2023-02-07 19:59     ` bug#61326: Adding --no-add-suffix to zip patch Adam Sjøgren via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-08  1:21       ` Ruijie Yu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-08  3:28         ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sdvjzy6ud0j.fsf@netyu.xyz \
    --to=bug-gnu-emacs@gnu.org \
    --cc=61326@debbugs.gnu.org \
    --cc=asjo@koldfront.dk \
    --cc=eliz@gnu.org \
    --cc=ruijie@netyu.xyz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).