This library seems very nice (thanks!), but I immediately hit a bug testing it with Emacs default settings, in which backups are stored in the same directory as the original file.
This results in the call to (file-name-all-completions file dir) in backup-walker-get-sorted-backups including the original filename as well as the backup filenames, and consequently triggers an error in backup-walker-get-version due to the unhandled edge case whereby string-match doesn't return a match, and (match-end 0) then gives us something arbitrary from a previous match, which might be a larger number than the length of the filename, and therefore substring fails (or returns a bad value).
Code is:
(defsubst backup-walker-get-version (fn &optional start)
"return version number given backup"
(setq start (or start
(length (file-name-sans-versions fn))))
(string-to-number
(substring fn
(string-match "[[:digit:]]+" fn start)
(match-end 0))))
And:
(defun backup-walker-get-sorted-backups (filename)
;; [...]
(let* ((filename (file-name-sans-versions
(make-backup-file-name (expand-file-name filename))))
(file (file-name-nondirectory filename))
(dir (file-name-directory filename))
(comp (file-name-all-completions file dir))
(prefix-len (length file)))
(cons filename (mapcar
(lambda (f)
(substring (cdr f) prefix-len))
(sort (mapcar (lambda (f)
(cons (backup-walker-get-version f prefix-len)
f))
comp)
(lambda (f1 f2)
(not (< (car f1) (car f2)))))))))
It seems like we can resolve this with the following change to that latter function:
- (comp (file-name-all-completions file dir))
+ (comp (delete file (file-name-all-completions file dir)))
This library seems very nice (thanks!), but I immediately hit a bug testing it with Emacs default settings, in which backups are stored in the same directory as the original file.
This results in the call to
(file-name-all-completions file dir)inbackup-walker-get-sorted-backupsincluding the original filename as well as the backup filenames, and consequently triggers an error inbackup-walker-get-versiondue to the unhandled edge case wherebystring-matchdoesn't return a match, and(match-end 0)then gives us something arbitrary from a previous match, which might be a larger number than the length of the filename, and thereforesubstringfails (or returns a bad value).Code is:
And:
It seems like we can resolve this with the following change to that latter function: