diff --git a/.gitignore b/.gitignore
index 0b4fa26..27e7fee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,10 +2,9 @@
*.jar
lib
classes
-pom.xml
README.html
docs
-target
-pom.xml*
+src/raynes/fs/target
doc
-test/me/raynes/testfiles/round*
\ No newline at end of file
+test/me/raynes/testfiles/round*
+/.idea
\ No newline at end of file
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..167ff69
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,7 @@
+- repo: local
+ hooks:
+ - id: pom_generator
+ name: pom_generator
+ entry: pom_generator.sh
+ language: script
+ pass_filenames: false
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index b9d0e4d..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: clojure
-lein: lein2
-script: lein2 midje
\ No newline at end of file
diff --git a/README.markdown b/README.md
similarity index 66%
rename from README.markdown
rename to README.md
index ea4654f..866d6bc 100644
--- a/README.markdown
+++ b/README.md
@@ -1,12 +1,17 @@
# fs - File system utilities for Clojure
-[](http://travis-ci.org/Raynes/fs)
-
-[API docs](http://raynes.github.com/fs/)
+```clj
+[fs "1.4.7"]
+```
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.
+## pre-commit
+
+- Install: https://pre-commit.com/
+- running locally: This will also happen automatically before committing to a branch, but you can also run the tasks with `pre-commit run --all-files`
+
## Usage
This library is simple. It is just a collection of functions that do things with the file system. The one thing
@@ -22,33 +27,6 @@ because I probably want it. Make sure you include tests. Also, make sure they pa
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.6"]
-
-
-With Maven:
-
-
- me.raynes
- fs
- 1.4.6
-
-
## License
Copyright (C) 2010-2013 Miki Tebeka, Anthony Grimes
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9ed976c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,92 @@
+
+
+ 4.0.0
+ com.farmlogs
+ fs
+ jar
+ 1.4.7-SNAPSHOT
+ fs
+ File system utilities for clojure
+ https://github.com/FarmLogs/fs
+
+
+ Eclipse Public License - v 1.0
+ http://www.eclipse.org/legal/epl-v10.html
+
+
+
+ https://github.com/FarmLogs/fs
+ scm:git:git://github.com/FarmLogs/fs.git
+ scm:git:ssh://git@github.com/FarmLogs/fs.git
+ 63d694889a981854aa7ec35f42bd69ac7004591f
+
+
+ src
+ test
+
+
+ resources
+
+
+
+
+ resources
+
+
+ target
+ target/classes
+
+
+
+
+ central
+ https://repo1.maven.org/maven2/
+
+ false
+
+
+ true
+
+
+
+ clojars
+ https://repo.clojars.org/
+
+ true
+
+
+ true
+
+
+
+ releases
+ s3p://fl-maven-repo/mvn
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+ org.clojure
+ clojure
+ 1.11.1
+
+
+ org.apache.commons
+ commons-compress
+ 1.21
+
+
+
+
+
diff --git a/pom_generator.sh b/pom_generator.sh
new file mode 100755
index 0000000..d0d0956
--- /dev/null
+++ b/pom_generator.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+lein pom
+env -i git add pom.xml
\ No newline at end of file
diff --git a/project.clj b/project.clj
index a1170c1..1508693 100644
--- a/project.clj
+++ b/project.clj
@@ -1,14 +1,33 @@
-(defproject me.raynes/fs "1.4.6"
+(defproject me.raynes/fs "1.4.7"
: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.1.3"]
+ :url "https://github.com/FarmLogs/fs"
+ :min-lein-version "2.0.0"
+ :plugins [[lein-file-replace "0.1.0"]
+ [s3-wagon-private "1.3.5"]
+ [lein-midje "3.1.3"]
[codox "0.8.10"]]
- :codox {:src-dir-uri "https://github.com/Raynes/fs/blob/master/"
- :src-linenum-anchor-prefix "L"
- :defaults {:doc/format :markdown}}
- :deploy-repositories {"releases" :clojars}
- :profiles {:dev {:dependencies [[midje "1.6.3"]]}})
+ :profiles {:dev {:dependencies [[midje "1.6.3"]]}}
+ :repositories {"releases" {:url "s3p://fl-maven-repo/mvn"
+ :username :env/AMAZON_KEY
+ :passphrase :env/AMAZON_SECRET
+ :sign-releases false}}
+ :dependencies [[org.clojure/clojure "1.4.0"]
+ [org.apache.commons/commons-compress "1.21"]
+ [org.tukaani/xz "1.9"]]
+ :test-selectors {:default (complement :integration)
+ :integration :integration
+ :third-party :third-party
+ :docker (complement :third-party)
+ :all (constantly true)}
+
+ :release-tasks [["vcs" "assert-committed"]
+ ["change" "version"
+ "leiningen.release/bump-version" "release"]
+ ["vcs" "commit"]
+ ["vcs" "tag" "--no-sign"]
+ ["deploy"]
+ ["file-replace" "README.md" "\\[api \"" "\"]" "version"]
+ ["change" "version" "leiningen.release/bump-version"]
+ ["vcs" "commit"]])
diff --git a/src/me/raynes/fs.clj b/src/me/raynes/fs.clj
index cd20a13..d3a7802 100644
--- a/src/me/raynes/fs.clj
+++ b/src/me/raynes/fs.clj
@@ -5,7 +5,9 @@
[clojure.java.io :as io]
[clojure.string :as string]
[clojure.java.shell :as sh])
- (:import [java.io File FilenameFilter]))
+ (:import [java.io File FilenameFilter]
+ [java.nio.file Files Path]
+ [java.nio.file.attribute FileAttribute]))
;; 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
@@ -22,21 +24,20 @@
(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`."
+ "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`."
+ "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 "~")
@@ -44,15 +45,15 @@
(if (neg? sep)
(home (subs path 1))
(io/file (home (subs path 1 sep)) (subs path (inc sep)))))
- (io/file path))))
+ 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
+ "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."
+ the paths and cwd."
[path & paths]
(when-let [path (apply
io/file (if (= path ".")
@@ -63,61 +64,61 @@
path
(io/file *cwd* path))))
+(extend-protocol clojure.java.io/Coercions
+ Path
+ (as-file [this] (.toFile this))
+ (as-url [this] (. this (toFile) (toUrl))))
+
(defn list-dir
- "List files and directories under `path`."
+ "List files and directories under path."
[path]
- (seq (.listFiles (file path))))
-
-(defmacro ^:private predicate [s path]
- `(if ~path
- (. ~path ~s)
- false))
+ (seq (.list (file path))))
(defn absolute?
- "Return true if `path` is absolute."
+ "Return true if path is absolute."
[path]
- (predicate isAbsolute (io/file path)))
+ (.isAbsolute (io/file path)))
(defn executable?
- "Return true if `path` is executable."
+ "Return true if path is executable."
[path]
- (predicate canExecute (file path)))
+ (.canExecute (file path)))
(defn readable?
- "Return true if `path` is readable."
+ "Return true if path is readable."
[path]
- (predicate canRead (file path)))
+ (.canRead (file path)))
(defn writeable?
- "Return true if `path` is writeable."
+ "Return true if path is writeable."
[path]
- (predicate canWrite (file path)))
+ (.canWrite (file path)))
(defn delete
- "Delete `path`."
+ "Delete path."
[path]
- (predicate delete (file path)))
+ (.delete (file path)))
(defn exists?
- "Return true if `path` exists."
+ "Return true if path exists."
[path]
- (predicate exists (file path)))
+ (.exists (file path)))
-(defn absolute
- "Return absolute file."
+(defn absolute-path
+ "Return absolute path."
[path]
- (.getAbsoluteFile (file path)))
+ (.getAbsolutePath (file path)))
-(defn normalized
- "Return normalized (canonical) file."
+(defn normalized-path
+ "Return normalized (canonical) path."
[path]
(.getCanonicalFile (file path)))
(defn ^String base-name
- "Return the base name (final segment/file part) of a `path`.
+ "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 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)))
@@ -131,107 +132,45 @@
:else base))))
(defn directory?
- "Return true if `path` is a directory."
+ "Return true if path is a directory."
[path]
- (predicate isDirectory (file path)))
+ (.isDirectory (file path)))
(defn file?
- "Return true if `path` is a file."
+ "Return true if path is a file."
[path]
- (predicate isFile (file path)))
+ (.isFile (file path)))
(defn ^Boolean hidden?
- "Return true if `path` is hidden."
+ "Return true if path is hidden."
[path]
- (predicate isHidden (file path)))
+ (.isHidden (file path)))
-(defn delete-dir
- "Delete a directory tree."
- [root]
- (when (directory? root)
- (doseq [path (.listFiles (file root))]
- (delete-dir path)))
- (delete root))
+(defn- ^Path as-path
+ "Convert path to a java.nio.file.Path."
+ [path]
+ (.toPath (file path)))
+
+(defn ^Boolean link?
+ "Return true if path is a link."
+ [path]
+ (Files/isSymbolicLink (as-path path)))
+
+(defn ^File link
+ "Create a \"hard\" link from path to target."
+ [path target]
+ (file (Files/createLink (as-path path) (as-path target))))
-(defmacro ^:private include-java-7-fns []
- (when (try (import '[java.nio.file Files Path LinkOption CopyOption]
- '[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. The arguments
- are in the opposite order from the link(2) system
- call."
- [new-file existing-file]
- (file (Files/createLink (as-path new-file) (as-path existing-file))))
-
- (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
- [link-options](http://docs.oracle.com/javase/7/docs/api/java/nio/file/LinkOption.html)
- 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
- [link-options](http://docs.oracle.com/javase/7/docs/api/java/nio/file/LinkOption.html)
- 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))
-
- (defn move
- "Move or rename a file to a target file. Requires Java version 7 or greater. Optional
- [copy-options](http://docs.oracle.com/javase/7/docs/api/java/nio/file/CopyOption.html)
- may be provided."
- [source target & copy-options]
- (Files/move (as-path source) (as-path target) (into-array CopyOption copy-options))))))
-
-(include-java-7-fns)
+(defn ^File sym-link
+ "Create a \"soft\" link from path to target."
+ [path target]
+ (file (Files/createSymbolicLink
+ (as-path path)
+ (as-path target)
+ (make-array FileAttribute 0))))
(defn split-ext
- "Returns a vector of `[name extension]`."
+ "Returns a vector of [name extension]."
[path]
(let [base (base-name path)
i (.lastIndexOf base ".")]
@@ -272,11 +211,11 @@
[path]
(.mkdirs (file path)))
-(def ^{:doc "The root of a unix system is `/`, `nil` on Windows"}
+(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."
+ "Split path to components."
[path]
(let [pathstr (str path)
jregx (str "\\Q" File/separator "\\E")]
@@ -287,7 +226,7 @@
:else (seq (.split pathstr jregx)))))
(defn rename
- "Rename `old-path` to `new-path`. Only works on files."
+ "Rename old-path to new-path. Only works on files."
[old-path new-path]
(.renameTo (file old-path) (file new-path)))
@@ -301,21 +240,21 @@
(throw (IllegalArgumentException. (str path " not found")))))
(defn copy
- "Copy a file from `from` to `to`. Return `to`."
+ "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`
+ "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]]."
+ "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)
@@ -323,12 +262,12 @@
(defn- temp-create
"Create a temporary file or dir, trying n times before giving up."
- [prefix suffix tries f]
- (let [tmp (file (tmpdir) (temp-name prefix suffix))]
- (when (pos? tries)
- (if (f tmp)
- tmp
- (recur prefix suffix (dec tries) f)))))
+ ([prefix suffix tries f]
+ (loop [tries (range tries)]
+ (let [tmp (file (tmpdir) (temp-name prefix suffix))]
+ (if (and (seq tries) (f tmp))
+ tmp
+ (recur (rest tries)))))))
(defn temp-file
"Create a temporary file. Returns nil if file could not be created
@@ -342,25 +281,7 @@
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)))
-
-(defn ephemeral-file
- "Create an ephemeral file (will be deleted on JVM exit).
- Returns nil if file could not be created even after n tries
- (default 10)."
- ([prefix] (ephemeral-file prefix "" 10))
- ([prefix suffix] (ephemeral-file prefix suffix 10))
- ([prefix suffix tries] (when-let [created (temp-create prefix suffix tries create)]
- (doto created .deleteOnExit))))
-
-(defn ephemeral-dir
- "Create an ephemeral directory (will be deleted on JVM exit).
- Returns nil if dir could not be created even after n tries
- (default 10)."
- ([prefix] (ephemeral-dir prefix "" 10))
- ([prefix suffix] (ephemeral-dir prefix suffix 10))
- ([prefix suffix tries] (when-let [created (temp-create prefix suffix tries mkdirs)]
- (doto created .deleteOnExit))))
+ ([prefix suffix tries] (temp-create prefix suffix tries mkdir)))
; Taken from https://github.com/jkk/clj-glob. (thanks Justin!)
(defn- glob->regex
@@ -425,91 +346,57 @@
[root dirs files]))
(defn iterate-dir
- "Return a sequence `[root dirs files]`, starting from `path` in depth-first order"
+ "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]`.
+ '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`."
+ "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- char-to-int
- [c]
- (- (int c) 48))
-
-(defn- chmod-octal-digit
- [f i user?]
- (if (> i 7)
- (throw (IllegalArgumentException. "Bad mode"))
- (do (.setReadable f (pos? (bit-and i 4)) user?)
- (.setWritable f (pos? (bit-and i 2)) user?)
- (.setExecutable f (pos? (bit-and i 1)) user?))))
-
-(defn- chmod-octal
- [mode path]
- (let [[user group world] (map char-to-int mode)
- f (file path)]
- (if (not= group world)
- (throw (IllegalArgumentException.
- "Bad mode. Group permissions must be equal to world permissions"))
- (do (chmod-octal-digit f world false)
- (chmod-octal-digit f user true)
- path))))
-
(defn chmod
"Change file permissions. Returns path.
- `mode` can be a permissions string in octal or symbolic format.
- Symbolic: 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.
- Octal: a string of three octal digits representing user, group, and
- world permissions. The three bits of each digit signify read, write,
- and execute permissions (in order of significance). Note that group
- and world permissions must be equal.
+ '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
- ```"
+ (chmod \"+x\" \"/tmp/foo\") -> Sets executable for everyone
+ (chmod \"u-wx\" \"/tmp/foo\") -> Unsets owner write and executable"
[mode path]
(assert-exists path)
- (if (re-matches #"^\d{3}$" mode)
- (chmod-octal mode 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)))
+ (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."
+ "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."
+ "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)
@@ -531,15 +418,13 @@
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 delete-dir
+ "Delete a directory tree."
+ [root]
+ (when (directory? root)
+ (doseq [path (map #(file root %) (.list (file root)))]
+ (delete-dir path)))
+ (delete root))
(defn parents
"Get all the parent directories of a path."
@@ -563,7 +448,7 @@
".clj")))
(defn path-ns
- "Takes a `path` to a Clojure file and constructs a namespace symbol
+ "Takes a path to a Clojure file and constructs a namespace symbol
out of the path."
[path]
(symbol
@@ -572,14 +457,14 @@
(replace \/ \.))))
(defn find-files*
- "Find files in `path` by `pred`."
+ "Find files in path by pred."
[path pred]
(filter pred (-> path file file-seq)))
(defn find-files
- "Find files matching given `pattern`."
+ "Find files matching given pattern."
[path pattern]
- (find-files* path #(re-matches pattern (.getName ^File %))))
+ (find-files* path #(re-matches pattern (.getName %))))
(defn exec
"Execute a shell command in the current directory"
@@ -587,20 +472,20 @@
(sh/with-sh-dir *cwd* (apply sh/sh body)))
(defmacro with-cwd
- "Execute `body` with a changed working directory."
+ "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!`."
+ "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]]"
+ "set!s the value of *cwd* to path. Only works inside of
+ with-mutable-cwd"
[path]
(set! *cwd* (file path)))
diff --git a/src/me/raynes/fs/compression.clj b/src/me/raynes/fs/compression.clj
index 0bc9a29..329aa6c 100644
--- a/src/me/raynes/fs/compression.clj
+++ b/src/me/raynes/fs/compression.clj
@@ -6,92 +6,61 @@
(org.apache.commons.compress.archivers.tar TarArchiveInputStream
TarArchiveEntry)
(org.apache.commons.compress.compressors bzip2.BZip2CompressorInputStream
- xz.XZCompressorInputStream)
- (java.io ByteArrayOutputStream)))
+ xz.XZCompressorInputStream)))
(defn unzip
- "Takes the path to a zipfile `source` and unzips it to target-dir."
+ "Takes the path to a zipfile source and unzips it to target-dir."
([source]
(unzip source (name source)))
([source target-dir]
- (with-open [zip (ZipFile. (fs/file source))]
- (let [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))))
+ (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."
- [^java.util.zip.ZipOutputStream zip-output-stream [^String name content & remain]]
+ [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 ^bytes 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]...]```.
+ 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]
+ 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)]
+ (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]...]```.
+ 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- slurp-bytes [fpath]
- (with-open [data (io/input-stream (fs/file fpath))]
- (with-open [out (ByteArrayOutputStream.)]
- (io/copy data out)
- (.toByteArray out))))
-
-(defn make-zip-stream-from-files
- "Like make-zip-stream but takes a sequential of file paths and builds filename-content-pairs
- based on those"
- [fpaths]
- (let [filename-content-pairs (map (juxt fs/base-name slurp-bytes) fpaths)]
- (make-zip-stream filename-content-pairs)))
-
-(defn zip-files
- "Zip files provided in argument vector to a single zip. Converts the argument list:
-
- ```(fpath1 fpath2...)```
-
- into filename-content -pairs, using the original file's basename as the filename in zip`and slurping the content:
-
- ```([fpath1-basename fpath1-content] [fpath2-basename fpath2-content]...)``"
- [filename fpaths]
- (io/copy (make-zip-stream-from-files fpaths)
- (fs/file filename)))
-
(defn- tar-entries
"Get a lazy-seq of entries in a tarfile."
[^TarArchiveInputStream tin]
@@ -99,35 +68,31 @@
(cons entry (lazy-seq (tar-entries tin)))))
(defn untar
- "Takes a tarfile `source` and untars it to `target`."
+ "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)
- (when (.isFile entry)
- (fs/chmod (apply str (take-last
- 3 (format "%05o" (.getMode entry))))
- (.getPath output-file)))))))
+ (io/copy tin output-file)))))
(defn gunzip
- "Takes a path to a gzip file `source` and unzips it."
+ "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."
+ "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."
+ "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.)