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