bug#79467: 14.1.0; Prevent orphaning of preview files

2025-09-19 Thread Arash Esbati
Al Haji-Ali  writes:

> Apologies, I am attaching a corrected version now and will take this
> onboard going forward with the patches.

Thanks Al.  I slightly massaged your patch and installed it.  Closing.

Best, Arash



___
bug-auctex mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-auctex


bug#79467: 14.1.0; Prevent orphaning of preview files

2025-09-19 Thread Al Haji-Ali
On 19/09/2025, Arash Esbati wrote:
> Can you please check the indentation of the code you've added?
> Otherwise, I think we're good to go.
Apologies, I am attaching a corrected version now and will take this
onboard going forward with the patches.

-- Al

>From 7c36a9746656a6fbd676768bc3224508fb544d93 Mon Sep 17 00:00:00 2001
From: Al Haji-Ali 
Date: Wed, 3 Sep 2025 15:41:46 +0100
Subject: [PATCH] preview: Prevent orphaning of preview files

* preview.el (preview-gs-sentinel): Delete preview.ps file when process
is not restarted.
(preview-dvips-abort): Delete temporary directory if not used.
(preview-gs-place): Delete old files before overwriting 'filenames. Save
filename in new overlay when `preview-leave-open-previews-visible' is
non-nil.
(preview--delete-overlay-files): New function.
(preview-disable preview-delete): Use function above.
(preview-dvipng-place-all): Do not add `preview-ps-file' twice in
filenames and always delete oldfiles.
---
 preview.el | 155 +++--
 1 file changed, 102 insertions(+), 53 deletions(-)

