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_file=/etc/neurodebian/neurodebian.cfg
20 nd_mirror_origin=http://neuro.debian.net/debian
21 nd_mirror_default=$nd_mirror_origin # or may be AWS?
23 # To be set by cmdline args
25 ae_components=software,data
38 # - apt priority! (so we could avoid automagic upgrades etc)
41 ae_tempdir=$(mktemp -d)
42 trap "rm -rf \"$ae_tempdir\"" TERM INT EXIT
48 if [ "$ae_verbose" -ge $level ]; then
49 # use stderr for printing within functions stdout of which might be used
64 nd-aptenable $nd_aptenable_version
66 Copyright (C) 2014 Yaroslav Halchenko <debian@onerussian.com>
68 Licensed under GNU Public License version 3 or later.
69 This is free software; see the source for copying conditions. There is NO
70 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
72 Written by Yaroslav Halchenko for the NeuroDebian project.
79 if [ -z "$ae_dry_run" ]; then
90 Usage: nd-aptenable [options]
92 Enables NeuroDebian repository for the current Debian or Ubuntu release.
97 Name of the Debian/Ubuntu release to be used. If not specified,
98 it is deduced from the apt-cache policy output, by taking repository
99 of Debian or Ubuntu origin with highest priority.
101 -f, --flavor=full|libre
102 Which flavor of the repository should be enabled:
103 libre -- Only main component, containing only DFSG-compliant content.
104 full -- Includes main, contrib, and non-free.
105 If not specified -- deduced from the output of apt-cache policy
107 -c, --components=c1,c2,c3
108 Comma separated list of components to enable among:
109 software -- primary software repository
110 data -- data packages
111 devel -- "overlay" of development versions (like Debians' "experimental").
112 Not sufficient on its own and available only from the main site
113 If not specified -- "software,data"
115 -m, --mirror=NAME|URL
116 Which mirror to use. Could be a mirror code-name (as specified in
117 /etc/neurodebian/neurodebian.cfg), or a URL.
120 If apt file already present, it would not be overriden (by default).
121 Use this option to overwrite.
124 Which suffix to add to the apt file, in case you are trying to enable
125 multiple repositories
127 --sources, --no-sources
128 Either to enable deb-src lines. If none specified -- would be enabled if
129 sources for a core package (apt) are available.
132 Do not perform any changes -- generated configurations and commands will
133 simply be printed to stdout
136 Enable additional progress messages. Could be used multiple times
139 Make operation quiet -- only error messages would be output
142 Print short description, usage summary and option list.
145 Print version information and exit.
149 non-0 exit status in case of error. Error exit code would depend
150 on which command has failed
154 - Enable software and data components from the optimal (according to
155 netselect) mirror. Some information about progress will be printed
159 - Quietly enable -devel repository for the current release, and place apt
160 configuration into /etc/apt/sources.list.d/neurodebian.sources-devel.list
162 nd-aptenable -q --suffix=-devel -c devel
164 - Force sid distribution, all the components, from the Japan mirror:
166 nd-aptenable -q --suffix=-de-sid-full -c software,data,devel -m jp
171 get_neurodebian_cfg()
173 # First we try to fetch the most recent version from the github
174 print_verbose 3 "Fetching config file from the github repository"
175 cfgfile_temp="$ae_tempdir/neurodebian.cfg"
176 wget -c -q -O$cfgfile_temp https://raw.githubusercontent.com/neurodebian/neurodebian/master/neurodebian.cfg \
177 && { echo $cfgfile_temp; } \
178 || { [ -e "$nd_config_file" ] && return "$nd_config_file"; }
179 # if not -- should blow up
186 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')]))"
191 nd_config=`get_neurodebian_cfg`
192 # $exe_dir/nd_querycfg -F" " --config-file="$nd_config" "mirrors" \
193 query_cfg_section "$nd_config" "mirrors" \
194 | while read mirror_name mirror_url; do
195 # verify that url is just a url
196 if echo "$mirror_url" | grep -v -e '^[a-z0-9:+]*://[-+_%.a-z0-9/]*$'; then
197 print_verbose 1 "Mirror $mirror_name has 'illegit' URL: $mirror_url. Skipping"
199 echo "$mirror_name $mirror_url"
204 # select "closest" mirror according to netselect.
205 print_verbose 2 "Selecting the 'best' mirror using netselect"
206 if ! which netselect >/dev/null; then
207 print_verbose 1 "netselect (apt-get install netselect) needed to select the 'best' mirror was not found"
208 print_verbose 1 "Selecting the default repository: $nd_mirror_default"
209 echo $nd_mirror_default
211 get_mirrors | awk '{print $2;}' | $ae_sudo xargs netselect -D -s 1 | awk '{print $2;}'
216 # given mirror alias -- find its url
217 url=$(get_mirrors | awk "/^$1 /{print \$2;}")
218 if [ -z "$url" ]; then
219 error 9 "Cannot resolve mirror $1 to the URL"
226 # Get apt-cache policy output in a single list for matching suites
227 # (could be a separated with \| or , for multiple choices, e.g.
229 # get_apt_policy Debian,Ubuntu
231 # get_apt_policy NeuroDebian
233 apt-cache policy | grep -B1 -e "o=\(${suites//,/\\|}\)" | tr '\n' ' ' | sed -e 's, -- ,\n,g' | grep -v -e '-\(updates\|security\)' | sort -nr
238 echo "$ae_components" | tr ',' '\n' | grep -q "^$1\$"
243 # Commandline options handling
246 # Parse commandline options (taken from the getopt examples from the Debian util-linux package)
247 # Note that we use `"$@"' to let each command-line parameter expand to a
248 # separate word. The quotes around `$@' are essential!
249 # We need CLOPTS as the `eval set --' would nuke the return value of getopt.
250 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' -- "$@"`
252 if [ $? != 0 ] ; then
253 error 2 "Problem with parsing cmdline. Terminating..."
256 # Note the quotes around `$CLOPTS': they are essential!
257 eval set -- "$CLOPTS"
259 if [ `whoami` != "root" ]; then
265 -r|--release) shift; ae_release="$1"; shift;;
266 -f|--flavor) shift; ae_flavor="$1"; shift;;
267 -c|--components) shift; ae_components="$1"; shift;;
268 -m|--mirror) shift; ae_mirror="$1"; shift;;
269 --print-mirrors) get_mirrors; exit 0;;
270 --print-best-mirror) netselect_mirror; exit 0;;
271 -n|--dry-run) ae_dry_run=1; shift;;
272 --suffix) shift; ae_suffix="$1"; shift;;
273 --overwrite) ae_overwrite="$1"; shift;;
274 --sources) ae_sources=1; shift;;
275 --no-sources) ae_sources=0; shift;;
276 -q|--quiet) ae_verbose=0; shift;;
277 -v|--verbose) ae_verbose=$(($ae_verbose+1)); shift;;
278 -h|--help) print_help; exit 0;;
279 --version) print_version; exit 0;;
281 *) error 1 "Internal error! ($1)";;
286 if [ $# -gt 0 ] ; then
292 [ -z "$ae_sudo" ] || print_verbose 1 "This script requires root access. Since current user is not root, sudo will be used"
295 # Basic system/environment knowledge
298 ae_output_file=/etc/apt/sources.list.d/neurodebian.sources${ae_suffix}.list
300 apt_policy=$(get_apt_policy "Debian,Ubuntu" )
302 if [ -z "$ae_release" ]; then
303 ae_release=$(echo "$apt_policy" | head -1 | sed -e 's/.*,n=\([^,]*\),.*/\1/g')
306 if [ -z "$ae_flavor" ]; then
307 ae_flavor=$(echo "$apt_policy" | grep -e ",n=$ae_release," | grep -qe 'c=\(non-free\|restricted\)' && echo "full" || echo "libre")
311 # Determine which mirror to use
314 # knowing mirror is not necessary for -devel available only from the main site
315 if include_component software || include_component data; then
316 # for now just use default
317 if [ -z "$ae_mirror" ]; then # none specified
318 ae_mirror_url=$nd_mirror_origin
320 if ! [[ "$ae_mirror" =~ ".*://.*" ]]; then
322 best) ae_mirror_url=$(netselect_mirror);;
323 default) ae_mirror_url=$nd_mirror_default;;
324 origin) ae_mirror_url=$nd_mirror_origin;;
325 *) ae_mirror_url=$(get_mirror_url "$ae_mirror");;
328 ae_mirror_url="$ae_mirror" # it was some kind of a URL already
338 full) apt_flavor="contrib non-free";;
339 libre) apt_flavor="";;
340 *) error 5 "Unknown value of flavor $apt_flavor. Must be full or libre"
343 if [ -z "$ae_sources" ]; then
344 apt-cache showsrc apt >&/dev/null && ae_sources=1 || ae_sources=0
347 if [ $ae_sources -eq 0 ]; then
355 if include_component software; then
357 # NeuroDebian software repository
358 deb $ae_mirror_url $ae_release main $apt_flavor
359 ${sources_comment}deb-src $ae_mirror_url $ae_release main $apt_flavor
363 if include_component data; then
365 # NeuroDebian data repository
366 deb $ae_mirror_url data main $apt_flavor
367 ${sources_comment}deb-src $ae_mirror_url data main $apt_flavor
371 if include_component devel; then
373 # NeuroDebian -devel repository
374 deb http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
375 ${sources_comment}deb-src http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
379 if [ -e "$ae_output_file" ] && [ -z "$ae_overwrite" ]; then
380 if diff "$ae_output_file" <(echo "$apt_list") | grep -q .; then
382 print_verbose 1 "File $ae_output_file already exists, containing:\n`cat \"$ae_output_file\"`\n\nI: New configuration is different:\n$apt_list"
383 if get_apt_policy NeuroDebian >/dev/null; then
384 print_verbose 1 "NeuroDebian repositories are already available, thus skipping the rest."
385 print_verbose 1 "Rerun with --overwrite if you would like to reconfigure."
388 print_verbose 1 "NeuroDebian configuration is found but not yet available -- continuing with new configuration."
391 print_verbose 1 "New configuration is identical to existing and NeuroDebian repository is already enabled."
392 print_verbose 1 "Skiping the rest. Rerun with --overwrite if you would like to reconfigure."
396 print_verbose 1 "Generating $ae_output_file"
397 if [ -z "$ae_dry_run" ]; then
398 echo "$apt_list" | $ae_sudo bash -c "cat - >| '$ae_output_file'"
407 # Assure present archive GPG key for APT system
410 # Figure out if key needs to be imported (if ran within package,
411 # should already be there due to neurodebian-keyring package)
412 if LANG=C eval $ae_sudo apt-key export $nd_key_id 2>&1 1>/dev/null | grep -qe "nothing exported"; then
413 print_verbose 1 "Fetching the key from the server"
414 eval_dry apt-key adv --recv-keys --keyserver pgp.mit.edu $nd_key_id
418 # Finalizing (apt-get update etc)
421 print_verbose 1 "Updating APT listings, might take a few minutes"
422 if [ -z "$ae_dry_run" ]; then
423 apt_logfile="$ae_tempdir/apt.log"
424 $ae_sudo apt-get update 1>"$apt_logfile" 2>&1 \
425 && rm -f "$apt_logfile" \
428 error 5 "E: Update failed with exit code $? (above output logged into $apt_logfile)."
431 eval_dry apt-get update
434 if [ "$ae_verbose" -ge 2 ]; then
435 print_verbose 2 "Currently enabled NeuroDebian suites/mirrors:"
436 get_apt_policy NeuroDebian