Fix #1096: Debian install script fails on Debian 11.7
[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 [ "$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         exit
426 fi
427
428 # Put the install log in tmp, to avoid writing to PWD during a new install
429 rm install.log 2> /dev/null
430 install_log=$(mktemp "${TMPDIR:-/tmp}/geeqie.XXXXXXXXXX")
431
432 sleep 100 | zenity --title="$title" --text="Checking for installed files" --width=370 --progress --pulsate 2> /dev/null &
433 zen_pid=$!
434
435 # Get the standard options that are not yet installed
436 i=0
437 for file in $optional_array
438 do
439         if [ $((i % 2)) -eq 0 ]
440         then
441                 package_title="$file"
442         else
443                 if package_query "$file"
444                 then
445                         if [ -z "$option_string" ]
446                         then
447                                 option_string="${install_option:+${install_option}}\n${package_title}\n${file}"
448                         else
449                                 option_string="${option_string:+${option_string}}\n$install_option\n${package_title}\n${file}"
450                         fi
451                 fi
452         fi
453         i=$((i + 1))
454 done
455
456 kill $zen_pid 2> /dev/null
457
458 # Ask the user which options to install
459 if [ -n "$option_string" ]
460 then
461         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)
462         then
463                 exit_install
464         fi
465 fi
466
467 # Start of Zenity progress section
468 zen_pipe=$(mktemp -u "${TMPDIR:-/tmp}/geeqie.XXXXXXXXXX")
469 mkfifo "$zen_pipe"
470 (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 &
471
472 printf '%b\n' "2" > "$zen_pipe"
473 printf '%b\n' "#Installing essential libraries..." > "$zen_pipe"
474
475 install_essential "$gtk_version"
476
477 printf '%b\n' "4" > "$zen_pipe"
478 printf '%b\n' "#Installing options..." > "$zen_pipe"
479
480 install_options
481
482 printf '%b\n' "6" > "$zen_pipe"
483 printf '%b\n' "#Installing extra loaders..." > "$zen_pipe"
484
485 printf '%b\n' "10" > "$zen_pipe"
486 printf '%b\n' "#Getting new sources from server..." > "$zen_pipe"
487
488 if [ "$mode" = "install" ]
489 then
490         if ! git clone git://geeqie.org/geeqie.git >> "$install_log" 2>&1
491         then
492                 git_error=$(tail -n5 "$install_log" 2>&1)
493                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
494                 exit_install
495         fi
496 else
497         if ! git checkout master >> "$install_log" 2>&1
498         then
499                 git_error="$(tail -n25 "$install_log" 2>&1)"
500                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
501                 exit_install
502         fi
503         if ! git pull >> "$install_log" 2>&1
504         then
505                 git_error=$(tail -n5 "$install_log" 2>&1)
506                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
507                 exit_install
508         fi
509 fi
510
511 printf '%b\n' "20" > "$zen_pipe"
512 printf '%b\n' "#Cleaning installed version..." > "$zen_pipe"
513
514 if [ $mode = "install" ]
515 then
516         cd geeqie || exit 1
517 else
518         sudo --askpass  ninja -C build uninstall
519 fi
520
521 printf '%b\n' "30" > "$zen_pipe"
522 printf '%b\n' "#Checkout required version..." > "$zen_pipe"
523
524 if [ "$BACK" ]
525 then
526         if ! git checkout master~"$BACK" >> "$install_log" 2>&1
527         then
528                 git_error=$(tail -n5 "$install_log" 2>&1)
529                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
530                 exit_install
531         fi
532 elif [ "$COMMIT" ]
533 then
534
535         if ! git checkout "$COMMIT" >> "$install_log" 2>&1
536         then
537                 git_error=$(tail -n5 "$install_log" 2>&1)
538                 zenity --title="$title" --width=370 --height=400 --error --text="Git error:\n\n$git_error" 2> /dev/null
539                 exit_install
540         fi
541 elif [ "$TAG" ]
542 then
543         if ! git checkout "$TAG" >> "$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                 exit
549         fi
550 fi
551
552 printf '%b\n' "40" > "$zen_pipe"
553 printf '%b\n' "#Creating configuration files..." > "$zen_pipe"
554
555 if [ -z "${gtk_version%%GTK3*}" ]
556 then
557         meson setup build
558         printf '%b\n' "90 " > "$zen_pipe"
559         printf '%b\n' "#Installing Geeqie..." > "$zen_pipe"
560         ninja -C build install
561 else
562         meson setup build
563         meson configure build
564         printf '%b\n' "90 " > "$zen_pipe"
565         printf '%b\n' "#Installing Geeqie..." > "$zen_pipe"
566         ninja -C build install
567 fi
568
569 rm "$install_pass_script"
570 mv -f "$install_log" "./build/install.log"
571
572 printf '%b\n' "100 " > "$zen_pipe"
573 rm "$zen_pipe"
574
575 (for i in $(seq 0 4 100)
576 do
577         printf '%b\n' "$i"
578         sleep 0.1
579 done) | zenity --progress --title="$title" --width=370 --text="Geeqie installation complete...\n" --auto-close --percentage=0 2> /dev/null
580
581 exit