Skip to content

Commit fc10591

Browse files
committed
x
1 parent b77370f commit fc10591

File tree

11 files changed

+141
-19
lines changed

11 files changed

+141
-19
lines changed

project.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
:resource-paths ["test-resources-extra"
129129
"test-resources"]}
130130

131-
:refactor-nrepl {:dependencies [[refactor-nrepl "3.3.2"]
131+
:refactor-nrepl {:dependencies [[refactor-nrepl "3.4.1"]
132132
[nrepl "0.9.0"]]
133133
;; cider-nrepl is a :provided dependency from refactor-nrepl.
134134
:plugins [[cider/cider-nrepl "0.28.2" :exclusions [nrepl]]]}

src/formatting_stack/branch_formatter.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
(pretty-printer/new {}))
8383

8484
(defn format-and-lint-branch! [& {:keys [target-branch in-background? reporter]
85-
:or {target-branch "master"
85+
:or {target-branch (strategies/default-branch-name)
8686
in-background? (not (System/getenv "CI"))
8787
reporter default-reporter}}]
8888
(let [default-strategies [(fn [& {:as options}]
@@ -97,7 +97,7 @@
9797
:in-background? in-background?)))
9898

9999
(defn lint-branch! [& {:keys [target-branch in-background? reporter]
100-
:or {target-branch "master"
100+
:or {target-branch (strategies/default-branch-name)
101101
in-background? false
102102
reporter default-reporter}}]
103103
(let [default-strategies [(fn [& {:as options}]

src/formatting_stack/linters/ns_aliases.clj

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
"Observes these guidelines: https://stuartsierra.com/2015/05/10/clojure-namespace-aliases"
33
(:require
44
[clojure.string :as string]
5+
[formatting-stack.linters.ns-aliases.impl :as impl]
56
[formatting-stack.protocols.linter :as linter]
6-
[formatting-stack.util :refer [ensure-coll ensure-sequential process-in-parallel!]]
7+
[formatting-stack.strategies :as strategies]
8+
[formatting-stack.util :refer [ensure-sequential process-in-parallel!]]
79
[nedap.utils.modular.api :refer [implement]]))
810

911
(defn clause= [a b]
@@ -88,8 +90,17 @@
8890
:source :formatting-stack/ns-aliases})))))
8991
(mapcat ensure-sequential)))
9092

91-
(defn new [{:keys [acceptable-aliases-whitelist]
92-
:or {acceptable-aliases-whitelist default-acceptable-aliases-whitelist}}]
93+
(defn new
94+
"If `:augment-acceptable-aliases-whitelist?` is true,
95+
all aliases already used in your current project (as Git status and branch info indicates) will be deemed acceptable."
96+
[{:keys [acceptable-aliases-whitelist
97+
augment-acceptable-aliases-whitelist?]
98+
:or {acceptable-aliases-whitelist default-acceptable-aliases-whitelist
99+
augment-acceptable-aliases-whitelist? true}}]
93100
(implement {:id ::id
94-
:acceptable-aliases-whitelist acceptable-aliases-whitelist}
101+
:acceptable-aliases-whitelist
102+
(cond-> acceptable-aliases-whitelist
103+
(and augment-acceptable-aliases-whitelist?
104+
impl/namespace-aliases-for*)
105+
(impl/merge-aliases (impl/project-aliases {:cache-key (strategies/current-branch-name)})))}
95106
linter/--lint! lint!))
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
(ns formatting-stack.linters.ns-aliases.impl
2+
(:require
3+
[clojure.set :as set]
4+
[clojure.spec.alpha :as spec]
5+
[formatting-stack.strategies :as strategies]
6+
[nedap.speced.def :as speced])
7+
(:import
8+
(java.io File)))
9+
10+
(spec/def ::alias (spec/or :simple-alias symbol?
11+
:directive keyword?))
12+
13+
(spec/def ::aliases (spec/coll-of ::alias :kind vector?))
14+
15+
(spec/def ::project-aliases (spec/map-of symbol? ::aliases))
16+
17+
(speced/defn ^::project-aliases merge-aliases [^::project-aliases m1, ^::project-aliases m2]
18+
(merge-with (fn [x y]
19+
(vec (reduce into #{} [x y])))
20+
m1
21+
m2))
22+
23+
(def namespace-aliases-for*
24+
"Not available if not using refactor-nrepl >= 3.4.1."
25+
(when-let [f (try
26+
(requiring-resolve 'refactor-nrepl.ns.libspecs/namespace-aliases-for)
27+
(catch Exception _
28+
nil))]
29+
@f))
30+
31+
(defn namespace-aliases-for [files]
32+
(when namespace-aliases-for*
33+
(let [{:keys [clj cljs]} (namespace-aliases-for* files true)]
34+
(merge-aliases clj cljs))))
35+
36+
;; NOTE: this isn't necessarily a "strategy" (which would reside in the `strategies` ns),
37+
;; since it's composed of other strategy calls.
38+
;; This is more of a handy helper at the moment.
39+
(defn stable-files
40+
"Files that already existed as of the default branch,
41+
and that haven't been touched in the current branch"
42+
[]
43+
(let [with (set (strategies/all-files :files []))
44+
without (reduce into #{} [(strategies/git-diff-against-default-branch :files [])
45+
(strategies/git-completely-staged :files [])
46+
(strategies/git-not-completely-staged :files [])])
47+
corpus (set/difference with without)]
48+
(->> corpus
49+
(mapv (speced/fn [^String s]
50+
(File. s))))))
51+
52+
(def project-aliases (memoize
53+
(fn [{_cache-key :cache-key}] ;; there's a cache key for correct memoization
54+
55+
;; note that memoizing results is correct -
56+
;; results don't have to be recomputed as the git status changes:
57+
;; touching more files doesn't alter the fact that these aliases already were existing.
58+
(namespace-aliases-for (stable-files)))))

src/formatting_stack/processors/test_runner.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[clojure.test]
99
[formatting-stack.processors.test-runner.impl :refer [ns->sym testable-namespaces]]
1010
[formatting-stack.protocols.processor :as processor]
11-
[formatting-stack.strategies :refer [git-completely-staged git-diff-against-default-branch git-not-completely-staged]]
11+
[formatting-stack.strategies :as strategies :refer [git-completely-staged git-diff-against-default-branch git-not-completely-staged]]
1212
[nedap.utils.modular.api :refer [implement]]))
1313

1414
;; Not provided into any default stack, as it would be overly assuming about users' practices
@@ -32,7 +32,7 @@
3232
Out of those files, namespaces are derived (1:N, using smart heuristics),
3333
and those namespaces are run via `#'clojure.test/run-tests`."
3434
[& {:keys [target-branch]
35-
:or {target-branch "master"}}]
35+
:or {target-branch (strategies/default-branch-name)}}]
3636
(let [filenames (->> (git-diff-against-default-branch :target-branch target-branch)
3737
(concat (git-completely-staged :files []))
3838
(concat (git-not-completely-staged :files []))

src/formatting_stack/strategies.clj

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
A strategy may not return nil."
1414
(:require
15+
[clojure.java.shell :refer [sh]]
1516
[clojure.string :as string]
1617
[clojure.tools.namespace.repl :as tools.namespace.repl]
1718
[formatting-stack.protocols.spec :as protocols.spec]
@@ -27,7 +28,7 @@
2728
(def git-command "git")
2829

2930
(speced/defn all-files
30-
"This strategy unconditionally processes all files."
31+
"This strategy unconditionally processes all Clojure and ClojureScript files."
3132
[& {:keys [^::protocols.spec/filenames files]}]
3233
;; This first `binding` is necessary for obtaining an absolutized list of deletions
3334
(binding [impl/*skip-existing-files-check?* true]
@@ -80,11 +81,33 @@
8081
(impl/extract-clj-files)
8182
(into files)))
8283

84+
(defn current-branch-name []
85+
(-> (sh "git" "rev-parse" "--abbrev-ref" "HEAD")
86+
(:out)
87+
(string/split-lines)
88+
(first)))
89+
90+
(defn default-branch-name []
91+
(let [all-branches (->> (sh "git" "branch")
92+
:out
93+
string/split-lines
94+
(map (fn [s]
95+
(-> s (string/split #"\s+") last)))
96+
(set))]
97+
98+
(or (reduce (fn [_ branch]
99+
(when (contains? all-branches branch)
100+
(reduced branch)))
101+
nil
102+
["master" "main" "stable" "dev"])
103+
;; return something, for not breaking code that traditionally assumed "master":
104+
"master")))
105+
83106
(defn git-diff-against-default-branch
84107
"This strategy processes all files that this branch has modified.
85108
The diff is compared against the `:target-branch` option."
86109
[& {:keys [target-branch impl files blacklist]
87-
:or {target-branch "master"
110+
:or {target-branch (default-branch-name)
88111
;; We filter for Added, Copied, Modified and Renamed files,
89112
;; excluding Unmerged, Deleted, Type-changed, Broken (pair), and Unknown files
90113
impl (impl/file-entries git-command "diff" "--name-only" "--diff-filter=ACMR" target-branch "--")

test/functional/formatting_stack/linters/ns_aliases.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
[matcher-combinators.test :refer [match?]]))
77

88
(deftest lint!
9-
(let [linter (sut/new {:max-lines-per-ns 4})]
9+
(let [linter (sut/new {:max-lines-per-ns 4
10+
:augment-acceptable-aliases-whitelist? false})]
1011
(are [filename expected] (match? expected
1112
(linter/lint! linter [filename]))
1213
"test-resources/valid_syntax.clj"

test/integration/formatting_stack/strategies.clj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,14 @@
167167
;; Creating a file which collides with a ref, should not impact #'sut/git-diff-against-default-branch
168168
;; see https://git.io/JKG8m
169169
(let [git-sha-named-file (io/file git-integration-dir @root-commit)]
170-
(try
170+
(try
171171
;; creating a file with a filename which collides with a sha.
172-
(spit git-sha-named-file creatable-contents)
173-
(expect-sane-output! (sut/git-diff-against-default-branch :target-branch @root-commit))
174-
(finally
175-
(sh "git" "reset" "--" @root-commit)
176-
(-> git-sha-named-file .delete)
177-
(cleanup-testing-repo!))))))
172+
(spit git-sha-named-file creatable-contents)
173+
(expect-sane-output! (sut/git-diff-against-default-branch :target-branch @root-commit))
174+
(finally
175+
(sh "git" "reset" "--" @root-commit)
176+
(-> git-sha-named-file .delete)
177+
(cleanup-testing-repo!))))))
178178

179179
(deftest git-not-completely-staged
180180

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(ns integration.formatting-stack.strategies.default-branch-name
2+
(:require
3+
[clojure.test :refer [deftest is]]
4+
[formatting-stack.strategies :as sut]))
5+
6+
;; This deftest lives in its own ns, for not having unrelated fixtures interfere
7+
(deftest default-branch-name
8+
(is (= "main" (sut/default-branch-name))))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(ns unit.formatting-stack.linters.ns-aliases.impl
2+
(:require
3+
[clojure.test :refer [are deftest]]
4+
[formatting-stack.linters.ns-aliases.impl :as sut]
5+
[matcher-combinators.matchers :as matchers]
6+
[matcher-combinators.test :refer [match?]]))
7+
8+
(deftest merge-aliases
9+
(are [m1 m2 expected] (match? expected
10+
(sut/merge-aliases m1 m2))
11+
{} {} {}
12+
{'a ['b]} {} {'a ['b]}
13+
{} {'a ['b]} {'a ['b]}
14+
{'a ['b]} {'a ['c]} {'a (matchers/in-any-order ['b 'c])}
15+
{'a ['b]} {'a ['b]} {'a ['b]}
16+
{'a ['b 'c] 'd ['e 'f]} {'a ['g 'h] 'd ['i 'j]} {'a (matchers/in-any-order ['b 'c 'g 'h])
17+
'd (matchers/in-any-order ['e 'f 'i 'j])}
18+
{'a ['b 'c] 'd ['e 'f]} {'a ['b 'c] 'd ['e 'f]} {'a (matchers/in-any-order ['b 'c])
19+
'd (matchers/in-any-order ['e 'f])}))

test/unit/formatting_stack/processors/test_runner/impl.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
(are [input expected] (= expected
3030
(sut/sut-consumers corpus input))
3131
(the-ns 'formatting-stack.strategies) [(the-ns 'integration.formatting-stack.strategies)
32+
(the-ns 'integration.formatting-stack.strategies.default-branch-name)
3233
(the-ns 'unit.formatting-stack.strategies)])))
3334

3435
(deftest permutations
@@ -72,4 +73,5 @@
7273
;; `sut` alias detection
7374
["src/formatting_stack/strategies.clj"]
7475
[(the-ns 'integration.formatting-stack.strategies)
76+
(the-ns 'integration.formatting-stack.strategies.default-branch-name)
7577
(the-ns 'unit.formatting-stack.strategies)]))

0 commit comments

Comments
 (0)