1#!/usr/local/bin/python 2# 3# This script generates a master INDEX file for the CD images built by the 4# FreeBSD release engineers. Each disc is given a list of desired packages. 5# Dependencies of these packages are placed on either the same disc or an 6# earlier disc. The resulting master INDEX file is then written out. 7# 8# Usage: package-split.py <INDEX> <master INDEX> 9# 10# $FreeBSD: stable/9/release/scripts/package-split.py 253613 2013-07-24 13:43:09Z gjb $ 11 12import os 13import sys 14 15try: 16 arch = os.environ["PKG_ARCH"] 17except: 18 arch = os.uname()[4] 19print "Using arch %s" % (arch) 20 21if 'PKG_VERBOSE' in os.environ: 22 verbose = 1 23else: 24 verbose = 0 25 26# List of packages for dvd1. 27def dvd1_packages(): 28 pkgs = ['archivers/unzip', 29 'devel/subversion', 30 'devel/subversion-static', 31 'emulators/linux_base-f10', 32 'lang/perl5.14', 33 'misc/freebsd-doc-all', 34 'net/mpd5', 35 'net/rsync', 36 'ports-mgmt/portaudit', 37 'ports-mgmt/portmaster', 38 'shells/bash', 39 'shells/zsh', 40 'security/sudo', 41 'sysutils/screen', 42 'www/firefox', 43 'www/links', 44 'x11-drivers/xf86-video-vmware', 45 'x11/gnome2', 46 'x11/kde4', 47 'x11/xorg']; 48 return pkgs 49 50# The list of desired packages 51def desired_packages(): 52 dvd1 = dvd1_packages() 53 return [dvd1] 54 55# Suck the entire INDEX file into a two different dictionaries. The first 56# dictionary maps port names (origins) to package names. The second 57# dictionary maps a package name to a list of its dependent packages. 58PACKAGE_COL=0 59ORIGIN_COL=1 60DEPENDS_COL=8 61 62def load_index(index): 63 deps = {} 64 pkgs = {} 65 line_num = 1 66 for line in index: 67 fields = line.split('|') 68 name = fields[PACKAGE_COL] 69 if name in deps: 70 sys.stderr.write('%d: Duplicate package %s\n' % (line_num, name)) 71 sys.exit(1) 72 origin = fields[ORIGIN_COL].replace('/usr/ports/', '', 1) 73 if origin in pkgs: 74 sys.stderr.write('%d: Duplicate port %s\n' % (line_num, origin)) 75 sys.exit(1) 76 deps[name] = fields[DEPENDS_COL].split() 77 pkgs[origin] = name 78 line_num = line_num + 1 79 return (deps, pkgs) 80 81# Layout the packages on the various CD images. Here's how it works. We walk 82# each disc in the list of discs. Within each disc we walk the list of ports. 83# For each port, we add the package name to a dictionary with the value being 84# the current disc number. We also add all of the dependent packages. If 85# a package is already in the dictionary when we go to add it, we just leave 86# the dictionary as it is. This means that each package ends up on the first 87# disc that either lists it or contains it as a dependency. 88def layout_discs(discs, pkgs, deps): 89 disc_num = 1 90 layout = {} 91 for disc in discs: 92 for port in disc: 93 if port not in pkgs: 94 sys.stderr.write('Disc %d: Unable to find package for %s\n' % 95 (disc_num, port)) 96 continue 97 pkg = pkgs[port] 98 pkg_list = [pkg] + deps[pkg] 99 for pkg in pkg_list: 100 if pkg not in layout: 101 if verbose: 102 print "--> Adding %s to Disc %d" % (pkg, disc_num) 103 layout[pkg] = disc_num 104 disc_num = disc_num + 1 105 return layout 106 107# Generate a master INDEX file based on the generated layout. The way this 108# works is that for each INDEX line, we check to see if the package is in the 109# layout. If it is, we put that INDEX line into the master INDEX and append 110# a new field with the disc number to the line. 111def generate_index(index, layout, master_index): 112 for line in index: 113 pkg = line.split('|')[PACKAGE_COL] 114 if pkg in layout: 115 new_line = '%s|%d\n' % (line.splitlines()[0], layout[pkg]) 116 master_index.write(new_line) 117 118# Verify the command line arguments 119if len(sys.argv) != 3: 120 sys.stderr.write('Invalid number of arguments\n') 121 sys.stderr.write('Usage: package-split.py <source INDEX> <master INDEX>\n') 122 sys.exit(1) 123 124print "Loading %s..." % (sys.argv[1]) 125index = file(sys.argv[1]) 126(deps, pkgs) = load_index(index) 127discs = desired_packages() 128layout = layout_discs(discs, pkgs, deps) 129index.seek(0) 130print "Generating %s..." % (sys.argv[2]) 131master_index = file(sys.argv[2], 'w') 132generate_index(index, layout, master_index) 133index.close() 134master_index.close() 135