]> git.eshelyaron.com Git - emacs.git/commitdiff
make-directory now returns t if dir already exists
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 17 Dec 2022 20:15:30 +0000 (12:15 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 17 Dec 2022 22:24:16 +0000 (14:24 -0800)
This new feature will help fix a copy-directory bug (Bug#58919).
Its implementation does not rely on make-directory handlers
supporting the new feature, as it no longer uses a make-directory
handler H in any way other than (funcall H DIR), thus using
only the intersection of the old and new behavior for handlers.
This will give us time to fix handlers at our leisure.
* lisp/files.el (files--ensure-directory): New arg MKDIR.
All uses changed.
(files--ensure-directory, make-directory):
Return non-nil if DIR is already a directory.  All uses changed.
* test/lisp/files-tests.el (files-tests-make-directory):
Test new return-value convention.

doc/lispref/files.texi
etc/NEWS
lisp/files.el
test/lisp/files-tests.el

index b3f63b8f32a6d4c26a91be72a3db25150d5cd70d..a767f9c28d581bf535dab68020866e53af0ade19 100644 (file)
@@ -3209,6 +3209,9 @@ This command creates a directory named @var{dirname}.  If
 @var{parents} is non-@code{nil}, as is always the case in an
 interactive call, that means to create the parent directories first,
 if they don't already exist.
+As a function, @code{make-directory} returns non-@code{nil} if @var{dirname}
+already exists as a directory and @var{parents} is non-@code{nil},
+and returns @code{nil} if it successfully created @var{dirname}.
 @code{mkdir} is an alias for this.
 @end deffn
 
index 72421b03191285a58a4d7c3d3a7f7041c129c9fe..c5820a5f045c8b30ee4071399546498c0cd10c67 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -4486,6 +4486,11 @@ and cannot work with regular styles such as 'basic' or 'flex'.
 ** Magic file handlers for make-directory-internal are no longer needed.
 Instead, Emacs uses the already-existing make-directory handlers.
 
++++
+** (make-directory DIR t) returns non-nil if DIR already exists.
+This can let a caller know whether it created DIR.  Formerly,
+make-directory's return value was unspecified.
+
 \f
 * Changes in Emacs 29.1 on Non-Free Operating Systems
 
index c74e7e808e4e30ea6f176c1d6c21122224a4889a..235eacee704266fbc14c4207a5b1a9dac8770522 100644 (file)
@@ -6193,18 +6193,17 @@ instance of such commands."
       (rename-buffer (generate-new-buffer-name base-name))
       (force-mode-line-update))))
 
-(defun files--ensure-directory (dir)
-  "Make directory DIR if it is not already a directory.  Return nil."
+(defun files--ensure-directory (mkdir dir)
+  "Use function MKDIR to make directory DIR if it is not already a directory.
+Return non-nil if DIR is already a directory."
   (condition-case err
-      (make-directory-internal dir)
+      (funcall mkdir dir)
     (error
-     (unless (file-directory-p dir)
-       (signal (car err) (cdr err))))))
+     (or (file-directory-p dir)
+        (signal (car err) (cdr err))))))
 
 (defun make-directory (dir &optional parents)
   "Create the directory DIR and optionally any nonexistent parent dirs.
-If DIR already exists as a directory, signal an error, unless
-PARENTS is non-nil.
 
 Interactively, the default choice of directory to create is the
 current buffer's default directory.  That is useful when you have
@@ -6214,8 +6213,9 @@ Noninteractively, the second (optional) argument PARENTS, if
 non-nil, says whether to create parent directories that don't
 exist.  Interactively, this happens by default.
 
-If creating the directory or directories fail, an error will be
-raised."
+Return non-nil if PARENTS is non-nil and DIR already exists as a
+directory, and nil if DIR did not already exist but was created.
+Signal an error if unsuccessful."
   (interactive
    (list (read-file-name "Make directory: " default-directory default-directory
                         nil nil)
@@ -6223,25 +6223,27 @@ raised."
   ;; If default-directory is a remote directory,
   ;; make sure we find its make-directory handler.
   (setq dir (expand-file-name dir))
-  (let ((handler (find-file-name-handler dir 'make-directory)))
-    (if handler
-       (funcall handler 'make-directory dir parents)
-      (if (not parents)
-         (make-directory-internal dir)
-       (let ((dir (directory-file-name (expand-file-name dir)))
-             create-list parent)
-         (while (progn
-                  (setq parent (directory-file-name
-                                (file-name-directory dir)))
-                  (condition-case ()
-                      (files--ensure-directory dir)
-                    (file-missing
-                     ;; Do not loop if root does not exist (Bug#2309).
-                     (not (string= dir parent)))))
-           (setq create-list (cons dir create-list)
-                 dir parent))
-         (dolist (dir create-list)
-            (files--ensure-directory dir)))))))
+  (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory)))
+                   #'(lambda (dir) (funcall handler 'make-directory dir))
+                 #'make-directory-internal)))
+    (if (not parents)
+        (funcall mkdir dir)
+      (let ((dir (directory-file-name (expand-file-name dir)))
+            already-dir create-list parent)
+        (while (progn
+                 (setq parent (directory-file-name
+                               (file-name-directory dir)))
+                 (condition-case ()
+                     (ignore (setq already-dir
+                                   (files--ensure-directory mkdir dir)))
+                   (error
+                    ;; Do not loop if root does not exist (Bug#2309).
+                    (not (string= dir parent)))))
+          (setq create-list (cons dir create-list)
+                dir parent))
+        (dolist (dir create-list)
+          (setq already-dir (files--ensure-directory mkdir dir)))
+        already-dir))))
 
 (defun make-empty-file (filename &optional parents)
   "Create an empty file FILENAME.
index efafb5583ac547277c4770bb91f7318569c15311..b9fbeb8a4e00a703a23933ee82a767df5e0da8dc 100644 (file)
@@ -1261,11 +1261,11 @@ works as expected if the default directory is quoted."
            (a/b (concat dirname "a/b")))
       (write-region "" nil file)
       (should-error (make-directory "/"))
-      (should-not (make-directory "/" t))
+      (should (make-directory "/" t))
       (should-error (make-directory dir))
-      (should-not (make-directory dir t))
+      (should (make-directory dir t))
       (should-error (make-directory dirname))
-      (should-not (make-directory dirname t))
+      (should (make-directory dirname t))
       (should-error (make-directory file))
       (should-error (make-directory file t))
       (should-not (make-directory subdir1))