]> git.eshelyaron.com Git - emacs.git/commitdiff
Make `C-c C-w' copy the executable bits to the new file
authorLars Ingebrigtsen <larsi@gnus.org>
Thu, 2 Dec 2021 12:21:20 +0000 (13:21 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Thu, 2 Dec 2021 12:21:53 +0000 (13:21 +0100)
* lisp/files.el (write-file): When visiting an executable file,
make the new file executable, too (bug#18915).

etc/NEWS
lisp/files.el

index 55733c6895d49c9acc64941295240a58d7165470..eda12142fed83056b04208869c3b185ad168c210 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -75,6 +75,12 @@ time.
 \f
 * Changes in Emacs 29.1
 
+---
+** 'write-file' will now copy some file mode bits.
+If the current buffer is visiting a file that is executable, the
+'C-c C-w' command will now make the new file executable, too.
+
++++
 ** New user option 'process-error-pause-time'.
 This determines how long to pause Emacs after a process
 filter/sentinel error has been handled.
index 07279c4c871b9d6cb7c4cf7d6712af2988df6a6e..9ed63a60f8157b53f03f895930e77644f03f2b19 100644 (file)
@@ -4745,7 +4745,6 @@ using \\<minibuffer-local-map>\\[next-history-element].
 If optional second arg CONFIRM is non-nil, this function
 asks for confirmation before overwriting an existing file.
 Interactively, confirmation is required unless you supply a prefix argument."
-;;  (interactive "FWrite file: ")
   (interactive
    (list (if buffer-file-name
             (read-file-name "Write file: "
@@ -4756,33 +4755,44 @@ Interactively, confirmation is required unless you supply a prefix argument."
                            default-directory)
                           nil nil))
         (not current-prefix-arg)))
-  (or (null filename) (string-equal filename "")
-      (progn
-       ;; If arg is a directory name,
-       ;; use the default file name, but in that directory.
-       (if (directory-name-p filename)
-           (setq filename (concat filename
-                                  (file-name-nondirectory
-                                   (or buffer-file-name (buffer-name))))))
-       (and confirm
-            (file-exists-p filename)
-            ;; NS does its own confirm dialog.
-            (not (and (eq (framep-on-display) 'ns)
-                      (listp last-nonmenu-event)
-                      use-dialog-box))
-            (or (y-or-n-p (format-message
-                            "File `%s' exists; overwrite? " filename))
-                (user-error "Canceled")))
-       (set-visited-file-name filename (not confirm))))
-  (set-buffer-modified-p t)
-  ;; Make buffer writable if file is writable.
-  (and buffer-file-name
-       (file-writable-p buffer-file-name)
-       (setq buffer-read-only nil))
-  (save-buffer)
-  ;; It's likely that the VC status at the new location is different from
-  ;; the one at the old location.
-  (vc-refresh-state))
+  (let ((old-modes
+         (and buffer-file-name
+              ;; File may have gone away; ignore errors in that case.
+              (ignore-errors (file-modes buffer-file-name)))))
+    (or (null filename) (string-equal filename "")
+        (progn
+         ;; If arg is a directory name,
+         ;; use the default file name, but in that directory.
+         (if (directory-name-p filename)
+             (setq filename (concat filename
+                                    (file-name-nondirectory
+                                     (or buffer-file-name (buffer-name))))))
+         (and confirm
+              (file-exists-p filename)
+              ;; NS does its own confirm dialog.
+              (not (and (eq (framep-on-display) 'ns)
+                        (listp last-nonmenu-event)
+                        use-dialog-box))
+              (or (y-or-n-p (format-message
+                              "File `%s' exists; overwrite? " filename))
+                  (user-error "Canceled")))
+         (set-visited-file-name filename (not confirm))))
+    (set-buffer-modified-p t)
+    ;; Make buffer writable if file is writable.
+    (and buffer-file-name
+         (file-writable-p buffer-file-name)
+         (setq buffer-read-only nil))
+    (save-buffer)
+    ;; If the old file was executable, then make the new file
+    ;; executable, too.
+    (when (and old-modes
+               (not (zerop (logand #o111 old-modes))))
+      (set-file-modes buffer-file-name
+                      (logior (logand #o111 old-modes)
+                              (file-modes buffer-file-name))))
+    ;; It's likely that the VC status at the new location is different from
+    ;; the one at the old location.
+    (vc-refresh-state)))
 \f
 (defun file-extended-attributes (filename)
   "Return an alist of extended attributes of file FILENAME.