-
Notifications
You must be signed in to change notification settings - Fork 0
/
archive.clj
92 lines (82 loc) · 2.45 KB
/
archive.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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
(ns sisyphus.archive
(:require
[clojure.java.io :as io])
(:import
[java.util UUID]
[java.util.zip GZIPInputStream GZIPOutputStream]
[java.nio.file Paths]
[org.apache.commons.io FilenameUtils]
[org.apache.commons.compress.archivers.tar
TarArchiveInputStream
TarArchiveOutputStream
TarArchiveEntry]))
(defn path-for
[path]
(.toPath (io/file path)))
(defn up-path
[s up]
(let [path (path-for s)]
(try
(.toString (.subpath path up (.getNameCount path)))
(catch IllegalArgumentException e
""))))
(defn base-name
[path]
(when-not (empty? path)
(FilenameUtils/getBaseName path)))
(defn tar-input-stream
[path]
(TarArchiveInputStream.
(GZIPInputStream.
(io/input-stream path))))
(defn tar-output-stream
[path]
(TarArchiveOutputStream.
(GZIPOutputStream.
(io/output-stream path))))
(defn tar-gz-seq
[archive]
(when-let [item (.getNextTarEntry archive)]
(cons item (lazy-seq (tar-gz-seq archive)))))
(defn directory-path?
[path]
(= (last path) \/))
(defn trim-slash
[path]
(if (directory-path? path)
(.substring path 0 (dec (.length path)))
path))
(defn pack!
[tar-path folder-path]
(let [out (tar-output-stream tar-path)
folder-path (trim-slash folder-path)
folder-base (base-name folder-path)]
(doseq [inf (file-seq (io/file folder-path)) :when (.isFile inf)]
(let [entry-path (.replaceFirst
(.getPath inf)
(str folder-path "/")
(str folder-base "/"))
entry (TarArchiveEntry. entry-path)]
(.setSize entry (.length inf))
(.putArchiveEntry out entry)
(io/copy (io/input-stream inf) out)
(.closeArchiveEntry out)))
(.finish out)
(.close out)
(io/file tar-path)))
(defn unpack!
[tar-file out-path]
(let [tar-file (io/file tar-file)
out-path (io/file out-path)
archive (tar-input-stream tar-file)]
(.mkdirs out-path)
(doseq [entry (tar-gz-seq archive)]
(let [entry-path (up-path (.getName entry) 1)
out-file (io/file (str out-path "/" entry-path))]
(.mkdirs (.getParentFile out-file))
(with-open [outf (io/output-stream out-file)]
(let [bytes (byte-array 32768)]
(loop [nread (.read archive bytes 0 32768)]
(when (> nread -1)
(.write outf bytes 0 nread)
(recur (.read archive bytes 0 32768))))))))))