-
Notifications
You must be signed in to change notification settings - Fork 14
/
update.clj
159 lines (138 loc) · 5.4 KB
/
update.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
(ns depot.outdated.update
(:require [clojure.tools.deps.alpha.reader :as reader]
[depot.outdated :as depot]
[rewrite-clj.zip :as rzip]
[clojure.zip :as zip]))
(defn zip-skip-ws
"Skip whitespace, comments, and uneval nodes."
[loc]
(loop [loc loc]
(if (and loc
(not (rzip/end? loc))
(#{:comment :whitespace :newline :comma :uneval} (rzip/tag loc)))
(recur (zip/right loc))
loc)))
(defn zright
"Like [[rewrite-clj.zip/right]], but also skip over uneval nodes"
[loc]
(some-> loc rzip/right zip-skip-ws))
(defn zget
"Like [[clojure.core/get]], but for a zipper over a map.
Takes and returns a zipper (loc)."
[loc key]
(rzip/right
(rzip/find-value (rzip/down loc) (comp zright zright) key)))
(defn update-loc?
"Should the version at the current position be updated?
Returns true unless any ancestor has the `^:depot/ignore` metadata."
[loc]
(not (rzip/find loc
rzip/up
(fn [loc]
(:depot/ignore (meta (rzip/sexpr loc)))))))
(defmacro with-print-namespace-maps [bool & body]
(if (find-var 'clojure.core/*print-namespace-maps*)
`(binding [*print-namespace-maps* ~bool]
~@body)
;; pre Clojure 1.9
`(do ~@body)))
(defn try-update-artifact
"Attempt to update a specific version in a `:deps` or `:extra-deps` map.
`loc` points at the artifact name (map key)."
[loc consider-types repos]
(if (update-loc? loc)
(let [artifact (rzip/sexpr loc)
coords-loc (zright loc)]
(if-let [latest (get (depot/current-latest-map artifact
(rzip/sexpr coords-loc)
{:consider-types consider-types
:deps-map repos})
"Latest")]
(if-let [[version-loc version-key]
(or (some-> (zget coords-loc :mvn/version) (vector :mvn/version))
(some-> (zget coords-loc :sha) (vector :sha)))]
(let [old-version (rzip/sexpr version-loc)]
(if (#{"RELEASE" "LATEST"} old-version) ;; ignore these Maven 2 legacy identifiers
loc
(do
(with-print-namespace-maps false
(println " " artifact (pr-str {version-key old-version}) "->" (pr-str {version-key latest})))
(rzip/left
(rzip/up
(rzip/replace version-loc latest))))))
loc)
loc))
loc))
(defn update-deps
"Update all deps in a `:deps` or `:extra-deps` map.
`loc` points at the map."
[loc consider-types repos]
(if-let [first-key (rzip/down loc)]
(rzip/up
(loop [loc first-key]
(let [loc' (try-update-artifact loc consider-types repos)
loc'' (zright (zright loc'))]
(if loc''
(recur loc'')
loc'))))
loc))
(defn zmap-vals
"Given a zipper pointing at a map, apply a tranformation to each value of the
map."
[loc f & args]
(let [loc' (rzip/down loc)]
(if loc'
(loop [keyloc loc']
(let [valloc (apply f (zright keyloc) args)]
(if-let [next-keyloc (zright valloc)]
(recur next-keyloc)
(rzip/up valloc))))
loc)))
(declare update-all)
(defn update-aliases
"Update all `:aliases`, expects a loc pointing at the `:aliases` map."
[loc consider-types repos]
(zmap-vals loc update-all consider-types repos))
(defn update-all
"Update all `:deps`, `:extra-deps`, and `:aliases`.
Expects a loc to the top level `deps.edn` map.
`consider-types` is a set, one of [[depot.outdated/version-types]].
`repos` is a map with optional keys `:mvn/repos` and `:mvn/local-repo`."
[loc consider-types repos]
(let [update-key (fn [loc k]
(if-let [deps-loc (zget loc k)]
(rzip/up (update-deps deps-loc consider-types repos))
loc))
loc (-> loc
(update-key :deps)
(update-key :extra-deps)
(update-key :override-deps))]
(if-let [aliases-loc (zget loc :aliases)]
(rzip/up (update-aliases aliases-loc consider-types repos))
loc)))
(defn update-deps-edn!
"Destructively update a `deps.edn` file.
Read a `deps.edn` file, update all dependencies in it to their latest version,
unless marked with `^:depot/ignore` metadata, then overwrite the file with the
updated version. Preserves whitespace and comments.
This will consider user and system-wide `deps.edn` files for locating Maven
repositories, but only considers the given file when determining current
versions.
`consider-types` is a set, one of [[depot.outdated/version-types]]. "
[file consider-types]
(println "Updating:" file)
(let [deps (-> (reader/clojure-env)
:config-files
reader/read-deps)
repos (select-keys deps [:mvn/repos :mvn/local-repo])
loc (rzip/of-file file)
old-deps (slurp file)
loc' (update-all loc consider-types repos)
new-deps (rzip/root-string loc')]
(when (and loc' new-deps) ;; defensive check to prevent writing an empty deps.edn
(if (= old-deps new-deps)
(println " All up to date!")
(try
(spit file new-deps)
(catch java.io.FileNotFoundException e
(println " [ERROR] Permission denied: " file)))))))