Created
October 20, 2011 05:09
-
-
Save bpsm/1300472 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns jardifference | |
(:import (java.util.jar JarFile JarEntry JarOutputStream)) | |
(:require (clojure.java [io :as io]) | |
(clojure [set :as set]))) | |
(defn jar-entry-seq | |
[^JarFile jf] | |
(enumeration-seq (.entries jf))) | |
(defn jar-entry-map | |
[^JarFile jf] | |
(apply merge {} | |
(for [^JarEntry je (jar-entry-seq jf) :when (not (.isDirectory je))] | |
{(.getName je) je}))) | |
(defn same-content? | |
[^JarFile jf1 ^JarEntry je1 ^JarFile jf2 ^JarEntry je2] | |
(with-open [in1 (.getInputStream jf1 je1) | |
in2 (.getInputStream jf2 je2)] | |
(loop [c1 (.read in1), c2 (.read in2)] | |
(if (or (= -1 c1) (= -1 c2)) | |
(= c1 c2) | |
(recur (.read in1) (.read in2)))))) | |
(defn same? | |
[^JarFile jf1 ^JarEntry je1 ^JarFile jf2 ^JarEntry je2] | |
(and (= (.getSize je1) (.getSize je2)) | |
(= (.getCrc je1) (.getCrc je2)) | |
(= (.getCompressedSize je1) (.getCompressedSize je2)) | |
(same-content? jf1 je1 jf2 je2))) | |
(def noop (constantly nil)) | |
(defn compare-jars | |
[jf-old jf-new & | |
{:keys [identical changed deleted created] | |
:or {identical noop, changed noop, deleted noop, created noop}}] | |
(let [m-old (jar-entry-map jf-old), m-new (jar-entry-map jf-new)] | |
(doseq [name (-> (concat (keys m-old) (keys m-new)) set sort) | |
:let [je-old (m-old name), je-new (m-new name)]] | |
(cond (not je-old) (created jf-new je-new) | |
(not je-new) (deleted jf-old je-old) | |
(same? jf-old je-old jf-new je-new) (identical jf-old je-old) | |
:else (changed jf-new je-new))))) | |
(defn copy-entry | |
[^JarOutputStream out ^JarFile jf ^JarEntry je] | |
(with-open [in (.getInputStream jf je)] | |
(.putNextEntry out je) | |
(io/copy in out) | |
(.closeEntry out))) | |
(defn open-jar | |
^JarFile [^String path] | |
(JarFile. path)) | |
(defn make-diff-jar | |
[jf-diff-name & jf-names] | |
{:pre [(even? (count jf-names))]} | |
(with-open [jout-diff (JarOutputStream. (io/output-stream jf-diff-name))] | |
(let [copy (partial copy-entry jout-diff)] | |
(doseq [[jf-old-name jf-new-name] (partition 2 jf-names)] | |
(with-open [jf-old (open-jar jf-old-name) | |
jf-new (open-jar jf-new-name)] | |
(compare-jars jf-old jf-new :changed copy :created copy)))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment