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