-
Notifications
You must be signed in to change notification settings - Fork 22
/
decompress.clj
62 lines (56 loc) · 2.66 KB
/
decompress.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(ns cljsjs.impl.decompress
(:require [boot.util :as util]
[clojure.java.io :as io])
(:import [org.apache.commons.compress.compressors CompressorStreamFactory FileNameUtil ]
[org.apache.commons.compress.archivers ArchiveStreamFactory ArchiveInputStream]))
(def file-name-util (delay (FileNameUtil. {".gz" ""
".xz" ""
".bzip2" ""
".bz2" ""
".tgz" ".tar"
".tbz2" ".tar"
".tlz" ".tar"}
"")))
(defn not-decompressable? [e]
(re-find #"No Compressor found for the stream signature\." (.getMessage e)))
(defn try-decompress-stream [is & [{:keys [format]}]]
(try
(cond-> (CompressorStreamFactory.)
format (.createCompressorInputStream format is true) ;; for concatenated bzip2, gzip and xz
(not format) (.createCompressorInputStream is))
(catch Exception e
(if (not-decompressable? e)
is
(throw e)))))
(defn mark-not-supported? [e]
(re-find #"Mark is not supported\." (.getMessage e)))
(defn unpackage-stream [is & [{:keys [format]}]]
(try
(cond-> (ArchiveStreamFactory.)
format (.createArchiveInputStream format is)
(not format) (.createArchiveInputStream is))
(catch Exception e
(if (mark-not-supported? e)
is
(throw e)))))
(defn decompress-file [in out-dir & [{:keys [compression-format archive-format]}]]
(with-open [is (-> (io/input-stream in)
(try-decompress-stream {:format compression-format})
(unpackage-stream {:format archive-format}))]
(if (instance? ArchiveInputStream is)
(let [count (loop [i 0
entry (.getNextEntry is)]
(if entry
(if-not (.isDirectory entry)
(let [target (io/file out-dir (.getName entry))]
(io/make-parents target)
;; After .getNextEntry the stream points to the specific archive entry
(io/copy is target)
(recur (inc i) (.getNextEntry is)))
(recur i (.getNextEntry is)))
i))]
(util/info (format "Extracted %d files\n" count)))
(let [target (io/file out-dir (.getUncompressedFilename @file-name-util (.getName (io/file in))))]
(io/make-parents target)
(io/copy is target)
(util/info (format "Extracted 1 file\n"))))))