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:
13 nd_aptenable_version=0.1
16 nd_config_file=/etc/neurodebian/neurodebian.cfg
17 nd_mirror_origin=http://neuro.debian.net/debian
18 nd_mirror_default=$nd_mirror_origin # or may be AWS?
20 # To be set by cmdline args
22 ae_components=software,data
35 # - apt priority! (so we could avoid automagic upgrades etc)
38 ae_tempdir=$(mktemp -d)
39 trap "rm -rf \"$ae_tempdir\"" TERM INT EXIT
45 if [ "$ae_verbose" -ge $level ]; then
46 # use stderr for printing within functions stdout of which might be used
61 nd-aptenable $nd_aptenable_version
63 Copyright (C) 2014 Yaroslav Halchenko <debian@onerussian.com>
65 Licensed under GNU Public License version 3 or later.
66 This is free software; see the source for copying conditions. There is NO
67 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
69 Written by Yaroslav Halchenko for the NeuroDebian project.
76 if [ -z "$ae_dry_run" ]; then
87 Usage: nd-aptenable [options]
89 Enables NeuroDebian repository for the current Debian or Ubuntu release.
94 Name of the Debian/Ubuntu release to be used. If not specified,
95 it is deduced from the apt-cache policy output, by taking repository
96 of Debian or Ubuntu origin with highest priority.
98 -f, --flavor=full|libre
99 Which flavor of the repository should be enabled:
100 libre -- Only main component, containing only DFSG-compliant content.
101 full -- Includes main, contrib, and non-free.
102 If not specified -- deduced from the output of apt-cache policy
104 -c, --components=c1,c2,c3
105 Comma separated list of components to enable among:
106 software -- primary software repository
107 data -- data packages
108 devel -- "overlay" of development versions (like Debians' "experimental").
109 Not sufficient on its own and available only from the main site
110 If not specified -- "software,data"
112 -m, --mirror=NAME|URL
113 Which mirror to use. Could be a mirror code-name (as specified in
114 /etc/neurodebian/neurodebian.cfg), or a URL (TODO).
117 If apt file already present, it would not be overriden (by default).
118 Use this option to overwrite.
121 Which suffix to add to the apt file, in case you are trying to enable
122 multiple repositories
124 --sources, --no-sources
125 Either to enable deb-src lines. If none specified -- would be enabled if
126 sources for a core package (apt) are available.
129 Do not perform any changes -- generated configurations and commands will
130 simply be printed to stdout
133 Enable additional progress messages. Could be used multiple times
136 Make operation quiet -- only error messages would be output
139 Print short description, usage summary and option list.
142 Print version information and exit.
146 non-0 exit status in case of error. Error exit code would depend
147 on which command has failed
151 - Enable software and data components from the optimal (according to
152 netselect) mirror. Some information about progress will be printed
156 - Quietly enable -devel repository for the current release, and place apt
157 configuration into /etc/apt/sources.list.d/neurodebian.sources-devel.list
159 nd-aptenable -q --suffix=-devel -c devel
161 - Force sid distribution, all the components, from the Japan mirror:
163 nd-aptenable -q --suffix=-de-sid-full -c software,data,devel -m jp
168 get_neurodebian_cfg()
170 # First we try to fetch the most recent version from the github
171 print_verbose 3 "Fetching config file from the github repository"
172 cfgfile_temp="$ae_tempdir/neurodebian.cfg"
173 wget -c -q -O$cfgfile_temp https://raw.githubusercontent.com/neurodebian/neurodebian/master/neurodebian.cfg \
174 && { echo $cfgfile_temp; } \
175 || { [ -e "$nd_config_file" ] && return "$nd_config_file"; }
176 # if not -- should blow up
183 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')]))"
188 # echo "TODO: fetch uptodate neurodebian.cfg"
189 nd_config=`get_neurodebian_cfg`
190 # $exe_dir/nd_querycfg -F" " --config-file="$nd_config" "mirrors" \
191 query_cfg_section "$nd_config" "mirrors" \
192 | while read mirror_name mirror_url; do
193 # verify that url is just a url
194 if echo "$mirror_url" | grep -v -e '^[a-z0-9:+]*://[-+_%.a-z0-9/]*$'; then
195 print_verbose 1 "Mirror $mirror_name has 'illegit' URL: $mirror_url. Skipping"
197 echo "$mirror_name $mirror_url"
202 # select "closest" mirror according to netselect.
203 print_verbose 2 "Selecting the 'best' mirror using netselect"
204 if ! which netselect >/dev/null; then
205 print_verbose 1 "netselect (apt-get install netselect) needed to select the 'best' mirror was not found"
206 print_verbose 1 "Selecting the default repository: $nd_mirror_default"
207 echo $nd_mirror_default
209 get_mirrors | awk '{print $2;}' | $ae_sudo xargs netselect -D -s 1 | awk '{print $2;}'
213 # given mirror alias -- find its url
214 url=$(get_mirrors | awk "/^$1 /{print \$2;}")
215 if [ -z "$url" ]; then
216 error 9 "Cannot resolve mirror $1 to the URL"
223 # Get apt-cache policy output in a single list for matching suites
224 # (could be a separated with \| or , for multiple choices, e.g.
226 # get_apt_policy Debian,Ubuntu
228 # get_apt_policy NeuroDebian
230 apt-cache policy | grep -B1 -e "o=\(${suites//,/\\|}\)" | tr '\n' ' ' | sed -e 's, -- ,\n,g' | grep -v -e '-\(updates\|security\)' | sort -nr
235 echo "$ae_components" | tr ',' '\n' | grep -q "^$1\$"
240 # Commandline options handling
243 # Parse commandline options (taken from the getopt examples from the Debian util-linux package)
244 # Note that we use `"$@"' to let each command-line parameter expand to a
245 # separate word. The quotes around `$@' are essential!
246 # We need CLOPTS as the `eval set --' would nuke the return value of getopt.
247 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' -- "$@"`
249 if [ $? != 0 ] ; then
250 error 2 "Problem with parsing cmdline. Terminating..."
253 # Note the quotes around `$CLOPTS': they are essential!
254 eval set -- "$CLOPTS"
256 if [ `whoami` != "root" ]; then
262 -r|--release) shift; ae_release="$1"; shift;;
263 -f|--flavor) shift; ae_flavor="$1"; shift;;
264 -c|--components) shift; ae_components="$1"; shift;;
266 -m|--mirror) shift; ae_mirror="$1"; shift;;
268 --print-mirrors) get_mirrors; exit 0;;
269 --print-best-mirror) netselect_mirror; exit 0;;
270 -n|--dry-run) ae_dry_run=1; shift;;
271 --suffix) shift; ae_suffix="$1"; shift;;
272 --overwrite) ae_overwrite="$1"; shift;;
273 --sources) ae_sources=1; shift;;
274 --no-sources) ae_sources=0; shift;;
275 -q|--quiet) ae_verbose=0; shift;;
276 -v|--verbose) ae_verbose=$(($ae_verbose+1)); shift;;
277 -h|--help) print_help; exit 0;;
278 --version) print_version; exit 0;;
280 *) error 1 "Internal error! ($1)";;
285 if [ $# -gt 0 ] ; then
291 [ -z "$ae_sudo" ] || print_verbose 1 "This script requires root access. Since current user is not root, sudo will be used"
294 # Basic system/environment knowledge
297 ae_output_file=/etc/apt/sources.list.d/neurodebian.sources${ae_suffix}.list
299 apt_policy=$(get_apt_policy "Debian,Ubuntu" )
301 if [ -z "$ae_release" ]; then
302 ae_release=$(echo "$apt_policy" | head -1 | sed -e 's/.*,n=\([^,]*\),.*/\1/g')
305 if [ -z "$ae_flavor" ]; then
306 ae_flavor=$(echo "$apt_policy" | grep -e ",n=$ae_release," | grep -qe 'c=\(non-free\|restricted\)' && echo "full" || echo "libre")
310 # Determine which mirror to use
313 # TODO -- determine mirror URL
314 # 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
321 # TODO -- determine from the abbreviation
323 best) ae_mirror_url=$(netselect_mirror);;
324 default) ae_mirror_url=$nd_mirror_default;;
325 origin) ae_mirror_url=$nd_mirror_origin;;
326 *) ae_mirror_url=$(get_mirror_url "$ae_mirror");;
329 ae_mirror_url="$ae_mirror" # it was some kind of a URL already
339 full) apt_flavor="contrib non-free";;
340 libre) apt_flavor="";;
341 *) error 5 "Unknown value of flavor $apt_flavor. Must be full or libre"
344 if [ -z "$ae_sources" ]; then
345 apt-cache showsrc apt >&/dev/null && ae_sources=1 || ae_sources=0
348 if [ $ae_sources -eq 0 ]; then
356 if include_component software; then
358 # NeuroDebian software repository
359 deb $ae_mirror_url $ae_release main $apt_flavor
360 ${sources_comment}deb-src $ae_mirror_url $ae_release main $apt_flavor
364 if include_component data; then
366 # NeuroDebian data repository
367 deb $ae_mirror_url data main $apt_flavor
368 ${sources_comment}deb-src $ae_mirror_url data main $apt_flavor
372 if include_component devel; then
374 # NeuroDebian -devel repository
375 deb http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
376 ${sources_comment}deb-src http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
380 if [ -e "$ae_output_file" ] && [ -z "$ae_overwrite" ]; then
381 # TODO: compare the content
382 if diff "$ae_output_file" <(echo "$apt_list") | grep -q .; then
384 print_verbose 1 "File $ae_output_file already exists, containing:\n`cat \"$ae_output_file\"`\n\nI: New configuration is different:\n$apt_list"
385 if get_apt_policy NeuroDebian >/dev/null; then
386 print_verbose 1 "NeuroDebian repositories are already available, thus skipping the rest."
387 print_verbose 1 "Rerun with --overwrite if you would like to reconfigure."
390 print_verbose 1 "NeuroDebian configuration is found but not yet available -- continuing with new configuration."
393 print_verbose 1 "New configuration is identical to existing and NeuroDebian repository is already enabled."
394 print_verbose 1 "Skiping the rest. Rerun with --overwrite if you would like to reconfigure."
398 print_verbose 1 "Generating $ae_output_file"
399 if [ -z "$ae_dry_run" ]; then
400 echo "$apt_list" | $ae_sudo bash -c "cat - >| '$ae_output_file'"
409 # Assure present archive GPG key for APT system
412 # Figure out if key needs to be imported (if ran within package,
413 # should already be there due to neurodebian-keyring package)
414 if LANG=C eval $ae_sudo apt-key export $nd_key_id 2>&1 1>/dev/null | grep -qe "nothing exported"; then
415 print_verbose 1 "Fetching the key from the server"
416 eval_dry apt-key adv --recv-keys --keyserver pgp.mit.edu $nd_key_id
420 # Finalizing (apt-get update etc)
423 print_verbose 1 "Updating APT listings, might take a few minutes"
424 if [ -z "$ae_dry_run" ]; then
425 apt_logfile="$ae_tempdir/apt.log"
426 $ae_sudo apt-get update 1>"$apt_logfile" 2>&1 \
427 && rm -f "$apt_logfile" \
430 error 5 "E: Update failed with exit code $? (above output logged into $apt_logfile)."
433 eval_dry apt-get update
436 if [ "$ae_verbose" -ge 2 ]; then
437 print_verbose 2 "Currently enabled NeuroDebian suites/mirrors:"
438 get_apt_policy NeuroDebian