redo path handling

db4
erg 2008-03-25 19:50:39 -05:00
parent fd0d489543
commit b13e0f7042
3 changed files with 155 additions and 54 deletions

View File

@ -9,6 +9,9 @@ io.files.unique sequences strings accessors ;
[ "passwd" ] [ "/etc/passwd" file-name ] unit-test [ "passwd" ] [ "/etc/passwd" file-name ] unit-test
[ "awk" ] [ "/usr/libexec/awk/" file-name ] unit-test [ "awk" ] [ "/usr/libexec/awk/" file-name ] unit-test
[ "awk" ] [ "/usr/libexec/awk///" file-name ] unit-test [ "awk" ] [ "/usr/libexec/awk///" file-name ] unit-test
[ "" ] [ "" file-name ] unit-test
[ "/" ] [ "/" file-name ] unit-test
[ "///" ] [ "///" file-name ] unit-test
[ ] [ [ ] [
{ "Hello world." } { "Hello world." }
@ -144,3 +147,51 @@ io.files.unique sequences strings accessors ;
] keep file-info size>> ] keep file-info size>>
] with-unique-file ] with-unique-file
] unit-test ] unit-test
[ "/usr/lib" ] [ "/usr" "lib" append-path ] unit-test
[ "/usr/lib" ] [ "/usr/" "lib" append-path ] unit-test
[ "/lib" ] [ "/usr/" "/lib" append-path ] unit-test
[ "/lib/" ] [ "/usr/" "/lib/" append-path ] unit-test
[ "/usr/lib" ] [ "/usr" "./lib" append-path ] unit-test
[ "/usr/lib/" ] [ "/usr" "./lib/" append-path ] unit-test
[ "/lib" ] [ "/usr" "../lib" append-path ] unit-test
[ "/lib/" ] [ "/usr" "../lib/" append-path ] unit-test
[ "/lib" ] [ "/" "../lib" append-path ] unit-test
[ "/lib/" ] [ "/" "../lib/" append-path ] unit-test
[ "" ] [ "" "." append-path ] unit-test
[ "" ".." append-path ] must-fail
[ "/" ] [ "/" "./." append-path ] unit-test
[ "/" ] [ "/" "././" append-path ] unit-test
[ "/" ] [ "/" "../.." append-path ] unit-test
[ "/" ] [ "/" "../../" append-path ] unit-test
[ "/lib" ] [ "/" "../../lib" append-path ] unit-test
[ "/lib/" ] [ "/" "../../lib/" append-path ] unit-test
[ "/a/b/lib" ] [ "/a/b/c/d/e/f/" "../../../../lib" append-path ] unit-test
[ "/a/b/lib/" ] [ "/a/b/c/d/e/f/" "../../../../lib/" append-path ] unit-test
[ "" "../lib/" append-path ] must-fail
[ "lib" ] [ "" "lib" append-path ] unit-test
[ "lib" ] [ "" "./lib" append-path ] unit-test
[ "/lib/bux" ] [ "/usr" "/lib/bux" append-path ] unit-test
[ "/lib/bux/" ] [ "/usr" "/lib/bux/" append-path ] unit-test
[ "foo/" ] [ "foo/bar/." parent-directory ] unit-test
[ "foo/" ] [ "foo/bar/./" parent-directory ] unit-test
[ "foo/" ] [ "foo/bar/baz/.." parent-directory ] unit-test
[ "foo/" ] [ "foo/bar/baz/../" parent-directory ] unit-test
[ "." parent-directory ] must-fail
[ "./" parent-directory ] must-fail
[ ".." parent-directory ] must-fail
[ "../" parent-directory ] must-fail
[ "../../" parent-directory ] must-fail
[ "foo/.." parent-directory ] must-fail
[ "foo/../" parent-directory ] must-fail
[ "bar/foo" ] [ "bar/baz" "..///foo" append-path ] unit-test
[ "bar/baz/foo" ] [ "bar/baz" ".///foo" append-path ] unit-test
[ "bar/foo" ] [ "bar/baz" "./..//foo" append-path ] unit-test
[ "bar/foo" ] [ "bar/baz" "./../././././././///foo" append-path ] unit-test

View File

