]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - gamepack-manager
Merge branch 'webp' into 'master'
[xonotic/netradiant.git] / gamepack-manager
1 #! /usr/bin/env bash
2
3 # get usage help this way:
4 # ./gamepack_manager -h
5
6 : "${CP:=cp -v}"
7 : "${CP_R:=cp -r --preserve=timestamps}"
8 : "${GIT:=git}"
9 : "${SVN:=svn}"
10 : "${WGET:=wget}"
11 : "${ECHO:=echo}"
12 : "${MKDIR:=mkdir -v}"
13 : "${MKDIR_P:=mkdir -vp}"
14 : "${RM_R:=rm -vrf}"
15 : "${MV:=mv -v}"
16 : "${TAR:=tar}"
17 : "${UNZIPPER:=unzip}"
18
19 set -e
20
21 default_download_dir='build/download'
22 default_install_dir='build'
23
24 games_dir='games'
25 pack_suffix='Pack'
26
27 free_license_list='BSD GPL'
28
29 printRawDB () {
30 cat <<\EOF
31 #######################################################
32 #                                                     #
33 #  IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT  #
34 #                                                     #
35 #   Use two whitespaces or more as column separator   #
36 #                                                     #
37 #######################################################
38
39 #######################################################
40 # Obsolete packs                                      #
41 #######################################################
42
43 # Quake2World was renamed as Quetoo
44 # Other gamepacks have better version available
45
46 # OpenArena     unknown      zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OpenArenaPack.zip
47 # Quake         proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/QuakePack.zip
48 # Quake2World   GPL          svn     svn://jdolan.dyndns.org/quake2world/trunk/gtkradiant
49 # Tremulous     proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/TremulousPack/branches/1.5/
50 # Unvanquished  unknown      zip     http://ingar.intranifty.net/gtkradiant/files/gamepacks/UnvanquishedPack.zip
51 # Warsow        GPL          svn     https://svn.bountysource.com/wswpack/trunk/netradiant/games/WarsowPack/
52 # Warsow        GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/WarsowPack.zip
53
54 #######################################################
55 # Usable packs                                        #
56 #######################################################
57
58 DarkPlaces      GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/DarkPlacesPack/branches/1.5/
59 Doom3           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Doom3Pack/branches/1.5/
60 ET              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/ETPack/branches/1.5/
61 Heretic2        proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Her2Pack/branches/1.5/
62 JediAcademy     proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/JAPack/branches/1.5/
63 Neverball       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/NeverballPack.zip
64 Nexuiz          GPL          gitdir  git://git.icculus.org/divverent/nexuiz.git misc/netradiant-NexuizPack master
65 OpenArena       GPL          git     https://github.com/NeonKnightOA/oagamepack.git
66 Osirion         GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OsirionPack.zip
67 Prey            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/PreyPack/trunk/
68 Q3              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q3Pack/trunk/ 29
69 Quake2          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q2Pack/branches/1.5/
70 Quake4          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q4Pack/branches/1.5/
71 Quake           GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/Quake1Pack.zip
72 Quetoo          GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/QuetooPack/branches/1.5/
73 Tremulous       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/TremulousPack.zip
74 TurtleArena     proprietary  git     https://github.com/Turtle-Arena/turtle-arena-radiant-pack.git
75 UFOAI           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/UFOAIPack/branches/1.5/
76 Unvanquished    BSD          svn     https://github.com/Unvanquished/unvanquished-mapeditor-support.git/trunk/build/netradiant
77 Warsow          GPL          git     https://github.com/Warsow/NetRadiantPack.git
78 Wolf            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/WolfPack/branches/1.5/
79 Xonotic         GPL          git     https://gitlab.com/xonotic/netradiant-xonoticpack.git
80 EOF
81 }
82
83 sanitizeDB () {
84         sed -e 's/#.*//;s/[ \t][ \t][ \t]*/\t/g;s/^[ \t]*//;s/[ \t]*$//' \
85         | grep -v '^$'
86 }
87
88 inList () {
89         [ "$(grep "^${1}$")" = "${1}" ]
90 }
91
92 printList () {
93         echo "${1}" \
94         | tr ' ' '\n' \
95         | grep -v '^$' \
96         | sort -u
97 }
98
99 dedupeList () {
100         printList "${1}" \
101         | tr '\n' ' ' \
102         | sed -e 's/ $//'
103 }
104
105 printGamePackDB () {
106         printRawDB \
107         | sanitizeDB
108 }
109
110 printLicenseList () {
111         printGamePackDB \
112         | awk '{ print $2 }' \
113         | sort -u
114 }
115
116 printNameList () {
117         printGamePackDB \
118         | awk '{ print $1 }' \
119         | sort -u
120 }
121
122 printNameListByLicense () {
123         local arg_license_list
124         local license_list
125         local license
126
127         arg_license_list="${1}"
128         license_list=''
129
130         for license in ${arg_license_list}
131         do
132                 case "${license}" in
133                         'none')
134                                 break
135                         ;;
136                         'all')
137                                 license_list="$(printLicenseList)"
138                                 break
139                         ;;
140                         'free')
141                                 license_list="${license_list} ${free_license_list}"
142                         ;;
143                         *)
144                                 if printLicenseList | inList "${license}"
145                                 then
146                                         license_list="${license_list} ${license}"
147                                 else
148                                         printError "unknown license: ${license}"
149                                 fi
150                         ;;
151                 esac
152         done
153
154         license_list="$(dedupeList "${license_list}")"
155
156         for license in ${license_list}
157         do
158                 printGamePackDB \
159                 | awk '$2 == "'"${license}"'"' \
160                 | awk '{ print $1 }'
161         done
162 }
163
164 printNameListByName () {
165         local argname_list
166         local name_list
167         local name
168
169         argname_list="${1}"
170         name_list=''
171
172         for name in ${argname_list}
173         do
174                 case "${name}" in
175                         'none')
176                                 break
177                         ;;
178                         'all')
179                                 local name_list
180                                 name_list="$(printNameList)"
181                                 break
182                         ;;
183                         *)
184                                 if printNameList | inList "${name}"
185                                 then
186                                         local name_list
187                                         name_list="${name_list} ${name}"
188                                 else
189                                         printError "unknown name: ${name}"
190                                 fi
191                         ;;
192                 esac
193         done
194
195         name_list="$(dedupeList "${name_list}")"
196
197         for name in ${name_list}
198         do
199                 printGamePackDB \
200                 | awk '$1 == "'"${name}"'"' \
201                 | awk '{ print $1 }'
202         done
203 }
204
205 printPackLine () {
206         local name
207
208         name="${1}"
209
210         printGamePackDB \
211         | awk '$1 == "'"${name}"'"'
212 }
213
214 getValue () {
215         local name
216         local key
217
218         name="${1}"
219         key="${2}"
220
221         printPackLine "${name}" \
222         | awk '{ print $'"${key}"' }'
223 }
224
225 downloadExtraUrls ()
226 {
227         local dir
228
229         dir="${1}"
230
231         if [ -f "${dir}/extra-urls.txt" ]
232         then
233                 while IFS='     ' read -r FILE URL
234                 do
235                         (
236                                 ${WGET} -O "${dir}/${FILE}" "${URL}"
237                         ) </dev/null
238                 done < "${dir}/extra-urls.txt"
239         fi
240 }
241
242 downloadPack () {
243         local download_dir
244         local name
245         local license
246         local source_type
247         local source_url
248         local pack
249         local reference
250         local subdir
251         local branch
252
253         download_dir="${1}"
254         name="${2}"
255
256         license="$(getValue "${name}" '2')"
257         source_type="$(getValue "${name}" '3')"
258         source_url="$(getValue "${name}" '4')"
259
260         pack="${name}${pack_suffix}"
261
262         ${MKDIR_P} "${download_dir}"
263
264         (
265                 cd "${download_dir}"
266
267                 ${ECHO} ''
268                 ${ECHO} "Available pack: ${pack}"
269                 ${ECHO} "  License: ${license}"
270                 ${ECHO} "  Download via ${source_type} from ${source_url}"
271                 ${ECHO} ''
272
273                 if [ -d "${download_dir}/${pack}" ]
274                 then
275                         ${ECHO} "Updating ${name}…"
276                 else
277                         ${ECHO} "Downloading ${pack}…"
278                 fi
279
280                 case "${source_type}" in
281                         'svn')
282                                 reference="$(getValue "${name}" '5')"
283                                 if [ -z "${reference}" ]
284                                 then
285                                         reference='HEAD'
286                                 fi
287
288                                 if [ -d "${download_dir}/${pack}" ]
289                                 then
290                                         ${SVN} update -r"${reference}" "${pack}"
291                                 else
292                                         ${SVN} checkout -r"${reference}" "${source_url}" "${pack}"
293                                 fi
294                         ;;
295                         'zip')
296                                 ${RM_R} 'zipdownload'
297                                 ${MKDIR} 'zipdownload'
298                                 (
299                                         cd 'zipdownload'
300                                         ${WGET} "${source_url}"
301                                         ${UNZIPPER} './'*.zip
302                                 )
303                                 ${RM_R} "${pack}"
304                                 ${MKDIR} "${pack}"
305                                 ${MV} 'zipdownload/'*'/'* "${pack}/"
306                                 ${RM_R} 'zipdownload'
307                         ;;
308                         'gitdir')
309                                 subdir="$(getValue "${name}" '5')"
310                                 branch="$(getValue "${name}" '6')"
311                                 ${RM_R} "${pack}"
312                                 ${GIT} archive --remote="${source_url}" --prefix="${pack}/" "${branch}":"${subdir}" \
313                                 | ${TAR} xvf -
314                         ;;
315                         'git')
316                                 if [ -d "${download_dir}/${pack}" ]
317                                 then
318                                         (
319                                                 cd "${pack}"
320                                                 ${GIT} pull
321                                         )
322                                 else
323                                         ${GIT} clone "${source_url}" "${pack}"
324                                 fi
325                         ;;
326                 esac
327
328                 if [ -d "${download_dir}/${pack}" ]
329                 then
330                         (
331                                 cd "${download_dir}/${pack}"
332                                 downloadExtraUrls "${pack}"
333                         )
334                 fi
335
336         )
337 }
338
339 downloadPackList () {
340         local download_dir
341         local name_list
342
343         download_dir="${1}"
344         name_list="${2}"
345
346         for name in ${name_list}
347         do
348                 if printNameList | inList "${name}"
349                 then
350                         downloadPack "${download_dir}" "${name}"
351                 else
352                         printError "unknown name: ${name}"
353                 fi
354         done
355 }
356
357 installPack () {
358         local download_dir
359         local install_dir
360         local name
361         local pack
362         local path
363         local game_file
364         local game_dir
365
366         download_dir="${1}"
367         install_dir="${2}"
368         name="${3}"
369
370         pack="${name}${pack_suffix}"
371
372         ${MKDIR_P} "${real_install_dir}/${games_dir}"
373
374         # Some per-game workaround for malformed gamepack
375         case "${name}" in
376                 'JediAcademy')
377                         pack="${pack}/Tools"
378                 ;;
379                 'Prey'|'Q3')
380                         pack="${pack}/tools"
381                 ;;
382                 'Wolf')
383                         pack="${pack}/bin"
384                 ;;
385         esac
386
387         path="${download_dir}/${pack}"
388
389         for game_file in "${path}/${games_dir}/"*'.game'
390         do
391                 if [ x"${game_file}" != x"${path}/"*'.game' ]
392                 then
393                         ${CP} "${game_file}" "${real_install_dir}/${games_dir}/"
394                 fi
395         done
396
397         for game_dir in "${path}/"*'.game'
398         do
399                 if [ x"${game_dir}" != x"${path}/"*'.game' ]
400                 then
401                         ${CP_R} "${game_dir}" "${real_install_dir}/"
402                 fi
403         done
404 }
405
406 installPackList () {
407         local download_dir
408         local install_dir
409         local name_list
410
411         download_dir="${1}"
412         install_dir="${2}"
413         name_list="${3}"
414
415         for name in ${name_list}
416         do
417                 if printNameList | inList "${name}"
418                 then
419                         installPack "${download_dir}" "${install_dir}" "${name}"
420                 else
421                         printError "unknown name: ${name}"
422                 fi
423         done
424 }
425
426 printError () {
427         printf 'ERROR: %s\n' "${1}" >&2
428         exit 1
429 }
430
431 printHelp () {
432         local tab
433         local prog_name
434
435         tab="$(printf '\t')"
436         prog_name="$(basename "$(readlink -f "${0}")")"
437
438         cat <<-EOF
439         Usage: ${prog_name} [OPTION] [SELECTION <ARGUMENTS>] [ACTION]
440
441         OPTIONS:
442         ${tab}-dd, --download-dir DIRNAME
443         ${tab}${tab}store downloaded games to DIRNAME (default: ${default_download_dir})
444
445         ${tab}-id, --install-dir DIRNAME
446         ${tab}${tab}store installed games to DIRNAME (default: ${default_install_dir})
447
448         SELECTIONS:
449         ${tab}-n, --name NAMES…
450         ${tab}${tab}select games by name (default: none)
451         ${tab}${tab}special keyword: all, none
452         ${tab}${tab}available games:
453         $(printNameList | sed -e 's/^/\t\t\t/')
454
455         ${tab}-l, --license LICENSES…
456         ${tab}${tab}select games by license (default: none)
457         ${tab}${tab}special keyword: free, all, none
458         ${tab}${tab}available licenses:
459         $(printLicenseList | sed -e 's/^/\t\t\t/')
460
461         ACTIONS:
462         ${tab}-ln, --list-names
463         ${tab}${tab}list all game names
464
465         ${tab}-ll, --list-licenses
466         ${tab}${tab}list all game licenses
467
468         ${tab}-ls, --list
469         ${tab}${tab}list selected games
470
471         ${tab}-d, --download
472         ${tab}${tab}download selected games
473
474         ${tab}-i, --install
475         ${tab}${tab}install selected games
476
477         ${tab}-h, --help
478         ${tab}${tab}print this help
479
480         Example:
481         ${tab}${prog_name} --license GPL BSD --download --install
482
483         EOF
484
485         exit
486 }
487
488 option_list=''
489
490 list_selected='false'
491 list_licenses='false'
492 list_names='false'
493
494 download_packs='false'
495 install_packs='false'
496
497 by_license='false'
498 by_name='false'
499
500 arg_type=''
501 selected_list=''
502 license_list=''
503 name_list=''
504 install_dir=''
505
506 while ! [ -z "${1}" ]
507 do
508
509         if printList "${option_list}" | inList "${1}"
510         then
511                 printError "option called more than once: ${1}"
512         fi
513
514         if echo "${@}" | tr ' ' '\n' | inList '--help'
515         then
516                 printHelp
517         elif echo "${@}" | tr ' ' '\n' | inList '-h'
518         then
519                 printHelp
520         fi
521
522         case "${1}" in
523                 '--list-licenses'|'-ll')
524                         arg_type=''
525                         list_licenses='true'
526                 ;;
527                 '--list-names'|'-ln')
528                         arg_type=''
529                         list_names='true'
530                 ;;
531                 '--list-selected'|'-ls')
532                         arg_type=''
533                         list_selected='true'
534                         option_list="${option_list} ${1}"
535                 ;;
536                 '--download'|'-d')
537                         arg_type=''
538                         download_packs='true'
539                         option_list="${option_list} ${1}"
540                 ;;
541                 '--install'|'-i')
542                         arg_type=''
543                         install_packs='true'
544                         option_list="${option_list} ${1}"
545                 ;;
546                 '--license'|'-l')
547                         by_license='true'
548                         arg_type='pack-license'
549                         option_list="${option_list} ${1}"
550                 ;;
551                 '--name'|'-n')
552                         by_name='true'
553                         arg_type='pack-name'
554                         option_list="${option_list} ${1}"
555                 ;;
556                 '--download-dir'|'-dd')
557                         arg_type='download-dir'
558                         option_list="${option_list} ${1}"
559                 ;;
560                 '--install-dir'|'-id')
561                         arg_type='install-dir'
562                         option_list="${option_list} ${1}"
563                 ;;
564                 '-'*)
565                         printError "unknown option: ${1}"
566                 ;;
567                 *)
568                         case "${arg_type}" in
569                                 'pack-license')
570                                         license_list="${license_list} ${1}"
571                                 ;;
572                                 'pack-name')
573                                         name_list="${name_list} ${1}"
574                                 ;;
575                                 'download-dir')
576                                         if [ -z "${download_dir}" ]
577                                         then
578                                                 download_dir="${1}"
579                                         else
580                                                 printError "more than one download dir: ${1}"
581                                         fi
582                                 ;;
583                                 'install-dir')
584                                         if [ -z "${install_dir}" ]
585                                         then
586                                                 install_dir="${1}"
587                                         else
588                                                 printError "more than one install dir: ${1}"
589                                         fi
590                                 ;;
591                                 *)
592                                         printError "misplaced argument: ${1}"
593                                 ;;
594                         esac
595                 ;;
596         esac
597
598         shift
599 done
600
601 # compatibility with legacy Makefile
602 if [ "${DOWNLOAD_GAMEPACKS}" = 'yes' ]
603 then
604         ! [ -z "${DOWNLOADDIR}" ] && download_dir="${DOWNLOADDIR}"
605         ! [ -z "${INSTALLDIR}" ] && install_dir="${INSTALDIR}"
606         license_list='free'
607         by_license='true'
608         download_packs='true'
609         install_packs='true'
610 fi
611
612 if [ -z "${download_dir}" ]
613 then
614         download_dir="${default_download_dir}"
615 fi
616
617 if [ -z "${install_dir}" ]
618 then
619         install_dir="${default_install_dir}"
620 fi
621
622 if "${by_license}"
623 then
624         selected_list="${selected_list} $(printNameListByLicense "${license_list}")"
625 fi
626
627 if "${by_name}"
628 then
629         selected_list="${selected_list} $(printNameListByName "${name_list}")"
630 fi
631
632 selected_list="$(dedupeList "${selected_list}")"
633
634 ${MKDIR_P} "${download_dir}"
635 ${MKDIR_P} "${install_dir}"
636 real_download_dir="$(readlink -f "${download_dir}")"
637 real_install_dir="$(readlink -f "${install_dir}")"
638
639 if "${list_licenses}"
640 then
641         printLicenseList
642 fi
643
644 if "${list_names}"
645 then
646         printNameList
647 fi
648 if "${list_selected}"
649 then
650         printList "${selected_list}"
651 fi
652
653 if "${download_packs}"
654 then
655         downloadPackList "${real_download_dir}" "${selected_list}"
656 fi
657
658 if "${install_packs}"
659 then
660         installPackList "${real_download_dir}" "${real_install_dir}" "${selected_list}"
661 fi
662
663 #EOF