]>
Commit | Line | Data |
---|---|---|
5a34afb9 JR |
1 | #!/bin/bash |
2 | ||
3 | [[ "${BASH_SOURCE[0]}" != "${0}" ]] || set -e -u | |
4 | ||
5 | ### Globals: | |
6 | ||
7 | declare -r gitroot=https://raw.githubusercontent.com/apertium | |
8 | declare -ar pmodules=(trunk staging nursery incubator) | |
9 | declare -ar lmodules=(languages incubator) | |
10 | ||
11 | declare -r svnroot_giella=https://victorio.uit.no/langtech/trunk | |
12 | ||
13 | ||
14 | ### Functions: | |
15 | discover_url_apertium () { | |
16 | local -r dir=$1 | |
17 | local url= | |
18 | local -a modules | |
19 | if [[ ${dir} = *-*-* ]]; then | |
20 | modules=( "${pmodules[@]}" ) | |
21 | else | |
22 | modules=( "${lmodules[@]}" ) | |
23 | fi | |
24 | for module in "${modules[@]}"; do | |
25 | submodules=$(curl -Ss --fail "${gitroot}/apertium-${module}/master/.gitmodules") | |
26 | # url="${svnroot}${module}/${dir}" | |
27 | if url=$(grep "[[:space:]]*url = .*/${dir}.git$" <<<"${submodules}"); then | |
28 | url=${url#*url = } | |
29 | # TODO: Option to use ssh urls? | |
30 | url=${url/git@github.com:/https:\/\/github.com\/} | |
31 | echo "Assuming git url of ${dir} is ${url}" >&2 | |
32 | echo "${url}" | |
33 | return 0 | |
34 | fi | |
35 | done | |
36 | echo "WARNING: Couldn't find git url of ${dir}" >&2 | |
37 | if ! msg=$(curl -Ss --fail "${gitroot}/apertium-languages/master/.gitmodules"); then | |
38 | printf "\n%s\n\n" "${msg}" >&2 | |
39 | echo "You may want to see http://wiki.apertium.org/wiki/Using_SVN#Host_not_found_when_using_proxy" >&2 | |
40 | echo "or make sure you have a working internet connection." >&2 | |
41 | fi | |
42 | return 1 | |
43 | } | |
44 | discover_url_giella () { | |
45 | local -r dir=$1 | |
46 | local -r url="${svnroot_giella}/${dir}" | |
47 | echo "Assuming SVN url of ${dir} is ${url}" >&2 | |
48 | echo "${url}" | |
49 | } | |
50 | ||
51 | dir_of_dep () { | |
52 | if [[ $1 = giella-* ]]; then | |
53 | echo "langs/${1##giella-}" | |
54 | else | |
55 | echo "$1" | |
56 | fi | |
57 | } | |
58 | bins_of_dep () { | |
59 | if [[ $1 = giella-* ]]; then | |
60 | echo "langs/${1##giella-}/tools/mt/apertium" | |
61 | else | |
62 | echo "$1" | |
63 | fi | |
64 | } | |
65 | ||
66 | make_dep () { | |
67 | local -r dep=$1 | |
68 | local -r dir=$(dir_of_dep "${dep}") | |
69 | # Let cwd be GTHOME from here on in; langs should exist under this dir: | |
70 | GTHOME=$(pwd) | |
71 | GTCORE=$GTHOME/gtcore | |
72 | export GTHOME | |
73 | export GTCORE | |
74 | ( | |
75 | cd "${dir}" | |
76 | pwd | |
77 | ./autogen.sh | |
78 | if [[ ${dep} = giella-* ]]; then | |
79 | ./configure --enable-apertium --with-hfst --enable-syntax | |
80 | V=1 make # giella so memory hungry, -j1 | |
81 | elif [[ ${dep} = gtcore ]]; then | |
82 | ./configure | |
83 | make -j3 | |
84 | else | |
85 | make -j3 | |
86 | fi | |
87 | ) | |
88 | } | |
89 | ||
90 | is_dep_updated () { | |
91 | local -r dep=$1 | |
92 | local -r dir=$(dir_of_dep "${dep}") | |
93 | if [[ -d ${dir} ]]; then | |
94 | if [[ -d "${dir}/.git" ]]; then | |
95 | if [[ -z "$(cd "${dir}" && git fetch --dry-run)" ]]; then | |
96 | echo yes | |
97 | return 0 | |
98 | else | |
99 | echo no | |
100 | return 0 | |
101 | fi | |
102 | fi | |
103 | if [[ -z $(svn status -qu "${dir}") ]]; then | |
104 | echo yes | |
105 | return 0 | |
106 | fi | |
107 | fi | |
108 | echo no | |
109 | } | |
110 | ||
111 | get_dep () { | |
112 | local -r depth=$1 | |
113 | local -r dep=$2 | |
114 | local -r dir=$(dir_of_dep "${dep}") | |
115 | local url= | |
116 | if [[ -d ${dir} ]]; then | |
117 | ( | |
118 | cd "${dir}" | |
119 | printf "Updating existing %s (%s)\n" "${dir}" "$(pwd)" | |
120 | if [[ -d .git ]]; then | |
121 | git pull | |
122 | else | |
123 | svn up | |
124 | fi | |
125 | ) | |
126 | else | |
127 | if [[ ${dep} = giella-* || ${dep} = gtcore ]]; then | |
128 | url=$(discover_url_giella "${dir}") && svn checkout "${url}" "${dir}" | |
129 | else | |
130 | url=$(discover_url_apertium "${dir}") && if [[ $depth -gt 0 ]]; then | |
131 | git clone --depth "${depth}" "${url}" "${dir}" | |
132 | else | |
133 | git clone "${url}" "${dir}" | |
134 | fi | |
135 | fi | |
136 | fi | |
137 | } | |
138 | ||
139 | in_array () { | |
140 | local e | |
141 | for e in "${@:2}"; do | |
142 | [[ "$e" == "$1" ]] && return 0 | |
143 | done | |
144 | return 1 | |
145 | } | |
146 | ||
147 | get_pair () { | |
148 | local -r depth=$1 | |
149 | local -r keep_going=$2 | |
150 | local -r skip_if_up_to_date=$3 | |
151 | local -r pair=apertium-${4##apertium-} | |
152 | # shellcheck disable=SC2124 | |
153 | local -r skip="${@:5}" # intentionally assigning array to string | |
154 | ||
155 | if [[ ${skip_if_up_to_date} == true && $(is_dep_updated "${pair}") == "yes" ]]; then | |
156 | printf "Existing pair %s is already up to date. Skipping build step.\\n" "${pair}" | |
157 | return 0 | |
158 | fi | |
159 | ||
160 | get_dep "${depth}" "${pair}" | |
161 | # Mac has ancient bash, so no declare -A for us | |
162 | local -a deps=() | |
163 | local -a depn=() | |
164 | while read -r n dep; do | |
165 | local orglang | |
166 | orglang=$(split_org_langs "${dep}") | |
167 | local lang=${orglang##* } | |
168 | # shellcheck disable=SC2068 | |
169 | if in_array "${lang}" ${skip[@]}; then # intentionally unquoted skip | |
170 | echo | |
171 | echo "Skipping data ${dep} as instructed." | |
172 | echo | |
173 | else | |
174 | deps+=( "${dep}" ) | |
175 | depn+=( "${n}" ) | |
176 | fi | |
177 | done < <(awk -F'[][[:space:]]+' '/^ *AP_CHECK_LING\(/ && $2 && $4 {print $2, $4}' "${pair}"/configure.ac) | |
178 | ||
179 | if [[ ${#deps[@]} -ne 0 ]]; then | |
180 | for dep in "${deps[@]}"; do | |
181 | if ! get_data "${depth}" "${skip_if_up_to_date}" "${keep_going}" "${dep}"; then | |
182 | echo | |
183 | echo "WARNING: Couldn't get dependency ${dep}; pair ${pair} might not get set up correctly." | |
184 | echo | |
185 | if ${keep_going}; then | |
186 | echo "WARNING: Continuing on as if nothing happened ..." | |
187 | echo | |
188 | sleep 1 | |
189 | else | |
190 | exit 1 | |
191 | fi | |
192 | fi | |
193 | done | |
194 | fi | |
195 | cd "${pair}" | |
196 | autogen="./autogen.sh " | |
197 | for i in "${!depn[@]}"; do | |
198 | binsdir=$(bins_of_dep "${deps[i]}") | |
199 | autogen="${autogen} --with-lang${depn[i]}=../${binsdir}" | |
200 | done | |
201 | ${autogen} | |
202 | make -j3 | |
203 | make test || echo "make test failed, but that's probably fine." | |
204 | ||
205 | cat <<EOF | |
206 | ||
207 | All done! | |
208 | ||
209 | You can now "cd ${pair}" or one of the dependencies, edit some files | |
210 | and type "make -j3 langs" to compile again. | |
211 | ||
212 | EOF | |
213 | } | |
214 | ||
215 | split_org_langs () { | |
216 | local -r org=$( if [[ $1 = giella-* ]]; then echo giella; else echo apertium; fi ) | |
217 | local -r langs=${1#${org}-} | |
218 | echo "${org} ${langs}" | |
219 | } | |
220 | ||
221 | maybe_symlink_GTHOME () { | |
222 | if [[ -d $1 ]]; then | |
223 | echo | |
224 | echo "Found $1 here, using that." | |
225 | echo | |
226 | elif [[ -z ${GTHOME+x} ]]; then | |
227 | echo | |
228 | echo "GTHOME is unset; will have to build $1 without it." | |
229 | echo | |
230 | elif [[ -d $GTHOME/$1 ]]; then | |
231 | echo | |
232 | echo "Found $1 in your \$GTHOME, symlinking to that to avoid recompilation." | |
233 | echo | |
234 | test -d langs || mkdir langs | |
235 | ln -sf "$GTHOME/$1" "$1" | |
236 | else | |
237 | echo | |
238 | echo "GTHOME is set but there is no $GTHOME/$1; will have to build $1 from scratch." | |
239 | echo | |
240 | fi | |
241 | } | |
242 | ||
243 | get_data () { | |
244 | local -r depth=$1 | |
245 | local -r keep_going=$2 | |
246 | local -r skip_if_up_to_date=$3 | |
247 | local -r orglangs=$(split_org_langs "$4") | |
248 | local -r org=${orglangs%% *} | |
249 | local -r langs=${orglangs##* } | |
250 | ||
251 | if [[ ${langs} = *-* ]]; then | |
252 | get_pair "$@" | |
253 | else | |
254 | local -r mdep=${org}-${langs} | |
255 | if [[ $org = giella ]]; then | |
256 | maybe_symlink_GTHOME "langs/${langs}" | |
257 | maybe_symlink_GTHOME gtcore | |
258 | get_dep "${depth}" gtcore | |
259 | make_dep gtcore | |
260 | fi | |
261 | ||
262 | if [[ ${skip_if_up_to_date} == true && $(is_dep_updated "${mdep}") == "yes" ]]; then | |
263 | printf "Dependency %s is up-to-date, skipping update and build.\\n" "$3" | |
264 | else | |
265 | if get_dep "${depth}" "${mdep}"; then | |
266 | make_dep "${mdep}" | |
267 | else | |
268 | return 1 | |
269 | fi | |
270 | fi | |
271 | fi | |
272 | } | |
273 | ||
274 | show_help () { | |
275 | cat <<EOF | |
276 | USAGE | |
277 | ${0##*/} PAIR | |
278 | ${0##*/} -l [MODULE...] | |
279 | ||
280 | DESCRIPTION | |
281 | Run with just one argument, it will download and set up the | |
282 | Apertium development data for the specified language pair. | |
283 | ||
284 | With the -l option, it will list available language pairs. Give | |
285 | one or more MODULE arguments to list only pairs in that SVN | |
286 | module (one of "trunk", "staging", "nursery", "incubator"). | |
287 | The same behavior can be invoked for language modules using -m. | |
288 | ||
289 | OPTIONS | |
290 | -h display this help and exit | |
291 | -l list available packages instead of setting up data | |
292 | -m list available language modules instead of setting up | |
293 | data | |
294 | -k keep going even if a dependency fails | |
295 | -s skip the build step for up-to-date dependencies/pairs | |
296 | -x DEP skip data dependency DEP (useful if DEP is installed | |
297 | through a package manager); may be specified multiple | |
298 | times | |
299 | -d DEPTH specify a --depth to 'git clone' | |
300 | ||
301 | EXAMPLES | |
302 | ${0##*/} nno-nob | |
303 | ||
304 | Download and set up apertium-nno-nob, along with its nno and | |
305 | nob dependencies. | |
306 | ||
307 | sudo apt-get install giella-sme | |
308 | ${0##*/} -x sme sme-nob | |
309 | ||
310 | Install giella-sme through apt-get, then install download and set | |
311 | up apertium-sme-nob, along with the nob dependency (but not sme). | |
312 | ||
313 | ${0##*/} -l trunk | |
314 | ||
315 | List available language pairs in SVN trunk. | |
316 | ||
317 | ${0##*/} -l | grep kaz | |
318 | ||
319 | List available language pairs involving Kazakh. | |
320 | EOF | |
321 | } | |
322 | ||
323 | is_in () { | |
324 | local -r pattern="$1" | |
325 | local element | |
326 | shift | |
327 | ||
328 | for element; do | |
329 | [[ ${element} = "${pattern}" ]] && return 0 | |
330 | done | |
331 | return 1 | |
332 | } | |
333 | ||
334 | ||
335 | list_modules () { | |
336 | curl -Ss --fail "${gitroot}/apertium-${module}/master/.gitmodules" \ | |
337 | | grep "[[:space:]]*url = .*.git$" \ | |
338 | | sed 's%.*url = .*/%%' \ | |
339 | | sed 's/[.]git$//' \ | |
340 | | sed 's/^apertium-//' | |
341 | echo | |
342 | } | |
343 | ||
344 | list_pairs () { | |
345 | local -a modules=("$@") | |
346 | local module | |
347 | ||
348 | # Defaulting to all modules: | |
349 | if [[ ${#modules[@]} -eq 0 ]]; then | |
350 | modules=( "${pmodules[@]}" ) | |
351 | fi | |
352 | # Sanity-check input: | |
353 | for module in "${modules[@]}"; do | |
354 | if ! is_in "${module}" "${pmodules[@]}"; then | |
355 | echo "ERROR: '${module}' not recognised as a language pair module"'!' >&2 | |
356 | echo >&2 | |
357 | show_help >&2 | |
358 | exit 1 | |
359 | fi | |
360 | done | |
361 | ||
362 | for module in "${modules[@]}"; do | |
363 | echo "# Pairs in ${module}:" | |
364 | list_modules "${module}" |grep -e '-' | |
365 | echo | |
366 | done | |
367 | } | |
368 | ||
369 | list_language_modules() { | |
370 | local -a modules=("$@") | |
371 | local module | |
372 | ||
373 | # Defaulting to all modules: | |
374 | if [[ ${#modules[@]} -eq 0 ]]; then | |
375 | modules=( "${lmodules[@]}" ) | |
376 | fi | |
377 | # Sanity-check input: | |
378 | for module in "${modules[@]}"; do | |
379 | if ! is_in "${module}" "${lmodules[@]}"; then | |
380 | echo "ERROR: '${module}' not recognised as an language module module"'!' >&2 | |
381 | echo >&2 | |
382 | show_help >&2 | |
383 | exit 1 | |
384 | fi | |
385 | done | |
386 | ||
387 | for module in "${modules[@]}"; do | |
388 | echo "# Language modules in ${module}:" | |
389 | list_modules "${module}" | grep -ve '-' | |
390 | done | |
391 | } | |
392 | ||
393 | sanity_check () { | |
394 | if ! command -V git >/dev/null; then | |
395 | cat >&2 <<EOF | |
396 | ||
397 | You need to install git first! | |
398 | ||
399 | If you use apt-get, it's typically: | |
400 | ||
401 | sudo apt-get install git | |
402 | ||
403 | If you use rpm/dnf, it's typically: | |
404 | ||
405 | sudo dnf install git | |
406 | ||
407 | EOF | |
408 | fi | |
409 | } | |
410 | ||
411 | main () { | |
412 | sanity_check | |
413 | local do_list_pairs=false | |
414 | local keep_going=false | |
415 | local do_list_language_modules=false | |
416 | local skip_if_up_to_date=false | |
417 | local -a skip=() | |
418 | local depth=0 | |
419 | while getopts ":hklmsx:d:" opt; do | |
420 | case "$opt" in | |
421 | h) | |
422 | show_help | |
423 | exit 0 | |
424 | ;; | |
425 | x) | |
426 | skip+=( "${OPTARG}" ) | |
427 | ;; | |
428 | d) | |
429 | depth="${OPTARG}" | |
430 | ;; | |
431 | l) | |
432 | do_list_pairs=true | |
433 | ;; | |
434 | m) | |
435 | do_list_language_modules=true | |
436 | ;; | |
437 | k) | |
438 | keep_going=true | |
439 | ;; | |
440 | s) | |
441 | skip_if_up_to_date=true | |
442 | ;; | |
443 | \?) | |
444 | echo "ERROR: Invalid option: -$OPTARG" >&2 | |
445 | echo >&2 | |
446 | show_help >&2 | |
447 | exit 1 | |
448 | ;; | |
449 | esac | |
450 | done | |
451 | shift "$((OPTIND-1))" | |
452 | ||
453 | if ${do_list_pairs}; then | |
454 | list_pairs "$@" | |
455 | elif ${do_list_language_modules}; then | |
456 | list_language_modules "$@" | |
457 | else | |
458 | if [[ $# -lt 1 ]]; then | |
459 | echo "ERROR: No language pair specified." >&2 | |
460 | echo >&2 | |
461 | show_help >&2 | |
462 | exit 1 | |
463 | fi | |
464 | for d in "$@"; do | |
465 | get_data "${depth}" "${keep_going}" "${skip_if_up_to_date}" "$d" "${skip[@]:-}" | |
466 | done | |
467 | fi | |
468 | } | |
469 | ||
470 | if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then | |
471 | echo "${BASH_SOURCE[0]} is being sourced; chmod +x and use ./${BASH_SOURCE[0]} to actually run." >&2 | |
472 | else | |
473 | main "$@" | |
474 | fi |