(ns metabase.util.compress (:require [clojure.java.io :as io] [clojure.string :as str]) (:import (java.io File) (org.apache.commons.compress.archivers.tar TarArchiveEntry TarArchiveInputStream TarArchiveOutputStream) (org.apache.commons.compress.compressors.gzip GzipCompressorInputStream GzipCompressorOutputStream GzipParameters))) | |
(set! *warn-on-reflection* true) | |
Tar file entries as a lazy sequence. | (defn entries [^TarArchiveInputStream tar] (lazy-seq (when-let [entry (.getNextEntry tar)] (cons entry (entries tar))))) |
Compress directory | (defn tgz [^File src ^File dst] (when-not (.exists src) (throw (ex-info (format "Path is not readable or does not exist: %s" src) {:path src}))) (let [prefix (.getPath (.getParentFile src))] (with-open [tar (-> (io/output-stream dst) (GzipCompressorOutputStream. (doto (GzipParameters.) (.setModificationTime (System/currentTimeMillis)))) (TarArchiveOutputStream. 512 "UTF-8"))] (.setLongFileMode tar TarArchiveOutputStream/LONGFILE_POSIX) (doseq [^File f (file-seq src) :let [path-in-tar (subs (.getPath f) (count prefix)) entry (TarArchiveEntry. f path-in-tar)]] (.putArchiveEntry tar entry) (when (.isFile f) (with-open [s (io/input-stream f)] (io/copy s tar))) (.closeArchiveEntry tar))) dst)) |
Uncompress tar+gzip file | (defn untgz [^File archive ^File dst] (with-open [tar (-> (io/input-stream archive) (GzipCompressorInputStream.) (TarArchiveInputStream.))] (let [tar-entries (entries tar)] (count (for [^TarArchiveEntry e tar-entries :let [actual-name (last (.split (.getName e) "/"))] ;; skip hidden files :when (not (str/starts-with? actual-name "."))] (let [f (io/file dst (.getName e))] (if (.isFile e) (io/copy tar f) (.mkdirs f)) true)))))) |