Skip to content

Commit

Permalink
🚧 Ongoing work on issue #3
Browse files Browse the repository at this point in the history
  • Loading branch information
pmonks committed Sep 1, 2023
1 parent d8a54f0 commit eb41e92
Show file tree
Hide file tree
Showing 16 changed files with 1,503 additions and 1,626 deletions.
13 changes: 13 additions & 0 deletions .github/ISSUE_TEMPLATE/Invalid_id_constructed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: 🐛 Invalid SPDX identifier constructed
about: When the library constructs an invalid SPDX identifier. 😢

---

## `lice-comb` API(s) you were calling, if known:

_e.g. `lice-comb.deps/deps-licenses`_

## Input data that you provided to that API:

_e.g. a license name, or the URI of a file containing the license text, or the `tools.deps` coordinate of the dependency, etc._
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ This library leverages, and is inspired by, the *excellent* [SPDX project](https

* `lice-comb` (all versions) requires an internet connection.

* `lice-comb` (all versions) assumes Maven is installed and in the `PATH` (but has fallback logic if it isn't).

* `lice-comb` (v2.0+) requires JDK 11 or higher.

## Installation
Expand Down Expand Up @@ -54,9 +56,10 @@ $ deps-try com.github.pmonks/lice-comb

### 1.x -> 2.x

Implementing [issue #3](https://github.com/pmonks/lice-comb/issues/3) resulted in the creation of a [new SPDX-specific library (`clj-spdx`)](https://github.com/pmonks/clj-spdx) that leverages [the official SPDX Java library](https://github.com/spdx/Spdx-Java-Library). Because of irreconcilable differences in how that Java library represents license data compared to `lice-comb` v1.x, as well as the addition of support for SPDX license exceptions, it was not possible to retain backwards compatibility.
The implementation of [issue #3](https://github.com/pmonks/lice-comb/issues/3) resulted in a number of unavoidable breaking changes, including:

The backwards compatibility breaking changes are limited to the (removed) `lice-comb.spdx` namespace however, so if you're not using that namespace you should be unaffected. If you are using that namespace, migration involves migrating to [`clj-spdx`](https://github.com/pmonks/clj-spdx), and (possibly) the `lice-comb.matching` namespace.
* A wholesale change from returning sets of SPDX identifiers to returning sets of SPDX expressions
* The creation of [a dedicated SPDX-specific library (`clj-spdx`)](https://github.com/pmonks/clj-spdx) that leverages [the official SPDX Java library](https://github.com/spdx/Spdx-Java-Library)

## Contributor Information

Expand Down
2 changes: 1 addition & 1 deletion deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
tolitius/xml-in {:mvn/version "0.1.1"}
hato/hato {:mvn/version "0.9.0"}
miikka/clj-base62 {:mvn/version "0.1.1"}
com.github.pmonks/clj-spdx {:mvn/version "1.0.88"}
com.github.pmonks/clj-spdx {:mvn/version "1.0.91"}
com.github.pmonks/rencg {:mvn/version "1.0.34"}}
:aliases
{:build {:deps {com.github.pmonks/pbr {:mvn/version "RELEASE"}}
Expand Down
45 changes: 27 additions & 18 deletions src/lice_comb/deps.clj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
[lice-comb.impl.data :as lcd]
[lice-comb.impl.utils :as lcu]))

;####TODO: FIGURE OUT HOW TO HANDLE METADATA FOR OVERRIDES / FALLBACKS!!!!
(def ^:private overrides-d (delay (lcd/load-edn-resource "lice_comb/deps/overrides.edn")))
(def ^:private fallbacks-d (delay (lcd/load-edn-resource "lice_comb/deps/fallbacks.edn")))

Expand All @@ -52,13 +53,17 @@
(when ga
[(symbol (first (s/split (str ga) #"\$"))) info]))

(defmulti dep->ids
"Attempt to detect the license(s) in a tools.deps style dep (a MapEntry or
two-element sequence of [groupId/artifactId dep-info])."
(defmulti dep->expressions
"Attempt to detect the SPDX license expression(s) (a set) in a tools.deps
style dep (a MapEntry or two-element sequence of
`[groupId/artifactId dep-info]`).
The result has metadata attached that describes how the identifiers in the
expression(s) were determined."
{:arglists '([[ga info]])}
(fn [[_ info]] (:deps/manifest info)))

(defmethod dep->ids :mvn
(defmethod dep->expressions :mvn
[dep]
(when dep
(let [[ga info] (normalise-dep dep)
Expand All @@ -67,35 +72,39 @@
(if-let [override (check-overrides ga version)]
override
(let [pom-uri (lcmvn/pom-uri-for-gav group-id artifact-id version)
license-ids (check-fallbacks ga
(if-let [license-ids (lcmvn/pom->ids pom-uri)]
license-ids
(lcu/nset (mapcat lcf/zip->ids (:paths info)))))] ; If we didn't find any licenses in the dep's POM, check the dep's JAR(s) too
license-ids)))))
expressions (check-fallbacks ga
(if-let [expressions (lcmvn/pom->expressions pom-uri)]
expressions
;####TODO: MERGE METADATA MAPS!!!!
(lcu/nset (mapcat lcf/zip->expressions (:paths info)))))] ; If we didn't find any licenses in the dep's POM, check the dep's JAR(s) too
expressions)))))

(defmethod dep->ids :deps
(defmethod dep->expressions :deps
[dep]
(when dep
(let [[ga info] (normalise-dep dep)
version (:git/sha info)]
(if-let [override (check-overrides ga version)]
override
(check-fallbacks ga (lcf/dir->ids (:deps/root info)))))))
(check-fallbacks ga (lcf/dir->expressions (:deps/root info)))))))

(defmethod dep->ids nil
(defmethod dep->expressions nil
[_])

(defmethod dep->ids :default
(defmethod dep->expressions :default
[dep]
(throw (ex-info (str "Unexpected manifest type '" (:deps/manifest (second dep)) "' for dependency " dep) {:dep dep})))
(throw (ex-info (str "Unexpected manifest type '" (:deps/manifest (second dep)) "' for dependency " dep)
{:dep dep})))

(defn deps-licenses
"Attempt to detect the license(s) in a tools.deps 'lib map', returning a new
lib map with the licenses assoc'ed in (in key :lice-comb/licenses)"
(defn deps-expressions
"Attempt to detect the SPDX license expression(s) in a tools.deps 'lib map',
returning a new lib map with the licenses assoc'ed in (in key
`:lice-comb/license-expressions`)"
[deps]
(when deps
(into {}
(pmap #(let [[k v] %] [k (assoc v :lice-comb/licenses (dep->ids [k v]))]) deps))))
;####TODO: CHECK WHETHER METADATA MAPS NEED TO BE MERGED!!!!
(pmap #(let [[k v] %] [k (assoc v :lice-comb/license-expressions (dep->expressions [k v]))]) deps))))

(defn init!
"Initialises this namespace upon first call (and does nothing on subsequent
Expand Down
49 changes: 31 additions & 18 deletions src/lice_comb/files.clj
Original file line number Diff line number Diff line change
Expand Up @@ -51,38 +51,51 @@
(throw (java.nio.file.NotDirectoryException. (str dir))))
(throw (java.io.FileNotFoundException. (str dir)))))))

(defn file->ids
"Attempts to determine the SPDX license identifier(s) (a set) from the given
(defn file->expressions
"Attempts to determine the SPDX license expression(s) (a set) from the given
file (an InputStream or something that can have an io/input-stream opened on
it). If an InputStream is provided, the associated filename should also be
provided as the second parameter (it is unnecessary in other cases)."
([f] (file->ids f (lcu/filename f)))
provided as the second parameter (it is unnecessary in other cases).
The result has metadata attached that describes how the identifiers in the
expression(s) were determined."
([f] (file->expressions f (lcu/filename f)))
([f fname]
(when (and f fname)
(let [fname (s/lower-case fname)]
(cond (= fname "pom.xml") (lcmvn/pom->ids f)
(s/ends-with? fname ".pom") (lcmvn/pom->ids f)
(cond (= fname "pom.xml") (lcmvn/pom->expressions f)
(s/ends-with? fname ".pom") (lcmvn/pom->expressions f)
:else (lcmtch/text->ids (io/input-stream f))))))) ; Default is to assume it's a plain text file containing license text(s)

(defn dir->ids
"Attempt to detect the license(s) in a directory. dir may be a String or a
java.io.File, both of which must refer to a directory."
(defn dir->expressions
"Attempt to detect the SPDX license expression(s) (a set) in a directory. dir
may be a String or a java.io.File, both of which must refer to a
readable directory.
The result has metadata attached that describes how the identifiers in the
expression(s) were determined."
[dir]
(when dir
(lcu/nset (mapcat file->ids (probable-license-files dir)))))
;####TODO: MERGE METADATA MAPS AND EMBELLISH :source!!!!
(lcu/nset (mapcat file->expressions (probable-license-files dir)))))

(defn zip->expressions
"Attempt to detect the SPDX license expression(s) in a ZIP file. zip may be a
String or a java.io.File, both of which must refer to a ZIP-format compressed
file.
(defn zip->ids
"Attempt to detect the license(s) in a ZIP file. zip may be a String or a
java.io.File, both of which must refer to a ZIP-format compressed file."
The result has metadata attached that describes how the identifiers in the
expression(s) were determined."
[zip]
(when zip
(let [zip-file (io/file zip)]
(java.util.zip.ZipFile. zip-file) ; This no-op forces validation of the zip file - ZipInputStream does not reliably perform validation
(with-open [zip-is (java.util.zip.ZipInputStream. (io/input-stream zip-file))]
(loop [licenses nil
entry (.getNextEntry zip-is)]
(loop [result #{}
entry (.getNextEntry zip-is)]
(if entry
(if (probable-license-file? entry)
(recur (set/union licenses (file->ids zip-is (lcu/filename entry))) (.getNextEntry zip-is))
(recur licenses (.getNextEntry zip-is)))
(doall (some-> (seq licenses) set)))))))) ; Realise the result before we exit the `with-open` scope
;####TODO: MERGE METADATA MAPS AND EMBELLISH :source!!!!
(recur (set/union result (file->expressions zip-is (lcu/filename entry))) (.getNextEntry zip-is))
(recur result (.getNextEntry zip-is)))
(doall (some-> (seq result) set)))))))) ; De-lazy the result before we exit the with-open scope
Loading

0 comments on commit eb41e92

Please sign in to comment.