guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.3-75-g46e782


From: Ludovic Courtès
Subject: [Guile-commits] GNU Guile branch, stable-2.0, updated. v2.0.3-75-g46e7820
Date: Sun, 18 Dec 2011 20:28:36 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=46e78202f093e4582f44555412472d1bedb75037

The branch, stable-2.0 has been updated
       via  46e78202f093e4582f44555412472d1bedb75037 (commit)
       via  7948c5d9eb8ef22689dbd29126a5971250d1db26 (commit)
       via  1629429d63170b1c5a19e72e838cab331c7eba8b (commit)
       via  af98fafabfa1a6d22688ff491fea63155665f2e5 (commit)
      from  ed4c3739668b4b111b38555b8bc101cb74c87c1c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 46e78202f093e4582f44555412472d1bedb75037
Author: Ludovic Courtès <address@hidden>
Date:   Sun Dec 18 21:27:56 2011 +0100

    doc: Add link from `opendir' to (ice-9 ftw).
    
    * doc/ref/posix.texi (File System): Add link to "File Tree Walk".

commit 7948c5d9eb8ef22689dbd29126a5971250d1db26
Author: Ludovic Courtès <address@hidden>
Date:   Sun Dec 18 21:25:24 2011 +0100

    doc: Use address@hidden {Scheme Procedure}' in `misc-modules.texi'.
    
    * doc/ref/misc-modules.texi: Use address@hidden {Scheme Procedure}' instead 
of
      address@hidden'.

commit 1629429d63170b1c5a19e72e838cab331c7eba8b
Author: Ludovic Courtès <address@hidden>
Date:   Sun Dec 18 21:14:33 2011 +0100

    ftw: Add `scandir'.
    
    Suggested by Nala Ginrut <address@hidden>.
    
    * module/ice-9/ftw.scm (scandir): New procedure.
    * test-suite/tests/ftw.test ("scandir"): New test prefix.
    * doc/ref/misc-modules.texi (File Tree Walk): Document `scandir'.

commit af98fafabfa1a6d22688ff491fea63155665f2e5
Author: Ludovic Courtès <address@hidden>
Date:   Thu Dec 15 23:32:24 2011 +0100

    ftw: Add an optional `stat' parameter to `file-system-fold' and `-tree'.
    
    * module/ice-9/ftw.scm (file-system-fold): Add an optional `stat'
      parameter.  Use it instead of `lstat'.  Handle the case where (STAT child)
      fails.
      (file-system-tree): Likewise, and pass it to `file-system-fold'.
    
    * doc/ref/misc-modules.texi (File Tree Walk): Update the documentation
      of these functions.

-----------------------------------------------------------------------

Summary of changes:
 doc/ref/misc-modules.texi |  113 +++++++++++++++++++++++++++------------------
 doc/ref/posix.texi        |    4 ++
 module/ice-9/ftw.scm      |   70 ++++++++++++++++++++--------
 test-suite/tests/ftw.test |    8 +++
 4 files changed, 131 insertions(+), 64 deletions(-)

diff --git a/doc/ref/misc-modules.texi b/doc/ref/misc-modules.texi
index ee12489..42b74fc 100644
--- a/doc/ref/misc-modules.texi
+++ b/doc/ref/misc-modules.texi
@@ -1098,6 +1098,9 @@ try to use one of them.  The reason for two versions is 
that the full
 @section File Tree Walk
 @cindex file tree walk
 
address@hidden file system traversal
address@hidden directory traversal
+
 The functions in this section traverse a tree of files and
 directories.  They come in two flavors: the first one is a high-level
 functional interface, and the second one is similar to the C @code{ftw}
@@ -1109,9 +1112,9 @@ GNU C Library Reference Manual}).
 @end example
 @sp 1
 
address@hidden file-system-tree file-name [enter?]
address@hidden {Scheme Procedure} file-system-tree file-name [enter? [stat]]
 Return a tree of the form @code{(@var{file-name} @var{stat}
address@hidden ...)} where @var{stat} is the result of @code{(lstat
address@hidden ...)} where @var{stat} is the result of @code{(@var{stat}
 @var{file-name})} and @var{children} are similar structures for each
 file contained in @var{file-name} when it designates a directory.
 
@@ -1121,6 +1124,9 @@ directory @var{name}; the default value is a procedure 
that always
 returns @code{#t}.  When a directory does not match @var{enter?}, it
 nonetheless appears in the resulting tree, only with zero children.
 
+The @var{stat} argument is optional and defaults to @code{lstat}, as for
address@hidden (see below.)
+
 The example below shows how to obtain a hierarchical listing of the
 files under the @file{module/language} directory in the Guile source
 tree, discarding their @code{stat} info:
@@ -1163,7 +1169,7 @@ tree, discarding their @code{stat} info:
     @dots{}))
   @dots{}))
 @end example
address@hidden defun
address@hidden deffn
 
 @cindex file system combinator
 
@@ -1174,7 +1180,7 @@ than building up a tree of entries in memory, like
 directly as a directory tree is traversed; in fact,
 @code{file-system-tree} is implemented in terms of it.
 
address@hidden file-system-fold enter? leaf down up skip init file-name
address@hidden {Scheme Procedure} file-system-fold enter? leaf down up skip 
init file-name [stat]
 Traverse the directory at @var{file-name}, recursively, and return the
 result of the successive applications of the @var{leaf}, @var{down},
 @var{up}, and @var{skip} procedures as described below.
@@ -1183,7 +1189,7 @@ Enter sub-directories only when @code{(@var{enter?} 
@var{path}
 @var{stat} @var{result})} returns true.  When a sub-directory is
 entered, call @code{(@var{down} @var{path} @var{stat} @var{result})},
 where @var{path} is the path of the sub-directory and @var{stat} the
-result of @code{(false-if-exception (lstat @var{path}))}; when it is
+result of @code{(false-if-exception (@var{stat} @var{path}))}; when it is
 left, call @code{(@var{up} @var{path} @var{stat} @var{result})}.
 
 For each file in a directory, call @code{(@var{leaf} @var{path}
@@ -1203,6 +1209,11 @@ file name, then @var{path} is also an absolute file 
name.  Files and
 directories, as identified by their device/inode number pair, are
 traversed only once.
 
+The optional @var{stat} argument defaults to @code{lstat}, which means
+that symbolic links are not followed; the @code{stat} procedure can be
+used instead when symbolic links are to be followed (@pxref{File System,
+stat}).
+
 The example below illustrates the use of @code{file-system-fold}:
 
 @example
@@ -1234,11 +1245,23 @@ to `du --apparent-size' with GNU Coreutils.)"
 (total-file-size "/dev/null")
 @result{} 0
 @end example
