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 Debian "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 not specified -- deduced based on ??? TODO
128 Do not perform any changes -- generated configurations and commands will
129 simply be printed to stdout
132 Enable additional progress messages. Could be used multiple times
135 Make operation quiet -- only error messages would be output
138 Print short description, usage summary and option list.
141 Print version information and exit.
145 non-0 exit status in case of error. Error exit code would depend
146 on which command has failed
150 - Enable software and data components from the optimal (according to
151 netselect) mirror. Some information about progress will be printed
155 - Quietly enable -devel repository for the current release, and place apt
156 configuration into /etc/apt/sources.list.d/neurodebian.sources-devel.list
158 nd-aptenable -q --suffix=-devel -c devel
160 - Force sid distribution, all the components, from the Japan mirror:
162 nd-aptenable -q --suffix=-de-sid-full -c software,data,devel -m jp
167 get_neurodebian_cfg()
169 # First we try to fetch the most recent version from the github
170 print_verbose 3 "Fetching config file from the github repository"
171 cfgfile_temp="$ae_tempdir/neurodebian.cfg"
172 wget -c -q -O$cfgfile_temp https://raw.githubusercontent.com/neurodebian/neurodebian/master/neurodebian.cfg \
173 && { echo $cfgfile_temp; } \
174 || { [ -e "$nd_config_file" ] && return "$nd_config_file"; }
175 # if not -- should blow up
182 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')]))"
187 # echo "TODO: fetch uptodate neurodebian.cfg"
188 nd_config=`get_neurodebian_cfg`
189 # $exe_dir/nd_querycfg -F" " --config-file="$nd_config" "mirrors" \
190 query_cfg_section "$nd_config" "mirrors" \
191 | while read mirror_name mirror_url; do
192 # verify that url is just a url
193 if echo "$mirror_url" | grep -v -e '^[a-z0-9:+]*://[-+_%.a-z0-9/]*$'; then
194 print_verbose 1 "Mirror $mirror_name has 'illegit' URL: $mirror_url. Skipping"
196 echo "$mirror_name $mirror_url"
201 # select "closest" mirror according to netselect.
202 print_verbose 2 "Selecting the 'best' mirror using netselect"
203 if ! which netselect >/dev/null; then
204 print_verbose 1 "netselect (apt-get install netselect) needed to select the 'best' mirror was not found"
205 print_verbose 1 "Selecting the default repository: $nd_mirror_default"
206 echo $nd_mirror_default
208 get_mirrors | awk '{print $2;}' | $ae_sudo xargs netselect -D -s 1 | awk '{print $2;}'
212 # given mirror alias -- find its url
213 url=$(get_mirrors | awk "/^$1 /{print \$2;}")
214 if [ -z "$url" ]; then
215 error 9 "Cannot resolve mirror $1 to the URL"
222 # Get apt-cache policy output in a single list for matching suites
223 # (could be a separated with \| or , for multiple choices, e.g.
225 # get_apt_policy Debian,Ubuntu
227 # get_apt_policy NeuroDebian
229 apt-cache policy | grep -B1 -e "o=\(${suites//,/\\|}\)" | tr '\n' ' ' | sed -e 's, -- ,\n,g' | grep -v -e '-\(updates\|security\)' | sort -nr
234 echo "$ae_components" | tr ',' '\n' | grep -q "^$1\$"
239 # Commandline options handling
242 # Parse commandline options (taken from the getopt examples from the Debian util-linux package)
243 # Note that we use `"$@"' to let each command-line parameter expand to a
244 # separate word. The quotes around `$@' are essential!
245 # We need CLOPTS as the `eval set --' would nuke the return value of getopt.
246 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' -- "$@"`
248 if [ $? != 0 ] ; then
249 error 2 "Problem with parsing cmdline. Terminating..."
252 # Note the quotes around `$CLOPTS': they are essential!
253 eval set -- "$CLOPTS"
255 if [ `whoami` != "root" ]; then
261 -r|--release) shift; ae_release="$1"; shift;;
262 -f|--flavor) shift; ae_flavor="$1"; shift;;
263 -c|--components) shift; ae_components="$1"; shift;;
265 -m|--mirror) shift; ae_mirror="$1"; shift;;
267 --print-mirrors) get_mirrors; exit 0;;
268 --print-best-mirror) netselect_mirror; exit 0;;
269 -n|--dry-run) ae_dry_run=1; shift;;
270 --suffix) shift; ae_suffix="$1"; shift;;
271 --overwrite) ae_overwrite="$1"; shift;;
272 --sources) ae_sources=1; shift;;
273 --no-sources) ae_sources=0; shift;;
274 -q|--quiet) ae_verbose=0; shift;;
275 -v|--verbose) ae_verbose=$(($ae_verbose+1)); shift;;
276 -h|--help) print_help; exit 0;;
277 --version) print_version; exit 0;;
279 *) error 1 "Internal error! ($1)";;
284 if [ $# -gt 0 ] ; then
290 [ -z "$ae_sudo" ] || print_verbose 1 "This script requires root access. Since current user is not root, sudo will be used"
293 # Basic system/environment knowledge
296 ae_output_file=/etc/apt/sources.list.d/neurodebian.sources${ae_suffix}.list
298 apt_policy=$(get_apt_policy "Debian,Ubuntu" )
300 if [ -z "$ae_release" ]; then
301 ae_release=$(echo "$apt_policy" | head -1 | sed -e 's/.*,n=\([^,]*\),.*/\1/g')
304 if [ -z "$ae_flavor" ]; then
305 ae_flavor=$(echo "$apt_policy" | grep -e ",n=$ae_release," | grep -qe 'c=\(non-free\|restricted\)' && echo "full" || echo "libre")
309 # Determine which mirror to use
312 # TODO -- determine mirror URL
313 # Not necessary for -devel available only from the main site
314 if include_component software || include_component data; then
315 # for now just use default
316 if [ -z "$ae_mirror" ]; then # none specified
317 ae_mirror_url=$nd_mirror_origin
319 if ! [[ "$ae_mirror" =~ ".*://.*" ]]; then
320 # TODO -- determine from the abbreviation
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" ] || [ $ae_sources -eq 0 ]; then
351 if include_component software; then
353 # NeuroDebian software repository
354 deb $ae_mirror_url $ae_release main $apt_flavor
355 ${sources_comment}deb-src $ae_mirror_url $ae_release main $apt_flavor
359 if include_component data; then
361 # NeuroDebian data repository
362 deb $ae_mirror_url data main $apt_flavor
363 ${sources_comment}deb-src $ae_mirror_url data main $apt_flavor
367 if include_component devel; then
369 # NeuroDebian -devel repository
370 deb http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
371 ${sources_comment}deb-src http://neuro.debian.net/debian-devel $ae_release main $apt_flavor
375 if [ -e "$ae_output_file" ] && [ -z "$ae_overwrite" ]; then
376 # TODO: compare the content
378 print_verbose 1 "File $ae_output_file already exists, containing:\n\n`cat \"$ae_output_file\"`\n\nI: Use --overwrite option to regenerate with:\n\n$apt_list"
379 if get_apt_policy NeuroDebian >/dev/null; then
380 print_verbose 1 "NeuroDebian repositories are already available, thus skipping the rest."
381 print_verbose 1 "Rerun with --overwrite if you would like to reconfigure."
385 print_verbose 1 "Generating $ae_output_file"
386 if [ -z "$ae_dry_run" ]; then
387 echo "$apt_list" | $ae_sudo bash -c "cat - >| '$ae_output_file'"
396 # Assure present archive GPG key for APT system
399 # Figure out if key needs to be imported (if ran within package,
400 # should already be there due to neurodebian-keyring package)
401 if LANG=C eval $ae_sudo apt-key export $nd_key_id 2>&1 1>/dev/null | grep -qe "nothing exported"; then
402 print_verbose 1 "Fetching the key from the server"
403 eval_dry apt-key adv --recv-keys --keyserver pgp.mit.edu $nd_key_id
407 # Finalizing (apt-get update etc)
410 print_verbose 1 "Updating APT listings, might take a few minutes"
411 if [ -z "$ae_dry_run" ]; then
412 apt_logfile="$ae_tempdir/apt.log"
413 $ae_sudo apt-get update 1>"$apt_logfile" 2>&1 \
414 && rm -f "$apt_logfile" \
417 error 5 "E: Update failed with exit code $? (above output logged into $apt_logfile)."
420 eval_dry apt-get update
423 if [ "$ae_verbose" -ge 2 ]; then
424 print_verbose 2 "Currently enabled NeuroDebian suites/mirrors:"
425 get_apt_policy NeuroDebian