Function: vc-rename-file

vc-rename-file is an autoloaded, interactive and byte-compiled function defined in vc.el.gz.

Signature

(vc-rename-file OLD NEW)

Documentation

Rename file OLD to NEW in both working tree and repository.

When called interactively, read OLD and NEW, defaulting OLD to the current buffer's file name if it's under version control.

View in manual

Probably introduced at or before Emacs version 31.1.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/vc/vc.el.gz
;;;###autoload
(defun vc-rename-file (old new)
  "Rename file OLD to NEW in both working tree and repository.
When called interactively, read OLD and NEW, defaulting OLD to the
current buffer's file name if it's under version control."
  ;; FIXME: Support renaming whole directories.
  ;; The use of `vc-call' will need to change to something like
  ;;
  ;;     (vc-call-backend (if dir
  ;;                          (vc-responsible-backend file)
  ;;                        (vc-backend file))
  ;;                      'rename-file old new)
  ;;
  ;; as was done in `vc-revert-file'; see bug#43464.  --spwhitton
  (interactive (list (read-file-name "VC rename file: " nil
                                     (and (vc-backend buffer-file-name)
                                          buffer-file-name)
                                     t)
                     (read-file-name "Rename to: ")))
  ;; in CL I would have said (setq new (merge-pathnames new old))
  (let ((old-base (file-name-nondirectory old)))
    (when (and (not (string-empty-p old-base))
               (string-empty-p (file-name-nondirectory new)))
      (setq new (concat new old-base))))
  (cl-callf expand-file-name old)
  (cl-callf expand-file-name new)
  (let ((oldbuf (get-file-buffer old))
        (default-directory (file-name-directory old)))
    (when (and oldbuf (buffer-modified-p oldbuf))
      (error "Please save files before moving them"))
    (when (get-file-buffer new)
      (error "Already editing new file name"))
    (when (file-exists-p new)
      (error "New file already exists"))
    (let ((state (vc-state old)))
      (unless (memq state '(up-to-date edited added))
	(error "Please %s files before moving them"
	       (if (stringp state) "check in" "update"))))
    (vc-call rename-file old new)
    (vc-file-clearprops old)
    (vc-file-clearprops new)
    ;; Move the actual file (unless the backend did it already)
    (when (file-exists-p old) (rename-file old new))
    ;; ?? Renaming a file might change its contents due to keyword expansion.
    ;; We should really check out a new copy if the old copy was precisely equal
    ;; to some checked-in revision.  However, testing for this is tricky....
    (when oldbuf
      (with-current-buffer oldbuf
	(let ((buffer-read-only buffer-read-only))
	  (set-visited-file-name new))
	(vc-mode-line new (vc-backend new))
	(set-buffer-modified-p nil)))))