address@hidden defun
address@hidden deffn
 
 The alternative C-like functions are described below.
 
address@hidden ftw startname proc ['hash-size n]
address@hidden {Scheme Procedure} scandir name [select? [entry<?]]
+Return the list of the names of files contained in directory @var{name}
+that match predicate @var{select?} (by default, all files).  The
+returned list of file names is sorted according to @var{entry<?}, which
+defaults to @code{string-locale<?} such that file names are sorted in
+the locale's alphabetical order (@pxref{Text Collation}).
+
+This procedure is modeled after the C library function of the same name
+(@pxref{Scanning Directory Content,,, libc, GNU C Library Reference
+Manual}).
address@hidden deffn
+
address@hidden {Scheme Procedure} ftw startname proc ['hash-size n]
 Walk the file system tree descending from @var{startname}, calling
 @var{proc} for each file and directory.
 
@@ -1291,10 +1314,10 @@ to set the size of the hash table used to track items 
already visited.
 In the current implementation, returning address@hidden from @var{proc}
 is the only valid way to terminate @code{ftw}.  @var{proc} must not
 use @code{throw} or similar to escape.
address@hidden defun
address@hidden deffn
 
 
address@hidden nftw startname proc ['chdir] ['depth] ['hash-size n] ['mount] 
['physical]
address@hidden {Scheme Procedure} nftw startname proc ['chdir] ['depth] 
['hash-size n] ['mount] ['physical]
 Walk the file system tree starting at @var{startname}, calling
 @var{proc} for each file and directory.  @code{nftw} has extra
 features over the basic @code{ftw} described above.
@@ -1397,7 +1420,7 @@ caused the stop.
 In the current implementation, returning address@hidden from @var{proc}
 is the only valid way to terminate @code{ftw}.  @var{proc} must not
 use @code{throw} or similar to escape.
address@hidden defun
address@hidden deffn
 
 
 @node Queues
@@ -1563,7 +1586,7 @@ a list, but they could be printed (infinitely) with for 
example
 @end example
 
 @sp 1
address@hidden make-stream proc initial-state
address@hidden {Scheme Procedure} make-stream proc initial-state
 Return a new stream, formed by calling @var{proc} successively.
 
 Each call is @code{(@var{proc} @var{state})}, it should return a pair,
@@ -1571,32 +1594,32 @@ the @code{car} being the value for the stream, and the 
@code{cdr}
 being the new @var{state} for the next call.  For the first call
 @var{state} is the given @var{initial-state}.  At the end of the
 stream, @var{proc} should return some non-pair object.
address@hidden defun
address@hidden deffn
 
address@hidden stream-car stream
address@hidden {Scheme Procedure} stream-car stream
 Return the first element from @var{stream}.  @var{stream} must not be
 empty.
address@hidden defun
address@hidden deffn
 
address@hidden stream-cdr stream
address@hidden {Scheme Procedure} stream-cdr stream
 Return a stream which is the second and subsequent elements of
 @var{stream}.  @var{stream} must not be empty.
address@hidden defun
address@hidden deffn
 
address@hidden stream-null? stream
address@hidden {Scheme Procedure} stream-null? stream
 Return true if @var{stream} is empty.
address@hidden defun
address@hidden deffn
 
address@hidden list->stream list
address@hidden vector->stream vector
address@hidden {Scheme Procedure} list->stream list
address@hidden {Scheme Procedure} vector->stream vector
 Return a stream with the contents of @var{list} or @var{vector}.
 
 @var{list} or @var{vector} should not be modified subsequently, since
 it's unspecified whether changes there will be reflected in the stream
 returned.
address@hidden defun
address@hidden deffn
 
address@hidden port->stream port readproc
address@hidden {Scheme Procedure} port->stream port readproc
 Return a stream which is the values obtained by reading from
 @var{port} using @var{readproc}.  Each read call is
 @code{(@var{readproc} @var{port})}, and it should return an EOF object
@@ -1607,34 +1630,34 @@ For example a stream of characters from a file,
 @example
 (port->stream (open-input-file "/foo/bar.txt") read-char)
 @end example
address@hidden defun
address@hidden deffn
 
address@hidden stream->list stream
address@hidden {Scheme Procedure} stream->list stream
 Return a list which is the entire contents of @var{stream}.
address@hidden defun
address@hidden deffn
 
address@hidden stream->reversed-list stream
address@hidden {Scheme Procedure} stream->reversed-list stream
 Return a list which is the entire contents of @var{stream}, but in
 reverse order.
address@hidden defun
address@hidden deffn
 
address@hidden stream->list&length stream
address@hidden {Scheme Procedure} stream->list&length stream
 Return two values (@pxref{Multiple Values}), being firstly a list
 which is the entire contents of @var{stream}, and secondly the number
 of elements in that list.
address@hidden defun
address@hidden deffn
 
address@hidden stream->reversed-list&length stream
address@hidden {Scheme Procedure} stream->reversed-list&length stream
 Return two values (@pxref{Multiple Values}) being firstly a list which
 is the entire contents of @var{stream}, but in reverse order, and
 secondly the number of elements in that list.
address@hidden defun
address@hidden deffn
 
address@hidden stream->vector stream
address@hidden {Scheme Procedure} stream->vector stream
 Return a vector which is the entire contents of @var{stream}.
address@hidden defun
address@hidden deffn
 
address@hidden stream-fold proc init stream0 @dots{} streamN
address@hidden {Scheme Procedure} stream-fold proc init stream0 @dots{} streamN
 Apply @var{proc} successively over the elements of the given streams,
 from first to last until the end of the shortest stream is reached.
 Return the result from the last @var{proc} call.
@@ -1643,9 +1666,9 @@ Each call is @code{(@var{proc} elem0 @dots{} elemN 
prev)}, where each
 @var{elem} is from the corresponding @var{stream}.  @var{prev} is the
 return from the previous @var{proc} call, or the given @var{init} for
 the first call.
address@hidden defun
address@hidden deffn
 
address@hidden stream-for-each proc stream0 @dots{} streamN
address@hidden {Scheme Procedure} stream-for-each proc stream0 @dots{} streamN
 Call @var{proc} on the elements from the given @var{stream}s.  The
 return value is unspecified.
 
@@ -1653,16 +1676,16 @@ Each call is @code{(@var{proc} elem0 @dots{} elemN)}, 
where each
 @var{elem} is from the corresponding @var{stream}.
 @code{stream-for-each} stops when it reaches the end of the shortest
 @var{stream}.
address@hidden defun
address@hidden deffn
 
address@hidden stream-map proc stream0 @dots{} streamN
address@hidden {Scheme Procedure} stream-map proc stream0 @dots{} streamN
 Return a new stream which is the results of applying @var{proc} to the
 elements of the given @var{stream}s.
 
 Each call is @code{(@var{proc} elem0 @dots{} elemN)}, where each
 @var{elem} is from the corresponding @var{stream}.  The new stream
 ends when the end of the shortest given @var{stream} is reached.
address@hidden defun
address@hidden deffn
 
 
 @node Buffered Input
@@ -1681,7 +1704,7 @@ characters which are to be handed out on reading the 
port.  A notion
 of further input for an application level logical expression is
 maintained too, and passed through to the reader.
 
address@hidden make-buffered-input-port reader
address@hidden {Scheme Procedure} make-buffered-input-port reader
 Create an input port which returns characters obtained from the given
 @var{reader} function.  @var{reader} is called (@var{reader} cont),
 and should return a string or an EOF object.
@@ -1696,9 +1719,9 @@ application level notion, set with
 @code{set-buffered-input-continuation?!} below.  If the user has
 entered a partial expression then it allows @var{reader} for instance
 to give a different prompt to show more is required.
address@hidden defun
address@hidden deffn
 
address@hidden make-line-buffered-input-port reader
address@hidden {Scheme Procedure} make-line-buffered-input-port reader
 @cindex Line buffered input
 Create an input port which returns characters obtained from the
 specified @var{reader} function, similar to
@@ -1708,9 +1731,9 @@ expected to be a line-oriented.
 @var{reader} is called (@var{reader} cont), and should return a string
 or an EOF object as above.  Each string is a line of input without a
 newline character, the port code inserts a newline after each string.
address@hidden defun
address@hidden deffn
 
address@hidden set-buffered-input-continuation?! port cont
address@hidden {Scheme Procedure} set-buffered-input-continuation?! port cont
 Set the input continuation flag for a given buffered input
 @var{port}.
 
@@ -1725,7 +1748,7 @@ example with the Scheme @code{read} function 
(@pxref{Scheme Read}),
 (let ((obj (read my-port)))
   ...
 @end example
address@hidden defun
address@hidden deffn
 
 
 @c Local Variables:
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index 469c4da..1dc5a80 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -843,6 +843,10 @@ be empty for this to succeed.  The return value is 
unspecified.
 @cindex directory contents
 Open the directory specified by @var{dirname} and return a directory
 stream.
+
+Before using this and the procedures below, make sure to see the
+higher-level procedures for directory traversal that are available
+(@pxref{File Tree Walk}).
 @end deffn
 
 @deffn {Scheme Procedure} directory-stream? object
diff --git a/module/ice-9/ftw.scm b/module/ice-9/ftw.scm
index 539d80b..c335e97 100644
--- a/module/ice-9/ftw.scm
+++ b/module/ice-9/ftw.scm
@@ -193,9 +193,11 @@
   #:use-module (ice-9 match)
   #:use-module (ice-9 vlist)
   #:use-module (srfi srfi-1)
+  #:autoload   (ice-9 i18n)   (string-locale<?)
   #:export (ftw nftw
             file-system-fold
-            file-system-tree))
+            file-system-tree
+            scandir))
 
 (define (directory-files dir)
   (let ((dir-stream (opendir dir)))
@@ -387,15 +389,17 @@
 ;;; `file-system-fold' & co.
 ;;;
 
-(define (file-system-fold enter? leaf down up skip init file-name)
+(define* (file-system-fold enter? leaf down up skip init file-name
+                           #:optional (stat lstat))
   "Traverse the directory at FILE-NAME, recursively.  Enter
 sub-directories only when (ENTER? PATH STAT RESULT) returns true.  When
 a sub-directory is entered, call (DOWN PATH STAT RESULT), where PATH is
-the path of the sub-directory and STAT the result of (lstat PATH); when
+the path of the sub-directory and STAT the result of (stat PATH); when
 it is left, call (UP PATH STAT RESULT).  For each file in a directory,
 call (LEAF PATH STAT RESULT).  When ENTER? returns false, call (SKIP
 PATH STAT RESULT).  Return the result of these successive applications.
-When FILE-NAME names a flat file,(LEAF PATH STAT INIT) is returned."
+When FILE-NAME names a flat file, (LEAF PATH STAT INIT) is returned.
+The optional STAT parameter defaults to `lstat'."
 
   (define (mark v s)
     (vhash-cons (cons (stat:dev s) (stat:ino s)) #t v))
@@ -405,7 +409,7 @@ When FILE-NAME names a flat file,(LEAF PATH STAT INIT) is 
returned."
 
   (let loop ((name     file-name)
              (path     "")
-             (dir-stat (false-if-exception (lstat file-name)))
+             (dir-stat (false-if-exception (stat file-name)))
              (result   init)
              (visited  vlist-null))
 
@@ -452,16 +456,14 @@ When FILE-NAME names a flat file,(LEAF PATH STAT INIT) is 
returned."
                                subdirs))
                         (else
                          (let* ((child (string-append full-name "/" entry))
-                                (stat  (lstat child))) ; cannot fail
-                           (cond
-                            ((eq? (stat:type stat) 'directory)
-                             (liip (readdir dir)
-                                   result
-                                   (alist-cons entry stat subdirs)))
-                            (else
-                             (liip (readdir dir)
-                                   (leaf child stat result)
-                                   subdirs)))))))
+                                (st    (false-if-exception (stat child))))
+                           (if (and stat (eq? (stat:type st) 'directory))
+                               (liip (readdir dir)
+                                     result
+                                     (alist-cons entry st subdirs))
+                               (liip (readdir dir)
+                                     (leaf child st result)
+                                     subdirs))))))
 
                 ;; Directory FULL-NAME not readable.
                 ;; XXX: It's up to the user to distinguish between not
