emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/assess 979c26b3b7 73/95: Add assess-with-filesystem


From: ELPA Syncer
Subject: [elpa] externals/assess 979c26b3b7 73/95: Add assess-with-filesystem
Date: Tue, 19 Jul 2022 15:57:35 -0400 (EDT)

branch: externals/assess
commit 979c26b3b79785be0786f6d99f49469f8277051e
Author: Damien Cassou <damien@cassou.me>
Commit: Phillip Lord <phillip.lord@russet.org.uk>

    Add assess-with-filesystem
    
    (assess-with-filesystem SPEC &rest FORMS)
    
    Create temporary file hierarchy according to SPEC and run FORMS.
    
    SPEC is a list of specifications for file system entities which
    are to be created.
---
 .gitignore          |  2 +-
 assess.el           | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/assess-test.el | 50 +++++++++++++++++++++++++++
 3 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 26c5cded2f..7479b28172 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,4 @@
 *.elc
 /dist
 /assess-pkg.el
-
+/test/assess-test.org
diff --git a/assess.el b/assess.el
index 1460bace74..bee76dfb11 100644
--- a/assess.el
+++ b/assess.el
@@ -590,6 +590,104 @@ See also `assess-make-related-file'."
            (kill-buffer ,temp-buffer))))))
 ;; #+end_src
 
+;; ** Creating Files and Directories
+;; I can write some documentation here if Phil wants to merge code below.
+;; *** Implementation
+;; #+BEGIN_SRC emacs-lisp
+(defun assess-with-filesystem--make-parent (spec path)
+  "If SPEC is a file name, create its parent directory rooted at PATH."
+  (save-match-data
+    (when (string-match "\\(.*\\)/" spec)
+      (make-directory (concat path "/" (match-string 1 spec)) t))))
+
+(defun assess-with-filesystem--init (spec &optional path)
+  "Interpret the SPEC inside PATH."
+  (setq path (or path "."))
+  (cond
+   ((listp spec)
+    (cond
+     ;; non-empty file
+     ((and (stringp (car spec))
+           (stringp (cadr spec)))
+      (when (string-match-p "/\\'" (car spec))
+        (error "Invalid syntax: `%s' - cannot create a directory with text 
content" (car spec)))
+      (assess-with-filesystem--make-parent (car spec) path)
+      (with-temp-file (concat path "/" (car spec))
+        (insert (cadr spec))))
+     ;; directory
+     ((and (stringp (car spec))
+           (consp (cadr spec)))
+      (make-directory (concat path "/" (car spec)) t)
+      (mapc (lambda (s) (assess-with-filesystem--init
+                    s (concat path "/" (car spec)))) (cadr spec)))
+     ;; recursive spec, this should probably never happen
+     (t (mapc (lambda (s) (assess-with-filesystem--init s path)) spec))))
+   ;; directory specified using a string
+   ((and (stringp spec)
+         (string-match-p "/\\'" spec))
+    (make-directory (concat path "/" spec) t))
+   ;; empty file
+   ((stringp spec)
+    (assess-with-filesystem--make-parent spec path)
+    (write-region "" nil (concat path "/" spec) nil 'no-message))
+   (t (error "Invalid syntax: `%s'" spec))))
+
+(defmacro assess-with-filesystem (spec &rest forms)
+  "Create temporary file hierarchy according to SPEC and run FORMS.
+
+SPEC is a list of specifications for file system entities which
+are to be created.
+
+File system entities are specified as follows:
+
+1. a string FILE is the name of file to be created
+  - if the string contains \"/\", parent directories are created
+    automatically
+  - if the string ends with \"/\", a directory is created
+2. a list of two elements (FILE CONTENT) specifies filename and the
+  content to put in the file
+  - the \"/\" rules apply in the same way as in 1., except you can not
+    create a directory this way
+3. a list where car is a string and cadr is a list (DIR SPEC) is a
+  recursive specification evaluated with DIR as current directory
+  - the \"/\" rules apply in the same way as in 1., except you can not
+    create a file this way, a directory is always created
+
+An example showing all the possibilities:
+
+  (\"empty_file\"
+   \"dir/empty_file\"
+   \"dir/subdir/\"
+   (\"non_empty_file\" \"content\")
+   (\"dir/anotherdir/non_empty_file\" \"tralala\")
+   (\"big_dir\" (\"empty_file\"
+              (\"non_empty_file\" \"content\")
+              \"subdir/empty_file\")))
+
+If we want to run some code in a directory with an empty file
+\"foo.txt\" present, we call:
+
+  (assess-with-filesystem '(\"foo\")
+    (code-here)
+    (and-some-more-forms))
+
+You should *not* depend on where exactly the hierarchy is created.
+By default, a new directory in `temporary-file-directory' is
+created and the specification is evaluated there, but this is up
+for change."
+  (declare (indent 1))
+  (let ((temp-root (make-symbol "temp-root"))
+        (old-dd (make-symbol "old-dd")))
+    `(let ((,temp-root (make-temp-file "temp-fs-" t))
+           (,old-dd default-directory))
+       (unwind-protect
+           (progn
+             (setq default-directory ,temp-root)
+             (mapc (lambda (s) (assess-with-filesystem--init s ".")) ,spec)
+             ,@forms)
+         (delete-directory ,temp-root t)
+         (setq default-directory ,old-dd)))))
+;; #+END_SRC
 ;; ** Indentation functions
 
 ;; There are two main ways to test indentation -- we can either take unindented
diff --git a/test/assess-test.el b/test/assess-test.el
index d3a0617d98..4fa902daf2 100644
--- a/test/assess-test.el
+++ b/test/assess-test.el
@@ -288,6 +288,56 @@ This also tests the advice on string=."
 
 ;; #+end_src
 
+;; ** Creating Files and Directories
+;; #+BEGIN_SRC emacs-lisp
+(ert-deftest assess-test-create-multiple-files ()
+  (assess-with-filesystem '("foo" "bar" "baz")
+    (should (file-regular-p "foo"))
+    (should (file-regular-p "bar"))
+    (should (file-regular-p "baz"))))
+
+(ert-deftest assess-test-create-multiple-directories-and-files ()
+  (assess-with-filesystem '("foo/" "bar/" "baz")
+    (should (file-directory-p "foo"))
+    (should (file-directory-p "bar"))
+    (should (file-regular-p "baz"))))
+
+(ert-deftest assess-test-create-nested-directories ()
+  (assess-with-filesystem '("foo/bar" "foo/baz/")
+    (should (file-regular-p "foo/bar"))
+    (should (file-directory-p "foo/baz"))))
+
+(defun assess-test-file-contain-p (file content)
+  "Return nil iff FILE does not contain CONTENT."
+  (and (file-regular-p file)
+       (with-temp-buffer
+         (insert-file-contents file)
+         (string-match-p content (buffer-string)))))
+
+(ert-deftest assess-test-create-non-empty-file ()
+  (assess-with-filesystem '(("foo" "amazing content"))
+    (should (assess-test-file-contain-p "foo" "amazing content"))))
+
+(ert-deftest assess-test-create-non-empty-nested-file ()
+  (assess-with-filesystem '(("foo/bar" "amazing content"))
+    (should (assess-test-file-contain-p "foo/bar" "amazing content"))))
+
+(ert-deftest assess-test-nest-files-recursively ()
+  (assess-with-filesystem '(("foo" ("bar" "baz" "bam/"))
+                     ("a/b" ("c" "d/"))
+                     ("x" (("y" ("z"))
+                           ("content" "content")
+                           "w")))
+    (should (file-regular-p "foo/bar"))
+    (should (file-regular-p "foo/baz"))
+    (should (file-regular-p "a/b/c"))
+    (should (file-regular-p "x/y/z"))
+    (should (file-regular-p "x/content"))
+    (should (file-regular-p "x/w"))
+    (should (assess-test-file-contain-p "x/content" "content"))
+    (should (file-directory-p "foo/bam"))
+    (should (file-directory-p "a/b/d"))))
+;; #+END_SRC
 ;; ** Indentation Tests
 
 ;; #+begin_src emacs-lisp



reply via email to

[Prev in Thread] Current Thread [Next in Thread]