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 via email to