From 389e85c020e7e59977e3c832a281f8b7844fecd4 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 3 May 2026 19:24:40 -0500 Subject: fix: use file basename when moving buffer + file `cj/--move-buffer-and-file` was building the destination as `(concat dir "/" (buffer-name))`. If the buffer had been renamed via `M-x rename-buffer`, or uniquified by Emacs with a `<2>` suffix when a second buffer visited the same filename, the move wrote a file with the wrong name on disk. I derived the destination basename from `buffer-file-name` instead, in both the internal helper and the interactive wrapper. The wrapper's overwrite-prompt now also formats the real target filename rather than the buffer name. I added two regression tests: one for a renamed buffer visiting `original.txt`, and one for a `<2>` uniquified buffer with a trailing-slash target directory. --- modules/custom-buffer-file.el | 8 +++-- ...test-custom-buffer-file-move-buffer-and-file.el | 40 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/modules/custom-buffer-file.el b/modules/custom-buffer-file.el index f99a0ee4..ce635cd0 100644 --- a/modules/custom-buffer-file.el +++ b/modules/custom-buffer-file.el @@ -110,11 +110,12 @@ If OK-IF-EXISTS is non-nil, overwrite existing file. Returns t on success, nil if buffer not visiting a file." (let* ((name (buffer-name)) (filename (buffer-file-name)) + (basename (and filename (file-name-nondirectory filename))) (dir (expand-file-name dir)) (dir (if (string-match "[/\\\\]$" dir) (substring dir 0 -1) dir)) - (newname (concat dir "/" name))) + (newname (and basename (expand-file-name basename dir)))) (if (not filename) (progn (message "Buffer '%s' is not visiting a file!" name) @@ -129,7 +130,10 @@ Returns t on success, nil if buffer not visiting a file." "Move both current buffer and the file it visits to DIR. When called interactively, prompts for confirmation if target file exists." (interactive (list (read-directory-name "Move buffer and file (to new directory): "))) - (let* ((target (expand-file-name (buffer-name) (expand-file-name dir)))) + (let* ((filename (buffer-file-name)) + (target (expand-file-name + (file-name-nondirectory (or filename (buffer-name))) + (expand-file-name dir)))) (condition-case _ (cj/--move-buffer-and-file dir nil) (file-already-exists diff --git a/tests/test-custom-buffer-file-move-buffer-and-file.el b/tests/test-custom-buffer-file-move-buffer-and-file.el index e8f4563d..8331db5c 100644 --- a/tests/test-custom-buffer-file-move-buffer-and-file.el +++ b/tests/test-custom-buffer-file-move-buffer-and-file.el @@ -225,6 +225,46 @@ (kill-buffer (current-buffer))) (test-move-buffer-and-file-teardown))) +(ert-deftest test-move-buffer-and-file-renamed-buffer-uses-file-basename () + "Should use visited file basename when buffer name differs." + (test-move-buffer-and-file-setup) + (unwind-protect + (let* ((source-dir (cj/create-test-subdirectory "source")) + (target-dir (cj/create-test-subdirectory "target")) + (source-file (expand-file-name "original.txt" source-dir)) + (target-file (expand-file-name "original.txt" target-dir)) + (wrong-target (expand-file-name "renamed-buffer" target-dir))) + (with-temp-file source-file + (insert "content")) + (find-file source-file) + (rename-buffer "renamed-buffer") + (cj/--move-buffer-and-file target-dir) + (should (file-exists-p target-file)) + (should-not (file-exists-p wrong-target)) + (should (string= (buffer-file-name) target-file)) + (kill-buffer (current-buffer))) + (test-move-buffer-and-file-teardown))) + +(ert-deftest test-move-buffer-and-file-uniquified-buffer-uses-file-basename () + "Should not use uniquified buffer names such as <2> as filenames." + (test-move-buffer-and-file-setup) + (unwind-protect + (let* ((source-dir (cj/create-test-subdirectory "source")) + (target-dir (cj/create-test-subdirectory "target")) + (source-file (expand-file-name "duplicate.txt" source-dir)) + (target-file (expand-file-name "duplicate.txt" target-dir)) + (wrong-target (expand-file-name "duplicate.txt<2>" target-dir))) + (with-temp-file source-file + (insert "content")) + (find-file source-file) + (rename-buffer "duplicate.txt<2>") + (cj/--move-buffer-and-file (concat target-dir "/")) + (should (file-exists-p target-file)) + (should-not (file-exists-p wrong-target)) + (should (string= (buffer-file-name) target-file)) + (kill-buffer (current-buffer))) + (test-move-buffer-and-file-teardown))) + (ert-deftest test-move-buffer-and-file-deeply-nested-target () "Should move to deeply nested target directory." (test-move-buffer-and-file-setup) -- cgit v1.2.3