bug#79467: 14.1.0; Prevent orphaning of preview files
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
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
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
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 (>=