@@ -474,15 +476,17 @@ When FILE-NAME names a flat file,(LEAF PATH STAT INIT) is 
returned."
       ;; Caller passed a FILE-NAME that names a flat file, not a directory.
       (leaf full-name dir-stat result)))))
 
-(define* (file-system-tree file-name #:optional (enter? (lambda (n s) #t)))
+(define* (file-system-tree file-name
+                           #:optional (enter? (lambda (n s) #t))
+                                      (stat lstat))
   "Return a tree of the form (FILE-NAME STAT CHILDREN ...) where STAT is
-the result of (lstat FILE-NAME) and CHILDREN are similar structures for
+the result of (stat FILE-NAME) and CHILDREN are similar structures for
 each file contained in FILE-NAME when it designates a directory.  The
 optional ENTER? predicate is invoked as (ENTER? NAME STAT) and should
 return true to allow recursion into directory NAME; the default value is
 a procedure that always returns #t.  When a directory does not match
 ENTER?, it nonetheless appears in the resulting tree, only with zero
-children."
+children.  The optional STAT parameter defaults to `lstat'."
   (define (enter?* name stat result)
     (enter? name stat))
   (define (leaf name stat result)
@@ -501,6 +505,34 @@ children."
   (define skip                   ; keep an entry for skipped directories
     leaf)
 
-  (caar (file-system-fold enter?* leaf down up skip '(()) file-name)))
+  (caar (file-system-fold enter?* leaf down up skip '(()) file-name stat)))
+
+(define* (scandir name #:optional (select? (const #t))
+                                  (entry<? string-locale<?))
+  "Return the list of the names of files contained in directory NAME
+that match predicate SELECT? (by default, all files.)  The returned list
+of file names is sorted according to ENTRY<?, which defaults to
+`string-locale<?'."
+  (define (enter? name stat result)
+    (and stat (string=? name name)))
+
+  (define (leaf name stat result)
+    (if (select? name)
+        (cons (basename name) result)
+        result))
+
+  (define (down name stat result)
+    (cons "." result))
+
+  (define (up name stat result)
+    (cons ".." result))
+
+  (define (skip name stat result)
+    ;; NAME itself is not readable.
+    #f)
+
+  (and=> (file-system-fold enter? leaf down up skip '() name stat)
+         (lambda (files)
+           (sort files entry<?))))
 
 ;;; ftw.scm ends here
diff --git a/test-suite/tests/ftw.test b/test-suite/tests/ftw.test
index 40e4c2a..3db3302 100644
--- a/test-suite/tests/ftw.test
+++ b/test-suite/tests/ftw.test
@@ -166,3 +166,11 @@
                        expected)))
              (_ #f))
             children)))))
+
+(with-test-prefix "scandir"
+
+  (pass-if "test-suite"
+    (let ((select? (cut string-suffix? ".test" <>)))
+      (match (scandir (string-append %test-dir "/tests") select?)
+        (("." ".." "00-initial-env.test" (? select?) ...)
+         #t)))))


hooks/post-receive
-- 
GNU Guile



reply via email to

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