-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrelease_extension
executable file
·317 lines (277 loc) · 9.14 KB
/
release_extension
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#! /bin/bash -e
function make_zip () {
z="$1"
d="$2"
pushd "$d" > /dev/null
rm -f "$z"
touch "$z"
if
! zip -9 \
"${z}.part" \
`find -L -not -wholename "*/.svn*"` \
-x '*~' \
-x '#*'
then
rm -f "$z"
rm -f "${z}.part"
echo "Failed to create package $z!" >&2
exit 1
fi
chmod --reference="$z" "${z}.part"
mv "${z}.part" "$z"
popd > /dev/null
}
function exit_rm () {
rm -rf "$tmp"
exit 1
}
function version_newer () {
local old=$1
local new=$2
local _IFS=$IFS
IFS=.
local old_split=($old)
local new_split=($new)
IFS=$_IFS
local i
for i in 0 1 2 ; do
local o=${old_split[i]}
local n=${new_split[i]}
[[ $o = 0[1-9]* ]] && o=${o#0}
[[ $n = 0[1-9]* ]] && n=${n#0}
if (( o < n )) ; then
return 0
elif (( o > n )) ; then
return 1
fi
done
return 1
}
function get_size () {
du -L -sb --exclude '*/.svn*' --exclude '*~' --exclude '#*' "$dir" | cut -f1
}
if ((! $# )) || [[ $1 =~ --?h.* ]]; then
cat << '__HELP__'
release_extension -t TRED_PATH -u URL -m METHOD -r REMOTE [ -n NAME ] -d DIR -p VALIDATE [-1]
TRED_PATH: Path to the tred repository.
URL : URL of the extension repository.
REMOTE: The target url or directory (depends on METHOD).
NAME: Name of the extension. If not given, equals to DIR.
DIR: The dir containing the extension to release.
VALIDATE: Full path to pml_validate (if not in $PATH).
METHOD: How the REMOTE dir should be reached?
's' for sshfs, 'r' for rsync, 'l' for local (default).
-1: Use for the very first version of a package.
__HELP__
exit
fi
while getopts 't:u:r:n:d:p:m:1' option ; do
case $option in
(t) tred_path=$OPTARG ;;
(u) url=$OPTARG ;;
(r) remote=$OPTARG ;;
(n) name=$OPTARG ;;
(d) dir=$OPTARG ;;
(p) validate=$OPTARG ;;
(m) method=$OPTARG ;;
(1) first=1 ;;
(*) exit 1 ;;
esac
done
if [[ ${!OPTIND} ]] ; then
echo Invalid argument ${!OPTIND} >&2
exit 1
fi
if [[ -z $remote ]] ; then
echo Remote not specified >&2
exit 1
fi
if [[ -z $dir ]] ; then
echo Dir not specified >&2
exit 1
fi
dir=${dir%/}
# Set default values
: ${tred_path:=/net/work/people/$USER/tred/tred.git}
: ${url:=http://ufal.mff.cuni.cz/tred/extensions/external}
#: ${remote:=ufal:/usr/share/drupal7/legacy/tred/extensions/external}
: ${validate:=pml_validate}
: ${method:=l}
if [[ -z $name ]] ; then
name=${dir##*/}
fi
bindir=$(readlink -f ${0%/*})
meta="$dir"/package.xml
(
shopt -s nullglob
xmllint --noout "$meta" "$dir"/resources/*.xml
)
if which $validate &>/dev/null && $validate -c &>/dev/null; then
if ! $validate -p "$tred_path"/tred_refactored/resources "$meta"; then
which $validate
echo $validate -p "$tred_path"/tred_refactored/resources "$meta" >&2
echo "Package meta file $meta is not a valid PML tred_package instance!" >&2
exit 1
fi
else
echo "WARNING: will not validate package.xml (PML validator pml_validate not found in PATH or not working)" >&2
fi
pkgname=$(xmllint --shell "$meta" <<<'cat //*[name()="pkgname"]/text()' | grep -v '^/ >\|-----')
if [[ $pkgname != $name ]] ; then
echo "Invalid package name: $pkgname != $name." >&2
exit 1
fi
repository=$(xmllint --shell "$meta" <<<'cat //*[name()="repository"]/@href' \
| grep 'href=')
repository=${repository## }
repository=${repository%[\"\']}
repository=${repository%/}
if [[ $repository != href=[\'\"]${url%/} ]] ; then
echo 'Repository reference does not match url:' \
$'\n'"$repository vs. $url." >&2
exit 1
fi
dependencies_ok=1
while read dependency ; do
wget -q --max-redirect=0 --method=HEAD "$dependency"/package.xml || {
echo "Cannot GET $dependency" >&2
dependencies_ok=0
}
done < <(
xmllint --shell "$meta" <<< 'cat //*[name() = "extension"]/@href' \
| grep href= | cut -f2 -d'"' )
(( dependencies_ok )) || exit 1
icon=$(perl -ne 'print $1 if m{<icon>([^<]+)</icon>}' "$meta" /dev/null)
if [[ $icon ]] ; then
echo "Icon $icon" >&2
else
echo Icon not found. >&2
fi
size=
s=$(get_size)
while [[ $s != "$size" ]] ; do
size=$s
echo "Updating install size to: $size" >&2
perl -MXML::LibXML -e '
($f, $size) = @ARGV;
$p = XML::LibXML->new->parse_file($f);
if ($p->documentElement->getAttribute("install_size") != $size) {
$p->documentElement->setAttribute("install_size", "$size");
rename $f, $f . "~";
$p->toFile($f);
}' \
"$meta" $size;
s=$(get_size)
done
tmp=$(mktemp --tmpdir -d)
found=1
make_zip "$tmp"/new.zip "$dir" > /dev/null
mkdir "$tmp"/new
unzip -qd "$tmp"/new "$tmp"/new.zip
sed -i.~size~ 's, install_size="[0-9]*",,g' "$tmp"/new/package.xml
wget -qO "$tmp"/old.zip "$url/$name".zip || found=0
if [[ ! $first ]] ; then
if ((found)) ; then
mkdir "$tmp"/old
unzip -qd "$tmp"/old "$tmp"/old.zip
sed -i 's, install_size="[0-9]*",,g' "$tmp"/old/package.xml
fi
up_to_date=1
if ((!found)) || diff -Nur "$tmp/old" "$tmp/new" | grep -q . ; then
up_to_date=0
fi
if ((up_to_date)) ; then
echo PACKAGE "$name" IS UP-TO-DATE >&2
exit_rm
fi
fi
mv "$tmp"/new/package.xml{.~size~,}
if [[ ! $first ]] ; then
script='print $1 if m{<version>([0-9.]+)</version>}'
prev_ver=$(perl -ne "$script" "$tmp/old/package.xml" /dev/null)
pkg_ver=$(perl -ne "$script" "$meta")
rm -rf "$tmp"/old
if [[ -n $prev_ver && -n $pkg_ver ]] ; then
if [[ $prev_ver == $pkg_ver ]]; then
echo Version $pkg_ver not changed. >&2
exit_rm
elif version_newer $pkg_ver $prev_ver ; then
echo New version $pkg_ver precedes the old version $prev_ver. >&2
exit_rm
else
echo Version change: "$prev_ver -> $pkg_ver" >&2
fi
elif [[ -z $pkg_ver ]] ; then
echo No version specified. >&2
exit_rm
fi
fi
if [[ $first ]] ; then
if file "$tmp"/old.zip | grep -q Zip.archive.data ; then
echo Old package exists >&2
exit_rm
fi
fi
zip_size=$(du -sb "$tmp/new.zip" | cut -f1)
echo "Zip size: $zip_size" >&2
perl -MXML::LibXML -e '
$f = shift;
print STDERR "File: $f\n";
$p = XML::LibXML->new->parse_file($f);
$p->documentElement->setAttribute("package_size","'$zip_size'");
$p->toFile($f);
' "$tmp/new/package.xml"
wget -qO "$tmp"/extensions.lst "$url"/extensions.lst
if grep -Eq "^!? *$name *$" "$tmp"/extensions.lst ; then
echo $name already in list. >&2
else
echo Adding $name to list. >&2
echo "$name" >> "$tmp"/extensions.lst
fi
mkdir "$tmp"/remote
if [[ $method == s ]] ; then
echo Transfering "$tmp/remote" to "$remote"... >&2
sshfs "$remote" "$tmp"/remote
else
cp "$tmp"/extensions.lst "$tmp"/remote/
fi
new="$name.$HOSTNAME.$USER.$$"
[[ -d "$tmp"/remote/"$new" ]] && rm -rf "$tmp"/remote/"$new"
mkdir "$tmp"/remote/"$new"
if [[ -f "$tmp/new/$icon" ]] ; then
mkdir "$tmp"/remote/"$new"/icons/
fi
cp "$tmp"/new/package.xml "$tmp"/remote/"$new"/
[[ -f "$tmp/new/$icon" ]] && cp "$tmp"/new/"$icon" "$tmp"/remote/"$new"/icons/
[[ -d "$tmp"/new/documentation ]] && cp -r "$tmp"/new/documentation "$tmp"/remote/"$new"/
cp "$tmp"/extensions.lst "$tmp"/remote/extensions.lst."$new"
cp "$tmp"/new.zip "$tmp"/remote/"$name".zip."$new"
[[ -f "$tmp"/remote/"$name".zip ]] && cp "$tmp"/remote/"$name".zip "$tmp"/remote/old-"$new".zip
[[ -f "$tmp"/remote/"$name".zip ]] && rm "$tmp"/remote/"$name".zip
mv "$tmp"/remote/"$name".zip."$new" "$tmp"/remote/"$name".zip
[[ -d "$tmp"/remote/"$name" ]] && mv "$tmp"/remote/"$name" "$tmp"/remote/old-"$new"
mv "$tmp"/remote/"$new" "$tmp"/remote/"$name"
rm -rf "$tmp"/remote/old-"$new"
cp "$tmp"/remote/extensions.lst "$tmp"/remote/extensions.lst.old-"$new"
# Cannot mv here: permission denied if the owner is someone else
mv "$tmp"/remote/extensions.lst."$new" "$tmp"/remote/extensions.lst \
|| ( rm "$tmp"/remote/extensions.lst && mv "$tmp"/remote/extensions.lst."$new" "$tmp"/remote/extensions.lst )
rm -f "$tmp"/remote/old-"$new".zip "$tmp"/remote/extensions.lst.old-"$new"
case $method in
(s) fusermount -u "$tmp"/remote ;;
(l) cp -r "$tmp"/remote "$remote"/ ;;
(r) echo 'Running rsync...' >&2
rsync -avr "$tmp"/remote/ "$remote" || echo Ignoring friendly errors ;;
esac
rm -rf "$tmp"
echo "Package $zip successfully created!" >&2
# Verify
wget -q "$url/$name/package.xml" -O- | grep -F "<version>$pkg_ver</version>" || {
echo "$pkg_ver" not found in online package.xml >&2
exit_rm
}
size=$(wget -q -O- "$url/$name.zip" | wc -c)
((size == zip_size)) || {
echo Uploaded zip has a different size >&2
exit_rm
}