diff --git a/changes.md b/changes.md index dce41318..b0fb199c 100644 --- a/changes.md +++ b/changes.md @@ -1,3 +1,10 @@ +## Changes from 1.2.0 to 1.2.1 + +#### Bugfixes + +* Fail when inferred source paths overlap with each other. + * Closes https://github.com/jonase/eastwood/issues/428 + ## Changes from 1.1.1 to 1.2.0 #### New diff --git a/src/eastwood/lint.clj b/src/eastwood/lint.clj index a96cbd55..0d0f7743 100644 --- a/src/eastwood/lint.clj +++ b/src/eastwood/lint.clj @@ -497,6 +497,8 @@ (-> s (.contains "target")) ;; https://github.com/jonase/eastwood/issues/409 (-> s (.contains ".gitlibs")))))) + (distinct) + (util/assert-no-dir-supersets) (set)) :test-paths #{}})) diff --git a/src/eastwood/util.clj b/src/eastwood/util.clj index 58b74008..3b4c0856 100644 --- a/src/eastwood/util.clj +++ b/src/eastwood/util.clj @@ -1245,15 +1245,42 @@ of these kind." (some exclude-linters--internal) boolean)) +(defn parent-dirs-set [f] + (->> f + (iterate (fn [^File f] + (some-> f .getCanonicalPath File. .getParent File.))) + (take-while some?) + (set))) + +(defn dir-superset? [^File candidate, other] + (if (->> [candidate other] + (map (fn [^File f] + (-> f .getCanonicalPath))) + (apply =)) + ;; In theory an x is a superset of itself, but we'll disregard that - + ;; we prefer to accept a duplicate entry over a confusing error message: + false + (boolean (some #{(-> candidate .getCanonicalPath File.)} + (parent-dirs-set other))))) + +(defn assert-no-dir-supersets [source-paths] + (doseq [candidate source-paths] + (doseq [other (remove #{candidate} source-paths)] + (when (dir-superset? candidate other) + (throw (ex-info (format "Inferred :source-path from resource `%s` which is a superset of resource `%s`. +Resource directories shouldn't overlap with each other, otherwise there would be an important ambiguity. +Eastwood cannot continue." + candidate + other) + {:superset candidate + :subset other}))))) + source-paths) + (defn dir-outside-root-dir? [^File f] {:pre [(-> f .isDirectory)]} (let [f (-> f .getCanonicalPath File.) root-dir (File. (System/getProperty "user.dir")) - parent-dirs (->> f - (iterate (fn [^File f] - (some-> f .getCanonicalPath File. .getParent File.))) - (take-while some?) - (set))] + parent-dirs (parent-dirs-set f)] (not (parent-dirs root-dir)))) (defn ast->ns [ast] diff --git a/test/eastwood/util_test.clj b/test/eastwood/util_test.clj index 1efbc9e0..f578f358 100644 --- a/test/eastwood/util_test.clj +++ b/test/eastwood/util_test.clj @@ -74,3 +74,24 @@ (File. ".") false (File. "src") false (File. "/") true)) + +(deftest dir-superset? + (are [candidate other expected] (testing [candidate other] + (is (= expected + (sut/dir-superset? (File. candidate) (File. other)))) + true) + "/" "." true + "/" "src" true + "/" "src/eastwood" true + ;; In theory an x is a superset of itself, but we'll disregard that - + ;; we prefer to accept a duplicate entry over a confusing error message: + "/" "/" false + "." "." false + "src" "src" false + "src/eastwood" "src/eastwood" false + + "." "src" true + "src" "." false + "src" "test" false + "src/eastwood" "src" false + "src" "src/eastwood" true))