> Maybe replace
>
> (symlink target pivot)
>
> by (symlink/remove-old target pivot)
>
> where
>
> (define (symlink/remove-old target link)
> "Make a symbolic link named LINK pointing to TARGET.
> If LINK already exists, it will be removed first.
> This is not an atomic operation."
> (catch 'system-error
> (lambda ()
> (symlink target link))
> (lambda stuff
> (if (= (system-error-errno stuff) EEXIST)
> (begin
> ;; remove old link and retry
> (delete-file link)
> (symlink/remove-old link target))
> (apply throw stuff)))))
>
> ?
Could we implement symlink/remove-old without catch and throw? Something
like:
--8<---------------cut here---------------start------------->8---
(define (symlink/remove-old target link)
"Make a symbolic link named LINK pointing to TARGET. If LINK already
exists, it will be removed first. This is not an atomic operation."
(when (file-exists? link)
(delete-file link))
(symlink target link))
--8<---------------cut here---------------end--------------->8---
We might also inline this into switch-symlinks like so.
--8<---------------cut here---------------start------------->8---
(define (switch-symlinks link target)
"Atomically switch LINK, a symbolic link, to point to TARGET. Works
both when LINK already exists and when it does not."
(let ((pivot (string-append link ".new")))
;; Delete pivot link in case it already exists. This can happen if
;; a previous switch-symlinks was interrupted.
(when (file-exists? pivot)
(delete-file pivot))
(symlink target pivot)
(rename-file pivot link)))
--8<---------------cut here---------------end--------------->8---
WDYT?