~ chicken-core (chicken-5) 92f023f28aa9b0455218ff8b92df92f043a8a81d


commit 92f023f28aa9b0455218ff8b92df92f043a8a81d
Author:     Peter Bex <peter@more-magic.net>
AuthorDate: Wed Jun 14 21:34:58 2017 +0200
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Sun Jul 2 10:28:41 2017 +1200

    Move several procedures from "posix" to "file"
    
    - delete-directory
    - glob
    - find-files
    
    This also moves the dependency on irregex from posix to file, since
    only these three procedures used irregex helpers.
    
    Signed-off-by: Evan Hanson <evhan@foldling.org>

diff --git a/file.scm b/file.scm
index c1768afa..cd0f6012 100644
--- a/file.scm
+++ b/file.scm
@@ -35,7 +35,7 @@
 
 (declare
   (unit file)
-  (uses extras pathname posix)
+  (uses extras irregex pathname posix)
   (fixnum)
   (disable-interrupts)
   (foreign-declare #<<EOF
@@ -47,6 +47,8 @@
 #else
 # define C_mkdir(str)	    C_fix(mkdir(C_c_string(str)))
 #endif
+
+#define C_rmdir(str)	    C_fix(rmdir(C_c_string(str)))
 EOF
 ))
 
@@ -83,6 +85,7 @@ EOF
 (import chicken scheme
 	chicken.foreign
 	chicken.io
+	chicken.irregex
 	chicken.pathname
 	chicken.posix)
 
@@ -90,6 +93,16 @@ EOF
 
 (define-foreign-variable strerror c-string "strerror(errno)")
 
+;; TODO: Some duplication from POSIX, to give better error messages.
+;; This really isn't so much posix-specific, and code like this is
+;; also in library.scm.  This should be deduplicated across the board.
+(define posix-error
+  (let ([strerror (foreign-lambda c-string "strerror" int)]
+	[string-append string-append] )
+    (lambda (type loc msg . args)
+      (let ([rn (##sys#update-errno)])
+	(apply ##sys#signal-hook type loc (string-append msg " - " (strerror rn)) args) ) ) ) )
+
 
 ;;; Like `delete-file', but does nothing if the file doesn't exist:
 
@@ -98,6 +111,30 @@ EOF
     (and (file-exists? file) (delete-file file))))
 
 
+;;; Directory management:
+
+(define delete-directory
+  (lambda (name #!optional recursive)
+    (define (rmdir dir)
+      (let ((sname (##sys#make-c-string dir)))
+	(unless (fx= 0 (##core#inline "C_rmdir" sname))
+	  (posix-error #:file-error 'delete-directory "cannot delete directory" dir))))
+    (##sys#check-string name 'delete-directory)
+    (if recursive
+	(let ((files (find-files ; relies on `find-files' to list dir-contents before dir
+		      name
+		      dotfiles: #t
+		      follow-symlinks: #f)))
+	  (for-each
+	   (lambda (f)
+	     ((cond ((symbolic-link? f) delete-file)
+		    ((directory? f) rmdir)
+		    (else delete-file))
+	      f))
+	   files)
+	  (rmdir name))
+	(rmdir name))))
+
 ;;; file-copy and file-move : they do what you'd think.
 
 (define (file-copy origfile newfile #!optional (clobber #f) (blocksize 1024))
@@ -220,4 +257,66 @@ EOF
 		     (##sys#string-append "cannot create temporary directory - " strerror)
 		     pn)))))))))
 