@ -3,7 +3,7 @@
USING: io.backend io.files.private io hashtables kernel math USING: io.backend io.files.private io hashtables kernel math
memory namespaces sequences strings assocs arrays definitions memory namespaces sequences strings assocs arrays definitions
system combinators splitting sbufs continuations io.encodings system combinators splitting sbufs continuations io.encodings
io.encodings.binary ; io.encodings.binary init ;
IN: io.files IN: io.files
HOOK: (file-reader) io-backend ( path -- stream ) HOOK: (file-reader) io-backend ( path -- stream )
@ -21,7 +21,26 @@ HOOK: (file-appender) io-backend ( path -- stream )
: <file-appender> ( path encoding -- stream ) : <file-appender> ( path encoding -- stream )
swap (file-appender) swap <encoder> ; swap (file-appender) swap <encoder> ;
HOOK: rename-file io-backend ( from to -- ) : file-lines ( path encoding -- seq )
<file-reader> lines ;
: with-file-reader ( path encoding quot -- )
>r <file-reader> r> with-stream ; inline
: file-contents ( path encoding -- str )
<file-reader> contents ;
: with-file-writer ( path encoding quot -- )
>r <file-writer> r> with-stream ; inline
: set-file-lines ( seq path encoding -- )
[ [ print ] each ] with-file-writer ;
: set-file-contents ( str path encoding -- )
[ write ] with-file-writer ;
: with-file-appender ( path encoding quot -- )
>r <file-appender> r> with-stream ; inline
! Pathnames ! Pathnames
: path-separator? ( ch -- ? ) windows? "/\\" "/" ? member? ; : path-separator? ( ch -- ? ) windows? "/\\" "/" ? member? ;
@ -32,42 +51,84 @@ HOOK: rename-file io-backend ( from to -- )
: left-trim-separators ( str -- newstr ) : left-trim-separators ( str -- newstr )
[ path-separator? ] left-trim ; [ path-separator? ] left-trim ;
: append-path ( str1 str2 -- str )
>r right-trim-separators "/" r>
left-trim-separators 3append ;
: prepend-path ( str1 str2 -- str )
swap append-path ; inline
: last-path-separator ( path -- n ? ) : last-path-separator ( path -- n ? )
[ length 1- ] keep [ path-separator? ] find-last* ; [ length 1- ] keep [ path-separator? ] find-last* ;
HOOK: root-directory? io-backend ( path -- ? ) HOOK: root-directory? io-backend ( path -- ? )
M: object root-directory? ( path -- ? ) path-separator? ; M: object root-directory? ( path -- ? )
dup empty? [ drop f ] [ [ path-separator? ] all? ] if ;
: special-directory? ( name -- ? ) { "." ".." } member? ;
ERROR: no-parent-directory path ; ERROR: no-parent-directory path ;
: parent-directory ( path -- parent ) : parent-directory ( path -- parent )
right-trim-separators { dup root-directory? [
{ [ dup empty? ] [ drop "/" ] } right-trim-separators
{ [ dup root-directory? ] [ ] } dup last-path-separator [
{ [ dup [ path-separator? ] contains? not ] [ drop "." ] } 1+ cut
{
{ "." [ 1 head* parent-directory ] }
{ ".." [
2 head* parent-directory parent-directory
] }
[ drop ]
} case
] [ no-parent-directory ] if
] unless ;
<PRIVATE
: head-path-separator? ( path1 ? -- ?' )
[
dup empty? [ drop t ] [ first path-separator? ] if
] [
drop f
] if ;
: head.? ( path -- ? ) "." ?head head-path-separator? ;
: head..? ( path -- ? ) ".." ?head head-path-separator? ;
: append-path-empty ( path1 path2 -- path' )
{
{ [ dup head.? ] [
1 tail left-trim-separators append-path-empty
] }
{ [ dup head..? ] [ drop no-parent-directory ] }
{ [ t ] [ nip ] }
} cond ;
PRIVATE>
: absolute-path? ( path -- ? )
dup empty? [ drop f ] [ first path-separator? ] if ;
: append-path ( str1 str2 -- str )
{
{ [ over empty? ] [ append-path-empty ] }
{ [ dup empty? ] [ drop ] }
{ [ dup absolute-path? ] [ nip ] }
{ [ dup head.? ] [ 1 tail left-trim-separators append-path ] }
{ [ dup head..? ] [
2 tail left-trim-separators
>r parent-directory r> append-path
] }
{ [ t ] [ { [ t ] [
dup last-path-separator drop 1+ cut >r right-trim-separators "/" r>
special-directory? [ no-parent-directory ] when left-trim-separators 3append
] } ] }
} cond ; } cond ;
: file-name ( path -- string ) : prepend-path ( str1 str2 -- str )
right-trim-separators { swap append-path ; inline
{ [ dup empty? ] [ drop "/" ] }
{ [ dup last-path-separator ] [ 1+ tail ] }
{ [ t ] [ drop ] }
} cond ;
: file-name ( path -- string )
dup root-directory? [
right-trim-separators
dup last-path-separator [ 1+ tail ] [ drop ] if
] unless ;
! File info
TUPLE: file-info type size permissions modified ; TUPLE: file-info type size permissions modified ;
HOOK: file-info io-backend ( path -- info ) HOOK: file-info io-backend ( path -- info )
@ -94,8 +155,12 @@ HOOK: cd io-backend ( path -- )
HOOK: cwd io-backend ( -- path ) HOOK: cwd io-backend ( -- path )
SYMBOL: current-directory
[ cwd current-directory set-global ] "current-directory" add-init-hook
: with-directory ( path quot -- ) : with-directory ( path quot -- )
cwd [ cd ] curry rot cd [ ] cleanup ; inline current-directory swap with-variable ; inline
! Creating directories ! Creating directories
HOOK: make-directory io-backend ( path -- ) HOOK: make-directory io-backend ( path -- )
@ -118,7 +183,7 @@ HOOK: make-directory io-backend ( path -- )
dup string? dup string?
[ tuck append-path directory? 2array ] [ nip ] if [ tuck append-path directory? 2array ] [ nip ] if
] with map ] with map
[ first special-directory? not ] subset ; [ first { "." ".." } member? not ] subset ;
: directory ( path -- seq ) : directory ( path -- seq )
normalize-directory dup (directory) fixup-directory ; normalize-directory dup (directory) fixup-directory ;
@ -199,34 +264,6 @@ DEFER: copy-tree-into
: resource-exists? ( path -- ? ) : resource-exists? ( path -- ? )
?resource-path exists? ; ?resource-path exists? ;
! Pathname presentations
TUPLE: pathname string ;
C: <pathname> pathname
M: pathname <=> [ pathname-string ] compare ;
: file-lines ( path encoding -- seq )
<file-reader> lines ;
: with-file-reader ( path encoding quot -- )
>r <file-reader> r> with-stream ; inline
: file-contents ( path encoding -- str )
<file-reader> contents ;
: with-file-writer ( path encoding quot -- )
>r <file-writer> r> with-stream ; inline
: set-file-lines ( seq path encoding -- )
[ [ print ] each ] with-file-writer ;
: set-file-contents ( str path encoding -- )
[ write ] with-file-writer ;
: with-file-appender ( path encoding quot -- )
>r <file-appender> r> with-stream ; inline
: temp-directory ( -- path ) : temp-directory ( -- path )
"temp" resource-path "temp" resource-path
dup exists? not dup exists? not
@ -235,6 +272,13 @@ M: pathname <=> [ pathname-string ] compare ;
: temp-file ( name -- path ) temp-directory prepend-path ; : temp-file ( name -- path ) temp-directory prepend-path ;
! Pathname presentations
TUPLE: pathname string ;
C: <pathname> pathname
M: pathname <=> [ pathname-string ] compare ;
! Home directory ! Home directory
: home ( -- dir ) : home ( -- dir )
{ {

View File

@ -6,3 +6,9 @@ IN: io.unix.files.tests
[ "/" ] [ "/etc/" parent-directory ] unit-test [ "/" ] [ "/etc/" parent-directory ] unit-test
[ "/" ] [ "/etc" parent-directory ] unit-test [ "/" ] [ "/etc" parent-directory ] unit-test
[ "/" ] [ "/" parent-directory ] unit-test [ "/" ] [ "/" parent-directory ] unit-test
[ "asdf" parent-directory ] must-fail
[ f ] [ "" root-directory? ] unit-test
[ t ] [ "/" root-directory? ] unit-test
[ t ] [ "//" root-directory? ] unit-test
[ t ] [ "///////" root-directory? ] unit-test