-
Notifications
You must be signed in to change notification settings - Fork 39
/
genup
executable file
·836 lines (826 loc) · 33.9 KB
/
genup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
#!/bin/bash
#
# Update portage tree and eix, then bring all packages in @world up-to-date.
# Clean up at the end, ensuring changes to files in /etc are processed.
# Will offer to update the kernel, if a new version has become available.
# Intended to be run interactively.
#
# Copyright (c) 2014-2020 sakaki <[email protected]>
#
# License (GPL v3.0)
# ------------------
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
set -e
set -u
shopt -s nullglob
# Scroll to the bottom of this script to follow the main program flow.
# ********************** variables *********************
PROGNAME="$(basename "${0}")"
VERSION="1.0.28"
ETCPROFILE="/etc/profile"
UPDATERSDIR="/etc/${PROGNAME}/updaters.d"
FIXUPSCRIPT="/etc/cron.weekly/fixup"
RED_TEXT="" GREEN_TEXT="" YELLOW_TEXT="" RESET_ATTS="" ALERT_TEXT=""
if [[ -v TERM && -n "${TERM}" && "${TERM}" != "dumb" ]]; then
RED_TEXT="$(tput setaf 1)$(tput bold)"
GREEN_TEXT="$(tput setaf 2)$(tput bold)"
YELLOW_TEXT="$(tput setaf 3)$(tput bold)"
RESET_ATTS="$(tput sgr0)"
ALERT_TEXT="$(tput bel)"
fi
declare -i VERBOSITY=1
PREFIXSTRING="* "
SHOWPREFIX="${GREEN_TEXT}${PREFIXSTRING}${RESET_ATTS}"
SHOWSUFFIX=""
# following variable is conformed on installation by ebuild
# (to reflect setting of "buildkernel" USE flag)
USE_BUILDKERNEL=true
# following variable is conformed on installation by ebuild
# (to reflect setting of "emtee" USE flag)
USE_EMTEE=false
VERBOSITYFLAG=""
ASKFLAG=""
ALERTFLAG=""
EMERGE=""
EMERGEARGS=""
BUILDKERNEL=""
BUILDKERNELARGS=""
EIXSYNCARGS=""
PUMP=""
NOPUMP="-distcc -distcc-pump"
FALLBACK_SENTINEL="/tmp/.full-emptytree-emerge-performed"
PORTAGEINFO=""
PORTAGEFEATURES=""
USE_NOCACHE=false
NOCACHE=""
if "${USE_NOCACHE}"; then
NOCACHE="nocache"
fi
declare -i KERNELBUILT=0 KERNELDEPLOYED=0 NEEDSDISPATCHCONF=0
declare -i WEBRSYNC=0
# program arguments (booleans in this case)
declare -i ARG_ASK=0 ARG_DEPLOYFROMSTAGING=0 ARG_HELP=0 ARG_NO_KERNEL_UPGRADE=0
declare -i ARG_VERBOSE=0 ARG_VERSION=0 ARG_DISPATCHCONF=0
declare -i ARG_KEEP_OLD_DISTFILES=0
declare -i ARG_NO_PERL_CLEANER=0
declare -i ARG_NO_EIX_SYNC=0 ARG_ALERT=0
declare -i ARG_IGNORE_REQUIRED_CHANGES=0 ARG_NO_CUSTOM_UPDATERS=0
declare -i ARG_NO_FIXUPS=0
declare -i ARG_NO_EIX_METADATA_UPDATE=0 ARG_NO_NOCACHE=0
declare -i ARG_NO_MODULE_REBUILD=0
declare -i ADJUSTMENT=19
# force TERM if none found (e.g. when running from cron)
# otherwise mach builds (firefox etc.) will fail
if ! tty -s; then
export TERM="dumb"
fi
# store copy of original args, and canonical path to genup itself
ORIGINAL_ARGS="${@}"
SCRIPTPATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
# ***************** various functions ******************
cleanup_and_exit_with_code() {
# add any cleanup code here
trap - EXIT
exit $1
}
show() {
local MESSAGE=${1:-""}
local VERBLEVEL=${2:-${VERBOSITY}}
if (( VERBLEVEL >=1 )); then
echo -e "${SHOWPREFIX}${MESSAGE}${SHOWSUFFIX}"
fi
}
alertshow() {
local MESSAGE=${1:-""}
local VERBLEVEL=${2:-${VERBOSITY}}
if ((ARG_ALERT==0)); then
show "${@}"
elif (( VERBLEVEL >=1 )); then
echo -e "${SHOWPREFIX}${MESSAGE}${SHOWSUFFIX}${ALERT_TEXT}"
fi
}
warning() {
echo -e "${YELLOW_TEXT}${PREFIXSTRING}${RESET_ATTS}${PROGNAME}: Warning: ${1}" >&2
}
die() {
echo
echo -e "${RED_TEXT}${PREFIXSTRING}${RESET_ATTS}${PROGNAME}: Error: ${1} - exiting" >&2
cleanup_and_exit_with_code 1
}
trap_cleanup() {
trap - SIGHUP SIGQUIT SIGINT SIGTERM SIGKILL EXIT
die "Caught signal"
}
trap trap_cleanup SIGHUP SIGQUIT SIGINT SIGTERM SIGKILL EXIT
test_yn() {
echo -n -e "${SHOWPREFIX}${1} (y/n)? ${SHOWSUFFIX}${ALERT_TEXT}"
read -r -n 1
echo
if [[ ${REPLY} =~ ^[Yy]$ ]]; then
return 0
else
return 1
fi
}
continue_yn() {
if ! test_yn "${1}"; then
echo -e "${RED_TEXT}${PREFIXSTRING}${RESET_ATTS}Quitting" >&2
cleanup_and_exit_with_code 1
fi
}
suppress_colours() {
RED_TEXT=""
GREEN_TEXT=""
YELLOW_TEXT=""
RESET_ATTS=""
SHOWPREFIX="${PREFIXSTRING}"
}
suppress_alert() {
ALERT_TEXT=""
}
suppress_colour_and_alert_if_output_not_to_a_terminal() {
if [ ! -t 1 -o ! -t 2 ]; then
# we are going to a non-terminal
suppress_colours
suppress_alert
fi
}
set_idle_io_priority() {
# prevent our operations stalling swap
ionice -c 3 -p $$
}
read_portage_info_if_necessary() {
if [ -z "${PORTAGEINFO}" ]; then
show "Checking Portage configuration, please wait..."
PORTAGEINFO="$(emerge --info)"
fi
}
check_gcc_config_and_reset_if_necessary() {
# check if gcc-config exists with an error - if it does, then
# attempt to set one based on the current gcc version number
# see https://wiki.gentoo.org/wiki/Upgrading_GCC
if ! gcc-config --get-current-profile >/dev/null 2>&1; then
# unset or invalid, attempt to force this to the current gcc
# version
read_portage_info_if_necessary
local CHOST="$(grep '^CHOST=.*' <<<"${PORTAGEINFO}")"
CHOST="$(cut -d\" -f2 <<< ${CHOST})"
local GCC_VERSION="$(eix --installed --exact sys-devel/gcc --format '<installedversions:NAMEVERSION>' --versionsort | tail -n 1)"
GCC_VERSION="${GCC_VERSION##*gcc-}"
local FULL_GCC_ID="${CHOST}-${GCC_VERSION}"
if gcc-config "${FULL_GCC_ID}"; then
warning "gcc configuration was reset"
env-update
if [ -s "${ETCPROFILE}" ]; then
set +e
set +u
source "${ETCPROFILE}"
set -e
set -u
fi
${EMERGE} ${VERBOSITYFLAG} --oneshot sys-devel/libtool
else
die "failed to set gcc configuration"
fi
fi
}
display_greeting() {
show "Gentoo System Updater v${VERSION}"
}
update_portage_tree_and_sync_eix() {
if ((ARG_NO_EIX_SYNC==0)); then
if ((WEBRSYNC==1)); then
# eix-sync will ignore other overlays in webrsync-gpg mode, so
# force them to update, and do this first, so changes are picked up
# by eix-update
# NB - make sure you have the "gentoo" overlay set to
# auto-sync = no in /etc/portage/repos.conf/gentoo.conf, otherwise
# it will also be rsync'd by the below, which is probably not
# what you want when webrsync-gpg is in use
show "Running emaint sync --auto to update overlays"
show "(make sure you have auto-sync = no in gentoo.conf)..."
${NOCACHE} emaint sync --auto
fi
show "Updating Portage tree and syncing the eix cache"
show "(this may take some time)..."
# no longer explicitly set -q
# (user can still do so via --eix-sync-args)
${NOCACHE} eix-sync ${EIXSYNCARGS}
else
warning "As requested, not performing eix-sync"
if ((WEBRSYNC==1)); then
warning "(also suppressing emaint sync --auto)"
fi
fi
}
remove_any_prior_emerge_resume_history() {
# as if we call emerge --resume later, we don't want any hangovers from the
# previous invocation
show "Removing any prior emerge history..."
emaint --fix cleanresume
}
ensure_portage_itself_is_up_to_date() {
show "Bringing Portage itself up to date..."
# don't fail on this, as an @world update may solve any blocks
${EMERGE} ${VERBOSITYFLAG} --oneshot --update sys-apps/portage || \
warning "Could not update Portage: proceeding anyway"
}
ensure_genup_itself_is_up_to_date() {
show "Bringing genup itself up to date..."
${EMERGE} ${VERBOSITYFLAG} --oneshot --update app-portage/genup
# if the above caused the version of genup to change, exec ourselves
# for a full restart
if [[ $("${SCRIPTPATH}" --version) != ${VERSION} ]]; then
warning "The version of genup has changed!"
warning "Restarting genup process..."
exec "${SCRIPTPATH}" ${ORIGINAL_ARGS}
fi
}
try_emtee_update_if_enabled() {
# if the emtee USE flag is enabled, then try doing an initial
# @world update with this tool; it is considerably less
# resource intensive in some update situations (and can
# also sometimes compute a successful update in cases where
# a vanilla emerge -DuU --with-bdeps=y @world fails)
if "${USE_EMTEE}"; then
# this is allowed to fail, since we'll try a full @world
# emerge afterwards anyhow
show "Attempting to update @world set (for new versions, or changed use flags)"
show "using emtee..."
rm -f "${FALLBACK_SENTINEL}"
if ${PUMP} emtee ${ASKFLAG} ${ALERTFLAG} ${VERBOSITYFLAG} --emerge-args="${EMERGEARGS}" --full-build-fallback-threshold=75; then
show "emtee run completed successfully!"
else
warning "emtee @world build did not complete successfully!"
fi
fi
}
update_all_packages_in_world_set_and_dependencies() {
# performs deep dependency tree update, including build-time dependencies
# will update any package whose use flags have changed
# the @world set includes the @system set
# will not re-emerge packages that are already up-to-date
declare -i RC USER_CHANGES_REQUIRED=0
show "Updating @world set (for new versions, or changed use flags)..."
if ((ARG_ASK==0 && ARG_IGNORE_REQUIRED_CHANGES==0)); then
# if in non-interactive mode, we'll check first if the build
# looks possible; you can set the --ignore-required-changes option to
# suppress this test
if grep -qi "The following \(keyword\|mask\|USE\|license\) changes are necessary to proceed" \
<(${EMERGE} ${VERBOSITYFLAG} ${EMERGEARGS} --pretend --deep \
--with-bdeps=y --changed-use --update --backtrack=50 @world 2>&1 || true); then
# silently note this fact, then fail later
USER_CHANGES_REQUIRED=1
fi
fi
if ! ${PUMP} ${EMERGE} ${ASKFLAG} ${ALERTFLAG} ${VERBOSITYFLAG} ${EMERGEARGS} --deep \
--with-bdeps=y --changed-use --update --backtrack=50 @world; then
# per make manpage, if multiple "j" opts are specified, the last
# one takes precedence, so this is legitimate
if MAKEOPTS="${MAKEOPTS-} -j1" FEATURES="${NOPUMP}" ${EMERGE} --resume; then
warning "emerge completed successfully, but only by restricting"
warning "build parallelism and distcc"
else
# we still have a problem, allow the user to attempt to fix if
# running interactively
if ((ARG_ASK==1)); then
warning "emerge did not complete successfully"
show "You can try to fix the problem in another console, then return here"
show "and resume the emerge"
continue_yn "Attempt to resume the emerge now"
MAKEOPTS="${MAKEOPTS-} -j1" ${EMERGE} --resume
else
die "Failed to complete the emerge due to error"
fi
fi
fi
# this may have looked like it went OK, but still failed, because user
# changes to e.g. /etc/portage/package.use are required (the resume
# list will be empty in this case, so the retry with parallelism
# off will 'succeed'): if this happens we'll bail out (unless explicitly
# requested not to, via the --ignore-required-changes option)
if ((USER_CHANGES_REQUIRED==1)); then
die "Could not update @world because config changes required (please see above)"
fi
}
rebuild_external_modules_if_necessary() {
if ((ARG_NO_MODULE_REBUILD==1)); then
return
fi
show "Creating any necessary external modules (e.g., VirtualBox)..."
# exclude packages ending in '-bin'... by convention, these are binary
# packages which means they aren't going to rebuild anything
# (and may even be binary kernel packages, swept up into the
# @module-rebuild set as they 'own' kernel modules in
# /lib/modules/<release>/...)
if ! ${PUMP} ${EMERGE} ${VERBOSITYFLAG} @module-rebuild --exclude '*-bin'; then
if MAKEOPTS="${MAKEOPTS-} -j1" FEATURES="${NOPUMP}" ${EMERGE} --resume; then
warning "emerge @module-rebuild completed successfully, but only by restricting"
warning "build parallelism and distcc"
else
warning "Failed to complete emerge @module-rebuild due to error"
warning "Continuing..."
fi
fi
}
rebuild_packages_depending_on_stale_libraries() {
# when a shared library gets updated, and its soname is changed
# all its consumers are not automatically rebuilt; assuming (the default)
# that the preserve-libs feature is set, Portage will keep the old
# library around (so that the application depending on it will keep working)
# the below emerge will rebuild any such consumers, so that the old
# library may be freed
show "Rebuilding any consumers of old shared libraries, which did not autoupdate..."
# do this twice - first, with getbinpkg enabled (as this'll pick up anything
# already rebuilt on the binhost, if one is used, saving time) and then again with it
# disabled, in case there are any local packages which need rebuilding (and
# where we need to suppress getbinpkg, otherwise it'll just re-install from the
# local tbz2)
if ! ${PUMP} ${EMERGE} ${VERBOSITYFLAG} @preserved-rebuild; then
if MAKEOPTS="${MAKEOPTS-} -j1" FEATURES="${NOPUMP}" ${EMERGE} --resume; then
warning "emerge @preserved-rebuild completed successfully, but only by restricting"
warning "build parallelism and distcc"
else
warning "Failed to complete emerge @preserved-rebuild due to error"
fi
fi
show "Rebuilding again, with getbinpkg suppressed, to catch any local-only packages..."
if ! FEATURES="-getbinpkg" ${PUMP} ${EMERGE} ${VERBOSITYFLAG} @preserved-rebuild; then
if MAKEOPTS="${MAKEOPTS-} -j1" FEATURES="-getbinpkg ${NOPUMP}" ${EMERGE} --resume; then
warning "emerge @preserved-rebuild completed successfully, but only by restricting"
warning "build parallelism and distcc"
else
die "Failed to complete emerge @preserved-rebuild due to error"
fi
fi
}
bring_old_perl_modules_up_to_date() {
# perl modules are built for a particular perl target, but are *not*
# automatically rebuilt when perl upgrades to a higher version - the
# below script fixes this
if ((ARG_NO_PERL_CLEANER==0)); then
show "Ensuring perl modules are matched to current version of perl..."
perl-cleaner ${VERBOSITYFLAG} --all
fi
}
cleanup_python_config() {
# remove uninstalled versions from /etc/python-exec/python-exec.conf
eselect python cleanup
}
run_custom_updaters_if_present() {
# if not inhibited, find any executable files in the /etc/genup/updaters.d
# top-level directory (resolving symlinks) and execute them in turn,
# failing if any returns a non-zero exit code
local NEXTPATH
local REALPATH
if ((ARG_NO_CUSTOM_UPDATERS==0)); then
if [ -d "${UPDATERSDIR}" ]; then
for NEXTPATH in "${UPDATERSDIR}"/*; do
REALPATH="$(readlink --canonicalize "${NEXTPATH}")"
if [[ -f "${REALPATH}" && -s "${REALPATH}" && -x "${REALPATH}" ]]; then
show "Running custom updater '${NEXTPATH}'..."
if ! "${REALPATH}"; then
die "Error running custom updater '${NEXTPATH}'"
fi
fi
done
fi
fi
}
run_fixups_if_present() {
# if not inhibited, and running on aarch64, and the file
# /etc/cron.weekly/fixup is present and executable, run it: this
# will apply any pending hotfixes, which is generally
# good hygiene to do prior to performing an update (this is
# currently only really of application on RPi systems running
# the gentoo-on-rpi-64bit image)
# NB: we do not treat it as a fatal error if some or all of the
# fixup scripts fail to complete successfully
if ((ARG_NO_FIXUPS==0)) && [[ -x "${FIXUPSCRIPT}" && "aarch64" == "$(uname -m)" ]]; then
show "Running fixup scripts via '${FIXUPSCRIPT}'..."
if ! "${FIXUPSCRIPT}"; then
warning "Not all fixups ran successfully!"
warning "Continuing anyway; check the log file"
warning "'/var/log/latest-fixup-run.log' for further details."
fi
fi
}
check_if_dispatch_conf_needs_to_be_run() {
# check if the user has any configuration file changes pending review
# by dispatch-conf, and set the NEEDSDISPATCHCONF variable accordingly
# we do a rough check to see if there are any pending changes
local DIRS_TO_CHECK="$(emerge --info | grep '^CONFIG_PROTECT=' | cut -d"\"" -f2)"
local PENDING_CHANGES="$(find ${DIRS_TO_CHECK} -name '*._cfg*' -type f -print)"
if [ -n "${PENDING_CHANGES}" ]; then
NEEDSDISPATCHCONF=1
else
NEEDSDISPATCHCONF=0
fi
}
interactively_resolve_clashing_config_file_changes() {
# where user has changed an e.g. /etc/ file overwritten by a package
# update, invoke an interactive tool allowing them to resolve the issue
# only available in interactive mode...
check_if_dispatch_conf_needs_to_be_run
if ((NEEDSDISPATCHCONF==1)); then
if ((ARG_ASK==1 || ARG_DISPATCHCONF==1)); then
alertshow "Handing any updated configuration file clashes..."
dispatch-conf
NEEDSDISPATCHCONF=2 # special flag; we'll recheck later
fi
# otherwise, user will be warned at end to run dispatch-conf
else
show "No configuration files need updating"
fi
}
offer_kernel_upgrade_to_staging_if_available() {
# we may have been instructed not to do this...
if ((ARG_NO_KERNEL_UPGRADE==1)); then
return
fi
local CURRENT_KV="$(readlink /usr/src/linux)"
local LATEST_KV_LINE="$(eselect kernel list | tail -n 1)"
local LATEST_KV="$(awk '{print $2}' <<< ${LATEST_KV_LINE})"
local LATEST_KV_INDEX="$(cut -d '[' -f 2 <<< ${LATEST_KV_LINE} | cut -d ']' -f 1)"
if ! grep -q '*' <<< "${LATEST_KV_LINE}"; then
show "A kernel upgrade is available! You are running ${CURRENT_KV}"
if ((ARG_ASK==0)) || test_yn "Would you like to upgrade to ${LATEST_KV}"; then
show "Setting up new kernel in staging..."
eselect kernel set "${LATEST_KV_INDEX}"
show "Entering buildkernel..."
# following does not require your USB key to be inserted, as it
# only builds to staging in /boot...
${BUILDKERNEL} ${ASKFLAG} ${ALERTFLAG} ${VERBOSITYFLAG} ${BUILDKERNELARGS} --stage-only
KERNELBUILT=1
else
show "OK, leaving your kernel as is, to upgrade subsequently, issue:"
show " eselect kernel list"
show " eselect kernel set <n>"
show " buildkernel"
fi
else
show "Your kernel (${CURRENT_KV}) is the latest version available!"
fi
}
purge_old_distfiles_if_desired() {
# by default, Portage keeps old source tarballs (distfiles) around
# forever (in /usr/portage/distfiles); the following command, from the
# gentoolkit package, will get rid of any not related to a currently
# installed ebuild
if ((ARG_KEEP_OLD_DISTFILES==0)); then
show "Purging currently unused source tarballs to save space..."
eclean ${VERBOSITYFLAG} --deep distfiles
fi
}
copy_new_kernel_from_staging_if_present_and_desired() {
declare -i DO_KERNELDEPLOY=0
if ((KERNELBUILT==1)); then
# we successfully built a new kernel to staging, now deploy it
# if the user wishes to
if ((ARG_DEPLOYFROMSTAGING==1)); then
DO_KERNELDEPLOY=1
elif ((ARG_ASK==1)); then
if test_yn "Would you like to copy your new kernel to the EFI system partition?"; then
DO_KERNELDEPLOY=1
fi
fi
if ((DO_KERNELDEPLOY==1)); then
show "Copying new kernel from staging..."
buildkernel ${ASKFLAG} ${ALERTFLAG} ${VERBOSITYFLAG} --copy-from-staging
KERNELDEPLOYED=1
fi
fi
}
update_environment() {
# append values in /etc/env.d/... files into /etc/profile.env
# also create /etc/ld.so.conf, and run ldconfig (to recreate
# /etc/ld.so.cache)
env-update
}
update_eix_metadata() {
# ensure eix metadata is up-to-date (will not be if
# only non-gentoo repos have changed in this run)
if ((ARG_NO_EIX_METADATA_UPDATE==0)); then
# following does not hit the network
show "Updating eix metadata..."
eix-sync -0 |& sed -e '/^Processing/d'
else
warning "As requested, not updating eix metadata"
fi
}
remove_unreferenced_packages() {
# following should be reasonably safe, it removes any packages that are not
# required by the transitive closure of @world set dependencies
show "Removing packages not required by @world set..."
${EMERGE} ${ASKFLAG} ${ALERTFLAG} ${VERBOSITYFLAG} --depclean
# we may have just blown away our old version of gcc, but not enabled
# the replacement version's config, so...
check_gcc_config_and_reset_if_necessary
}
rebuild_where_missing_libraries_detected() {
# check for missing shared library dependencies (possibly caused by
# emerge --depclean) and attempt to fix them, by re-emerging the broken
# libraries and binaries (shouldn't do much nowadays, but good to check!)
show "Fixing any broken/missing libraries and binaries caused by cleanup..."
revdep-rebuild
}
display_final_status() {
show
if ((KERNELBUILT==1)); then
if ((KERNELDEPLOYED==1)); then
show "A new kernel has been built successfully, and deployed to your"
show "EFI system partition; it will be used from the next reboot."
else
show "An updated kernel has been successfully built in the staging area!"
show "You can install it to your EFI system partition by issuing:"
show " buildkernel --copy-from-staging"
fi
elif ((ARG_NO_KERNEL_UPGRADE==0)); then
if buildkernel --is-new-kernel-available; then
warning "You are currently running with an older kernel"
warning "When ready, ensure you have copied the new version"
warning "to the EFI system partition"
warning "(using buildkernel --copy-from-staging), and then reboot to"
warning "start using it."
fi
fi
if ((NEEDSDISPATCHCONF==2)); then
# double-check that the user resolved everything earlier
check_if_dispatch_conf_needs_to_be_run
fi
if ((NEEDSDISPATCHCONF==1)); then
warning "There are configuration file changes pending review!"
warning "Please run dispatch-conf to interactively resolve them."
if "${USE_EMTEE}" && [[ -f "${FALLBACK_SENTINEL}" ]]; then
rm -f "${FALLBACK_SENTINEL}"
warning " TAKE CARE: a full --emptytree @world emerge has been performed;"
warning " you may need to retain your current version of many"
warning " configuration files - when prompted by dispatch-conf - to"
warning " retain full system functionality!"
warning " (use the 'z' / 'zap new' option where unsure)"
fi
else
show "There are no configuration file changes pending review."
fi
show "You may now wish to issue:"
show " source /etc/profile"
show "to ensure your current shell environment is fully up-to-date."
show "Subsequent login shells will automatically pick up any changes."
show
show "All done - your system is now up-to-date!"
}
print_usage() {
cat << EOF
Usage: ${PROGNAME} [options]
Options:
-a, --ask turns on interactive mode: you must confirm key actions
-A, --alert sound terminal bell when interaction required
(selecting this also automatically selects --ask)
-b, --buildkernel-args=ARGS
pass provided additional ARGS to the initial
(staging) buildkernel invocation (requires buildkernel
USE flag to have been set)
-c, --dispatch-conf run dispatch-conf, even if in non-interactive mode
-C, --no-custom-updaters
do not run any custom updaters from the
/etc/genup/updaters.d directory
-d, --deploy-from-staging
if an updated kernel is successfully built in staging,
afterwards try to copy it onto the EFI system partition
(requires buildkernel USE flag to have been set)
-e, --emerge-args=ARGS
pass provided additional ARGS to the main emerge
e.g., use --emerge-args='--autounmask-write' to
automatically make necessary changes to config files
-E, --no-emtee don't attempt to use the emtee tool, even when the
eponymous USE flag has been enabled
-F, --no-fixups
do not attempt to run /etc/cron.weekly/fixup, even
where this file is present and executable (fixups
are only in use on aarch64 systems)
-h, --help show this help message and exit
-i, --ignore-required-changes
don't exit with an error in the event that user-driven
changes are required (to /etc/portage/package.use etc.)
in order to complete the @world update step
-k, --keep-old-distfiles
don't purge source tarballs (distfiles) for uninstalled
versions of packages (or uninstalled packages)
-m, --no-eix-metadata-update
don't attempt to update eix metadata at the
completion of the run
-M, --no-module-rebuild
don't attempt to rebuild external modules
-n, --no-kernel-upgrade
do not attempt to run buildkernel (implied if
buildkernel USE flag has not been set)
-N, --no-nocache do not attempt to use nocache with eix-sync, even
when the nocache USE flag has been set
-p, --no-perl-cleaner do not attempt to run perl-cleaner
-r, --adjustment=N add integer N to the build niceness -20<=N<=19
(the default is 19, running builds at lowest possible
system priority to avoid slowing the system too much)
-S, --no-eix-sync do not attempt to run emaint sync --auto or eix-sync
-v, --verbose ask called programs to display more information
-V, --version display the version number of ${PROGNAME} and exit
-x, --eix-sync-args=ARGS
pass provided additional ARGS to eix-sync
(e.g. use --eix-sync-args="-q" to suppress output)
EOF
}
print_help() {
cat << EOF
${PROGNAME} - update Portage tree, all installed packages, and kernel
EOF
print_usage
}
print_version() {
printf "%s\n" "${VERSION}"
}
display_usage_message_and_bail_out() {
if [ ! -z "${1+x}" ]; then
printf "%s: %s\n" "${PROGNAME}" "${1}" >&2
fi
print_usage >&2
cleanup_and_exit_with_code 1
}
internal_consistency_option_checks() {
# following not exhaustive, just some more obvious snafus
local KERNMSG="--no-kernel-upgrade"
if ! "${USE_BUILDKERNEL}"; then
KERNMSG="buildkernel USE flag unset"
fi
if ((ARG_NO_KERNEL_UPGRADE==1)) || ! "${USE_BUILDKERNEL}"; then
if [[ -n "${BUILDKERNELARGS}" ]]; then
display_usage_message_and_bail_out "cannot specify --buildkernel-args with ${KERNMSG}"
fi
if ((ARG_DEPLOYFROMSTAGING==1)); then
display_usage_message_and_bail_out "cannot specify --deploy-from-staging with ${KERNMSG}"
fi
fi
if ((ADJUSTMENT<-20 || ADJUSTMENT>19)); then
display_usage_message_and_bail_out "must have -20 <= build niceness adjustment <= 19"
fi
}
read_portage_features_if_necessary() {
read_portage_info_if_necessary
if [ -z "${PORTAGEFEATURES}" ]; then
PORTAGEFEATURES="$(grep '^FEATURES.*$' <<<"${PORTAGEINFO}")"
fi
}
check_if_using_webrsync_gpg() {
# we have to amend the args to eix if using webrsync-gpg feature
read_portage_features_if_necessary
if grep -qi "webrsync-gpg" <<<"${PORTAGEFEATURES}"; then
# force use of emerge-webrsync instead of emerge --sync
show "Portage feature webrsync-gpg detected: using -w option with eix-sync"
EIXSYNCARGS="-w ${EIXSYNCARGS}"
WEBRSYNC=1
fi
}
check_if_using_distcc() {
# check for the relevant feature... turn on PUMP prefix if
# we find it
read_portage_features_if_necessary
if grep -qi "distcc-pump" <<<"${PORTAGEFEATURES}"; then
# set prefix for emerge in normal situation...
show "Portage feature distcc-pump detected: will pump emerge"
PUMP="" # no need for this, will work automatically
fi
}
process_command_line_options() {
local TEMP
declare -i RC
set +e
# error trapping off, as we want to handle errors
TEMP="$(getopt -o aAb:cCde:EFhikmMnNpr:SvVx: --long ask,alert,buildkernel-args:,dispatch-conf,no-custom-updaters,deploy-from-staging,emerge-args:,no-emtee,no-fixups,help,ignore-required-changes,keep-old-distfiles,no-eix-metadata-update,no-module-rebuild,no-kernel-upgrade,no-nocache,no-perl-cleaner,adjustment:,no-eix-sync,verbose,version,eix-sync-args: -n "${PROGNAME}" -- "${@}")"
RC="${?}"
set -e
if ((RC!=0)); then
display_usage_message_and_bail_out
fi
eval set -- "${TEMP}"
# extract options and their arguments into variables.
while true ; do
case "${1}" in
-a|--ask) ARG_ASK=1 ; shift ;;
-A|--alert) ARG_ALERT=1 ; ARG_ASK=1 ; shift ;;
-b|--buildkernel-args)
case "${2}" in
"") shift 2 ;;
*) BUILDKERNELARGS="${2}" ; shift 2 ;;
esac ;;
-c|--dispatch-conf) ARG_DISPATCHCONF=1 ; shift ;;
-C|--no-custom-updaters) ARG_NO_CUSTOM_UPDATERS=1 ; shift ;;
-d|--deploy-from-staging) ARG_DEPLOYFROMSTAGING=1 ; shift ;;
-e|--emerge-args)
case "${2}" in
"") shift 2 ;;
*) EMERGEARGS="${2}" ; shift 2 ;;
esac ;;
-E|--no-emtee) USE_EMTEE=false ; shift ;;
-F|--no-fixups) ARG_NO_FIXUPS=1 ; shift ;;
-h|--help) ARG_HELP=1 ; shift ;;
-i|--ignore-required-changes) ARG_IGNORE_REQUIRED_CHANGES=1 ; shift ;;
-k|--keep-old-distfiles) ARG_KEEP_OLD_DISTFILES=1 ; shift ;;
-m|--no-eix-metadata-update) ARG_NO_EIX_METADATA_UPDATE=1 ; shift ;;
-M|--no-module-rebuild) ARG_NO_MODULE_REBUILD=1 ; shift ;;
-n|--no-kernel-upgrade) ARG_NO_KERNEL_UPGRADE=1 ; shift ;;
-N|--no-nocache) ARG_NO_NOCACHE=1 ; shift ;;
-p|--no-perl-cleaner) ARG_NO_PERL_CLEANER=1 ; shift ;;
-r|--adjustment)
case "${2}" in
"") shift 2 ;;
*) ADJUSTMENT="${2}" ; shift 2 ;;
esac ;;
-S|--no-eix-sync) ARG_NO_EIX_SYNC=1 ; shift ;;
-v|--verbose) ARG_VERBOSE=1 ; shift ;;
-V|--version) ARG_VERSION=1 ; shift ;;
-x|--eix-sync-args)
case "${2}" in
"") shift 2 ;;
*) EIXSYNCARGS="${2}" ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) die "Internal error!" ;;
esac
done
# process 'perform-then-exit' options
if ((ARG_HELP==1)); then
print_help
cleanup_and_exit_with_code 0
elif ((ARG_VERSION==1)); then
print_version
cleanup_and_exit_with_code 0
fi
# setup emerge, buildkernel commands with specified niceness
EMERGE="nice -n ${ADJUSTMENT} emerge"
BUILDKERNEL="nice -n ${ADJUSTMENT} buildkernel"
# set verbosity
if ((ARG_VERBOSE==1)); then
VERBOSITY+=1
fi
if ((VERBOSITY>1)); then
VERBOSITYFLAG="--verbose"
fi
# set interactive mode
if ((ARG_ASK==1)); then
ASKFLAG="--ask"
fi
if ((ARG_ALERT==1)); then
ALERTFLAG="--alert"
else
suppress_alert
fi
# force 'no kernel upgrade' mode if buildkernel USE flag not set
if ! "${USE_BUILDKERNEL}"; then
ARG_NO_KERNEL_UPGRADE=1
fi
if ((ARG_NO_NOCACHE==1)); then
NOCACHE=""
fi
internal_consistency_option_checks
}
# *************** start of script proper ***************
suppress_colour_and_alert_if_output_not_to_a_terminal
set_idle_io_priority
process_command_line_options "${@}"
check_if_using_webrsync_gpg
check_if_using_distcc
display_greeting
check_gcc_config_and_reset_if_necessary
update_portage_tree_and_sync_eix
remove_any_prior_emerge_resume_history
run_fixups_if_present
ensure_portage_itself_is_up_to_date
ensure_genup_itself_is_up_to_date
try_emtee_update_if_enabled
update_all_packages_in_world_set_and_dependencies
remove_unreferenced_packages
rebuild_external_modules_if_necessary
rebuild_packages_depending_on_stale_libraries
bring_old_perl_modules_up_to_date
cleanup_python_config
interactively_resolve_clashing_config_file_changes
offer_kernel_upgrade_to_staging_if_available
remove_unreferenced_packages
rebuild_where_missing_libraries_detected
rebuild_packages_depending_on_stale_libraries
purge_old_distfiles_if_desired
copy_new_kernel_from_staging_if_present_and_desired
update_environment
update_eix_metadata
run_custom_updaters_if_present
display_final_status
cleanup_and_exit_with_code 0
# **************** end of script proper ****************