@@ -26,17 +26,20 @@ source mvn-tools || exit
26
26
# TODO: Support for deleted file detection:
27
27
# When a file is deleted from a source tree, the artifact should be
28
28
# added to the reactor and first cleaned.
29
+ # Support for pom artifacts:
30
+ # POM artifacts have no target/ directory to compare mtimes against.
29
31
30
32
31
33
# Functions.
32
34
# loadModules -- invoke whenever the modules array is needed.
33
35
loadModules () {
34
36
(( ${# modules[@]} )) && return
37
+ local profiles
35
38
36
39
# Build list of all modules allowed in the maven reactor.
37
- IFS=$' \n ' read -d ' ' -r -a profiles < <( xpathNodes ~ /.m2/settings.xml ' / settings/activeProfiles/activeProfile/text()' ) || :
40
+ IFS=$' \n ' read -d ' ' -r -a profiles < <( xmlstarlet sel -t -v ' /_: settings/_: activeProfiles/_: activeProfile/text()' ~ /.m2/settings.xml 2> /dev/null ) || :
38
41
emit " Enumerating modules in the Maven reactor" --
39
- modules=()
42
+ modules=(. )
40
43
addModules () {
41
44
grep -qF ' <module>' " $1 " || return 0
42
45
@@ -52,23 +55,26 @@ loadModules() {
52
55
53
56
done < <(
54
57
# Sub modules from the module's pom.xml's module list.
55
- xpathNodes " $1 " ' / project/modules/module/text()'
58
+ xmlstarlet sel -t -v ' /_: project/_: modules/_: module/text()' " $1 " 2> /dev/null || :
56
59
57
60
# Profile-enabled sub modules from the module's pom.xml's profiles module lists.
58
61
grep -qF ' <profile>' " $1 " && {
59
62
for profile in " ${profiles[@]} " ; do
60
- xpathNodes " $1 " " / project/profiles/profile/id[text()='$profile ']/../modules/module/text()"
63
+ xmlstarlet sel -t -v " /_: project/_: profiles/_: profile/_: id[text()='$profile ']/../_: modules/_: module/text()" " $1 " 2> /dev/null || :
61
64
done
62
65
}
63
66
)
64
67
}
65
68
addModules ./pom.xml
66
69
emit -$?
70
+
71
+ # printf ' - module: %s\n' "${modules[@]}" >&2
72
+ (( ${# modules[@]} ))
67
73
}
68
74
69
75
70
76
# Options.
71
- while getopts :aABcCdDfnr :h arg; do
77
+ while getopts :aABcCdDfn :h arg; do
72
78
case $arg in
73
79
a) autoFindArtifacts=1 ;;
74
80
A) resetArtifacts=1 ;;
@@ -79,7 +85,6 @@ while getopts :aABcCdDfnr:h arg; do
79
85
D) nodistribution=1 ;;
80
86
f) force=1 ;;
81
87
n) nodeploy=1 ;;
82
- r) remote=$OPTARG ;;
83
88
84
89
h) showHelp \
85
90
' Build and Deploy' \
@@ -96,16 +101,15 @@ while getopts :aABcCdDfnr:h arg; do
96
101
' -C' " Clean each artifact before building it (eg. when files were renamed/removed or to rebuild /lib)." \
97
102
' -d distribution' " The name in the reactor of the distribution artifact. (Default: [top dir name]-distribution)" \
98
103
' -D' " Do not try to build and deploy a distribution." \
104
+ ' -f' " Force default operations, no questions asked." \
99
105
' -n' " Do not try to deploy the distribution after building it."
100
- ' -r user@host' " Upload and deploy the distribution to user@host." \
101
106
102
107
exit ;;
103
108
esac
104
109
done
105
110
shift $(( OPTIND- 1 ))
106
111
107
112
# Validate parameters.
108
- [[ $remote ]] || emit -y " Missing remote"
109
113
distribution=${distribution:- ${PWD##*/ } -distribution}
110
114
[[ -e $distribution ]] || distribution=
111
115
(( nodistribution )) && distribution=
120
124
while (( ! nobuild )) ; do
121
125
122
126
if (( autoFindArtifacts )) ; then
123
- loadModules
127
+ loadModules || emit -r " No modules found. "
124
128
125
129
# Automatically find outdated artifacts.
126
130
emit " Scanning for outdated artifacts"
127
131
while read file; do
128
132
files=(" $file " )
129
- [[ $file = ./pom.xml ]] && files=(* /pom.xml)
133
+ # [[ $file = ./pom.xml ]] && files=(*/pom.xml)
130
134
131
135
for file in " ${files[@]} " ; do
132
136
target=$file
@@ -136,39 +140,53 @@ while (( ! nobuild )); do
136
140
target=${target# ./ }
137
141
138
142
# Only consider this target if it's in the module list.
139
- inArray " $target " " ${modules[@]} " || continue
143
+ inArray " $target " " ${modules[@]} " || {
144
+ # echo "Ignoring: $target, not a module." >&2
145
+ continue
146
+ }
140
147
141
148
emit " Adding (Outdated) : $bold$target$reset :$file "
142
149
targets+=(" $PWD /$target " )
143
150
done
144
- done < <( find . \
151
+ done < <( export -f latest
152
+ find . \
145
153
\( -type d ! \( -exec bash -c ' test -e "$1/pom.xml"' -- {} \; -o -name ' src' -o -path ' */src/*' \) -prune \) -o \
146
154
-name ' pom.xml' -exec bash -c '
147
155
shopt -s nullglob
148
- ref=( "${1%/pom.xml}"/target/*.{[jwe]ar,zip} )
156
+ ref=$(latest "${1%/pom.xml}"/target/*.{[jwe]ar,zip})
157
+ #printf "Candidate: %s <> %s" "$1" "$ref" >&2
149
158
if [[ -e $ref && $1 -nt $ref ]]; then
159
+ #echo ", outdated." >&2
150
160
echo "$1"
161
+ else
162
+ : #echo ", up-to-date." >&2
151
163
fi
152
164
:' -- {} \; -o \
153
165
! -type d -path ' */src/main/*' -exec bash -c '
154
166
shopt -s nullglob
155
167
for f; do
156
168
[[ ${f%%/src/main/*} != ${ref%/target/*} ]] && \
157
- ref=( "${f%%/src/main/*}"/target/*[.]{[jwe]ar,zip} )
169
+ ref=$(latest "${f%%/src/main/*}"/target/*[.]{[jwe]ar,zip})
158
170
if [[ ! -e $ref ]]; then
159
- continue
160
- # while [[ $f = */* && ! -e $f/pom.xml ]]
161
- # do f=${f%/*}; done
162
- # echo "$f"
171
+ # continue
172
+ while [[ $f = */* && ! -e $f/pom.xml ]]
173
+ do f=${f%/*}; done
174
+ echo "$f"
163
175
elif [[ $f -nt $ref ]]; then
164
176
echo "$f"
177
+ #echo "outdated: $f" >&2
178
+ else
179
+ : #echo "uptodate: $f, $ref" >&2
165
180
fi
166
181
done
167
182
:' -- {} + | sort -u)
168
183
fi
169
184
170
185
# Add manually specified targets.
171
186
opts=()
187
+ for profile in " ${profiles[@]} " ; do
188
+ opts+=(" -P$profile " )
189
+ done
172
190
for target; do
173
191
[[ $target = -* ]] && { opts+=(" $target " ); continue ; }
174
192
@@ -177,9 +195,10 @@ while (( ! nobuild )); do
177
195
done
178
196
cd " $root "
179
197
180
- (( ! ${# targets[@]} && ! force )) && {
181
- if ! ask -y! N ' No artifacts selected for build; build anyway?' ; then
182
- if (( nodeploy || nodistribution )) || ! ask -Y! n ' Continue deployment with existing build?' ; then
198
+ (( ! ${# targets[@]} )) && {
199
+ if (( force )) || ! ask -c ' y!N' ' No artifacts selected for build; build anyway?' ; then
200
+ if (( nodeploy || nodistribution || force )) || ! ask -c ' y!N' ' Continue deployment with existing build?' ; then
201
+ emit " No artifacts selected for build. Nothing to build or deploy."
183
202
exit
184
203
fi
185
204
@@ -209,35 +228,56 @@ while (( ! nobuild )); do
209
228
# Begin the build.
210
229
if (( ${# targets[@]} )) ; then
211
230
echo
212
- emit " Building"
213
- mvn -pl " $( printf ' %s,' " ${targets[@]} " ) " -npu -amd " ${opts[@]} " ${cleanAll: +clean} install & mvnpid=$!
231
+ if inArray . " ${targets[@]} " ; then
232
+ emit " Building with: mvn -npu " ${opts[@]} " ${cleanAll: +clean} install"
233
+ mvn -npu " ${opts[@]} " ${cleanAll: +clean} install & mvnpid=$!
234
+ else
235
+ emit " Building with: mvn -pl " $( printf ' %s,' " ${targets[@]} " ) " -npu -amd " ${opts[@]} " ${cleanAll: +clean} install"
236
+ mvn -pl " $( printf ' %s,' " ${targets[@]} " ) " -npu -amd " ${opts[@]} " ${cleanAll: +clean} install & mvnpid=$!
237
+ fi
214
238
(( clean && ! nodistribution )) && [[ -e $distribution ]] && ( sleep 10; kill -0 $mvnpid 2> /dev/null && rm -rf " $distribution /target/" ) & cleanpid=$!
215
- trap " kill $mvnpid $cleanpid 2>/dev/null" EXIT
239
+ trap " kill $mvnpid $cleanpid 2>/dev/null ||: " EXIT
216
240
wait $mvnpid
217
241
fi
218
242
219
243
break
220
244
done
221
245
222
246
if [[ -e $distribution ]] && (( ! nodeploy && ! nodistribution )) ; then
223
-
224
- # Upload the distribution.
225
247
echo
226
- emit " Shutting down remote distribution"
227
- ssh -qt " $remote " " $( printf ' s=%q/scripts/stop; [[ -e $s ]] || exit 0; "$s"' " ${src%%/* } " ) "
228
248
229
- emit " Unpacking distribution "
249
+ # Find the package
230
250
cd " $distribution /target/"
231
- unzip -uo " ${distribution##*/ } " -* .zip
232
- src=(" ${distribution##*/ } " -* /* /); src=(" ${src[@]%/ } " )
233
-
234
- emit " Uploading distribution to $remote "
235
- ssh -qt " $remote " " $( printf ' s=%q/scripts/stop; [[ -e $s ]] || exit 0; "$s" -w' " ${src%%/* } " ) "
236
- rsync -avP --delete-delay " ${src[@]} " " $remote " :" ${src%%/* } /"
237
-
238
- emit " (Re)Starting remote distribution"
239
- ssh -qt " $remote " " $( printf ' dist=%q
240
- "$dist/scripts/start" -f' " ${src%%/* } " ) "
251
+ shopt -s nullglob
252
+ package=(* .{[jwe]ar,zip})
253
+ shopt -u nullglob
254
+
255
+ # Handle the package
256
+ case $package in
257
+ * .zip)
258
+ emit " Unpacking distribution"
259
+ unzip -uo " $package "
260
+ src=(" ${distribution##*/ } " -* /* /); src=(" ${src[@]%/ } " )
261
+
262
+ emit " Shutting down remote distribution"
263
+ ssh -qt ${deployToPort: +-p " $deployToPort " } " $deployToHost " " $( printf ' bash -lc %q' " $( printf ' s=%q/scripts/stop; [[ -e $s ]] || exit 0; "$s"' " ${deployToPath:- ~} /${src%%/* } " ) " ) "
264
+
265
+ emit " Uploading distribution to $deployTo :${deployToPath:- ~} /${src%%/* } "
266
+ ssh -qt ${deployToPort: +-p " $deployToPort " } " $deployToHost " " $( printf ' bash -lc %q' " $( printf ' s=%q/scripts/stop; [[ -e $s ]] || exit 0; "$s" -w' " ${deployToPath:- ~} /${src%%/* } " ) " ) "
267
+ rsync -avP --delete-after -e " ssh ${deployToPort: +-p $deployToPort } " " ${src[@]} " " $deployToHost " :" ${deployToPath:- ~} /${src%%/* } /"
268
+
269
+ emit " (Re)Starting remote distribution"
270
+ ssh -qt ${deployToPort: +-p " $deployToPort " } " $deployToHost " " $( printf ' bash -lc %q' " $( printf ' dist=%q; "$dist/scripts/start" -f' " ${deployToPath:- ~} /${src%%/* } " ) " ) "
271
+ ;;
272
+ * .ear|* .war)
273
+ emit " Uploading package to $deployTo :${deployToPath:- ~} /$package "
274
+ rsync -avP --delete-after -e " ssh ${deployToPort: +-p $deployToPort } " " $package " " $deployToHost " :" ${deployToPath:- ~} "
275
+ ;;
276
+
277
+ * )
278
+ emit -R " Don't know how to handle package: $package "
279
+ ;;
280
+ esac
241
281
fi
242
282
243
283
# Print timestamp.
0 commit comments