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