pax_global_header 0000666 0000000 0000000 00000000064 12347627441 0014524 g ustar 00root root 0000000 0000000 52 comment=d0b5c72ddeedb3ed489d4381238c99e3f730345f
libraynes-fs-clojure-1.4.6/ 0000755 0000000 0000000 00000000000 12347627441 0015571 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/.gitignore 0000644 0000000 0000000 00000000145 12347627441 0017561 0 ustar 00root root 0000000 0000000 .lein*
*.jar
lib
classes
pom.xml
README.html
docs
target
pom.xml*
doc
test/me/raynes/testfiles/round* libraynes-fs-clojure-1.4.6/.travis.yml 0000644 0000000 0000000 00000000061 12347627441 0017677 0 ustar 00root root 0000000 0000000 language: clojure
lein: lein2
script: lein2 midje libraynes-fs-clojure-1.4.6/README.markdown 0000644 0000000 0000000 00000003524 12347627441 0020276 0 ustar 00root root 0000000 0000000 # fs - File system utilities for Clojure
[](http://travis-ci.org/Raynes/fs)
[API docs](http://raynes.github.com/fs/)
This library defines some utilities for working with the file system in Clojure. Mostly, it wants to fill the gap that
`clojure.java.io` leaves and add on (and prettify) what `java.io.File` provides.
## Usage
This library is simple. It is just a collection of functions that do things with the file system. The one thing
you should understand is `*cwd*`. This library wraps a lot of built-in Java file systemy things because it
pays attention to the `*cwd*` as the current working directory. Java has no way to change the cwd of a JVM so
if you want that behavior, you have to simulate it. This library tries to do that.
The foundation of the library is the `file` function. It is just like `clojure.java.io/file`, but it pays
attention to the value of `*cwd*`.
This is 100% a utility library. If you have something useful that it doesn't already have, open a pull request,
because I probably want it. Make sure you include tests. Also, make sure they pass.
fs is *not* an I/O utility library. We should try to keep things limited to file system activities.
## Artifacts
Library artifacts are [released to Clojars](https://clojars.org/me.raynes/fs). If you are using Maven, add the following repository
definition to your `pom.xml`:
``` xml
clojars.org
http://clojars.org/repo
```
### The Most Recent Release
With Leiningen:
[me.raynes/fs "1.4.4"]
With Maven:
me.raynes
fs
1.4.4
## License
Copyright (C) 2010-2013 Miki Tebeka, Anthony Grimes
Distributed under the Eclipse Public License, the same as Clojure.
libraynes-fs-clojure-1.4.6/project.clj 0000644 0000000 0000000 00000000774 12347627441 0017741 0 ustar 00root root 0000000 0000000 (defproject me.raynes/fs "1.4.6"
:description "File system utilities for clojure"
:license {:name "Eclipse Public License - v 1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:url "https://github.com/Raynes/fs"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.apache.commons/commons-compress "1.8"]]
:plugins [[lein-midje "3.0-alpha4"]
[codox "0.6.7"]]
:repositories {"releases" :clojars}
:profiles {:dev {:dependencies [[midje "1.5-alpha8"]]}})
libraynes-fs-clojure-1.4.6/src/ 0000755 0000000 0000000 00000000000 12347627441 0016360 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/src/me/ 0000755 0000000 0000000 00000000000 12347627441 0016761 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/src/me/raynes/ 0000755 0000000 0000000 00000000000 12347627441 0020262 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/src/me/raynes/fs.clj 0000644 0000000 0000000 00000040622 12347627441 0021370 0 ustar 00root root 0000000 0000000 (ns me.raynes.fs
"File system utilities in Clojure"
(:refer-clojure :exclude [name parents])
(:require [clojure.zip :as zip]
[clojure.java.io :as io]
[clojure.string :as string]
[clojure.java.shell :as sh])
(:import [java.io File FilenameFilter]))
;; Once you've started a JVM, that JVM's working directory is set in stone
;; and cannot be changed. This library will provide a way to simulate a
;; working directory change. `cwd` is considered to be the current working
;; directory for functions in this library. Unfortunately, this will only
;; apply to functions inside this library since we can't change the JVM's
;; actual working directory.
(def ^{:doc "Current working directory. This cannot be changed in the JVM.
Changing this will only change the working directory for functions
in this library."
:dynamic true}
*cwd* (.getCanonicalFile (io/file ".")))
(let [homedir (io/file (System/getProperty "user.home"))
usersdir (.getParent homedir)]
(defn home
"With no arguments, returns the current value of the user.home system
property. If a user is passed, returns that user's home directory. It
is naively assumed to be a directory with the same name as the user
located relative to the parent of the current value of user.home."
([] homedir)
([user] (if (empty? user) homedir (io/file usersdir user)))))
(defn expand-home
"If path begins with a tilde (~), expand the tilde to the value
of the user.home system property. If the path begins with a tilde
immediately followed by some characters, they are assumed to be a
username. This is expanded to the path to that user's home directory.
This is (naively) assumed to be a directory with the same name as the
user relative to the parent of the current value of user.home."
[path]
(let [path (str path)]
(if (.startsWith path "~")
(let [sep (.indexOf path File/separator)]
(if (neg? sep)
(home (subs path 1))
(io/file (home (subs path 1 sep)) (subs path (inc sep)))))
path)))
;; Library functions will call this function on paths/files so that
;; we get the cwd effect on them.
(defn ^File file
"If path is a period, replaces it with cwd and creates a new File object
out of it and paths. Or, if the resulting File object does not constitute
an absolute path, makes it absolutely by creating a new File object out of
the paths and cwd."
[path & paths]
(when-let [path (apply
io/file (if (= path ".")
*cwd*
path)
paths)]
(if (.isAbsolute ^File path)
path
(io/file *cwd* path))))
(defn list-dir
"List files and directories under path."
[path]
(seq (.listFiles (file path))))
(defmacro ^:private predicate [s path]
`(if ~path
(. ~path ~s)
false))
(defn absolute?
"Return true if path is absolute."
[path]
(predicate isAbsolute (io/file path)))
(defn executable?
"Return true if path is executable."
[path]
(predicate canExecute (file path)))
(defn readable?
"Return true if path is readable."
[path]
(predicate canRead (file path)))
(defn writeable?
"Return true if path is writeable."
[path]
(predicate canWrite (file path)))
(defn delete
"Delete path."
[path]
(predicate delete (file path)))
(defn exists?
"Return true if path exists."
[path]
(predicate exists (file path)))
(defn absolute
"Return absolute file."
[path]
(.getAbsoluteFile (file path)))
(defn normalized
"Return normalized (canonical) file."
[path]
(.getCanonicalFile (file path)))
(defn ^String base-name
"Return the base name (final segment/file part) of a path.
If optional `trim-ext` is a string and the path ends with that string,
it is trimmed.
If `trim-ext` is true, any extension is trimmed."
([path] (.getName (file path)))
([path trim-ext]
(let [base (.getName (file path))]
(cond (string? trim-ext) (if (.endsWith base trim-ext)
(subs base 0 (- (count base) (count trim-ext)))
base)
trim-ext (let [dot (.lastIndexOf base ".")]
(if (pos? dot) (subs base 0 dot) base))
:else base))))
(defn directory?
"Return true if path is a directory."
[path]
(predicate isDirectory (file path)))
(defn file?
"Return true if path is a file."
[path]
(predicate isFile (file path)))
(defn ^Boolean hidden?
"Return true if path is hidden."
[path]
(predicate isHidden (file path)))
(defn delete-dir
"Delete a directory tree."
[root]
(when (directory? root)
(doseq [path (.listFiles (file root))]
(delete-dir path)))
(delete root))
(defmacro ^:private include-java-7-fns []
(when (try (import '[java.nio.file Files Path LinkOption]
'[java.nio.file.attribute FileAttribute])
(catch Exception _ nil))
'(do
(extend-protocol io/Coercions
Path
(as-file [this] (.toFile this))
(as-url [this] (.. this (toFile) (toURL))))
(defn- ^Path as-path
"Convert path to a java.nio.file.Path.
Requires Java version 7 or greater."
[path]
(.toPath (file path)))
(defn ^Boolean link?
"Return true if path is a link.
Requires Java version 7 or greater."
[path]
(Files/isSymbolicLink (as-path path)))
(defn ^File link
"Create a \"hard\" link from path to target.
Requires Java version 7 or greater."
[path target]
(file (Files/createLink (as-path path) (as-path target))))
(defn ^File sym-link
"Create a \"soft\" link from path to target.
Requires Java version 7 or greater."
[path target]
(file (Files/createSymbolicLink
(as-path path)
(as-path target)
(make-array FileAttribute 0))))
(defn ^File read-sym-link
"Return the target of a 'soft' link.
Requires Java version 7 or greater."
[path]
(file (Files/readSymbolicLink (as-path path))))
;; Rewrite directory? and delete-dir to include LinkOptions.
(defn directory?
"Return true if path is a directory, false otherwise. Optional
LinkOptions may be provided to determine whether or not to follow
symbolic links."
[path & link-options]
(Files/isDirectory (as-path path)
(into-array LinkOption link-options)))
(defn delete-dir
"Delete a directory tree. Optional LinkOptions may be provided to
determine whether or not to follow symbolic links."
[root & link-options]
(when (apply directory? root link-options)
(doseq [path (.listFiles (file root))]
(apply delete-dir path link-options)))
(delete root)))))
(include-java-7-fns)
(defn split-ext
"Returns a vector of [name extension]."
[path]
(let [base (base-name path)
i (.lastIndexOf base ".")]
(if (pos? i)
[(subs base 0 i) (subs base i)]
[base nil])))
(defn extension
"Return the extension part of a file."
[path] (last (split-ext path)))
(defn name
"Return the name part of a file."
[path] (first (split-ext path)))
(defn parent
"Return the parent path."
[path]
(.getParentFile (file path)))
(defn mod-time
"Return file modification time."
[path]
(.lastModified (file path)))
(defn size
"Return size (in bytes) of file."
[path]
(.length (file path)))
(defn mkdir
"Create a directory."
[path]
(.mkdir (file path)))
(defn mkdirs
"Make directory tree."
[path]
(.mkdirs (file path)))
(def ^{:doc "The root of a unix system is /, nil on Windows"}
unix-root (when (= File/separator "/") File/separator))
(defn split
"Split path to components."
[path]
(let [pathstr (str path)
jregx (str "\\Q" File/separator "\\E")]
(cond (= pathstr unix-root) (list unix-root)
(and unix-root (.startsWith pathstr unix-root))
;; unix absolute path
(cons unix-root (seq (.split (subs pathstr 1) jregx)))
:else (seq (.split pathstr jregx)))))
(defn rename
"Rename old-path to new-path. Only works on files."
[old-path new-path]
(.renameTo (file old-path) (file new-path)))
(defn create
"Create a new file."
[^File f]
(.createNewFile f))
(defn- assert-exists [path]
(when-not (exists? path)
(throw (IllegalArgumentException. (str path " not found")))))
(defn copy
"Copy a file from 'from' to 'to'. Return 'to'."
[from to]
(assert-exists from)
(io/copy (file from) (file to))
to)
(defn tmpdir
"The temporary file directory looked up via the java.io.tmpdir
system property. Does not create a temporary directory."
[]
(System/getProperty "java.io.tmpdir"))
(defn temp-name
"Create a temporary file name like what is created for temp-file
and temp-dir."
([prefix] (temp-name prefix ""))
([prefix suffix]
(format "%s%s-%s%s" prefix (System/currentTimeMillis)
(long (rand 0x100000000)) suffix)))
(defn- temp-create
"Create a temporary file or dir, trying n times before giving up."
([prefix suffix tries f]
(loop [tries tries]
(let [tmp (file (tmpdir) (temp-name prefix suffix))]
(when (pos? tries)
(if (f tmp)
tmp
(recur (dec tries))))))))
(defn temp-file
"Create a temporary file. Returns nil if file could not be created
even after n tries (default 10)."
([prefix] (temp-file prefix "" 10))
([prefix suffix] (temp-file prefix suffix 10))
([prefix suffix tries] (temp-create prefix suffix tries create)))
(defn temp-dir
"Create a temporary directory. Returns nil if dir could not be created
even after n tries (default 10)."
([prefix] (temp-dir prefix "" 10))
([prefix suffix] (temp-dir prefix suffix 10))
([prefix suffix tries] (temp-create prefix suffix tries mkdirs)))
; Taken from https://github.com/jkk/clj-glob. (thanks Justin!)
(defn- glob->regex
"Takes a glob-format string and returns a regex."
[s]
(loop [stream s
re ""
curly-depth 0]
(let [[c j] stream]
(cond
(nil? c) (re-pattern
; We add ^ and $ since we check only for file names
(str "^" (if (= \. (first s)) "" "(?=[^\\.])") re "$"))
(= c \\) (recur (nnext stream) (str re c c) curly-depth)
(= c \/) (recur (next stream) (str re (if (= \. j) c "/(?=[^\\.])"))
curly-depth)
(= c \*) (recur (next stream) (str re "[^/]*") curly-depth)
(= c \?) (recur (next stream) (str re "[^/]") curly-depth)
(= c \{) (recur (next stream) (str re \() (inc curly-depth))
(= c \}) (recur (next stream) (str re \)) (dec curly-depth))
(and (= c \,) (< 0 curly-depth)) (recur (next stream) (str re \|)
curly-depth)
(#{\. \( \) \| \+ \^ \$ \@ \%} c) (recur (next stream) (str re \\ c)
curly-depth)
:else (recur (next stream) (str re c) curly-depth)))))
(defn glob
"Returns files matching glob pattern."
([pattern]
(let [parts (split pattern)
root (apply file (if (= (count parts) 1) ["."] (butlast parts)))]
(glob root (last parts))))
([^File root pattern]
(let [regex (glob->regex pattern)]
(seq (.listFiles
root
(reify FilenameFilter
(accept [_ _ filename]
(boolean (re-find regex filename)))))))))
(defn- iterzip
"Iterate over a zip, returns a sequence of the nodes with a nil suffix"
[z]
(when-not (zip/end? z)
(cons (zip/node z) (lazy-seq (iterzip (zip/next z))))))
(defn- f-dir? [^File f]
(when f (.isDirectory f)))
(defn- f-children [^File f]
(.listFiles f))
(defn- iterate-dir* [path]
(let [root (file path)
nodes (butlast (iterzip (zip/zipper f-dir? f-children nil root)))]
(filter f-dir? nodes)))
(defn- walk-map-fn [root]
(let [kids (f-children root)
dirs (set (map base-name (filter f-dir? kids)))
files (set (map base-name (filter (complement f-dir?) kids)))]
[root dirs files]))
(defn iterate-dir
"Return a sequence [root dirs files], starting from 'path' in depth-first order"
[path]
(map walk-map-fn (iterate-dir* path)))
(defn walk
"Lazily walk depth-first over the directory structure starting at
'path' calling 'func' with three arguments [root dirs files].
Returns a sequence of the results."
[func path]
(map #(apply func %) (iterate-dir path)))
(defn touch
"Set file modification time (default to now). Returns path."
[path & [time]]
(let [f (file path)]
(when-not (create f)
(.setLastModified f (or time (System/currentTimeMillis))))
f))
(defn chmod
"Change file permissions. Returns path.
'mode' can be any combination of \"r\" (readable) \"w\" (writable) and \"x\"
(executable). It should be prefixed with \"+\" to set or \"-\" to unset. And
optional prefix of \"u\" causes the permissions to be set for the owner only.
Examples:
(chmod \"+x\" \"/tmp/foo\") -> Sets executable for everyone
(chmod \"u-wx\" \"/tmp/foo\") -> Unsets owner write and executable"
[mode path]
(assert-exists path)
(let [[_ u op permissions] (re-find #"^(u?)([+-])([rwx]{1,3})$" mode)]
(when (nil? op) (throw (IllegalArgumentException. "Bad mode")))
(let [perm-set (set permissions)
f (file path)
flag (= op "+")
user (not (empty? u))]
(when (perm-set \r) (.setReadable f flag user))
(when (perm-set \w) (.setWritable f flag user))
(when (perm-set \x) (.setExecutable f flag user)))
path))
(defn copy+
"Copy src to dest, create directories if needed."
[src dest]
(mkdirs (parent dest))
(copy src dest))
(defn copy-dir
"Copy a directory from 'from' to 'to'. If 'to' already exists, copy the directory
to a directory with the same name as 'from' within the 'to' directory."
[from to]
(when (exists? from)
(if (file? to)
(throw (IllegalArgumentException. (str to " is a file")))
(let [from (file from)
to (if (exists? to)
(file to (base-name from))
(file to))
trim-size (-> from str count inc)
dest #(file to (subs (str %) trim-size))]
(mkdirs to)
(dorun
(walk (fn [root dirs files]
(doseq [dir dirs]
(when-not (directory? dir)
(-> root (file dir) dest mkdirs)))
(doseq [f files]
(copy+ (file root f) (dest (file root f)))))
from))
to))))
(defn copy-dir-into
"Copy directory into another directory if destination already exists."
[from to]
(if-not (exists? to)
(copy-dir from to)
(doseq [file (list-dir from)]
(if (directory? file)
(copy-dir file to)
(copy file (io/file to (base-name file)))))))
(defn parents
"Get all the parent directories of a path."
[f]
(when-let [parent (parent (file f))]
(cons parent (lazy-seq (parents parent)))))
(defn child-of?
"Takes two paths and checks to see if the first path is a parent
of the second."
[p c] (some #{(file p)} (parents c)))
(defn ns-path
"Takes a namespace symbol and creates a path to it. Replaces hyphens with
underscores. Assumes the path should be relative to cwd."
[n]
(file
(str (.. (str n)
(replace \- \_)
(replace \. \/))
".clj")))
(defn path-ns
"Takes a path to a Clojure file and constructs a namespace symbol
out of the path."
[path]
(symbol
(.. (.replaceAll (str path) "\\.clj" "")
(replace \_ \-)
(replace \/ \.))))
(defn find-files*
"Find files in path by pred."
[path pred]
(filter pred (-> path file file-seq)))
(defn find-files
"Find files matching given pattern."
[path pattern]
(find-files* path #(re-matches pattern (.getName %))))
(defn exec
"Execute a shell command in the current directory"
[& body]
(sh/with-sh-dir *cwd* (apply sh/sh body)))
(defmacro with-cwd
"Execute body with a changed working directory."
[cwd & body]
`(binding [*cwd* (file ~cwd)]
~@body))
(defmacro with-mutable-cwd
"Execute the body in a binding with *cwd* bound to *cwd*.
This allows you to change *cwd* with set!."
[& body]
`(binding [*cwd* *cwd*]
~@body))
(defn chdir
"set!s the value of *cwd* to path. Only works inside of
with-mutable-cwd"
[path]
(set! *cwd* (file path)))
libraynes-fs-clojure-1.4.6/src/me/raynes/fs/ 0000755 0000000 0000000 00000000000 12347627441 0020672 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/src/me/raynes/fs/compression.clj 0000644 0000000 0000000 00000007523 12347627441 0023734 0 ustar 00root root 0000000 0000000 (ns me.raynes.fs.compression
"Compression utilities."
(:require [clojure.java.io :as io]
[me.raynes.fs :as fs])
(:import (java.util.zip ZipFile GZIPInputStream)
(org.apache.commons.compress.archivers.tar TarArchiveInputStream
TarArchiveEntry)
(org.apache.commons.compress.compressors bzip2.BZip2CompressorInputStream
xz.XZCompressorInputStream)))
(defn unzip
"Takes the path to a zipfile source and unzips it to target-dir."
([source]
(unzip source (name source)))
([source target-dir]
(let [zip (ZipFile. (fs/file source))
entries (enumeration-seq (.entries zip))
target-file #(fs/file target-dir (str %))]
(doseq [entry entries :when (not (.isDirectory ^java.util.zip.ZipEntry entry))
:let [f (target-file entry)]]
(fs/mkdirs (fs/parent f))
(io/copy (.getInputStream zip entry) f)))
target-dir))
(defn- add-zip-entry
"Add a zip entry. Works for strings and byte-arrays."
[zip-output-stream [name content & remain]]
(.putNextEntry zip-output-stream (java.util.zip.ZipEntry. name))
(if (string? content) ;string and byte-array must have different methods
(doto (java.io.PrintStream. zip-output-stream true)
(.print content))
(.write zip-output-stream content))
(.closeEntry zip-output-stream)
(when (seq (drop 1 remain))
(recur zip-output-stream remain)))
(defn make-zip-stream
"Create zip file(s) stream. You must provide a vector of the
following form: [[filename1 content1][filename2 content2]...].
You can provide either strings or byte-arrays as content.
The piped streams are used to create content on the fly, which means
this can be used to make compressed files without even writing them
to disk." [& filename-content-pairs]
(let [file
(let [pipe-in (java.io.PipedInputStream.)
pipe-out (java.io.PipedOutputStream. pipe-in)]
(future
(with-open [zip (java.util.zip.ZipOutputStream. pipe-out)]
(add-zip-entry zip (flatten filename-content-pairs))))
pipe-in)]
(io/input-stream file)))
(defn zip
"Create zip file(s) on the fly. You must provide a vector of the
following form: [[filename1 content1][filename2 content2]...].
You can provide either strings or byte-arrays as content."
[filename & filename-content-pairs]
(io/copy (make-zip-stream filename-content-pairs)
(fs/file filename)))
(defn- tar-entries
"Get a lazy-seq of entries in a tarfile."
[^TarArchiveInputStream tin]
(when-let [entry (.getNextTarEntry tin)]
(cons entry (lazy-seq (tar-entries tin)))))
(defn untar
"Takes a tarfile source and untars it to target."
([source] (untar source (name source)))
([source target]
(with-open [tin (TarArchiveInputStream. (io/input-stream (fs/file source)))]
(doseq [^TarArchiveEntry entry (tar-entries tin) :when (not (.isDirectory entry))
:let [output-file (fs/file target (.getName entry))]]
(fs/mkdirs (fs/parent output-file))
(io/copy tin output-file)))))
(defn gunzip
"Takes a path to a gzip file source and unzips it."
([source] (gunzip source (name source)))
([source target]
(io/copy (-> source fs/file io/input-stream GZIPInputStream.)
(fs/file target))))
(defn bunzip2
"Takes a path to a bzip2 file source and uncompresses it."
([source] (bunzip2 source (name source)))
([source target]
(io/copy (-> source fs/file io/input-stream BZip2CompressorInputStream.)
(fs/file target))))
(defn unxz
"Takes a path to a xz file source and uncompresses it."
([source] (unxz source (name source)))
([source target]
(io/copy (-> source fs/file io/input-stream XZCompressorInputStream.)
(fs/file target))))
libraynes-fs-clojure-1.4.6/test/ 0000755 0000000 0000000 00000000000 12347627441 0016550 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/ 0000755 0000000 0000000 00000000000 12347627441 0017151 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/raynes/ 0000755 0000000 0000000 00000000000 12347627441 0020452 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/raynes/core_test.clj 0000644 0000000 0000000 00000024721 12347627441 0023141 0 ustar 00root root 0000000 0000000 (ns me.raynes.core-test
(:refer-clojure :exclude [name parents])
(:require [me.raynes.fs :refer :all]
[me.raynes.fs.compression :refer :all]
[midje.sweet :refer :all]
[clojure.java.io :as io]
[clojure.string :as string])
(:import java.io.File))
(def system-tempdir (System/getProperty "java.io.tmpdir"))
(defn create-walk-dir []
(let [root (temp-dir "fs-")]
(mkdir (file root "a"))
(mkdir (file root "b"))
(spit (file root "1") "1")
(spit (file root "a" "2") "1")
(spit (file root "b" "3") "1")
root))
(fact "Makes paths absolute."
(file ".") => *cwd*
(file "foo") => (io/file *cwd* "foo"))
(fact "Expands path to current user."
(let [user (System/getProperty "user.home")]
(expand-home "~") => (file user)
(expand-home (str "~" File/separator "foo")) => (file user "foo")))
(fact "Expands to given user."
(let [user (System/getProperty "user.home")
name (System/getProperty "user.name")]
(expand-home (str "~" name)) => (file user)
(expand-home (format "~%s/foo" name)) => (file user "foo")))
(fact (list-dir ".") => (has every? #(instance? File %)))
;; Want to change these files to be tempfiles at some point.
(when unix-root (against-background
[(around :contents (let [f (io/file "test/me/raynes/testfiles/bar")]
(.setExecutable f false)
(.setReadable f false)
(.setWritable f false)
?form
(.setExecutable f true)
(.setReadable f true)
(.setWritable f true)))]
(fact
(executable? "test/me/raynes/testfiles/foo") => true
(executable? "test/me/raynes/testfiles/bar") => false)
(fact
(readable? "test/me/raynes/testfiles/foo") => true
(readable? "test/me/raynes/testfiles/bar") => false)
(fact
(writeable? "test/me/raynes/testfiles/foo") => true
(writeable? "test/me/raynes/testfiles/bar") => false)))
(fact
(file? "test/me/raynes/testfiles/foo") => true
(file? ".") => false)
(fact
(exists? "test/me/raynes/testfiles/foo") => true
(exists? "ewjgnr4ig43j") => false)
(fact
(let [f (io/file "test/me/raynes/testfiles/baz")]
(.createNewFile f)
(delete f)
(exists? f) => false))
(fact
(directory? ".") => true
(directory? "test/me/raynes/testfiles/foo") => false)
(fact
(file? ".") => false
(file? "test/me/raynes/testfiles/foo") => true)
(fact
(let [tmp (temp-file "fs-")]
(exists? tmp) => true
(file? tmp) => true
(delete tmp)))
(fact
(let [tmp (temp-dir "fs-")]
(exists? tmp) => true
(directory? tmp) => true
(delete tmp)))
(fact
(absolute "foo") => (io/file *cwd* "foo"))
(fact
(normalized ".") => *cwd*)
(fact
(base-name "foo/bar") => "bar"
(base-name "foo/bar.txt" true) => "bar"
(base-name "bar.txt" ".txt") => "bar"
(base-name "foo/bar.txt" ".png") => "bar.txt")
(fact
(let [tmp (temp-file "fs-")]
(> (mod-time tmp) 0) => true
(delete tmp)))
(fact
(let [f (temp-file "fs-")]
(spit f "abc")
(size f) => 3
(delete f)))
(fact
(let [root (create-walk-dir)
result (delete-dir root)]
(exists? root) => false))
(fact
(let [f (temp-file "fs-")]
(delete f)
(mkdir f)
(directory? f) => true
(delete-dir f)))
(fact
(let [f (temp-file "fs-")
sub (file f "a" "b")]
(delete f)
(mkdirs sub)
(directory? sub) => true
(delete-dir f)))
(fact
(split (file "test/fs")) => (has-suffix ["test" "fs"]))
(when unix-root
(fact
(split (file "/tmp/foo/bar.txt")) => '("/" "tmp" "foo" "bar.txt")
(split (file "/")) => '("/")
(split "/") => '("/")
(split "") => '("")))
(fact
(let [f (temp-file "fs-")
new-f (str f "-new")]
(rename f new-f)
(exists? f) => false
(exists? new-f) => true
(delete new-f)))
(fact
(let [root (create-walk-dir)]
(walk vector root) => (contains [[root #{"b" "a"} #{"1"}]
[(file root "a") #{} #{"2"}]
[(file root "b") #{} #{"3"}]]
:in-any-order)
(delete-dir root)))
(fact
(let [from (temp-file "fs-")
to (temp-file "fs-")
data "What's up Doc?"]
(delete to)
(spit from data)
(copy from to)
(slurp from) => (slurp to)
(delete from)
(delete to)))
(fact
(let [f (temp-file "fs-")
t (mod-time f)]
(Thread/sleep 1000)
(touch f)
(> (mod-time f) t) => true
(let [t2 3000]
(touch f t2)
(mod-time f) => t2)
(delete f)))
(fact
(let [f (temp-file "fs-")]
(chmod "+x" f)
(executable? f) => true
(when-not (re-find #"Windows" (System/getProperty "os.name"))
(chmod "-x" f)
(executable? f) => false)
(delete f)))
(fact
(let [from (create-walk-dir)
to (temp-dir "fs-")
path (copy-dir from to)
dest (file to (base-name from))]
path => dest
(walk vector to) => (contains [[to #{(base-name from)} #{}]
[dest #{"b" "a"} #{"1"}]
[(file dest "a") #{} #{"2"}]
[(file dest "b") #{} #{"3"}]]
:in-any-order)
(delete-dir from)
(delete-dir to)))
(fact "copy-dir-into works as expected."
(let [from (create-walk-dir)
to (temp-dir "fs-")]
(copy-dir-into from to)
(walk vector to) => (contains [[(file to) #{"a" "b"} #{"1"}]
[(file to "a") #{} #{"2"}]
[(file to "b") #{} #{"3"}]]
:in-any-order)
(delete-dir from)
(delete-dir to)))
(when (System/getenv "HOME")
(fact
(let [env-home (io/file (System/getenv "HOME"))]
(home) => env-home
(home "") => env-home
(home (System/getProperty "user.name")) => env-home)))
(tabular
(fact (split-ext ?file) => ?ext)
?file ?ext
"fs.clj" ["fs" ".clj"]
"fs." ["fs" "."]
"fs.clj.bak" ["fs.clj" ".bak"]
"/path/to/fs" ["fs" nil]
"" ["fs" nil]
"~user/.bashrc" [".bashrc" nil])
(tabular
(fact (extension ?file) => ?ext)
?file ?ext
"fs.clj" ".clj"
"fs." "."
"fs.clj.bak" ".bak"
"/path/to/fs" nil
"" nil
".bashrc" nil)
(tabular
(fact (name ?file) => ?ext)
?file ?ext
"fs.clj" "fs"
"fs." "fs"
"fs.clj.bak" "fs.clj"
"/path/to/fs" "fs"
"" "fs"
".bashrc" ".bashrc")
(fact "Can change cwd with with-cwd."
(let [old *cwd*]
(with-cwd "foo"
*cwd* => (io/file old "foo"))))
(fact "Can change cwd mutably with with-mutable-cwd"
(let [old *cwd*]
(with-mutable-cwd
(chdir "foo")
*cwd* => (io/file old "foo"))))
(with-cwd "test/me/raynes/testfiles"
(fact
(unzip "ggg.zip" "zggg")
(exists? "zggg/ggg") => true
(exists? "zggg/hhh/jjj") => true
(delete-dir "zggg"))
(fact (zip "fro.zip" ["bbb.txt" "bbb"])
(exists? "fro.zip") => true
(unzip "fro.zip" "fro")
(exists? "fro/bbb.txt") => true
(delete "fro.zip")
(delete-dir "fro"))
(fact "about zip round trip"
(zip "round.zip" ["some.txt" "some text"])
(unzip "round.zip" "round")
(slurp (file "round/some.txt")) => "some text")
(fact
(untar "ggg.tar" "zggg")
(exists? "zggg/ggg") => true
(exists? "zggg/hhh/jjj") => true
(delete-dir "zggg"))
(fact
(gunzip "ggg.gz" "ggg")
(exists? "ggg") => true
(delete "ggg"))
(fact
(bunzip2 "bbb.bz2" "bbb")
(exists? "bbb") => true
(delete "bbb"))
(fact
(unxz "xxx.xz" "xxx")
(exists? "xxx") => true
(delete "xxx")))
(let [win-root (when-not unix-root "c:")]
(fact
(parents (str win-root "/foo/bar/baz")) => (just [(file (str win-root "/foo"))
(file (str win-root "/foo/bar"))
(file (str win-root "/"))]
:in-any-order)
(parents (str win-root "/")) => nil))
(fact
(child-of? "/foo/bar" "/foo/bar/baz") => truthy
(child-of? "/foo/bar/baz" "/foo/bar") => falsey)
(fact
(path-ns "foo/bar/baz_quux.clj") => 'foo.bar.baz-quux)
(fact
(str (ns-path 'foo.bar.baz-quux)) => (has-suffix (string/join File/separator ["foo" "bar" "baz_quux.clj"])))
(fact
(let [win-root (when-not unix-root "c:")]
(absolute? (str win-root "/foo/bar")) => true
(absolute? (str win-root "/foo/")) => true
(absolute? "foo/bar") => false
(absolute? "foo/") => false))
(defmacro run-java-7-tests []
(when (try (import '[java.nio.file Files Path LinkOption]
'[java.nio.file.attribute FileAttribute])
(catch Exception _ nil))
'(do
(def test-files-path "test/me/raynes/testfiles")
(fact
(let [files (find-files test-files-path #"ggg\.*")
gggs (map #(file (str test-files-path "/ggg." %)) '(gz tar zip))]
(every? (set gggs) files) => true))
(fact
(let [fs1 (find-files test-files-path #"ggg\.*")
fs2 (find-files* test-files-path #(re-matches #"ggg\.*" (.getName %)))]
(= fs1 fs2) => true))
(fact
(let [f (touch (io/file test-files-path ".hidden"))]
(hidden? f)
(delete f)))
(fact
(let [target (io/file test-files-path "ggg.tar")
hard (link (io/file test-files-path "hard.link") target)
soft (sym-link (io/file test-files-path "soft.link") target)]
(file? hard) => true
(file? soft) => true
(link? soft) => true
(= (read-sym-link soft) target)
(delete hard)
(delete soft)))
(fact
(let [soft (sym-link (io/file test-files-path "soft.link") test-files-path)]
(link? soft) => true
(file? soft) => false
(directory? soft) => true
(directory? soft LinkOption/NOFOLLOW_LINKS) => false
(delete soft)))
(fact
(let [root (create-walk-dir)
soft-a (sym-link (io/file root "soft-a.link") (io/file root "a"))
soft-b (sym-link (io/file root "soft-b.link") (io/file root "b"))]
(delete-dir soft-a LinkOption/NOFOLLOW_LINKS)
(exists? (io/file root "a" "2")) => true
(delete-dir soft-b)
(exists? (io/file root "b" "3")) => false
(delete-dir root)
(exists? root) => false)))))
(run-java-7-tests)
libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/ 0000755 0000000 0000000 00000000000 12347627441 0022454 5 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/bar 0000755 0000000 0000000 00000000000 12347627441 0023134 0 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/bbb.bz2 0000644 0000000 0000000 00000000060 12347627441 0023614 0 ustar 00root root 0000000 0000000 BZh91AY&SY‡Æ‹ M€ @ "h0X]ÉáBBw, libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/foo 0000755 0000000 0000000 00000000000 12347627441 0023153 0 ustar 00root root 0000000 0000000 libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/ggg.gz 0000644 0000000 0000000 00000000033 12347627441 0023556 0 ustar 00root root 0000000 0000000 ‹ÑMåN ggg KËÏ !esŒ libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/ggg.tar 0000644 0000000 0000000 00000013000 12347627441 0023722 0 ustar 00root root 0000000 0000000 ./._ggg 000644 000766 000024 00000000252 11671246721 012751 0 ustar 00anthony staff 000000 000000 Mac OS X 2 x ª ATTR ª ˜ ˜ com.apple.quarantine q/0001;00000000;; ggg 000644 000766 000024 00000000003 11671246721 012371 0 ustar 00anthony staff 000000 000000 foo hhh/ 000755 000766 000024 00000000000 11671247002 012451 5 ustar 00anthony staff 000000 000000 hhh/._jjj 000644 000766 000024 00000000252 11671247017 013373 0 ustar 00anthony staff 000000 000000 Mac OS X 2 x ª ATTR ª ˜ ˜ com.apple.quarantine q/0001;00000000;; hhh/jjj 000644 000766 000024 00000000004 11671247017 013151 0 ustar 00anthony staff 000000 000000 bar
libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/ggg.zip 0000644 0000000 0000000 00000000671 12347627441 0023750 0 ustar 00root root 0000000 0000000 PK
U•‹? hhh/UT NåNÒNåNux ö PK
\•‹?é³¢ hhh/jjjUT NåNÄNåNux ö bar
PK
;•‹?!esŒ gggUT ÑMåNÄNåNux ö fooPK
U•‹? íA hhh/UT NåNux ö PK
\•‹?é³¢ ¤> hhh/jjjUT NåNux ö PK
;•‹?!esŒ ¤ƒ gggUT ÑMåNux ö PK à à libraynes-fs-clojure-1.4.6/test/me/raynes/testfiles/xxx.xz 0000644 0000000 0000000 00000000070 12347627441 0023663 0 ustar 00root root 0000000 0000000 ý7zXZ i"Þ6 ! GX:C xz
º-Òƒ kéð¥B™
YZ