-
Notifications
You must be signed in to change notification settings - Fork 0
/
version-timestamps.sh
executable file
·186 lines (172 loc) · 4.99 KB
/
version-timestamps.sh
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/bin/sh
#
# This is free and unencumbered software released into the public domain.
# See the UNLICENSE file for details.
#
# ------------------------------------------------------------------------
# version-timestamps.sh
# ------------------------------------------------------------------------
# Gets timestamps for the last time a component was released.
#
# For each G:A:V argument passed to the script,
# there is one line of output, formatted as follows:
#
# G:A:V releaseTimestamp lastDeployed
# --------------------------------------------------------------
# Set the M2_REPO_PATH variable to the desired Maven repository.
# This can be a remote repository, or a local file path.
# --------------------------------------------------------------
test "$M2_REPO_PATH" && repo=$M2_REPO_PATH ||
repo=https://maven.scijava.org/content/groups/public
# G=groupId, A=artifactId, V=version
processGAV() {
debug processGAV $@
g=$1; a=$2; v=$3
releaseTimestamp=$(releaseTimestamp "$g" "$a" "$v")
latestVersion=$(latestVersion "$g" "$a")
case "$latestVersion" in
*-SNAPSHOT)
lastDeployed=$(snapshotTimestamp "$g" "$a" "$latestVersion")
;;
*)
lastDeployed=$(releaseTimestamp "$g" "$a" "$latestVersion")
;;
esac
echo "$g:$a:$v $releaseTimestamp $lastDeployed"
}
# Given a release GAV, discerns when it was deployed.
releaseTimestamp() {
debug releaseTimestamp $@
g=$1; a=$2; v=$3
case "$repo" in
/*) # LOCAL
# Obtain timestamp from the local file system.
# Much faster than doing a remote call via cURL.
for f in "$repo"/*/"$(gpath "$g")/$a/$v/$a-$v.pom"
do
test -f "$f" &&
# NB: We assume GNU stat here, for now!
formatTimestamp "$(stat -c %y "$f")" ||
# No file; probably no such release.
echo 0
done | sort | tail -n1
;;
*) # REMOTE
# Query the POM's HTTP header for the last modified time.
url="$repo/$(gpath "$g")/$a/$v/$a-$v.pom"
debug "releaseTimestamp: url -> $url"
modified=$(curl -Ifs "$url" | grep '^Last-Modified' | sed 's/^[^ ]* //')
debug "releaseTimestamp: modified -> $modified"
test "$modified" &&
formatTimestamp "$modified" ||
# Invalid URL; probably no such release.
echo 0
;;
esac
}
# Given a GA, discerns the latest version (snapshot or release).
latestVersion() {
debug latestVersion $@
# Extract <versioning><latest> value.
extractTag latest $@
}
# Given a GAV, discerns when that snapshot was last deployed.
snapshotTimestamp() {
debug snapshotTimestamp $@
g=$1; a=$2; v=$3
# Extract <versioning><snapshot><timestamp> value.
extractTag timestamp "$g" "$a/$v" | tr -d '.'
}
# Given a GA(V), extracts an XML tag from local or remote maven-metadata.xml.
extractTag() {
debug extractTag $@
tag=$1; g=$2; av=$3
case "$repo" in
/*) # LOCAL
# Extract tag value from each maven-metadata.xml.
# Then sort and take the last entry as newest.
for f in "$repo"/*/"$(gpath "$g")/$av/maven-metadata.xml"
do
cat "$f" | tagValue "$tag"
done | sort | tail -n1
;;
*) # REMOTE
# Extract versioning/latest from the remote metadata.
metadata=$(downloadMetadata "$g" "$av")
tagValue=$(echo "$metadata" | tagValue "$tag")
debug "extractTag: $tag -> $tagValue"
test "$tagValue" || die 1 "No $tag tag in metadata:\n$metadata"
echo "$tagValue"
;;
esac
}
# Downloads maven-metadata.xml from the remote repository as needed.
downloadMetadata() {
debug downloadMetadata $@
g=$1; av=$2
url="$repo/$(gpath "$g")/$av/maven-metadata.xml"
test "$cachedMetadata" || cachedMetadata=$(curl -fs "$url")
test "$cachedMetadata" || die 2 "Cannot access metadata remotely from: $url"
debug "downloadMetadata: cachedMetadata ->\n$cachedMetadata"
echo "$cachedMetadata"
}
# Clears the contents of downloaded maven-metadata.xml.
clearMetadataCache() {
debug clearMetadataCache $@
unset cachedMetadata
}
# Converts dot-separated groupId into slash-separated form.
gpath() {
debug gpath $@
echo "$1" | tr '.' '/'
}
# Converts a timestamp to YYYYmmddHHMMSS format.
formatTimestamp() {
debug formatTimestamp $@
# Grr, BSD date vs. GNU date!
# On macOS, you must `brew install coreutils`.
which gdate >/dev/null &&
gdate -d "$1" +%Y%m%d%H%M%S ||
date -d "$1" +%Y%m%d%H%M%S
}
# Extract the CDATA of the given element.
tagValue() {
# NB: I would love to use xmllint --xpath for this, but it
# segfaulted in some of my tests. So we go low tech instead.
debug tagValue $@
grep "<$1>" | sed "s_.*<$1>\(.*\)</$1>.*_\1_"
}
# Exits the script with an error code + message.
die() {
debug die $@
echo "$2" 1>&2
exit $1
}
debug() {
test "$DEBUG" && echo "[DEBUG] $@" 1>&2
}
# ----
# Main
# ----
while test $# -gt 0
do
clearMetadataCache
case "$1" in
*:*:*)
gav=$1
g=${gav%%:*}
rest=${gav#*:}
a=${rest%%:*}
v=${rest#*:}
cacheFile=.cache/"version-timestamps-$g-$a-$v"
if [ -f "$cacheFile" ]; then cat "$cacheFile"
elif [ -d .cache ]; then processGAV "$g" "$a" "$v" | tee "$cacheFile"
else processGAV "$g" "$a" "$v"
fi
;;
*)
echo "[WARNING] Ignoring invalid argument: $1" 2>&1
;;
esac
shift
done