]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - gamepack-manager
Merge branch 'gcc10' 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 -va}"
7 : "${CP_R:=cp -Rva}"
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 AlienArena      GPL          svn     https://svn.code.sf.net/p/alienarena-cc/code/trunk/tools/netradiant_gamepack/AlienArenaPack
59 DarkPlaces      GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/DarkPlacesPack/branches/1.5/
60 Doom3           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Doom3Pack/branches/1.5/
61 ET              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/ETPack/branches/1.5/
62 Heretic2        proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Her2Pack/branches/1.5/
63 JediAcademy     proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/JAPack/branches/1.5/
64 Kingpin         unknown      zip     http://download.kingpin.info/kingpin/editing/maps/map_editors/NetRadiant/addon/Kingpinpack.zip
65 Neverball       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/NeverballPack.zip
66 Nexuiz          GPL          gitdir  git://git.icculus.org/divverent/nexuiz.git misc/netradiant-NexuizPack master
67 OpenArena       GPL          git     https://github.com/NeonKnightOA/oagamepack.git
68 Osirion         GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OsirionPack.zip
69 Prey            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/PreyPack/trunk/
70 Q3              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q3Pack/trunk/ 29
71 Q3Rally         proprietary  svn     https://svn.code.sf.net/p/q3rallysa/code/tools/radiant-config/radiant15-netradiant/
72 Quake2          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q2Pack/branches/1.5/
73 Quake4          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q4Pack/branches/1.5/
74 Quake           GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/Quake1Pack.zip
75 Quetoo          GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/QuetooPack/branches/1.5/
76 SmokinGuns      unknown      git     https://github.com/smokin-guns/smokinguns-mapeditor-support.git
77 Tremulous       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/TremulousPack.zip
78 TurtleArena     proprietary  git     https://github.com/Turtle-Arena/turtle-arena-radiant-pack.git
79 UFOAI           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/UFOAIPack/branches/1.5/
80 Unvanquished    BSD          git     https://github.com/Unvanquished/unvanquished-mapeditor-support.git
81 Warsow          GPL          git     https://github.com/Warsow/NetRadiantPack.git
82 Wolf            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/WolfPack/branches/1.5/
83 Xonotic         GPL          git     https://gitlab.com/xonotic/netradiant-xonoticpack.git
84 EOF
85 }
86
87 if command -v gsed >/dev/null
88 then
89         SED=gsed
90 elif sed --help >/dev/null 2>&1
91 then
92         SED=sed
93 else
94         printf 'ERROR: GNU sed is missing\n' >&2
95         exit 1
96 fi
97
98 printRealPath ()
99 {
100         if command -v grealpath >/dev/null
101         then
102                 grealpath "${1}"
103         elif command -v realpath >/dev/null
104         then
105                 realpath "${1}"
106         elif command -v greadlink >/dev/null
107         then
108                 # test greadlink first as greadlink has the feature on macos
109                 # but readlink only has it on linux, note that it's probably
110                 # the same on bsd
111                 # note: (g)readlink requires the file to be create first
112                 greadlink -f "${1}"
113         elif command -v readlink >/dev/null
114         then
115                 # --help and -f options are GNU readlink things
116                 if readlink --help >/dev/null 2>&1
117                 then
118                         readlink -f "${1}"
119                 else
120                         if ! python -c "import os; print(os.path.realpath('${1}'))"
121                         then
122                                 printf 'ERROR: GNU realpath or other way to compute real path of a file is missing\n' >&2
123                                 exit 1
124                         fi
125                 fi
126         fi
127 }
128
129 sanitizeDB () {
130         ${SED} -e 's/#.*//;s/[ \t][ \t][ \t]*/\t/g;s/^[ \t]*//;s/[ \t]*$//' \
131         | grep -v '^$'
132 }
133
134 inList () {
135         [ "$(grep "^${1}$")" = "${1}" ]
136 }
137
138 printList () {
139         echo "${1}" \
140         | tr ' ' '\n' \
141         | grep -v '^$' \
142         | sort -u
143 }
144
145 dedupeList () {
146         printList "${1}" \
147         | tr '\n' ' ' \
148         | ${SED} -e 's/ $//'
149 }
150
151 printGamePackDB () {
152         printRawDB \
153         | sanitizeDB
154 }
155
156 printLicenseList () {
157         printGamePackDB \
158         | awk '{ print $2 }' \
159         | sort -u
160 }
161
162 printNameList () {
163         printGamePackDB \
164         | awk '{ print $1 }' \
165         | sort -u
166 }
167
168 printNameListByLicense () {
169         local arg_license_list
170         local license_list
171         local license
172
173         arg_license_list="${1}"
174         license_list=''
175
176         for license in ${arg_license_list}
177         do
178                 case "${license}" in
179                         'none')
180                                 break
181                                 ;;
182                         'all')
183                                 license_list="$(printLicenseList)"
184                                 break
185                                 ;;
186                         'free')
187                                 license_list="${license_list} ${free_license_list}"
188                                 ;;
189                         *)
190                                 if printLicenseList | inList "${license}"
191                                 then
192                                         license_list="${license_list} ${license}"
193                                 else
194                                         printError "unknown license: ${license}"
195                                 fi
196                                 ;;
197                 esac
198         done
199
200         license_list="$(dedupeList "${license_list}")"
201
202         for license in ${license_list}
203         do
204                 printGamePackDB \
205                 | awk '$2 == "'"${license}"'"' \
206                 | awk '{ print $1 }'
207         done
208 }
209
210 printNameListByName () {
211         local argname_list
212         local name_list
213         local name
214
215         argname_list="${1}"
216         name_list=''
217
218         for name in ${argname_list}
219         do
220                 case "${name}" in
221                         'none')
222                                 break
223                                 ;;
224                         'all')
225                                 local name_list
226                                 name_list="$(printNameList)"
227                                 break
228                                 ;;
229                         *)
230                                 if printNameList | inList "${name}"
231                                 then
232                                         local name_list
233                                         name_list="${name_list} ${name}"
234                                 else
235                                         printError "unknown name: ${name}"
236                                 fi
237                                 ;;
238                 esac
239         done
240
241         name_list="$(dedupeList "${name_list}")"
242
243         for name in ${name_list}
244         do
245                 printGamePackDB \
246                 | awk '$1 == "'"${name}"'"' \
247                 | awk '{ print $1 }'
248         done
249 }
250
251 printPackLine () {
252         local name
253
254         name="${1}"
255
256         printGamePackDB \
257         | awk '$1 == "'"${name}"'"'
258 }
259
260 getValue () {
261         local name
262         local key
263
264         name="${1}"
265         key="${2}"
266
267         printPackLine "${name}" \
268         | awk '{ print $'"${key}"' }'
269 }
270
271 downloadExtraUrls ()
272 {
273         if [ -f 'extra-urls.txt' ]
274         then
275                 while IFS='     ' read -r extra_file extra_url
276                 do
277                         (
278                                 ${WGET} -O "${extra_file}" "${extra_url}"
279                         ) </dev/null
280                 done < 'extra-urls.txt'
281         fi
282 }
283
284 downloadPack () {
285         local download_dir
286         local name
287         local license
288         local source_type
289         local source_url
290         local pack
291         local reference
292         local subdir
293         local branch
294
295         download_dir="${1}"
296         name="${2}"
297
298         license="$(getValue "${name}" '2')"
299         source_type="$(getValue "${name}" '3')"
300         source_url="$(getValue "${name}" '4')"
301
302         pack="${name}${pack_suffix}"
303
304         ${MKDIR_P} "${download_dir}"
305
306         (
307                 cd "${download_dir}"
308
309                 ${ECHO} ''
310                 ${ECHO} "Available pack: ${pack}"
311                 ${ECHO} "  License: ${license}"
312                 ${ECHO} "  Download via ${source_type} from ${source_url}"
313                 ${ECHO} ''
314
315                 if [ -d "${download_dir}/${pack}" ]
316                 then
317                         ${ECHO} "Updating ${name}…"
318                 else
319                         ${ECHO} "Downloading ${pack}…"
320                 fi
321
322                 case "${source_type}" in
323                         'svn')
324                                 reference="$(getValue "${name}" '5')"
325                                 if [ -z "${reference}" ]
326                                 then
327                                         reference='HEAD'
328                                 fi
329
330                                 if [ -d "${pack}" ]
331                                 then
332                                         if [ -d "${pack}/.git" ]
333                                         then
334                                                 (
335                                                         cd "${pack}"
336                                                         ${GIT} svn fetch
337                                                 )
338                                         else
339                                                 ${SVN} update -r"${reference}" "${pack}"
340                                         fi
341                                 else
342                                         ${SVN} checkout -r"${reference}" "${source_url}" "${pack}" \
343                                         || ${GIT} svn clone "${source_url}" "${pack}"
344                                 fi
345                                 ;;
346                         'zip')
347                                 ${RM_R} 'zipdownload'
348                                 ${MKDIR} 'zipdownload'
349                                 (
350                                         cd 'zipdownload'
351                                         ${WGET} "${source_url}"
352                                         ${UNZIPPER} './'*.zip
353                                 )
354                                 ${RM_R} "${pack}"
355                                 ${MKDIR} "${pack}"
356                                 if [ -d 'zipdownload/games' ]
357                                 then
358                                         ${MV} 'zipdownload/'* "${pack}/"
359                                 else
360                                         ${MV} 'zipdownload/'*'/'* "${pack}/"
361                                 fi
362                                 ${RM_R} 'zipdownload'
363                                 ;;
364                         'gitdir')
365                                 local subdir="$(getValue "${name}" '5')"
366                                 local branch="$(getValue "${name}" '6')"
367                                 ${RM_R} "${pack}"
368                                 ${GIT} archive --remote="${source_url}" --prefix="${pack}/" "${branch}":"${subdir}" \
369                                 | ${TAR} xvf -
370                                 ;;
371                         'git')
372                                 if [ -d "${pack}" ]
373                                 then
374                                         (
375                                                 cd "${pack}"
376                                                 ${GIT} pull
377                                         )
378                                 else
379                                         ${GIT} clone "${source_url}" "${pack}"
380                                 fi
381                                 ;;
382                 esac
383
384                 if [ -d "${pack}" ]
385                 then
386                         (
387                                 cd "${pack}"
388                                 downloadExtraUrls
389                         )
390                 fi
391
392         )
393 }
394
395 downloadPackList () {
396         local download_dir
397         local name_list
398
399         download_dir="${1}"
400         name_list="${2}"
401
402         for name in ${name_list}
403         do
404                 if printNameList | inList "${name}"
405                 then
406                         downloadPack "${download_dir}" "${name}"
407                 else
408                         printError "unknown name: ${name}"
409                 fi
410         done
411 }
412
413 installPack () {
414         local download_dir
415         local install_dir
416         local name
417         local pack
418         local path
419         local game_file
420         local game_dir
421
422         download_dir="${1}"
423         install_dir="${2}"
424         name="${3}"
425
426         pack="${name}${pack_suffix}"
427
428         ${MKDIR_P} "${install_dir}/${games_dir}"
429
430         # Some per-game workaround for malformed gamepack
431         case "${name}" in
432                 'JediAcademy')
433                         pack="${pack}/Tools"
434                         ;;
435                 'Prey'|'Q3')
436                         pack="${pack}/tools"
437                         ;;
438                 'Wolf')
439                         pack="${pack}/bin"
440                         ;;
441         esac
442
443         # mkeditorpacks-based gamepack
444         if [ -d "${download_dir}/${pack}/build/netradiant" ]
445         then
446                 pack="${pack}/build/netradiant"
447         fi
448
449         path="${download_dir}/${pack}"
450
451         for game_file in "${path}/${games_dir}/"*'.game'
452         do
453                 if [ x"${game_file}" != x"${path}/"*'.game' ]
454                 then
455                         ${CP} "${game_file}" "${real_install_dir}/${games_dir}/"
456                 fi
457         done
458
459         for game_dir in "${path}/"*'.game'
460         do
461                 if [ x"${game_dir}" != x"${path}/"*'.game' ]
462                 then
463                         ${CP_R} "${game_dir}" "${real_install_dir}/"
464                 fi
465         done
466 }
467
468 installPackList () {
469         local download_dir
470         local install_dir
471         local name_list
472
473         download_dir="${1}"
474         install_dir="${2}"
475         name_list="${3}"
476
477         for name in ${name_list}
478         do
479                 if printNameList | inList "${name}"
480                 then
481                         installPack "${download_dir}" "${install_dir}" "${name}"
482                 else
483                         printError "unknown name: ${name}"
484                 fi
485         done
486 }
487
488 printError () {
489         printf 'ERROR: %s\n' "${1}" >&2
490         exit 1
491 }
492
493 printHelp () {
494         local tab
495         local prog_name
496
497         tab="$(printf '\t')"
498         prog_name='gamepack-manager'
499
500         cat <<-EOF
501         Usage: ${prog_name} [OPTION] [SELECTION <ARGUMENTS>] [ACTION]
502
503         OPTIONS:
504         ${tab}-dd, --download-dir DIRNAME
505         ${tab}${tab}store downloaded games to DIRNAME (default: ${default_download_dir})
506
507         ${tab}-id, --install-dir DIRNAME
508         ${tab}${tab}store installed games to DIRNAME (default: ${default_install_dir})
509
510         SELECTIONS:
511         ${tab}-n, --name NAMES…
512         ${tab}${tab}select games by name (default: none)
513         ${tab}${tab}special keyword: all, none
514         ${tab}${tab}available games:
515         $(printNameList | ${SED} -e 's/^/\t\t\t/')
516
517         ${tab}-l, --license LICENSES…
518         ${tab}${tab}select games by license (default: none)
519         ${tab}${tab}special keyword: free, all, none
520         ${tab}${tab}available licenses:
521         $(printLicenseList | ${SED} -e 's/^/\t\t\t/')
522
523         ACTIONS:
524         ${tab}-ln, --list-names
525         ${tab}${tab}list all game names
526
527         ${tab}-ll, --list-licenses
528         ${tab}${tab}list all game licenses
529
530         ${tab}-ls, --list
531         ${tab}${tab}list selected games
532
533         ${tab}-d, --download
534         ${tab}${tab}download selected games
535
536         ${tab}-i, --install
537         ${tab}${tab}install selected games
538
539         ${tab}-h, --help
540         ${tab}${tab}print this help
541
542         Example:
543         ${tab}${prog_name} --license GPL BSD --download --install
544
545         EOF
546
547         exit
548 }
549
550 option_list=''
551
552 list_selected='false'
553 list_licenses='false'
554 list_names='false'
555
556 download_packs='false'
557 install_packs='false'
558
559 mkdir_download='false'
560 mkdir_install='false'
561
562 by_license='false'
563 by_name='false'
564
565 arg_type=''
566 selected_list=''
567 license_list=''
568 name_list=''
569 install_dir=''
570
571 while ! [ -z "${1}" ]
572 do
573
574         if printList "${option_list}" | inList "${1}"
575         then
576                 printError "option called more than once: ${1}"
577         fi
578
579         if echo "${@}" | tr ' ' '\n' | inList '--help'
580         then
581                 printHelp
582         elif echo "${@}" | tr ' ' '\n' | inList '-h'
583         then
584                 printHelp
585         fi
586
587         case "${1}" in
588                 '--list-licenses'|'-ll')
589                         arg_type=''
590                         list_licenses='true'
591                         option_list="${option_list} ${1}"
592                         ;;
593                 '--list-names'|'-ln')
594                         arg_type=''
595                         list_names='true'
596                         option_list="${option_list} ${1}"
597                         ;;
598                 '--list-selected'|'-ls')
599                         arg_type=''
600                         list_selected='true'
601                         option_list="${option_list} ${1}"
602                         ;;
603                 '--download'|'-d')
604                         arg_type=''
605                         download_packs='true'
606                         mkdir_download='true'
607                         option_list="${option_list} ${1}"
608                         ;;
609                 '--install'|'-i')
610                         arg_type=''
611                         install_packs='true'
612                         mkdir_download='true'
613                         mkdir_install='true'
614                         option_list="${option_list} ${1}"
615                         ;;
616                 '--license'|'-l')
617                         by_license='true'
618                         arg_type='pack-license'
619                         option_list="${option_list} ${1}"
620                         ;;
621                 '--name'|'-n')
622                         by_name='true'
623                         arg_type='pack-name'
624                         option_list="${option_list} ${1}"
625                         ;;
626                 '--download-dir'|'-dd')
627                         arg_type='download-dir'
628                         option_list="${option_list} ${1}"
629                         ;;
630                 '--install-dir'|'-id')
631                         arg_type='install-dir'
632                         option_list="${option_list} ${1}"
633                         ;;
634                 '-'*)
635                         printError "unknown option: ${1}"
636                         ;;
637                 *)
638                         case "${arg_type}" in
639                                 'pack-license')
640                                         license_list="${license_list} ${1}"
641                                         ;;
642                                 'pack-name')
643                                         name_list="${name_list} ${1}"
644                                         ;;
645                                 'download-dir')
646                                         if [ -z "${download_dir}" ]
647                                         then
648                                                 download_dir="${1}"
649                                         else
650                                                 printError "more than one download dir: ${1}"
651                                         fi
652                                         ;;
653                                 'install-dir')
654                                         if [ -z "${install_dir}" ]
655                                         then
656                                                 install_dir="${1}"
657                                         else
658                                                 printError "more than one install dir: ${1}"
659                                         fi
660                                         ;;
661                                 *)
662                                         printError "misplaced argument: ${1}"
663                                         ;;
664                         esac
665                         ;;
666         esac
667
668         shift
669 done
670
671 # compatibility with legacy Makefile
672 if [ "${DOWNLOAD_GAMEPACKS}" = 'yes' ]
673 then
674         if ! [ -z "${DOWNLOADDIR}" ]
675         then
676                 download_dir="${DOWNLOADDIR}"
677         fi
678
679         if ! [ -z "${INSTALLDIR}" ]
680         then
681                 install_dir="${INSTALLDIR}"
682         fi
683
684         license_list='free'
685         by_license='true'
686
687         download_packs='true'
688         mkdir_download='true'
689
690         install_packs='true'
691         mkdir_install='true'
692 fi
693
694 if [ -z "${download_dir}" ]
695 then
696         download_dir="${default_download_dir}"
697 fi
698
699 if [ -z "${install_dir}" ]
700 then
701         install_dir="${default_install_dir}"
702 fi
703
704 if "${by_license}"
705 then
706         selected_list="${selected_list} $(printNameListByLicense "${license_list}")"
707 fi
708
709 if "${by_name}"
710 then
711         selected_list="${selected_list} $(printNameListByName "${name_list}")"
712 fi
713
714 selected_list="$(dedupeList "${selected_list}")"
715
716 if "${mkdir_download}"
717 then
718         ${MKDIR_P} "${download_dir}"
719         real_download_dir="$(printRealPath "${download_dir}")"
720 fi
721
722 if "${mkdir_install}"
723 then
724         ${MKDIR_P} "${install_dir}"
725         real_install_dir="$(printRealPath "${install_dir}")"
726 fi
727
728 if "${list_licenses}"
729 then
730         printLicenseList
731 fi
732
733 if "${list_names}"
734 then
735         printNameList
736 fi
737 if "${list_selected}"
738 then
739         printList "${selected_list}"
740 fi
741
742 if "${download_packs}"
743 then
744         downloadPackList "${real_download_dir}" "${selected_list}"
745 fi
746
747 if "${install_packs}"
748 then
749         installPackList "${real_download_dir}" "${real_install_dir}" "${selected_list}"
750 fi
751
752 #EOF