+
+;;; Filename globbing:
+
+(define glob
+  (lambda paths
+    (let conc-loop ((paths paths))
+      (if (null? paths)
+	  '()
+	  (let ((path (car paths)))
+	    (let-values (((dir fil ext) (decompose-pathname path)))
+	      (let ((rx (##sys#glob->regexp (make-pathname #f (or fil "*") ext))))
+		(let loop ((fns (directory (or dir ".") #t)))
+		  (cond ((null? fns) (conc-loop (cdr paths)))
+			((irregex-match rx (car fns)) =>
+			 (lambda (m)
+			   (cons (make-pathname dir (irregex-match-substring m))
+				 (loop (cdr fns)))))
+			(else (loop (cdr fns))))))))))))
+
+
+;;; Find matching files:
+
+(define (find-files dir #!key (test (lambda _ #t))
+			      (action (lambda (x y) (cons x y)))
+			      (seed '())
+			      (limit #f)
+			      (dotfiles #f)
+			      (follow-symlinks #f))
+  (##sys#check-string dir 'find-files)
+  (let* ((depth 0)
+	 (lproc
+	  (cond ((not limit) (lambda _ #t))
+		((fixnum? limit) (lambda _ (fx< depth limit)))
+		(else limit)))
+	 (pproc
+	  (if (procedure? test)
+	      test
+	      (let ((test (irregex test))) ; force compilation
+		(lambda (x) (irregex-match test x))))))
+    (let loop ((dir dir)
+	       (fs (directory dir dotfiles))
+	       (r seed))
+      (if (null? fs)
+	  r
+	  (let* ((filename (##sys#slot fs 0))
+		 (f (make-pathname dir filename))
+		 (rest (##sys#slot fs 1)))
+	    (cond ((directory? f)
+		   (cond ((member filename '("." "..")) (loop dir rest r))
+			 ((and (symbolic-link? f) (not follow-symlinks))
+			  (loop dir rest (if (pproc f) (action f r) r)))
+			 ((lproc f)
+			  (loop dir
+				rest
+				(fluid-let ((depth (fx+ depth 1)))
+				  (loop f
+					(directory f dotfiles)
+					(if (pproc f) (action f r) r)))))
+			 (else (loop dir rest (if (pproc f) (action f r) r)))))
+		  ((pproc f) (loop dir rest (action f r)))
+		  (else (loop dir rest r))))))))
+
 )
diff --git a/posix-common.scm b/posix-common.scm
index 3543e6bd..ca8136a8 100644
--- a/posix-common.scm
+++ b/posix-common.scm
@@ -507,28 +507,6 @@ EOF
 	     #:file-error
 	     'current-directory "cannot retrieve current directory") ) ) ) )
 
-(define delete-directory
-  (lambda (name #!optional recursive)
-    (define (rmdir dir)
-      (let ((sname (##sys#make-c-string dir)))
-	(unless (fx= 0 (##core#inline "C_rmdir" sname))
-	  (posix-error #:file-error 'delete-directory "cannot delete directory" dir) )))
-    (##sys#check-string name 'delete-directory)
-    (if recursive
-      (let ((files (find-files ; relies on `find-files' to list dir-contents before dir
-                     name
-                     dotfiles: #t
-                     follow-symlinks: #f)))
-        (for-each
-          (lambda (f)
-            ((cond ((symbolic-link? f) delete-file)
-                   ((directory? f) rmdir)
-                   (else delete-file))
-             f))
-          files)
-        (rmdir name))
-      (rmdir name))))
-
 (define-inline (*create-directory loc name)
   (unless (fx= 0 (##core#inline "C_mkdir" (##sys#make-c-string name loc)))
     (posix-error #:file-error loc "cannot create directory" name)) )
@@ -575,72 +553,6 @@ EOF
 		      (loop)
 		      (cons file (loop)) ) ) ) ) ) ) ) )
 
-;;; Filename globbing:
-
-(define glob
-  (lambda paths
-    (let conc-loop ((paths paths))
-      (if (null? paths)
-	  '()
-	  (let ((path (car paths)))
-	    (let-values (((dir fil ext) (decompose-pathname path)))
-	      (let ((rx (##sys#glob->regexp (make-pathname #f (or fil "*") ext))))
-		(let loop ((fns (directory (or dir ".") #t)))
-		  (cond ((null? fns) (conc-loop (cdr paths)))
-			((irregex-match rx (car fns))
-			 => (lambda (m)
-			      (cons 
-			       (make-pathname dir (irregex-match-substring m))
-			       (loop (cdr fns)))) )
-			(else (loop (cdr fns))) ) ) ) ) ) ) ) ) )
-
-
-;;; Find matching files:
-
-(define (##sys#find-files dir pred action id limit follow dot loc)
-  (##sys#check-string dir loc)
-  (let* ((depth 0)
-         (lproc
-          (cond ((not limit) (lambda _ #t))
-                ((fixnum? limit) (lambda _ (fx< depth limit)))
-                (else limit) ) )
-         (pproc
-          (if (procedure? pred)
-              pred
-              (let ((pred (irregex pred))) ; force compilation
-                (lambda (x) (irregex-match pred x))))))
-    (let loop ((dir dir)
-               (fs (directory dir dot))
-               (r id))
-      (if (null? fs)
-          r
-          (let* ((filename (##sys#slot fs 0))
-                 (f (make-pathname dir filename))
-                 (rest (##sys#slot fs 1)))
-            (cond ((directory? f)
-                   (cond ((member filename '("." "..")) (loop dir rest r))
-                         ((and (symbolic-link? f) (not follow))
-                          (loop dir rest (if (pproc f) (action f r) r)))
-                         ((lproc f)
-                          (loop dir
-                                rest
-                                (fluid-let ((depth (fx+ depth 1)))
-                                  (loop f
-                                        (directory f dot)
-                                        (if (pproc f) (action f r) r)))))
-                         (else (loop dir rest (if (pproc f) (action f r) r)))))
-                  ((pproc f) (loop dir rest (action f r)))
-                  (else (loop dir rest r))))))))
-
-(define (find-files dir #!key (test (lambda _ #t))
-			      (action (lambda (x y) (cons x y)))
-                              (seed '())
-                              (limit #f)
-                              (dotfiles #f)
-                              (follow-symlinks #f))
-  (##sys#find-files dir test action seed limit follow-symlinks dotfiles 'find-files))
-
-
 ;;; umask
 
 (define file-creation-mode
diff --git a/posix.scm b/posix.scm
index b93d7bbe..d4815ff7 100644
--- a/posix.scm
+++ b/posix.scm
@@ -35,7 +35,7 @@
 
 (declare
   (unit posix)
-  (uses scheduler irregex pathname extras port lolevel)
+  (uses scheduler pathname extras port lolevel)
   (disable-interrupts)
   (not inline ##sys#interrupt-hook ##sys#user-interrupt-hook))
 
@@ -46,7 +46,7 @@
    create-session create-symbolic-link current-directory
    current-effective-group-id current-effective-user-id
    current-effective-user-name current-group-id current-process-id
-   current-user-id current-user-name delete-directory directory
+   current-user-id current-user-name directory
    directory? duplicate-fileno emergency-exit fcntl/dupfd fcntl/getfd
    fcntl/getfl fcntl/setfd fcntl/setfl fifo? fifo? file-access-time
    file-change-time file-close file-control file-creation-mode
@@ -55,8 +55,8 @@
    file-owner file-permissions file-position file-read file-read-access?
    file-select file-size file-stat file-test-lock file-truncate
    file-type file-unlock file-write file-write-access? fileno/stderr
-   fileno/stdin fileno/stdout find-files get-environment-variables
-   get-host-name glob local-time->seconds local-timezone-abbreviation
+   fileno/stdin fileno/stdout get-environment-variables
+   get-host-name local-time->seconds local-timezone-abbreviation
    open-input-file* open-input-pipe open-output-file* open-output-pipe
    open/append open/binary open/creat open/excl open/fsync open/noctty
    open/noinherit open/nonblock open/rdonly open/rdwr open/read
@@ -87,7 +87,6 @@
 (import scheme chicken)
 (import chicken.bitwise
 	chicken.foreign
-	chicken.irregex
 	chicken.memory
 	chicken.pathname
 	chicken.port
diff --git a/posixunix.scm b/posixunix.scm
index 1a8902db..63f0f891 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -115,7 +115,6 @@ static C_TLS struct stat C_statbuf;
 #define C_mkdir(str)        C_fix(mkdir(C_c_string(str), S_IRWXU | S_IRWXG | S_IRWXO))
 #define C_fchdir(fd)        C_fix(fchdir(C_unfix(fd)))
 #define C_chdir(str)        C_fix(chdir(C_c_string(str)))
-#define C_rmdir(str)        C_fix(rmdir(C_c_string(str)))
 
 #define open_binary_input_pipe(a, n, name)   C_mpointer(a, popen(C_c_string(name), "r"))
 #define open_text_input_pipe(a, n, name)     open_binary_input_pipe(a, n, name)
diff --git a/posixwin.scm b/posixwin.scm
index fec8759f..b6c6ff0b 100644
--- a/posixwin.scm
+++ b/posixwin.scm
@@ -117,7 +117,6 @@ static C_TLS TCHAR C_username[255 + 1] = "";
 
 #define C_mkdir(str)	    C_fix(mkdir(C_c_string(str)))
 #define C_chdir(str)	    C_fix(chdir(C_c_string(str)))
-#define C_rmdir(str)	    C_fix(rmdir(C_c_string(str)))
 
 /* DIRENT stuff */
 struct dirent
diff --git a/rules.make b/rules.make
index 418eb09a..14212cbc 100644
--- a/rules.make
+++ b/rules.make
@@ -702,7 +702,6 @@ posixunix.c: posixunix.scm \
 		chicken.bitwise.import.scm \
 		chicken.condition.import.scm \
 		chicken.foreign.import.scm \
-		chicken.irregex.import.scm \
 		chicken.memory.import.scm \
 		chicken.pathname.import.scm \
 		chicken.platform.import.scm \
@@ -712,7 +711,6 @@ posixwin.c: posixwin.scm \
 		chicken.condition.import.scm \
 		chicken.bitwise.import.scm \
 		chicken.foreign.import.scm \
-		chicken.irregex.import.scm \
 		chicken.memory.import.scm \
 		chicken.pathname.import.scm \
 		chicken.platform.import.scm \
@@ -742,6 +740,7 @@ repl.c: repl.scm \
 		chicken.eval.import.scm
 file.c: file.scm \
 		chicken.io.import.scm \
+		chicken.irregex.import.scm \
 		chicken.foreign.import.scm \
 		chicken.pathname.import.scm \
 		chicken.posix.import.scm
diff --git a/tests/test-find-files.scm b/tests/test-find-files.scm
index 62fe5a0a..30405fde 100644
--- a/tests/test-find-files.scm
+++ b/tests/test-find-files.scm
@@ -1,4 +1,4 @@
-(use data-structures posix)
+(use (chicken file) (chicken process-context) data-structures)
 (include "test.scm")
 
 (handle-exceptions exn
@@ -21,7 +21,7 @@
             "find-files-test-dir/dir-link-target/foo"
             "find-files-test-dir/dir-link-target/bar"))
 
-(change-directory "find-files-test-dir")
+(current-directory "find-files-test-dir")
 
 (cond-expand
   ((and windows (not cygwin))		; Cannot handle symlinks
@@ -209,5 +209,5 @@
 
 (test-end "find-files")
 
-(change-directory "..")
+(current-directory "..")
 (delete-directory "find-files-test-dir" #t)
diff --git a/types.db b/types.db
index 8aeaf28c..0b3077e6 100644
--- a/types.db
+++ b/types.db
@@ -1588,9 +1588,13 @@
 
 (chicken.file#create-temporary-directory (#(procedure #:clean #:enforce) chicken.file#create-temporary-directory () string))
 (chicken.file#create-temporary-file (#(procedure #:clean #:enforce) chicken.file#create-temporary-file (#!optional string) string))
+(chicken.file#delete-directory (#(procedure #:clean #:enforce) chicken.file#delete-directory (string #!optional *) string))
 (chicken.file#delete-file* (#(procedure #:clean #:enforce) chicken.file#delete-file* (string) *))
 (chicken.file#file-copy (#(procedure #:clean #:enforce) chicken.file#file-copy (string string #!optional * fixnum) fixnum))
 (chicken.file#file-move (#(procedure #:clean #:enforce) chicken.file#file-move (string string #!optional * fixnum) fixnum))
+(chicken.file#find-files (#(procedure #:enforce) chicken.file#find-files (string #!rest) list))
+(chicken.file#glob (#(procedure #:clean #:enforce) chicken.file#glob (#!rest string) list))
+
 
 ;; pathname
 
@@ -1933,7 +1937,6 @@
 (chicken.posix#current-process-id (#(procedure #:clean) chicken.posix#current-process-id () fixnum))
 (chicken.posix#current-user-id (#(procedure #:clean) chicken.posix#current-user-id () fixnum))
 (chicken.posix#current-user-name (#(procedure #:clean) chicken.posix#current-user-name () string))
-(chicken.posix#delete-directory (#(procedure #:clean #:enforce) chicken.posix#delete-directory (string #!optional *) string))
 (chicken.posix#directory (#(procedure #:clean #:enforce) chicken.posix#directory (#!optional string *) (list-of string)))
 (chicken.posix#directory? (#(procedure #:clean #:enforce) chicken.posix#directory? ((or string fixnum)) boolean))
 (chicken.posix#duplicate-fileno (#(procedure #:clean #:enforce) chicken.posix#duplicate-fileno (fixnum #!optional fixnum) fixnum))
@@ -1972,9 +1975,7 @@
 (chicken.posix#fileno/stderr fixnum)
 (chicken.posix#fileno/stdin fixnum)
 (chicken.posix#fileno/stdout fixnum)
-(chicken.posix#find-files (#(procedure #:enforce) chicken.posix#find-files (string #!rest) list))
 (chicken.posix#get-host-name (#(procedure #:clean) chicken.posix#get-host-name () string))
-(chicken.posix#glob (#(procedure #:clean #:enforce) chicken.posix#glob (#!rest string) list))
 (chicken.posix#local-time->seconds (#(procedure #:clean #:enforce) chicken.posix#local-time->seconds ((vector fixnum fixnum fixnum fixnum fixnum fixnum fixnum fixnum boolean fixnum)) integer))
 (chicken.posix#local-timezone-abbreviation (#(procedure #:clean) chicken.posix#local-timezone-abbreviation () string))
 (chicken.posix#open-input-file* (#(procedure #:clean #:enforce) chicken.posix#open-input-file* (fixnum #!optional symbol) input-port))
Trap