aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2022-12-17 12:15:30 -0800
committerPaul Eggert2022-12-17 14:24:16 -0800
commitbef1edc9cacb976120dff73b4d7bbdce6ade982b (patch)
treedd1420a157c9ce01c4d7297a380b8e8dcb86cb09
parent8a9579ca29df951ace35125873949e905fd1af2b (diff)
downloademacs-bef1edc9cacb976120dff73b4d7bbdce6ade982b.tar.gz
emacs-bef1edc9cacb976120dff73b4d7bbdce6ade982b.zip
make-directory now returns t if dir already exists
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.
-rw-r--r--doc/lispref/files.texi3
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/files.el58
-rw-r--r--test/lisp/files-tests.el6
4 files changed, 41 insertions, 31 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index b3f63b8f32a..a767f9c28d5 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -3209,6 +3209,9 @@ This command creates a directory named @var{dirname}. If
3209@var{parents} is non-@code{nil}, as is always the case in an 3209@var{parents} is non-@code{nil}, as is always the case in an
3210interactive call, that means to create the parent directories first, 3210interactive call, that means to create the parent directories first,
3211if they don't already exist. 3211if they don't already exist.
3212As a function, @code{make-directory} returns non-@code{nil} if @var{dirname}
3213already exists as a directory and @var{parents} is non-@code{nil},
3214and returns @code{nil} if it successfully created @var{dirname}.
3212@code{mkdir} is an alias for this. 3215@code{mkdir} is an alias for this.
3213@end deffn 3216@end deffn
3214 3217
diff --git a/etc/NEWS b/etc/NEWS
index 72421b03191..c5820a5f045 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -4486,6 +4486,11 @@ and cannot work with regular styles such as 'basic' or 'flex'.
4486** Magic file handlers for make-directory-internal are no longer needed. 4486** Magic file handlers for make-directory-internal are no longer needed.
4487Instead, Emacs uses the already-existing make-directory handlers. 4487Instead, Emacs uses the already-existing make-directory handlers.
4488 4488
4489+++
4490** (make-directory DIR t) returns non-nil if DIR already exists.
4491This can let a caller know whether it created DIR. Formerly,
4492make-directory's return value was unspecified.
4493
4489 4494
4490* Changes in Emacs 29.1 on Non-Free Operating Systems 4495* Changes in Emacs 29.1 on Non-Free Operating Systems
4491 4496
diff --git a/lisp/files.el b/lisp/files.el
index c74e7e808e4..235eacee704 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6193,18 +6193,17 @@ instance of such commands."
6193 (rename-buffer (generate-new-buffer-name base-name)) 6193 (rename-buffer (generate-new-buffer-name base-name))
6194 (force-mode-line-update)))) 6194 (force-mode-line-update))))
6195 6195
6196(defun files--ensure-directory (dir) 6196(defun files--ensure-directory (mkdir dir)
6197 "Make directory DIR if it is not already a directory. Return nil." 6197 "Use function MKDIR to make directory DIR if it is not already a directory.
6198Return non-nil if DIR is already a directory."
6198 (condition-case err 6199 (condition-case err
6199 (make-directory-internal dir) 6200 (funcall mkdir dir)
6200 (error 6201 (error
6201 (unless (file-directory-p dir) 6202 (or (file-directory-p dir)
6202 (signal (car err) (cdr err)))))) 6203 (signal (car err) (cdr err))))))
6203 6204
6204(defun make-directory (dir &optional parents) 6205(defun make-directory (dir &optional parents)
6205 "Create the directory DIR and optionally any nonexistent parent dirs. 6206 "Create the directory DIR and optionally any nonexistent parent dirs.
6206If DIR already exists as a directory, signal an error, unless
6207PARENTS is non-nil.
6208 6207
6209Interactively, the default choice of directory to create is the 6208Interactively, the default choice of directory to create is the
6210current buffer's default directory. That is useful when you have 6209current buffer's default directory. That is useful when you have
@@ -6214,8 +6213,9 @@ Noninteractively, the second (optional) argument PARENTS, if
6214non-nil, says whether to create parent directories that don't 6213non-nil, says whether to create parent directories that don't
6215exist. Interactively, this happens by default. 6214exist. Interactively, this happens by default.
6216 6215
6217If creating the directory or directories fail, an error will be 6216Return non-nil if PARENTS is non-nil and DIR already exists as a
6218raised." 6217directory, and nil if DIR did not already exist but was created.
6218Signal an error if unsuccessful."
6219 (interactive 6219 (interactive
6220 (list (read-file-name "Make directory: " default-directory default-directory 6220 (list (read-file-name "Make directory: " default-directory default-directory
6221 nil nil) 6221 nil nil)
@@ -6223,25 +6223,27 @@ raised."
6223 ;; If default-directory is a remote directory, 6223 ;; If default-directory is a remote directory,
6224 ;; make sure we find its make-directory handler. 6224 ;; make sure we find its make-directory handler.
6225 (setq dir (expand-file-name dir)) 6225 (setq dir (expand-file-name dir))
6226 (let ((handler (find-file-name-handler dir 'make-directory))) 6226 (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory)))
6227 (if handler 6227 #'(lambda (dir) (funcall handler 'make-directory dir))
6228 (funcall handler 'make-directory dir parents) 6228 #'make-directory-internal)))
6229 (if (not parents) 6229 (if (not parents)
6230 (make-directory-internal dir) 6230 (funcall mkdir dir)
6231 (let ((dir (directory-file-name (expand-file-name dir))) 6231 (let ((dir (directory-file-name (expand-file-name dir)))
6232 create-list parent) 6232 already-dir create-list parent)
6233 (while (progn 6233 (while (progn
6234 (setq parent (directory-file-name 6234 (setq parent (directory-file-name
6235 (file-name-directory dir))) 6235 (file-name-directory dir)))
6236 (condition-case () 6236 (condition-case ()
6237 (files--ensure-directory dir) 6237 (ignore (setq already-dir
6238 (file-missing 6238 (files--ensure-directory mkdir dir)))
6239 ;; Do not loop if root does not exist (Bug#2309). 6239 (error
6240 (not (string= dir parent))))) 6240 ;; Do not loop if root does not exist (Bug#2309).
6241 (setq create-list (cons dir create-list) 6241 (not (string= dir parent)))))
6242 dir parent)) 6242 (setq create-list (cons dir create-list)
6243 (dolist (dir create-list) 6243 dir parent))
6244 (files--ensure-directory dir))))))) 6244 (dolist (dir create-list)
6245 (setq already-dir (files--ensure-directory mkdir dir)))
6246 already-dir))))
6245 6247
6246(defun make-empty-file (filename &optional parents) 6248(defun make-empty-file (filename &optional parents)
6247 "Create an empty file FILENAME. 6249 "Create an empty file FILENAME.
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index efafb5583ac..b9fbeb8a4e0 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1261,11 +1261,11 @@ works as expected if the default directory is quoted."
1261 (a/b (concat dirname "a/b"))) 1261 (a/b (concat dirname "a/b")))
1262 (write-region "" nil file) 1262 (write-region "" nil file)
1263 (should-error (make-directory "/")) 1263 (should-error (make-directory "/"))
1264 (should-not (make-directory "/" t)) 1264 (should (make-directory "/" t))
1265 (should-error (make-directory dir)) 1265 (should-error (make-directory dir))
1266 (should-not (make-directory dir t)) 1266 (should (make-directory dir t))
1267 (should-error (make-directory dirname)) 1267 (should-error (make-directory dirname))
1268 (should-not (make-directory dirname t)) 1268 (should (make-directory dirname t))
1269 (should-error (make-directory file)) 1269 (should-error (make-directory file))
1270 (should-error (make-directory file t)) 1270 (should-error (make-directory file t))
1271 (should-not (make-directory subdir1)) 1271 (should-not (make-directory subdir1))