diff options
| author | Paul Eggert | 2017-09-10 20:37:17 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-09-10 20:38:19 -0700 |
| commit | cf9891e14e48a93bca2065fdd7998f5f677786dc (patch) | |
| tree | a4d310f7868b010342634c45f36964af33c91af7 | |
| parent | 01c885f21f343045783eb9ad1ff5f9b83d6cd789 (diff) | |
| download | emacs-cf9891e14e48a93bca2065fdd7998f5f677786dc.tar.gz emacs-cf9891e14e48a93bca2065fdd7998f5f677786dc.zip | |
Fix some make-directory bugs
* lisp/files.el (files--ensure-directory): New function.
(make-directory): Use it to avoid bugs when (make-directory FOO t)
is invoked on a non-directory, or on a directory hierarchy that
is being built by some other process while Emacs is running.
* test/lisp/files-tests.el (files-tests--make-directory): New test.
| -rw-r--r-- | lisp/files.el | 31 | ||||
| -rw-r--r-- | test/lisp/files-tests.el | 21 |
2 files changed, 41 insertions, 11 deletions
diff --git a/lisp/files.el b/lisp/files.el index 43aec8173d9..85e649fbb59 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -5320,6 +5320,14 @@ instance of such commands." | |||
| 5320 | (rename-buffer (generate-new-buffer-name base-name)) | 5320 | (rename-buffer (generate-new-buffer-name base-name)) |
| 5321 | (force-mode-line-update)))) | 5321 | (force-mode-line-update)))) |
| 5322 | 5322 | ||
| 5323 | (defun files--ensure-directory (dir) | ||
| 5324 | "Make directory DIR if it is not already a directory. Return nil." | ||
| 5325 | (condition-case err | ||
| 5326 | (make-directory-internal dir) | ||
| 5327 | (file-already-exists | ||
| 5328 | (unless (file-directory-p dir) | ||
| 5329 | (signal (car err) (cdr err)))))) | ||
| 5330 | |||
| 5323 | (defun make-directory (dir &optional parents) | 5331 | (defun make-directory (dir &optional parents) |
| 5324 | "Create the directory DIR and optionally any nonexistent parent dirs. | 5332 | "Create the directory DIR and optionally any nonexistent parent dirs. |
| 5325 | If DIR already exists as a directory, signal an error, unless | 5333 | If DIR already exists as a directory, signal an error, unless |
| @@ -5348,18 +5356,19 @@ raised." | |||
| 5348 | (if (not parents) | 5356 | (if (not parents) |
| 5349 | (make-directory-internal dir) | 5357 | (make-directory-internal dir) |
| 5350 | (let ((dir (directory-file-name (expand-file-name dir))) | 5358 | (let ((dir (directory-file-name (expand-file-name dir))) |
| 5351 | create-list) | 5359 | create-list parent) |
| 5352 | (while (and (not (file-exists-p dir)) | 5360 | (while (progn |
| 5353 | ;; If directory is its own parent, then we can't | 5361 | (setq parent (directory-file-name |
| 5354 | ;; keep looping forever | 5362 | (file-name-directory dir))) |
| 5355 | (not (equal dir | 5363 | (condition-case err |
| 5356 | (directory-file-name | 5364 | (files--ensure-directory dir) |
| 5357 | (file-name-directory dir))))) | 5365 | (file-missing |
| 5366 | ;; Do not loop if root does not exist (Bug#2309). | ||
| 5367 | (not (string= dir parent))))) | ||
| 5358 | (setq create-list (cons dir create-list) | 5368 | (setq create-list (cons dir create-list) |
| 5359 | dir (directory-file-name (file-name-directory dir)))) | 5369 | dir parent)) |
| 5360 | (while create-list | 5370 | (dolist (dir create-list) |
| 5361 | (make-directory-internal (car create-list)) | 5371 | (files--ensure-directory dir))))))) |
| 5362 | (setq create-list (cdr create-list)))))))) | ||
| 5363 | 5372 | ||
| 5364 | (defconst directory-files-no-dot-files-regexp | 5373 | (defconst directory-files-no-dot-files-regexp |
| 5365 | "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*" | 5374 | "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*" |
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index a2f2b74312f..b52965a02b4 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el | |||
| @@ -344,6 +344,27 @@ be invoked with the right arguments." | |||
| 344 | (cdr path-res) | 344 | (cdr path-res) |
| 345 | (insert-directory-wildcard-in-dir-p (car path-res))))))) | 345 | (insert-directory-wildcard-in-dir-p (car path-res))))))) |
| 346 | 346 | ||
| 347 | (ert-deftest files-tests--make-directory () | ||
| 348 | (let* ((dir (make-temp-file "files-mkdir-test" t)) | ||
| 349 | (dirname (file-name-as-directory dir)) | ||
| 350 | (file (concat dirname "file")) | ||
| 351 | (subdir1 (concat dirname "subdir1")) | ||
| 352 | (subdir2 (concat dirname "subdir2")) | ||
| 353 | (a/b (concat dirname "a/b"))) | ||
| 354 | (write-region "" nil file) | ||
| 355 | (should-error (make-directory "/")) | ||
| 356 | (should-not (make-directory "/" t)) | ||
| 357 | (should-error (make-directory dir)) | ||
| 358 | (should-not (make-directory dir t)) | ||
| 359 | (should-error (make-directory dirname)) | ||
| 360 | (should-not (make-directory dirname t)) | ||
| 361 | (should-error (make-directory file)) | ||
| 362 | (should-error (make-directory file t)) | ||
| 363 | (should-not (make-directory subdir1)) | ||
| 364 | (should-not (make-directory subdir2 t)) | ||
| 365 | (should-error (make-directory a/b)) | ||
| 366 | (should-not (make-directory a/b t)))) | ||
| 367 | |||
| 347 | 368 | ||
| 348 | (provide 'files-tests) | 369 | (provide 'files-tests) |
| 349 | ;;; files-tests.el ends here | 370 | ;;; files-tests.el ends here |