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, 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
26 ae_components=software,data
39 # - apt priority! (so we could avoid automagic upgrades etc)
42 ae_tempdir=$(mktemp -d)
43 trap "rm -rf \"$ae_tempdir\"" TERM INT EXIT
49 if [ "$ae_verbose" -ge $level ]; then
50 # use stderr for printing within functions stdout of which might be used
65 nd-aptenable $nd_aptenable_version
67 Copyright (C) 2014 Yaroslav Halchenko <debian@onerussian.com>
69 Licensed under GNU Public License version 3 or later.
70 This is free software; see the source for copying conditions. There is NO
71 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
73 Written by Yaroslav Halchenko for the NeuroDebian project.
80 if [ -z "$ae_dry_run" ]; then
91 Usage: nd-aptenable [options]
93 Enables NeuroDebian repository for the current Debian or Ubuntu release.
98 Name of the Debian/Ubuntu release to be used. If not specified,
99 it is deduced from the apt-cache policy output, by taking repository
100 of Debian or Ubuntu origin with highest priority.
102 -f, --flavor=full|libre
103 Which flavor of the repository should be enabled:
104 libre -- Only main component, containing only DFSG-compliant content.
105 full -- Includes main, contrib, and non-free.
106 If not specified -- deduced from the output of apt-cache policy
108 -c, --components=c1,c2,c3
109 Comma separated list of components to enable among:
110 software -- primary software repository
111 data -- data packages
112 devel -- "overlay" of development versions (like Debians' "experimental").
113 Not sufficient on its own and available only from the main site
114 If not specified -- "software,data"
116 -m, --mirror=NAME|URL
117 Which mirror to use. Could be a mirror code-name (as specified in
118 /etc/neurodebian/neurodebian.cfg), or a URL.
121 If apt file already present, it would not be overriden (by default).
122 Use this option to overwrite.
125 Which suffix to add to the apt file, in case you are trying to enable
126 multiple repositories
128 --sources, --no-sources
129 Either to enable deb-src lines. If none specified -- would be enabled if
130 sources for a core package (apt) are available.
133 Do not perform any changes -- generated configurations and commands will
134 simply be printed to stdout
137 Enable additional progress messages. Could be used multiple times
140 Make operation quiet -- only error messages would be output
143 Print short description, usage summary and option list.
146 Print version information and exit.
150 non-0 exit status in case of error. Error exit code would depend
151 on which command has failed
155 - Enable software and data components from the optimal (according to
156 netselect) mirror. Some information about progress will be printed
160 - Quietly enable -devel repository for the current release, and place apt
161 configuration into /etc/apt/sources.list.d/neurodebian.sources-devel.list
163 nd-aptenable -q --suffix=-devel -c devel
165 - Force sid distribution, all the components, from the Japan mirror:
167 nd-aptenable -q --suffix=-de-sid-full -c software,data,devel -m jp
172 get_neurodebian_cfg()
174 # First we try to fetch the most recent version from the github
175 print_verbose 3 "Fetching config file from the github repository"
176 cfgfile_temp="$ae_tempdir/neurodebian.cfg"
177 wget --no-check-certificate -c -q -O$cfgfile_temp \
179 && { echo $cfgfile_temp; } \
180 || { [ -e "$nd_config_file" ] \
181 && echo "$nd_config_file" \
182 || error 10 "Neither could fetch $nd_config_url, nor found $nd_config_file"; }
189 print_verbose 3 "Querying config $config_file section $section"
190 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')]))"
195 nd_config=`get_neurodebian_cfg`
196 # $exe_dir/nd_querycfg -F" " --config-file="$nd_config" "mirrors" \
197 query_cfg_section "$nd_config" "mirrors" \
198 | while read mirror_name mirror_url; do
199 # verify that url is just a url
200 if echo "$mirror_url" | grep -v -e '^[a-z0-9:+]*://[-+_%.a-z0-9/]*$'; then
201 print_verbose 1 "Mirror $mirror_name has 'illegit' URL: $mirror_url. Skipping"
203 echo "$mirror_name $mirror_url"
208 # select "closest" mirror according to netselect.
209 print_verbose 2 "Selecting the 'best' mirror using netselect"
210 if ! which netselect >/dev/null; then
211 print_verbose 1 "netselect (apt-get install netselect) needed to select the 'best' mirror was not found"
212 print_verbose 1 "Selecting the default repository: $nd_mirror_default"
213 echo $nd_mirror_default
215 get_mirrors | awk '{print $2;}' | $ae_sudo xargs netselect -D -s 1 | awk '{print $2;}'
220 # given mirror alias -- find its url
221 url=$(get_mirrors | awk "/^$1 /{print \$2;}")
222 if [ -z "$url" ]; then
223 error 9 "Cannot resolve mirror $1 to the URL"
230 # Get apt-cache policy output in a single list for matching suites
231 # (could be a separated with \| or , for multiple choices, e.g.
233 # get_apt_policy Debian,Ubuntu
235 # get_apt_policy NeuroDebian
237 apt-cache policy | grep -B1 -e "o=\(${suites//,/\\|}\)" | tr '\n' ' ' | sed -e 's, -- ,\n,g' | grep -v -e '-\(updates\|security\)' | sort -nr
242 echo "$ae_components" | tr ',' '\n' | grep -q "^$1\$"
247 # Commandline options handling
250 # Parse commandline options (taken from the getopt examples from the Debian util-linux package)
251 # Note that we use `"$@"' to let each command-line parameter expand to a
252 # separate word. The quotes around `$@' are essential!
253 # We need CLOPTS as the `eval set --' would nuke the return value of getopt.
254 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,dry-run,print-mirrors,print-best-mirror -n 'nd-aptenable' -- "$@"`
256 if [ $? != 0 ] ; then
257 error 2 "Problem with parsing cmdline. Terminating..."
260 # Note the quotes around `$CLOPTS': they are essential!
261 eval set -- "$CLOPTS"
263 if [ `whoami` != "root" ]; then
269 -r|--release) shift; ae_release="$1"; shift;;
270 -f|--flavor) shift; ae_flavor="$1"; shift;;
271 -c|--components) shift; ae_components="$1"; shift;;
272 -m|--mirror) shift; ae_mirror="$1"; shift;;
273 --print-mirrors) get_mirrors; exit 0;;
274 --print-best-mirror) netselect_mirror; exit 0;;
275 -n|--dry-run) ae_dry_run=1; shift;;
276 --suffix) shift; ae_suffix="$1"; shift;;
277 --overwrite) ae_overwrite="$1"; shift;;
278 --sources) ae_sources=1; shift;;
279 --no-sources) ae_sources=0; shift;;
280 -q|--quiet) ae_verbose=0; shift;;
281 -v|--verbose) ae_verbose=$(($ae_verbose+1)); shift;;
282 -h|--help) print_help; exit 0;;
283 --version) print_version; exit 0;;
285 *) error 1 "Internal error! ($1)";;
290 if [ $# -gt 0 ] ; then
296 [ -z "$ae_sudo" ] || print_verbose 1 "This script requires root access. Since current user is not root, sudo will be used"
299 # Basic system/environment knowledge
302 ae_output_file=/etc/apt/sources.list.d/neurodebian.sources${ae_suffix}.list
304 apt_policy=$(get_apt_policy "Debian,Ubuntu" )
306 if [ -z "$ae_release" ]; then
307 ae_release=$(echo "$apt_policy" | head -1 | sed -e 's/.*,n=\([^,]*\),.*/\1/g')
310 if [ -z "$ae_flavor" ]; then
311 ae_flavor=$(echo "$apt_policy" | grep -e ",n=$ae_release," | grep -qe 'c=\(non-free\|restricted\)' && echo "full" || echo "libre")
315 # Determine which mirror to use
318 # knowing mirror is not necessary for -devel available only from the main site
319 if include_component software || include_component data; then
320 # for now just use default
321 if [ -z "$ae_mirror" ]; then # none specified
322 ae_mirror_url=$nd_mirror_origin
324 if ! [[ "$ae_mirror" =~ ".*://.*" ]]; then
326 best) ae_mirror_url=$(netselect_mirror);;
327 default) ae_mirror_url=$nd_mirror_default;;
328 origin) ae_mirror_url=$nd_mirror_origin;;
329 *) ae_mirror_url=$(get_mirror_url "$ae_mirror");;
332 ae_mirror_url="$ae_mirror" # it was some kind of a URL already
342 full) apt_flavor="contrib non-free";;
343 libre) apt_flavor="";;
344 *) error 5 "Unknown value of flavor $apt_flavor. Must be full or libre"
347 if [ -z "$ae_sources" ]; then
348 apt-cache showsrc apt >&/dev/null && ae_sources=1 || ae_sources=0
351 if [ $ae_sources -eq 0 ]; then
359 if include_component software; then
361 # NeuroDebian software repository
362 deb $ae_mirror_url $ae_release main $apt_flavor
363 ${sources_comment}deb-src $ae_mirror_url $ae_release main $apt_flavor
367 if include_component data; then
369 # NeuroDebian data repository
370 deb $ae_mirror_url data main $apt_flavor
371 ${sources_comment}deb-src $ae_mirror_url data main $apt_flavor
375 if include_component devel; then
377 # NeuroDebian -devel repository
378 deb http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
379 ${sources_comment}deb-src http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
383 if [ -e "$ae_output_file" ] && [ -z "$ae_overwrite" ]; then
384 if diff "$ae_output_file" <(echo "$apt_list") | grep -q .; then
386 print_verbose 1 "File $ae_output_file already exists, containing:\n`cat \"$ae_output_file\"`\n\nI: New configuration is different:\n$apt_list"
387 if get_apt_policy NeuroDebian >/dev/null; then
388 print_verbose 1 "NeuroDebian repositories are already available, thus skipping the rest."
389 print_verbose 1 "Rerun with --overwrite if you would like to reconfigure."
392 print_verbose 1 "NeuroDebian configuration is found but not yet available -- continuing with new configuration."
395 print_verbose 1 "New configuration is identical to existing and NeuroDebian repository is already enabled."
396 print_verbose 1 "Skiping the rest. Rerun with --overwrite if you would like to reconfigure."
400 print_verbose 1 "Generating $ae_output_file"
401 if [ -z "$ae_dry_run" ]; then
402 echo "$apt_list" | $ae_sudo bash -c "cat - >| '$ae_output_file'"
411 # Assure present archive GPG key for APT system
414 # Figure out if key needs to be imported (if ran within package,
415 # should already be there due to neurodebian-keyring package)
416 if LANG=C eval $ae_sudo apt-key export $nd_key_id 2>&1 1>/dev/null | grep -qe "nothing exported"; then
417 print_verbose 1 "Fetching the key from the server"
418 eval_dry apt-key adv --recv-keys --keyserver pgp.mit.edu $nd_key_id
422 # Finalizing (apt-get update etc)
425 print_verbose 1 "Updating APT listings, might take a few minutes"
426 if [ -z "$ae_dry_run" ]; then
427 apt_logfile="$ae_tempdir/apt.log"
428 $ae_sudo apt-get update 1>"$apt_logfile" 2>&1 \
429 && rm -f "$apt_logfile" \
432 error 5 "E: Update failed with exit code $? (above output logged into $apt_logfile)."
435 eval_dry apt-get update
438 if [ "$ae_verbose" -ge 2 ]; then
439 print_verbose 2 "Currently enabled NeuroDebian suites/mirrors:"
440 get_apt_policy NeuroDebian