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