[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Apt configurator



I've attached the updated apt configurator to this message. This version is
much more fleshed out. See my previous message to debian-boot if you want to
try it.

It now loops so multiple sources can be added, and I added a sanity check
after each source is entered (apt-get update), so bad entries are not added.

I added support for CD's, and for an already-mounted mirror. I'd like to add
support for automounting a nfs mirror when apt is run, but apt doesn't
actually seem to provide hooks for that.

The CD support is still rough, it will first try /dev/cdrom and if that's
not found, prompts for the device name. More advanced autoprobing could be
added, and I encourage someone who knows something about this to do so (see
comment in source for where), and I also hope to make it have a list of
possibilities like the menu on the boot floppies. Once it has a device, it
uses apt-cdrom to scan the device and add it to sources.list, and loops
until you've entered all your cd's.

One thing I still need to add is non-us support. And I'm not really sure how
I want to do this. Are there enough non-us mirrors to justify making them
chose between them, or does it make more sense to just ask them if they want
it and put a pre-written line in if so?


I also have a weird problem with apt-cdrom that I need help from the apt
team to fix, I think. The problem is that once I have used apt-cdrom add,
apt-get update always spits out errors like:

Failed to fetch cdrom:Debian GNU_Linux slink (2.1) 1_4 main binary-i386
section 1 SAM19990908/debian/dists/stable/contrib/binary-i386/Packages
  Method gave a blank filename

... and exits with return code 100. As I understand it, apt-cdrom add might
scan the packages files itself and so apt-get update is unnecessary -- but
what if you want to use a cdrom + hit the ftp site for stable updates? You
have to use apt-get update then, and it doesn't work!

-- 
see shy jo
Template: aptconf/uri_type
Type: select
Choices: cdrom, http, ftp, nfs, filesystem
Default: cdrom
Description: Choose what method apt will use to access the Debian archive
 Apt can access the Debian archive in a variety of ways. Choose the access
 method apt should use. For example if you have a Debian cd, select "cdrom",
 while if you plan to install via a Debian mirror, choose "ftp" or "http".

Template: aptconf/country
Type: select
Choices: ${countries}, enter information manually
Default: US
Description: Select your country
 The first step in choosing what Debian mirror you use is selecting your
 country. If your country is not on this list, select a neighboring
 country. The goal is to find a mirror that is close to you on the network.
 .
 If you want to enter mirror information manually, select the last item on
 the list.

Template: aptconf/mirror
Type: select
Choices: ${mirrors}
Description: Choose the Debian mirror to use
 Select the Debian mirror apt should use. You should select a mirror that
 is close to you on the net.

Template: aptconf/hostname
Type: string
Description: Enter mirror hostname
 Enter the hostname of the Debian mirror you want to use.

Template: aptconf/directory
Type: string
Default: /debian
Description: Enter mirror directory
 Enter the directory the Debian mirror is located in.

Template: aptconf/baddir
Type: note
Description: Mirror not found.
 The directory you entered does not contain a subdirectory named "dists",
 so it doesn't seem to be a Debian mirror.

Template: aptconf/cd/dev
Type: string
Description: Enter CD ROM device file
 This program was unable to auto-detect a CD ROM drive, or there is no CD
 in the drive. Enter the device file to use to access your CD ROM, and place
 a Debian CD in the drive.

Template: aptconf/cd/bad
Type: note
Description: Bad CD
 Your CD was detected, but it does not seem to be a Debian CD.

Template: aptconf/cd/another
Type: boolean
Default: false
Description: Scan another CD?
 If you have another Debian CD (for example, the second in a two CD set),
 you should scan it now.

Template: aptconf/non-free
Type: boolean
Default: false
Description: Use non-free software?
 Debian makes available some non-free software. though this software is not
 part of Debian proper, it can be installed with apt. This software has
 limitations on its distribution, modification, and/or use. Do you wish to
 use this software?

Template: aptconf/contrib
Type: boolean
Default: false
Description: Use contrib software?
 Debian includes some software that, while free, does not work without other,
 non-free software. Do you wish to use this software?

Template: aptconf/distribution
Type: select
Choices: stable, unstable
Default: stable
Description: Select Debian distribution to use
 Debian comes in two flavors. Stable is well-tested and rarely changes.
 Unstable is untested and frequently changing. Which of the two do you wish
 to install?

Template: aptconf/badsource
Type: note
Description: Failed to access the Debian archive
 It's likely that you answered some questions incorrectly; when I tried
 to access the debian archive using the information you provided, apt
 gave the following error. I will run through the questions again,
 try to correct the error.
 .
 ${apt_error}

Template: aptconf/another
Type: boolean
Default: false
Description: Add another apt source?
 Apt can optionally install from multiple Debian archives. You have just
 successfully added a source to apt, and if you like, you can add another
 one.
#!/bin/sh -e

# Where is the mirrors master list?
MIRRORLIST=~/Mirrors.masterlist

PATH=$PATH:Client
if [ -e Client/confmodule.sh ]; then
	. Client/confmodule.sh
else
	. /usr/share/debconf/confmodule.sh
fi

# Pass in a URI type, this function returns a list of countries
# that have mirrors in them that match the type.
country_list () {
	perl -ne '
		BEGIN { $/="\n\n"; $type=shift }
		if (/Archive-$type:/) {
			($c)=/Country: (.*?)\s*\n/;
			$countries{$c}=1 if $c;
		}
		END { print join(", ", sort(keys %countries)) }
	' $1 $MIRRORLIST
}

# Pass in a URI type and a country, this function returns a 
# list of mirrors of the correct type in the country.
# The list is ordered with push mirrors at the top.
# Other orderings can be added here.
mirror_list () {
	perl -ne '
		BEGIN { $/="\n\n"; $type=shift; $country=shift }
		if (/Archive-$type:/ && /Country: $country\s*\n/) {
			($s)=/Site: (.*?)\n/;
			($t)=/Type: (.*?)\n/;
			$rating=0;
			$rating=1 if $t=~/push/i;
			$rating=2 if $t=~/push-primary/i;
			$mirrors{$s}=$rating;
		}
		END { print join(", ",
			sort { $mirrors{$b} <=> $mirrors{$a} }
			(keys %mirrors)) }
	' $1 "$2" $MIRRORLIST
}

# Pass in the URI type and the hostname of a mirror; this returns the
# directory the debian mirror is located in on that host.
mirror_dir () {
	perl -ne '
		BEGIN { $/="\n\n"; $type=shift; $mirror=shift }
		if (/Archive-$type: (.*)\n/) {
			print $1;
			exit;
		}
	' $1 $2 $MIRRORLIST
}

# After mounting a cd, call this function to scan
# it with apt-cdrom, which also adds it to the sources.list.
scan_cd () {
	# BUG: this makes contrib be added even if they
	#      said not to include it.
	clear
	echo "Scanning CD, this will take a minute."
	if apt-cdrom add --no-mount; then
		return 0
	else
		# Apt didn't like the cdrom for some reason.
		db_fset aptconf/cd/bad isdefault true
		db_input aptconf/cd/bad
		db_go
		return 1
	fi
}

# Make sure the file exists, and back it up.
touch /etc/apt/sources.list
cp -f /etc/apt/sources.list /etc/apt/sources.list.bak

# Establish the preliminaries.
db_version
#db_capb 'backup'
db_title 'Apt Configuration'

MAINLOOP=1

while [ "$MAINLOOP" ]; do
	MAINLOOP=''

	# Ask some unreleated questions to get started.
	db_beginblock
	db_fset aptconf/distribution isdefault true
	db_input low aptconf/distribution
	db_fset aptconf/uri_type isdefault true
	db_input critical aptconf/uri_type
	db_fset aptconf/non-free isdefault true
	db_input medium aptconf/non-free
	db_endblock
	db_go

	# If they choose to use non-free, ask about contrib.
	# Doesn't seem to make much sense to even ask, otherwise.
	db_get aptconf/non-free
	if [ "$RET" = true ]; then
		db_fset aptconf/contrib isdefault true
		db_input medium aptconf/contrib
		db_go
	fi

	db_get aptconf/uri_type
	URI="$RET"
	
	case "$URI" in
	ftp|http)
		# Ask them which country they're in.
		db_subst aptconf/country countries "`country_list $URI`"
		db_fset aptconf/country isdefault true
		db_input critical aptconf/country
		db_go
		
		db_get aptconf/country
		if [ "$RET" != "enter information manually" ]; then
			# Now prompt with the mirrors in the selected country.
			db_subst aptconf/mirror mirrors "`mirror_list $URI \"$RET\"`"
			db_fset aptconf/mirror isdefault true
			db_input critical aptconf/mirror
			db_go
			
			# Now shove the data about the mirror into some other
			# questions.
			db_get aptconf/mirror
			MIRROR="$RET"
			db_set aptconf/hostname $MIRROR
			db_set aptconf/directory "`mirror_dir $URI $MIRROR`"
		else
			# They elected to enter info manually.
			# Prompt for hostname and directory the mirror is in.
			db_beginblock
			db_fset aptconf/hostname isdefault true
			db_input critical aptconf/hostname
			db_fset aptconf/directory isdefault true
			db_input critical aptconf/directory
			db_endblock
			db_go
		fi
	;;
	cdrom)
		# First we need to figure out what device the cd is in.
		
		# If /dev/cdrom exists, use it.
		if [ -e /dev/cdrom ]; then
			CDDEV=/dev/cdrom
			db_set aptconf/cd/dev "$CDDEV"
		fi	
		# TODO: other probing here.

		LOOP=1
		while [ "$LOOP" ]; do
			# Make sure the cd is unmounted, we may be prompting
			# them to change cd's.
			umount /cdrom 2>/dev/null || true
		
			# Otherwise, prompt.
			# TODO: We could give them a list of likely devices..
			#       This is unfriendly right now.
			if [ -z "$CDDEV" ]; then
				db_input critical aptconf/cd/dev
				db_go
				db_get aptconf/cd/dev
				CDDEV="$RET"
			fi
			
			# Now try to mount the cdrom. If this fails, we loop,
			# and prompt again.
			if mount $CDDEV /cdrom -o ro -t iso9660; then
				scan_cd && LOOP=""
			else
				db_fset aptconf/cd/dev isdefault true
				CDDEV=""
			fi
		done
		
		# If we got this far, they were able to detect and scan 1 cd.
		# Now go into a loop, asking them if more cd's should be
		# scanned.
		LOOP=1
		while [ "$LOOP" ]; do
			# Make sure the cd is unmounted, we may be prompting
			# them to change cd's.
			umount /cdrom 2>/dev/null || true
		
			db_set aptconf/cd/another false
			db_fset aptconf/cd/another isdefault true
			db_input medium aptconf/cd/another
			db_go
			db_get aptconf/cd/another
			if [ "$RET" = true ]; then
				while ! mount $CDDEV /cdrom -o ro -t iso9660
				do
					db_fset aptconf/cd/dev isdefault true
					db_input critical aptconf/cd/dev
					db_go
					db_get aptconf/cd/dev
					CDDEV="$RET"
				done
				scan_cd
			else
				LOOP=''
			fi
		done
	;;
	
	filesystem|nfs)
		# nfs and filesystem are the same, really -- they need to
		# have a mirror already mounted somewhere.
		URI=file
		LOOP=1
		while [ "$LOOP" ]; do
			db_fset aptconf/directory isdefault true
			db_input critical aptconf/directory
			db_go
			db_get aptconf/directory
			
			# A very simple mirror sanity check.
			if [ ! -d "$RET/dists" ]; then
				db_fset aptconf/baddir isdefault true
				db_input critical aptconf/baddir
				db_go
			else
				LOOP=''
			fi
		done
	esac

	# Generate the sources.list line if we haven't already.
	if [ "$URI" != cdrom ]; then
		db_get aptconf/hostname
		HOST="$RET"
		db_get aptconf/directory
		DIR="$RET"
		db_get aptconf/distribution
		DIST="$RET"
		db_get aptconf/non-free
		if [ "$RET" = true ]; then
			NONFREE="non-free"
		fi
		db_get aptconf/contrib
		if [ "$RET" = true ]; then
			CONTRIB="contrib"
		fi
		
		if [ "$URI" = ftp -o "$URI" = http ]; then
			SEP=//
		fi
	
		echo "deb $URI:$SEP$HOST$DIR $DIST main $NONFREE $CONTRIB" >> /etc/apt/sources.list
		echo "deb-src $URI:$SEP$HOST$DIR $DIST main $NONFREE $CONTRIB" >> /etc/apt/sources.list

		# As a final sanity check, run apt-get update, and catch the
		# return code and errors. This is unnecessary (I think)
		# if we just added a cdrom, since apt-cdrom does enough checks.
		tempfile=`tempfile`
		clear
		echo "Testing apt sources ..."
		if ! apt-get update 2>$tempfile; then
			# Show the user the error message, remove the bad
			# entry, and loop.
			db_subst aptconf/badsource apt_error `tr '\n' ' ' < $tempfile`
			db_fset aptconf/badsource isdefault true
			db_input critical aptconf/badsource
			db_go
			rm -f $tempfile
			cp /etc/apt/sources.list.bak /etc/apt/sources.list
			MAINLOOP=1
		fi
	fi

	if [ -z "$MAINLOOP" ]; then
		# Now ask them if they want to add another entry, 
		# and if so, restart.
		db_set aptconf/another false
		db_fset aptconf/another isdefault true
		db_input medium aptconf/another
		db_go
		db_get aptconf/another
		if [ "$RET" = true ]; then
			MAINLOOP=1
			# Before looping, make a new backup.
			cp -f /etc/apt/sources.list /etc/apt/sources.list.bak
		fi
	fi
done

Reply to: