Subject: Re: bug#10347: 24.0.50; archive-mode includes warning messages from unzip in the content of extracted files

From: Juri Linkov <[email-masked]>
Date: Sun, 25 Dec 2011 23:28:52 +0200

Actually, `archive-rar-extract' has exactly the same problem.
When `unrar-free' can't extract some files from RAR archives,
it displays a confusing message:

  Removing old name: no such file or directory, /tmp/arc-rar1971TAO/file.txt

It needs the same treatment as 7z and zip.  But the difference is that
`unrar-free' outputs only to stdout, not to stderr.  And when the operation
is successful, it outputs long text with the known fixed message
"All OK" indicating success.  So we should check for this message,
and not display a message on success.

Here is a patch that adds `archive-extract-by-file' for RAR archives:

=== modified file 'lisp/arc-mode.el'
--- lisp/arc-mode.el	2011-12-15 07:24:10 +0000
+++ lisp/arc-mode.el	2011-12-25 21:27:01 +0000
@@ -1996,23 +2008,41 @@ (defun archive-rar-summarize (&optional
       (insert sep (make-string maxname ?-) "\n")
       (apply 'vector files))))
 
+(defun archive-extract-by-file (archive name command &optional stdout-test)
+  (let ((dest (make-temp-file "arc-dir" 'dir))
+	(stdout-file (make-temp-file "arc-stdout")))
+    (unwind-protect
+	(prog1
+	    (apply 'call-process
+		   (car command)
+		   nil
+		   `(:file ,stdout-file)
+		   nil
+		   (append (cdr command) (list archive name dest)))
+	  (with-temp-buffer
+	    (insert-file-contents stdout-file)
+	    (when (if (stringp stdout-test)
+		      (not (search-forward stdout-test nil t))
+		    (> (buffer-size) 0))
+	      (message "%s" (buffer-string))))
+	  (if (file-exists-p (expand-file-name name dest))
+	      (insert-file-contents-literally (expand-file-name name dest))))
+      (if (file-exists-p stdout-file)
+	  (delete-file stdout-file))
+      (if (file-exists-p (expand-file-name name dest))
+	  (delete-file (expand-file-name name dest)))
+      (while (file-name-directory name)
+	(setq name (directory-file-name (file-name-directory name)))
+	(delete-directory (expand-file-name name dest)))
+      (delete-directory dest))))
+
 (defun archive-rar-extract (archive name)
   ;; unrar-free seems to have no way to extract to stdout or even to a file.
   (if (file-name-absolute-p name)
       ;; The code below assumes the name is relative and may do undesirable
       ;; things otherwise.
       (error "Can't extract files with non-relative names")
-    (let ((dest (make-temp-file "arc-rar" 'dir)))
-      (unwind-protect
-          (progn
-            (call-process "unrar-free" nil nil nil
-                          "--extract" archive name dest)
-            (insert-file-contents-literally (expand-file-name name dest)))
-        (delete-file (expand-file-name name dest))
-        (while (file-name-directory name)
-          (setq name (directory-file-name (file-name-directory name)))
-          (delete-directory (expand-file-name name dest)))
-        (delete-directory dest)))))
+    (archive-extract-by-file archive name '("unrar-free" "--extract") "All OK")))
 
 ;;; Section: Rar self-extracting .exe archives.