diff --git a/preview.el b/preview.el
index 22316335..c6c002d6 100644
--- a/preview.el
+++ b/preview.el
@@ -637,7 +637,8 @@ Emacs color well."
 Gets the default PROCESS and STRING arguments
 and tries to restart Ghostscript if necessary."
   (condition-case err
-  (let ((status (process-status process)))
+  (let ((status (process-status process))
+keep-preview-ps)
 (when (memq status '(exit signal))
   (setq compilation-in-progress (delq process compilation-in-progress)))
 (when (buffer-name (process-buffer process))
@@ -662,18 +663,12 @@ and tries to restart Ghostscript if necessary."
  (point-max)))
 (insert-before-markers err)))
 (delete-process process)
-(if (or (null ov)
-(eq status 'signal))
-;; if process was killed explicitly by signal, or if nothing
-;; was processed, we give up on the matter altogether.
-(progn
-  (when preview-ps-file
-(condition-case nil
-(preview-delete-file preview-ps-file)
-  (file-error nil)))
-  (preview-gs-queue-empty))
-
-  ;; restart only if we made progress since last call
+(unless (or (null ov)
+(eq status 'signal))
+  ;; if process was killed explicitly by signal, or if
+  ;; nothing was processed, we give up on the matter
+  ;; altogether, otherwise restart only if we made
+  ;; progress since last call.
   (let (filenames)
 (dolist (ov preview-gs-outstanding)
   (setq filenames (overlay-get ov 'filenames))
@@ -684,7 +679,14 @@ and tries to restart Ghostscript if necessary."
   (setq preview-gs-queue (nconc preview-gs-outstanding
 preview-gs-queue))
   (setq preview-gs-outstanding nil)
-  (preview-gs-restart)))
+  ;; Keep preview-ps if another GS process is started.
+  (setq keep-preview-ps (preview-gs-restart)))
+(unless keep-preview-ps
+  (when preview-ps-file
+(condition-case nil
+(preview-delete-file preview-ps-file)
+  (file-error nil)))
+  (preview-gs-queue-empty)))
 (error (preview-log-error err "Ghostscript" process)))
   (preview-reraise-error process))
 
@@ -935,7 +937,15 @@ Pure borderless black-on-white will return an empty string."
 (condition-case nil
 (preview-delete-file preview-ps-file)
   (file-error nil)))
-  (setq TeX-sentinel-function nil))
+  (setq TeX-sentinel-function nil)
+
+  ;; When a command is aborted, there is a chance that this happens
+  ;; before the previews are generated but after a temp directory is
+  ;; created, in this case an empty folder is left behind. Make sure
+  ;; here that's not the case.
+  (when TeX-active-tempdir
+(unless (>= (nth 2 TeX-active-tempdir) 1)
+  (delete-directory (nth 0 TeX-active-tempdir)
 
 (defalias 'preview-dvipng-abort #'preview-dvips-abort)
 ;  "Abort a DviPNG run.")
@@ -1235,6 +1245,8 @@ RUN-BUFFER is the buffer of the TeX process,
 TEMPDIR is the correct copy of `TeX-active-tempdir',
 PS-FILE is a copy of `preview-ps-file', IMAGETYPE is the image type
 for the file extension."
+  ;; Delete files before overwriting property
+  (preview--delete-overlay-files ov)
   (overlay-put ov 'filenames
(unless (eq ps-file t)
  (list
@@ -1244,22 +1256,38 @@ for the file extension."
tempdir
   (overlay-put ov 'queued
   

bug#79467: 14.1.0; Prevent orphaning of preview files

2025-09-19 Thread Arash Esbati
Hi Al,

Al Haji-Ali  writes:

> This is a follow-up bug-report/patch from:
> https://lists.gnu.org/archive/html/auctex-devel/2025-08/msg00026.html
>
> This patch makes several changes in cases where certain scenarios lead
> to temporary preview files being left behind. These fall into two
> categories:
> 1. Cases in which files are left behind due to some failure. 
> 2. Cases in which the properties 'queued or 'filenames are overwritten
> without deleting the files which these properties point to.

Thanks, I have some minor comments, see below.

> From 565f387a9b181a588857055bef9d54c57f776813 Mon Sep 17 00:00:00 2001
> From: Al Haji-Ali 
> Date: Wed, 3 Sep 2025 15:41:46 +0100
> Subject: [PATCH] preview: Prevent orphaning of preview files
>
> * preview.el (preview-gs-sentinel): Delete preview.ps file when process
> is not restarted.
> (preview-dvips-abort): Delete temporary directory if not used.
> (preview-gs-place): Delete old files before overwriting 'filenames. Save
> filename in new overlay when `preview-leave-open-previews-visible' is
> non-nil.
> (preview--delete-overlay-files): New function.
> (preview-disable preview-delete): Use function above.
> (preview-dvipng-place-all): Do not add `preview-ps-file' twice in
> filenames and always delete oldfiles.
> ---
>  preview.el | 148 +++--
>  1 file changed, 99 insertions(+), 49 deletions(-)
>
> diff --git a/preview.el b/preview.el
> index 22316335..91303db4 100644
> --- a/preview.el
> +++ b/preview.el
> @@ -637,7 +637,8 @@ Emacs color well."
>  Gets the default PROCESS and STRING arguments
>  and tries to restart Ghostscript if necessary."
>(condition-case err
> -  (let ((status (process-status process)))
> +  (let ((status (process-status process))
> +keep-preview-ps)
>  (when (memq status '(exit signal))
>(setq compilation-in-progress (delq process 
> compilation-in-progress)))
>  (when (buffer-name (process-buffer process))
> @@ -662,18 +663,12 @@ and tries to restart Ghostscript if necessary."
>   (point-max)))
>  (insert-before-markers err)))
>  (delete-process process)
> -(if (or (null ov)
> +(unless (or (null ov)
>  (eq status 'signal))

The indentation looks odd, shouldn't the above look like this:

(unless (or (null ov)
(eq status 'signal))

?

> [...]
>(overlay-put ov 'queued
> (vector box nil snippet))
> -  (overlay-put ov 'preview-image
> -   (let ((default (list (preview-icon-copy 
> preview-nonready-icon
> - (if preview-leave-open-previews-visible
> - (if-let* ((img
> -(car
> - (delq
> -  nil
> -  (mapcar
> -   (lambda (ovr)
> - (and
> -  (eq (overlay-start ovr) (overlay-start 
> ov))
> -  (overlay-get ovr 'preview-image)))
> -   (overlays-at (overlay-start ov)))
> - img
> -   default)
> -   default)))
> +
> +  (if-let* ((old-ov
> + (and preview-leave-open-previews-visible
> +  (car
> +   (delq
> +nil
> +(mapcar
> + (lambda (ovr)
> +   (and
> +(eq (overlay-start ovr) (overlay-start ov))
> +(overlay-get ovr 'preview-image)
> +ovr))
> + (overlays-at (overlay-start ov
> +  (progn

Is this `progn' necessary?

> +(let* ((img (overlay-get old-ov 'preview-image))
> +   (filename (cadr img))
> +   (files-oov (overlay-get old-ov 'filenames))
> +   (files-ov  (overlay-get ov  'filenames)))
> +  (when img
> +(overlay-put ov 'preview-image img)
> +;; Transfer filename ownership to new overlay. The old one
> +;; will be cleared out and its files deleted.
> +(when-let* ((entry (assoc filename files-oov)))
> +  (overlay-put old-ov 'filenames
> +   (assq-delete-all filename files-oov))
> +  ;; Add the filename to the current overlay instead
> +  ;; if it's not already there
> +  (unless (assoc filename files-ov)
> +(overlay-put ov 'filenames
> + (cons entry files-ov)))
> +(overlay-put ov 'preview-image
> + (list (preview-icon-copy preview-nonready-icon
> +
>(preview-add-urgentization #'preview-gs-urgentize ov run-buffer)
>(lis

bug#79467: 14.1.0; Prevent orphaning of preview files

2025-09-18 Thread Al Haji-Ali
Hello,

This is a follow-up bug-report/patch from:
https://lists.gnu.org/archive/html/auctex-devel/2025-08/msg00026.html

This patch makes several changes in cases where certain scenarios lead to 
temporary preview files being left behind. These fall into two categories:
1. Cases in which files are left behind due to some failure. 
2. Cases in which the properties 'queued or 'filenames are overwritten without 
deleting the files which these properties point to.

The main idea of the patch is for overlays to take ownership of the files in 
'queued and 'filenames and track the ownership/do the necessary clean-up. For 
example, the change `preview-gs-place` in case 
`preview-leave-open-previews-visible` is non-nil: In this case, the ownership 
of the file is transferred to the new overlay along with the image.

Finally, slight refactoring by introducing a function 
`preview--delete-overlay-files` which deletes all files which are owned by an 
overlay.

Best regards,
-- Al

>From 565f387a9b181a588857055bef9d54c57f776813 Mon Sep 17 00:00:00 2001
From: Al Haji-Ali 
Date: Wed, 3 Sep 2025 15:41:46 +0100
Subject: [PATCH] preview: Prevent orphaning of preview files

* preview.el (preview-gs-sentinel): Delete preview.ps file when process
is not restarted.
(preview-dvips-abort): Delete temporary directory if not used.
(preview-gs-place): Delete old files before overwriting 'filenames. Save
filename in new overlay when `preview-leave-open-previews-visible' is
non-nil.
(preview--delete-overlay-files): New function.
(preview-disable preview-delete): Use function above.
(preview-dvipng-place-all): Do not add `preview-ps-file' twice in
filenames and always delete oldfiles.
---
 preview.el | 148 +++--
 1 file changed, 99 insertions(+), 49 deletions(-)

diff --git a/preview.el b/preview.el
index 22316335..91303db4 100644
--- a/preview.el
+++ b/preview.el
@@ -637,7 +637,8 @@ Emacs color well."
 Gets the default PROCESS and STRING arguments
 and tries to restart Ghostscript if necessary."
   (condition-case err
-  (let ((status (process-status process)))
+  (let ((status (process-status process))
+keep-preview-ps)
 (when (memq status '(exit signal))
   (setq compilation-in-progress (delq process compilation-in-progress)))
 (when (buffer-name (process-buffer process))
@@ -662,18 +663,12 @@ and tries to restart Ghostscript if necessary."
  (point-max)))
 (insert-before-markers err)))
 (delete-process process)
-(if (or (null ov)
+(unless (or (null ov)
 (eq status 'signal))
-;; if process was killed explicitly by signal, or if nothing
-;; was processed, we give up on the matter altogether.
-(progn
-  (when preview-ps-file
-(condition-case nil
-(preview-delete-file preview-ps-file)
-  (file-error nil)))
-  (preview-gs-queue-empty))
-
-  ;; restart only if we made progress since last call
+  ;; if process was killed explicitly by signal, or if
+  ;; nothing was processed, we give up on the matter
+  ;; altogether, otherwise restart only if we made
+  ;; progress since last call.
   (let (filenames)
 (dolist (ov preview-gs-outstanding)
   (setq filenames (overlay-get ov 'filenames))
@@ -684,7 +679,14 @@ and tries to restart Ghostscript if necessary."
   (setq preview-gs-queue (nconc preview-gs-outstanding
 preview-gs-queue))
   (setq preview-gs-outstanding nil)
-  (preview-gs-restart)))
+  ;; Keep preview-ps if another GS process is started.
+  (setq keep-preview-ps (preview-gs-restart)))
+(unless keep-preview-ps
+  (when preview-ps-file
+(condition-case nil
+(preview-delete-file preview-ps-file)
+  (file-error nil)))
+  (preview-gs-queue-empty)))
 (error (preview-log-error err "Ghostscript" process)))
   (preview-reraise-error process))

@@ -935,7 +937,15 @@ Pure borderless black-on-white will return an empty string."
 (condition-case nil
 (preview-delete-file preview-ps-file)
   (file-error nil)))
-  (setq TeX-sentinel-function nil))
+  (setq TeX-sentinel-function nil)
+
+  ;; When a command is aborted, there is a chance that this happens
+  ;; before the previews are generated but after a temp directory is
+  ;; created, in this case an empty folder is left behind. Make sure
+  ;; here that's not the case.
+  (when TeX-active-tempdir
+(unless (>=