Run shellcheck on script files
[geeqie.git] / geeqie-install-debian.sh
1 #!/bin/sh
2
3 ## @file
4 ## @brief Download, compile, and install Geeqie on Debian-based systems.
5 ##
6 ## If run from a folder that already contains the Geeqie sources, the source
7 ## code will be updated from the repository.
8 ## Dialogs allow the user to install additional features.
9 ##
10
11 version="2023-03-11"
12 description='
13 Geeqie is an image viewer.
14 This script will download, compile, and install Geeqie on Debian-based systems.
15 If run from a folder that already contains the Geeqie sources, the source
16 code will be updated from the repository.
17 Dialogs allow the user to install additional features.
18
19 Command line options are:
20 -v --version The version of this file
21 -h --help Output this text
22 -c --commit=ID Checkout and compile commit ID
23 -t --tag=TAG Checkout and compile TAG (e.g. v1.4 or v1.3)
24 -b --back=N Checkout commit -N (e.g. "-b 1" for last-but-one commit)
25 -l --list List required dependencies
26 '
27
28 # Essential for compiling
29 essential_array="git
30 build-essential
31 libglib2.0-0
32 libtool
33 meson
34 ninja-build
35 yelp-tools
36 help2man
37 doclifter"
38
39 # Optional for GTK3
40 optional_array="LCMS (for color management)
41 liblcms2-dev
42 exiv2 (for exif handling)
43 libgexiv2-dev
44 evince (for print preview)
45 evince
46 lua (for --remote commands)
47 liblua5.3-dev
48 libffmpegthumbnailer (for mpeg thumbnails)
49 libffmpegthumbnailer-dev
50 libtiff (for tiff support)
51 libtiff-dev
52 libjpeg (for jpeg support)
53 libjpeg-dev
54 librsvg2 (for viewing .svg images)
55 librsvg2-common
56 libwmf (for viewing .wmf images)
57 libwmf0.2-7-gtk
58 exiftran (for image rotation)
59 exiftran
60 imagemagick (for image rotation)
61 imagemagick
62 exiv2 command line (for jpeg export)
63 exiv2
64 jpgicc (for jpeg export color correction)
65 liblcms2-utils
66 pandoc (for generating README help file)
67 pandoc
68 gphoto2 (for tethered photography and camera download plugins)
69 gphoto2
70 libimage-exiftool-perl (for jpeg extraction plugin)
71 libimage-exiftool-perl
72 libheif (for HEIF support)
73 libheif-dev
74 webp-pixbuf-loader (for WebP images)
75 webp-pixbuf-loader
76 libdjvulibre (for DjVu images)
77 libdjvulibre-dev
78 libopenjp2 (for JP2 images)
79 libopenjp2-7-dev
80 libraw (for CR3 images)
81 libraw-dev
82 libomp (required by libraw)
83 libomp-dev
84 libarchive (for compressed files e.g. zip, including timezone)
85 libarchive-dev
86 libgspell (for spelling checks)
87 libgspell-1-dev
88 libchamplain gtk (for GPS maps)
89 libchamplain-gtk-0.12-dev
90 libchamplain (for GPS maps)
91 libchamplain-0.12-dev
92 libpoppler (for pdf file preview)
93 libpoppler-glib-dev"
94
95 ####################################################################
96 # Get System Info
97 # Derived from: https://github.com/coto/server-easy-install (GPL)
98 ####################################################################
99 lowercase()
100 {
101         printf '%b\n' "$1" | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/"
102 }
103
104 systemProfile()
105 {
106         OS="$(lowercase "$(uname)")"
107         KERNEL=$(uname -r)
108         MACH=$(uname -m)
109
110         if [ "${OS}" = "windowsnt" ]
111         then
112                 OS=windows
113         elif [ "${OS}" = "darwin" ]
114         then
115                 OS=mac
116         else
117                 OS=$(uname)
118                 if [ "${OS}" = "SunOS" ]
119                 then
120                         OS=Solaris
121                         ARCH=$(uname -p)
122                         OSSTR="${OS} ${REV}(${ARCH} $(uname -v))"
123                 elif [ "${OS}" = "AIX" ]
124                 then
125                         # shellcheck disable=SC2034
126                         OSSTR="${OS} $(oslevel) ($(oslevel -r))"
127                 elif [ "${OS}" = "Linux" ]
128                 then
129                         if [ -f /etc/redhat-release ]
130                         then
131                                 DistroBasedOn='RedHat'
132                                 DIST=$(sed s/\ release.*// /etc/redhat-release)
133                                 PSUEDONAME=$(sed s/.*\(// /etc/redhat-release | sed s/\)//)
134                                 REV=$(sed s/.*release\ // /etc/redhat-release | sed s/\ .*//)
135                         elif [ -f /etc/SuSE-release ]
136                         then
137                                 DistroBasedOn='SuSe'
138                                 PSUEDONAME=$(tr "\n" ' ' < /etc/SuSE-release | sed s/VERSION.*//)
139                                 REV=$(tr "\n" ' ' < /etc/SuSE-release | sed s/.*=\ //)
140                         elif [ -f /etc/mandrake-release ]
141                         then
142                                 DistroBasedOn='Mandrake'
143                                 PSUEDONAME=$(sed s/.*\(// /etc/mandrake-release | sed s/\)//)
144                                 REV=$(cat | sed s/.*release\ // /etc/mandrake-release | sed s/\ .*//)
145                         elif [ -f /etc/debian_version ]
146                         then
147                                 DistroBasedOn='Debian'
148                                 if [ -f /etc/lsb-release ]
149                                 then
150                                         DIST=$(grep '^DISTRIB_ID' /etc/lsb-release | awk -F= '{ print $2 }')
151                                         PSUEDONAME=$(grep '^DISTRIB_CODENAME' /etc/lsb-release | awk -F= '{ print $2 }')
152                                         REV=$(grep '^DISTRIB_RELEASE' /etc/lsb-release | awk -F= '{ print $2 }')
153                                 fi
154                         fi
155                         if [ -f /etc/UnitedLinux-release ]
156                         then
157                                 DIST="${DIST}[$(tr "\n" ' ' < /etc/UnitedLinux-release | sed s/VERSION.*//)]"
158                         fi
159                         OS=$(lowercase "$OS")
160                         DistroBasedOn=$(lowercase "$DistroBasedOn")
161                         readonly OS
162                         readonly DIST
163                         readonly DistroBasedOn
164                         readonly PSUEDONAME
165                         readonly REV
166                         readonly KERNEL
167                         readonly MACH
168                 fi
169         fi
170 }
171
172 install_essential()
173 {
174         for file in $essential_array
175         do
176                 if package_query "$file"
177                 then
178                         package_install "$file"
179                 fi
180         done
181
182         if [ "$1" = "GTK3" ]
183         then
184                 if package_query "libgtk-3-dev"
185                 then
186                         package_install libgtk-3-dev
187                 fi
188         else
189                 if package_query "libgtk2.0-dev"
190                 then
191                         package_install libgtk2.0-dev
192                 fi
193         fi
194 }
195
196 install_options()
197 {
198         if [ -n "$options" ]
199         then
200                 OLDIFS=$IFS
201                 IFS='|'
202                 # shellcheck disable=SC2086
203                 set $options
204                 while [ $# -gt 0 ]
205                 do
206                         package_install "$1"
207                         shift
208                 done
209                 IFS=$OLDIFS
210         fi
211 }
212
213 uninstall()
214 {
215         current_dir="$(basename "$PWD")"
216         if [ "$current_dir" = "geeqie" ]
217         then
218
219                 sudo --askpass  ninja -C build uninstall
220
221                 if ! zenity --title="Uninstall Geeqie" --width=370 --text="WARNING.\nThis will delete folder:\n\n$PWD\n\nand all sub-folders!" --question --ok-label="Cancel" --cancel-label="OK" 2> /dev/null
222                 then
223                         cd ..
224                         sudo --askpass rm -rf geeqie
225                 fi
226         else
227                 zenity --title="Uninstall Geeqie" --width=370 --text="This is not a geeqie installation folder!\n\n$PWD" --warning 2> /dev/null
228         fi
229
230         exit_install
231 }
232
233 package_query()
234 {
235         if [ "$DistroBasedOn" = "debian" ]
236         then
237
238                 # shellcheck disable=SC2086
239                 res=$(dpkg-query --show --showformat='${Status}' "$1" 2>> $install_log)
240                 if [ "${res}" = "install ok installed" ]
241                 then
242                         status=1
243                 else
244                         status=0
245                 fi
246         fi
247         return "$status"
248 }
249
250 package_install()
251 {
252         if [ "$DistroBasedOn" = "debian" ]
253         then
254                 # shellcheck disable=SC2024
255                 sudo --askpass apt-get --assume-yes install "$@" >> "$install_log" 2>&1
256         fi
257 }
258
259 exit_install()
260 {
261         rm "$install_pass_script" > /dev/null 2>&1
262
263         if [ -p "$zen_pipe" ]
264         then
265                 printf '%b\n' "100" > "$zen_pipe"
266                 printf '%b\n' "#End" > "$zen_pipe"
267         fi
268
269         zenity --title="$title" --width=370 --text="Geeqie is not installed\nLog file: $install_log" --info 2> /dev/null
270
271         rm "$zen_pipe" > /dev/null 2>&1
272
273         exit 1
274 }
275
276 # Entry point
277
278 IFS='
279 '
280
281 # If uninstall has been run, maybe the current directory no longer exists
282 if [ ! -d "$PWD" ]
283 then
284         zenity --error --title="Install Geeqie and dependencies" --width=370 --text="Folder $PWD does not exist!" 2> /dev/null
285
286         exit
287 fi
288
289 # Check system type
290 systemProfile
291 if [ "$DistroBasedOn" != "debian" ]
292 then
293         zenity --error --title="Install Geeqie and dependencies" --width=370 --text="Unknown operating system:\n
294 Operating System: $OS
295 Distribution: $DIST
296 Psuedoname: $PSUEDONAME
297 Revision: $REV
298 DistroBasedOn: $DistroBasedOn
299 Kernel: $KERNEL
300 Machine: $MACH" 2> /dev/null
301
302         exit
303 fi
304
305 # Parse the command line
306 OPTS=$(getopt -o vhc:t:b:ld: --long version,help,commit:,tag:,back:,list,debug: -- "$@")
307 eval set -- "$OPTS"
308
309 while true
310 do
311         case "$1" in
312                 -v | --version)
313                         printf '%b\n' "$version"
314                         exit
315                         ;;
316                 -h | --help)
317                         printf '%b\n' "$description"
318                         exit
319                         ;;
320                 -c | --commit)
321                         COMMIT="$2"
322                         shift
323                         shift
324                         ;;
325                 -t | --tag)
326                         TAG="$2"
327                         shift
328                         shift
329                         ;;
330                 -b | --back)
331                         BACK="$2"
332                         shift
333                         shift
334                         ;;
335                 -l | --list)
336                         LIST="$2"
337                         shift
338                         shift
339                         ;;
340                 *)
341                         break
342                         ;;
343         esac
344 done
345
346 if [ -n "$LIST" ]
347 then
348         printf '%b\n' "Essential libraries:"
349         for file in $essential_array
350         do
351                 printf '%b\n' "$file"
352         done
353
354         printf '\n'
355         printf '%b\n' "Optional libraries:"
356         for file in $optional_array
357         do
358                 printf '%b\n' "$file"
359         done
360
361         exit
362 fi
363
364 # If a Geeqie folder already exists here, warn the user
365 if [ -d "geeqie" ]
366 then
367         zenity --info --title="Install Geeqie and dependencies" --width=370 --text="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nA sub-folder named \"geeqie\" will be created in the\nfolder this script is run from, and the source code\nwill be downloaded to that sub-folder.\n\nA sub-folder of that name already exists.\nPlease try another folder." 2> /dev/null
368
369         exit
370 fi
371
372 # If it looks like a Geeqie download folder, assume an update
373 if [ -d ".git" ] && [ -d "src" ] && [ -f "geeqie.1" ]
374 then
375         mode="update"
376 else
377         # If it looks like something else is already installed here, warn the user
378         if [ -d ".git" ] || [ -d "src" ]
379         then
380                 zenity --info --title="Install Geeqie and dependencies" --width=370 --text="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nIt looks like you are running this script from a folder which already has software installed.\n\nPlease try another folder." 2> /dev/null
381
382                 exit
383         else
384                 mode="install"
385         fi
386 fi
387
388 # Use GTK3 as default
389 gtk3_installed=TRUE
390
391 if [ "$mode" = "install" ]
392 then
393         message="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will download, compile, and install Geeqie source\ncode and its dependencies.\n\nA sub-folder named \"geeqie\" will be created in the\nfolder this script is run from, and the source code\nwill be downloaded to that sub-folder.\n\nIn subsequent dialogs you may choose which\noptional features to install."
394
395         title="Install Geeqie and dependencies"
396         install_option=TRUE
397 else
398         message="This script is for use on Ubuntu and other\nDebian-based installations.\nIt will update the Geeqie source code and its\ndependencies, and will compile and install Geeqie.\n\nIn subsequent dialogs you may choose which\noptional features to install."
399
400         title="Update Geeqie and re-install"
401         install_option=FALSE
402 fi
403
404 # Ask whether to install GTK3 or uninstall
405
406 if ! gtk_version=$(zenity --title="$title" --width=370 --text="$message" --list --radiolist --column "" --column "" "$gtk3_installed" "Install" FALSE "Uninstall" --cancel-label="Cancel" --ok-label="OK" --hide-header 2> /dev/null)
407 then
408         exit
409 fi
410
411 # Environment variable SUDO_ASKPASS cannot be "zenity --password",
412 # so create a temporary script containing the command
413 install_pass_script=$(mktemp "${TMPDIR:-/tmp}/geeqie.XXXXXXXXXX")
414 printf '%b\n' "#!/bin/sh
415 if zenity --password --title=\"$title\" --width=370 2>/dev/null
416 then
417         exit 1
418 fi" > "$install_pass_script"
419 chmod +x "$install_pass_script"
420 export SUDO_ASKPASS="$install_pass_script"
421
422 if [ "$gtk_version" = "Uninstall" ]
423 then
424         uninstall
425 fi
426
427 # Put the install log in tmp, to avoid writing to PWD during a new install
428 rm install.log 2> /dev/null
429 install_log=$(mktemp "${TMPDIR:-/tmp}/geeqie.XXXXXXXXXX")
430
431 sleep 100 | zenity --title="$title" --text="Checking for installed files" --width=370 --progress --pulsate 2> /dev/null &
432 zen_pid=$!
433
434 # Get the standard options that are not yet installed
435 i=0
436 for file in $optional_array
437 do
438         if [ $((i % 2)) -eq 0 ]
439         then
440                 package_title="$file"
441         else
442                 if package_query "$file"
443                 then
444                         if [ -z "$option_string" ]
445                         then
446                                 option_string="${install_option:+${install_option}}\n${package_title}\n${file}"
447                         else
448                                 option_string="${option_string:+${option_string}}\n$install_option\n${package_title}\n${file}"
449                         fi
450                 fi
451         fi
452         i=$((i + 1))
453 done
454
455 kill "$zen_pid" 2> /dev/null
456
457 # Ask the user which options to install
458 if [ -n "$option_string" ]
459 then
460         if ! options=$(printf '%b\n' "$option_string" | zenity --title="$title" --width=400 --height=500 --list --checklist --text 'Select which library files to install:' --column='Select' --column='Library files' --column='Library' --hide-column=3 --print-column=3 2> /dev/null)
461         then
462                 exit_install
463         fi
464 fi
465
466 # Start of Zenity progress section
467 zen_pipe=$(mktemp -u "${TMPDIR:-/tmp}/geeqie.XXXXXXXXXX")
468 mkfifo "$zen_pipe"
469 (tail -f "$zen_pipe" 2> /dev/null) | zenity --progress --title="$title" --width=370 --text="Installing options..." --auto-close --auto-kill --percentage=0 2> /dev/null &
470
471 printf '%b\n' "2" > "$zen_pipe"
472 printf '%b\n' "#Installing essential libraries..." > "$zen_pipe"
473
474 install_essential "$gtk_version"
475
476 printf '%b\n' "4" > "$zen_pipe"
477 printf '%b\n' "#Installing options..." > "$zen_pipe"
478
479 install_options
480
481 printf '%b\n' "6" > "$zen_pipe"
482 printf '%b\n' "#Installing extra loaders..." > "$zen_pipe"
483
484 printf '%b\n' "10" > "$zen_pipe"
485 printf '%b\n' "#Getting new sources from server..." > "$zen_pipe"
486
487 if [ "$mode" = "install" ]
488 then
489         if ! git clone git://geeqie.org/geeqie.git >> "$install_log" 2>&1
490         then
491                 git_error=$(tail -n5 "$install_log" 2>&1)
492                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
493                 exit_install
494         fi
495 else
496         if ! git checkout master >> "$install_log" 2>&1
497         then
498                 git_error="$(tail -n25 "$install_log" 2>&1)"
499                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
500                 exit_install
501         fi
502         if ! git pull >> "$install_log" 2>&1
503         then
504                 git_error=$(tail -n5 "$install_log" 2>&1)
505                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
506                 exit_install
507         fi
508 fi
509
510 printf '%b\n' "20" > "$zen_pipe"
511 printf '%b\n' "#Cleaning installed version..." > "$zen_pipe"
512
513 if [ "$mode" = "install" ]
514 then
515         cd geeqie || exit 1
516 else
517         sudo --askpass  ninja -C build uninstall
518 fi
519
520 printf '%b\n' "30" > "$zen_pipe"
521 printf '%b\n' "#Checkout required version..." > "$zen_pipe"
522
523 if [ -n "$BACK" ]
524 then
525         if ! git checkout master~"$BACK" >> "$install_log" 2>&1
526         then
527                 git_error=$(tail -n5 "$install_log" 2>&1)
528                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
529                 exit_install
530         fi
531 elif [ -n "$COMMIT" ]
532 then
533
534         if ! git checkout "$COMMIT" >> "$install_log" 2>&1
535         then
536                 git_error=$(tail -n5 "$install_log" 2>&1)
537                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
538                 exit_install
539         fi
540 elif [ -n "$TAG" ]
541 then
542         if ! git checkout "$TAG" >> "$install_log" 2>&1
543         then
544                 git_error=$(tail -n5 "$install_log" 2>&1)
545                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
546                 exit_install
547         fi
548 fi
549
550 printf '%b\n' "40" > "$zen_pipe"
551 printf '%b\n' "#Creating configuration files..." > "$zen_pipe"
552
553 if [ -z "${gtk_version%%GTK3*}" ]
554 then
555         meson setup build
556         printf '%b\n' "90 " > "$zen_pipe"
557         printf '%b\n' "#Installing Geeqie..." > "$zen_pipe"
558         ninja -C build install
559 else
560         meson setup build
561         meson configure build
562         printf '%b\n' "90 " > "$zen_pipe"
563         printf '%b\n' "#Installing Geeqie..." > "$zen_pipe"
564         ninja -C build install
565 fi
566
567 rm "$install_pass_script"
568 mv -f "$install_log" "./build/install.log"
569
570 printf '%b\n' "100 " > "$zen_pipe"
571 rm "$zen_pipe"
572
573 (for i in $(seq 0 4 100)
574 do
575         printf '%b\n' "$i"
576         sleep 0.1
577 done) | zenity --progress --title="$title" --width=370 --text="Geeqie installation complete...\n" --auto-close --percentage=0 2> /dev/null
578
579 exit