Breaking broken ...

Far be it from me to complain about free software (!) but after spending the last few weeks working with the debian-cd package I'm more than a little bit horrified. Is this really what people are using to generate install CD's ?!

Ok, so it builds lots of different architectures, lots of different media formats, lots of different versions of Debian, but to be realistic, looking at the comments this code was written over 16 years ago in a mash-up of Makefiles, Bash and Perl, then added to as time has passed.

It is horrible.

After spending a few days pretending that I could customise the procedure and possibly understand what it was doing to the extent my changes weren't going to cause more harm than good, I gave up. It's a rat's nest.

Just to give an example, a large portion of the code is given over to working out which packages to include on the distribution medium (CD) , which involves generating a whole bunch of files, resolving dependencies, adding more files, re-resolving dependencies, then writing the results to a number of different files in formats specific to the next stage of the process. My brain hurts just thinking about it, and not just because it's mostly written in Perl.

So, I'm still doing battle with xorriso with regards to making the the entire installer one Python program, but I have managed to make my new, slightly more rational code bootable using the current Makefile. It looks something like this;

import apt_pkg
root = "<my fake root directory>"
apt_pkg.init_config()
conf = apt_pkg.config 
conf.set("Dir",root)
apt_pkg.init_system()
cache = apt_pkg.Cache()
depcache = apt_pkg.DepCache(cache)

required = ['xfce','debian-installer','kernel']
for pkg in required:
  if not pkg in cache:
    print("Unknown package (%s) requested" % pkg)
    continue
  if not len(cache[pkg].version_list):
    print("Package (%s) is virtual" % pkg)
    continue
  depcache.mark_install(cache[pkg],True)

for pkg in cache.packages:
  if not depcache.marked_install(pkg): continue
  c = depcache.get_candidate_ver(pkg)
  print("%s:%s:%s:%s\n" % (c.arch,c.section,pkg.name,c.size))

The principle here is python-apt, which is doing most of the work. What we're doing with mark_install is effectively calling apt with include dependencies for each of the top level requirements, at which point the internal apt tree has marked the top level and all lower dependencies.

If we then simply scan all packages and pick out the ones that are marked for installation, we end up with a complete dependency list for the top level packages we've asked for.

This code can be inserted 'inline' to replace the first half of what debian-cd effectively does and the resulting CD installs quite happily. Question; how many scripts and thousands of lines of Perl does this code replace?!

So my link of the day is Wikipedia's refactoring code entry!!!