2 #emacs: -*- mode: shell-script; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
3 #ex: set sts=4 ts=4 sw=4 et:
5 # Depends: apt (assumed to be present), python, wget
6 # Recommends: netselect
16 nd_aptenable_version=0.1
19 nd_config_url=https://raw.githubusercontent.com/neurodebian/neurodebian/master/neurodebian.cfg
20 nd_config_file=/etc/neurodebian/neurodebian.cfg
21 nd_mirror_origin=http://neuro.debian.net/debian
22 nd_mirror_default=$nd_mirror_origin # or may be AWS?
24 # To be set by cmdline args or via env variables with prefix ND_AE_
25 ae_release=${ND_AE_RELEASE:-}
26 ae_components=${ND_AE_COMPONENTS:-software,data}
27 ae_flavor=${ND_AE_FLAVOR:-}
28 ae_mirror=${ND_AE_MIRROR:-best}
29 ae_suffix=${ND_AE_SUFFIX:-}
30 ae_verbose=${ND_AE_VERBOSE:-1}
31 ae_overwrite=${ND_AE_OVERWRITE:-}
32 ae_sources=${ND_AE_SOURCES:-}
33 ae_install=${ND_AE_INSTALL:-}
34 ae_dry_run=${ND_AE_DRY_RUN:-}
35 ae_defun_only=${ND_AE_DEFUN_ONLY:-} # mode to source this file as a "library"
41 # - apt priority! (so we could avoid automagic upgrades etc)
44 ae_tempdir=$(mktemp -d)
45 trap "rm -rf \"$ae_tempdir\"" TERM INT EXIT
51 if [ "$ae_verbose" -ge $level ]; then
52 # use stderr for printing within functions stdout of which might be used
54 i=1; while [ $i -lt $level ]; do echo -ne " ">&2; i=$(($i+1)); done
69 nd-aptenable $nd_aptenable_version
71 Copyright (C) 2014 Yaroslav Halchenko <debian@onerussian.com>
73 Licensed under GNU Public License version 3 or later.
74 This is free software; see the source for copying conditions. There is NO
75 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 Written by Yaroslav Halchenko for the NeuroDebian project.
84 if [ -z "$ae_dry_run" ]; then
85 if eval "$ae_sudo $@" 1>|"$ae_tempdir/eval.log" 2>&1; then
86 rm "$ae_tempdir/eval.log"
88 error $? "Command $@ failed with exit code $?. Output was: `cat $ae_tempdir/eval.log`"
99 Usage: nd-aptenable [options]
101 Enables NeuroDebian repository for the current Debian or Ubuntu release.
105 -r, --release=RELEASE
106 Name of the Debian/Ubuntu release to be used. If not specified,
107 it is deduced from the apt-cache policy output, by taking repository
108 of Debian or Ubuntu origin with highest priority.
110 -f, --flavor=full|libre
111 Which flavor of the repository should be enabled:
112 libre -- Only main component, containing only DFSG-compliant content.
113 full -- Includes main, contrib, and non-free.
114 If not specified -- deduced from the output of apt-cache policy
116 -c, --components=c1,c2,c3
117 Comma separated list of components to enable among:
118 software -- primary software repository
119 data -- data packages
120 devel -- "overlay" of development versions (like Debians' "experimental").
121 Not sufficient on its own and available only from the main site
122 If not specified -- "software,data"
124 -m, --mirror=NAME|URL
125 Which mirror to use. Could be a mirror code-name (as specified in
126 /etc/neurodebian/neurodebian.cfg), or a URL.
129 If apt file already present, it would not be overriden (by default).
130 Use this option to overwrite.
133 Which suffix to add to the apt file, in case you are trying to enable
134 multiple repositories
136 --sources, --no-sources
137 Either to enable deb-src lines. If none specified -- would be enabled if
138 sources for a core package (apt) are available.
141 Do not perform any changes -- generated configurations and commands will
142 simply be printed to stdout
145 If found absent, all necessary tools (wget, netselect) if available will
149 Enable additional progress messages. Could be used multiple times
152 Make operation quiet -- only error messages would be output
155 Print short description, usage summary and option list.
158 Print version information and exit.
162 non-0 exit status in case of error. Error exit code would depend
163 on which command has failed
167 - Enable software and data components from the optimal (according to
168 netselect) mirror. Some information about progress will be printed
172 - Quietly enable -devel repository for the current release, and place apt
173 configuration into /etc/apt/sources.list.d/neurodebian.sources-devel.list
175 nd-aptenable -q --suffix=-devel -c devel
177 - Force sid distribution, all the components, from the Japan mirror:
179 nd-aptenable -q --suffix=-de-sid-full -c software,data,devel -m jp
184 get_neurodebian_cfg()
186 # First we try to fetch the most recent version from the github
187 print_verbose 3 "Fetching config file from the github repository"
188 cfgfile_temp="$ae_tempdir/neurodebian.cfg"
189 assure_command_from_package wget wget 1
190 wget --no-check-certificate -c -q -O$cfgfile_temp \
192 && { echo $cfgfile_temp; } \
193 || { [ -e "$nd_config_file" ] \
194 && echo "$nd_config_file" \
195 || error 10 "Neither could fetch $nd_config_url, nor found $nd_config_file"; }
202 print_verbose 3 "Querying config $config_file section $section"
203 assure_command_from_package python python-minimal 1
204 python -c "from ConfigParser import SafeConfigParser as SP; cfg = SP(); cfg.read('$config_file'); print('\n'.join([' '.join(x) for x in cfg.items('$section')]))"
209 nd_config=`get_neurodebian_cfg`
210 # $exe_dir/nd_querycfg -F" " --config-file="$nd_config" "mirrors" \
211 query_cfg_section "$nd_config" "mirrors" \
212 | while read mirror_name mirror_url; do
213 # verify that url is just a url
214 if echo "$mirror_url" | grep -v -e '^[a-z0-9:+]*://[-+_%.a-z0-9/]*$'; then
215 print_verbose 1 "Mirror $mirror_name has 'illegit' URL: $mirror_url. Skipping"
217 echo "$mirror_name $mirror_url"
221 get_package_version()
223 pkg_version=$(apt-cache policy "$1" | awk '/^ *Installed:/{print $2;}')
224 [ "$pkg_version" != '(none)' ] || pkg_version=''
229 # select "closest" mirror according to netselect.
230 print_verbose 2 "Selecting the 'best' mirror using netselect"
231 assure_command_from_package netselect
232 if ! which netselect >&/dev/null; then
233 print_verbose 1 "netselect (apt-get install netselect) needed to select the 'best' mirror was not found"
234 print_verbose 1 "Selecting the default repository: $nd_mirror_default"
235 echo $nd_mirror_default
237 # squeeze version doesn't have -D yet to force output of the URL not IP, but for our mirrors ATM it shouldn't matter
238 netselect_opts="-s 1"
239 netselect_version="$(get_package_version netselect)"
240 if dpkg --compare-versions "$netselect_version" ge 0.3.ds1-17; then
241 netselect_opts+=" -D"
243 if dpkg --compare-versions "$netselect_version" ge 0.3.ds1-15; then
244 netselect_opts+=" -I"
246 best_mirror=$(get_mirrors | awk '{print $2;}' | eval $ae_sudo xargs netselect $netselect_opts | awk '{print $2;}')
247 print_verbose 2 "Best mirror: $best_mirror"
254 # given mirror alias -- find its url
255 url=$(get_mirrors | awk "/^$1 /{print \$2;}")
256 if [ -z "$url" ]; then
257 error 9 "Cannot resolve mirror $1 to the URL"
264 # Get apt-cache policy output in a single list for matching suites
265 # (could be a separated with \| or , for multiple choices, e.g.
267 # get_apt_policy Debian,Ubuntu
269 # get_apt_policy NeuroDebian
271 $ae_sudo apt-cache policy | grep -B1 -e "o=\(${suites//,/\\|}\)" | tr '\n' ' ' | sed -e 's, -- ,\n,g' | grep -v -e '-\(updates\|security\)' | sort -nr
274 is_component_included()
276 echo "$ae_components" | tr ',' '\n' | grep -q "^$1\$"
281 apt-cache showsrc apt >&/dev/null && echo 1 || echo 0
284 assure_command_from_package()
290 which "$cmd" >&/dev/null && return 0
292 # if absent -- check availability of the package
293 apt_cache=$(LANG=C apt-cache policy "$pkg" 2>&1)
294 if [[ "$apt_cache" =~ "Unable to locate package" ]] || [[ "$apt_cache" =~ "Candidate: (none)" ]]; then
295 print_verbose 1 "Package $pkg providing command $cmd is N/A. Skipping"
298 if echo "$apt_cache" | grep -q '^\s*\*\*\*'; then
299 print_verbose 1 "WARNING -- command $cmd is N/A but package $pkg is claimed to be installed"
300 [ -z "$fail" ] && return 11 || error $fail "Command $cmd is required to proceed"
302 if [ "$ae_install" = "1" ]; then
303 print_verbose 1 "Installing $pkg package to get $cmd command"
304 eval_dry DEBIAN_FRONTEND=noninteractive apt-get install -y "$pkg"
307 print_verbose 1 "Command $cmd (from package $pkg) is N/A."
308 print_verbose 1 "Use with --install to get all necessary packages installed automatically"
309 [ -z "$fail" ] && return 12 || error $fail "Command $cmd is required to proceed"
313 # if it was requested -- return without doing anything
314 [ -z "$ae_defun_only" ] || return
317 # Commandline options handling
320 # Parse commandline options (taken from the getopt examples from the Debian util-linux package)
321 # Note that we use `"$@"' to let each command-line parameter expand to a
322 # separate word. The quotes around `$@' are essential!
323 # We need CLOPTS as the `eval set --' would nuke the return value of getopt.
324 CLOPTS=`getopt -o h,r:,m:,f:,c:,q,v,n --long help,version,quiet,verbose,mirror:,release:,flavor:,components:,suffix:,overwrite,sources,no-sources,install,dry-run,print-mirrors,print-best-mirror -n 'nd-aptenable' -- "$@"`
326 if [ $? != 0 ] ; then
327 error 2 "Problem with parsing cmdline. Terminating..."
330 # Note the quotes around `$CLOPTS': they are essential!
331 eval set -- "$CLOPTS"
333 if [ `whoami` != "root" ]; then
339 -r|--release) shift; ae_release="$1"; shift;;
340 -f|--flavor) shift; ae_flavor="$1"; shift;;
341 -c|--components) shift; ae_components="$1"; shift;;
342 -m|--mirror) shift; ae_mirror="$1"; shift;;
343 --print-mirrors) get_mirrors; exit 0;;
344 --print-best-mirror) netselect_mirror; exit 0;;
345 -n|--dry-run) ae_dry_run=1; shift;;
346 --suffix) shift; ae_suffix="$1"; shift;;
347 --overwrite) ae_overwrite="$1"; shift;;
348 --sources) ae_sources=1; shift;;
349 --no-sources) ae_sources=0; shift;;
350 --install) ae_install=1; shift;;
351 -q|--quiet) ae_verbose=0; shift;;
352 -v|--verbose) ae_verbose=$(($ae_verbose+1)); shift;;
353 -h|--help) print_help; exit 0;;
354 --version) print_version; exit 0;;
356 *) error 1 "Internal error! ($1)";;
361 if [ $# -gt 0 ] ; then
367 [ -z "$ae_sudo" ] || print_verbose 1 "This script requires root access. Since current user is not root, sudo will be used"
370 # Basic system/environment knowledge
373 ae_output_file=/etc/apt/sources.list.d/neurodebian.sources${ae_suffix}.list
375 apt_policy=$(get_apt_policy "Debian,Ubuntu" )
377 if [ -z "$ae_release" ]; then
378 ae_release=$(echo "$apt_policy" | head -1 | sed -e 's/.*,n=\([^,]*\),.*/\1/g')
381 if [ -z "$ae_flavor" ]; then
382 ae_flavor=$(echo "$apt_policy" | grep -e ",n=$ae_release," | grep -qe 'c=\(non-free\|restricted\)' && echo "full" || echo "libre")
386 # Determine which mirror to use
389 # knowing mirror is not necessary for -devel available only from the main site
390 if is_component_included software || is_component_included data; then
391 # for now just use default
392 if [ -z "$ae_mirror" ]; then # none specified
393 ae_mirror_url=$nd_mirror_origin
395 if ! [[ "$ae_mirror" =~ ".*://.*" ]]; then
397 best) ae_mirror_url=$(netselect_mirror);;
398 default) ae_mirror_url=$nd_mirror_default;;
399 origin) ae_mirror_url=$nd_mirror_origin;;
400 *) ae_mirror_url=$(get_mirror_url "$ae_mirror");;
403 ae_mirror_url="$ae_mirror" # it was some kind of a URL already
413 full) apt_flavor="contrib non-free";;
414 libre) apt_flavor="";;
415 *) error 5 "Unknown value of flavor $apt_flavor. Must be full or libre"
418 if [ -z "$ae_sources" ]; then
419 ae_sources=$(is_sources_enabled)
422 if [ $ae_sources -eq 0 ]; then
430 if is_component_included software; then
432 # NeuroDebian software repository
433 deb $ae_mirror_url $ae_release main $apt_flavor
434 ${sources_comment}deb-src $ae_mirror_url $ae_release main $apt_flavor
438 if is_component_included data; then
440 # NeuroDebian data repository
441 deb $ae_mirror_url data main $apt_flavor
442 ${sources_comment}deb-src $ae_mirror_url data main $apt_flavor
446 if is_component_included devel; then
448 # NeuroDebian -devel repository
449 deb http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
450 ${sources_comment}deb-src http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
454 if [ -e "$ae_output_file" ] && [ -z "$ae_overwrite" ]; then
455 if diff "$ae_output_file" <(echo "$apt_list") | grep -q .; then
457 print_verbose 1 "File $ae_output_file already exists, containing:\n`cat \"$ae_output_file\"`\n\nI: New configuration is different:\n$apt_list"
458 if get_apt_policy NeuroDebian >/dev/null; then
459 print_verbose 1 "NeuroDebian repositories are already available, thus skipping the rest."
460 print_verbose 1 "Rerun with --overwrite if you would like to reconfigure."
463 print_verbose 1 "NeuroDebian configuration is found but not yet available -- continuing with new configuration."
466 print_verbose 1 "New configuration is identical to existing and NeuroDebian repository is already enabled."
467 print_verbose 1 "Skiping the rest. Rerun with --overwrite if you would like to reconfigure."
471 print_verbose 1 "Generating $ae_output_file"
472 if [ -z "$ae_dry_run" ]; then
473 echo "$apt_list" | $ae_sudo bash -c "cat - >| '$ae_output_file'"
482 # Assure present archive GPG key for APT system
485 # Figure out if key needs to be imported (if ran within package,
486 # should already be there due to neurodebian-keyring package)
487 if LANG=C eval $ae_sudo apt-key export $nd_key_id 2>&1 1>/dev/null | grep -qe "nothing exported"; then
488 print_verbose 1 "Fetching the key from the server"
489 eval_dry apt-key adv --recv-keys --keyserver pgp.mit.edu $nd_key_id
494 # Finalizing (apt-get update etc)
497 print_verbose 1 "Updating APT listings, might take a few minutes"
498 if [ -z "$ae_dry_run" ]; then
499 apt_logfile="$ae_tempdir/apt.log"
500 $ae_sudo apt-get update 1>"$apt_logfile" 2>&1 \
501 && rm -f "$apt_logfile" \
503 apt_log=$(cat "$apt_logfile")
505 if echo "$apt_log" | grep -q "Malformed line [0-9]* in source list $ae_output_file"; then
506 $ae_sudo mv "${ae_output_file}" "${ae_output_file}-failed.disabled"
507 error 6 "Update failed to possible errorneous APT listing file produced by this script. Generated $ae_output_file renamed to ${ae_output_file}-failed.disabled to not interfer"
509 error 5 "Update failed with exit code $? (above output logged into $apt_logfile)."
512 eval_dry apt-get update
515 if [ "$ae_verbose" -ge 2 ]; then
516 print_verbose 2 "Currently enabled NeuroDebian suites/mirrors:"
517 get_apt_policy NeuroDebian