]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - release/scripts/package-split.py
Copy head to stable/8 as part of 8.0 Release cycle.
[FreeBSD/stable/8.git] / release / scripts / package-split.py
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$
11
12 import os
13 import sys
14
15 try:
16     arch = os.environ["PKG_ARCH"]
17 except:
18     arch = os.uname()[4]
19 print "Using arch %s" % (arch)
20
21 if 'PKG_VERBOSE' in os.environ:
22     verbose = 1
23 else:
24     verbose = 0
25
26 # List of packages for disc1.  This just includes packages sysinstall can
27 # install as a distribution
28 def disc1_packages():
29     pkgs = ['lang/perl5.8']
30     pkgs.extend(['x11/xorg',
31                  'devel/imake'])
32     if arch == 'i386':
33         pkgs.append('emulators/linux_base-fc4')
34     return pkgs
35
36 # List of packages for disc2.  This includes packages that the X desktop
37 # menu depends on (if it still exists) and other "nice to have" packages.
38 # For architectures that use a separate livefs, this is actually disc3.
39 def disc2_packages():
40             # X Desktops
41     if arch == 'ia64':
42         pkgs = ['x11/gnome2-lite',
43                 'x11/kde-lite']
44     else:
45         pkgs = ['x11/gnome2',
46                 'x11/kde3']
47     pkgs.extend(['x11-wm/afterstep',
48             'x11-wm/windowmaker',
49             'x11-wm/fvwm2',
50             # "Nice to have"
51             'archivers/unzip',
52             'astro/xearth',                 
53             'devel/gmake',
54             'editors/emacs',
55             'editors/vim-lite',
56             'emulators/mtools',
57             'graphics/png',
58             'graphics/xv',
59             'irc/xchat',
60             'mail/exim',
61             'mail/fetchmail',
62             'mail/mutt',
63             'mail/pine4',
64             'mail/popd',
65             'mail/xfmail',
66             'mail/postfix',
67             'net/cvsup-without-gui',
68             'net/rsync',
69             'net/samba3',
70             'news/slrn',
71             'news/tin',
72             'ports-mgmt/portupgrade',
73             'print/a2ps-letter',
74             'print/apsfilter',
75             'print/ghostscript-gnu-nox11',
76             'print/gv',
77             'print/psutils-letter',
78             'shells/bash',
79             'shells/pdksh',
80             'shells/zsh',
81             'security/sudo',
82             'www/links',
83             'www/lynx',
84             'x11/rxvt',
85             # Formerly on disc3
86             'ports-mgmt/portaudit'])
87     return pkgs
88
89 def docs_packages():
90     pkgs = ['misc/freebsd-doc-bn',
91             'misc/freebsd-doc-da',
92             'misc/freebsd-doc-de',
93             'misc/freebsd-doc-el',
94             'misc/freebsd-doc-en',
95             'misc/freebsd-doc-es',
96             'misc/freebsd-doc-fr',
97             'misc/freebsd-doc-hu',
98             'misc/freebsd-doc-it',
99             'misc/freebsd-doc-ja',
100             'misc/freebsd-doc-mn',
101             'misc/freebsd-doc-nl',
102             'misc/freebsd-doc-pl',
103             'misc/freebsd-doc-pt',
104             'misc/freebsd-doc-ru',
105             'misc/freebsd-doc-sr',
106             'misc/freebsd-doc-tr',
107             'misc/freebsd-doc-zh_cn',
108             'misc/freebsd-doc-zh_tw']
109     return pkgs
110
111 # The list of desired packages
112 def desired_packages():
113     disc1 = disc1_packages()
114     disc2 = disc2_packages()
115     docs = docs_packages()
116     return [disc1, disc2, docs]
117
118 # Suck the entire INDEX file into a two different dictionaries.  The first
119 # dictionary maps port names (origins) to package names.  The second
120 # dictionary maps a package name to a list of its dependent packages.
121 PACKAGE_COL=0
122 ORIGIN_COL=1
123 DEPENDS_COL=8
124
125 def load_index(index):
126     deps = {}
127     pkgs = {}
128     line_num = 1
129     for line in index:
130         fields = line.split('|')
131         name = fields[PACKAGE_COL]
132         if name in deps:
133             sys.stderr.write('%d: Duplicate package %s\n' % (line_num, name))
134             sys.exit(1)
135         origin = fields[ORIGIN_COL].replace('/usr/ports/', '', 1)
136         if origin in pkgs:
137             sys.stderr.write('%d: Duplicate port %s\n' % (line_num, origin))
138             sys.exit(1)
139         deps[name] = fields[DEPENDS_COL].split()
140         pkgs[origin] = name
141         line_num = line_num + 1
142     return (deps, pkgs)
143
144 # Layout the packages on the various CD images.  Here's how it works.  We walk
145 # each disc in the list of discs.  Within each disc we walk the list of ports.
146 # For each port, we add the package name to a dictionary with the value being
147 # the current disc number.  We also add all of the dependent packages.  If
148 # a package is already in the dictionary when we go to add it, we just leave
149 # the dictionary as it is.  This means that each package ends up on the first
150 # disc that either lists it or contains it as a dependency.
151 def layout_discs(discs, pkgs, deps):
152     disc_num = 1
153     layout = {}
154     for disc in discs:
155         for port in disc:
156             if port not in pkgs:
157                 sys.stderr.write('Disc %d: Unable to find package for %s\n' %
158                                  (disc_num, port))
159                 continue
160             pkg = pkgs[port]
161             pkg_list = [pkg] + deps[pkg]
162             for pkg in pkg_list:
163                 if pkg not in layout:
164                     if verbose:
165                         print "--> Adding %s to Disc %d" % (pkg, disc_num)
166                     layout[pkg] = disc_num
167         disc_num = disc_num + 1
168     return layout
169
170 # Generate a master INDEX file based on the generated layout.  The way this
171 # works is that for each INDEX line, we check to see if the package is in the
172 # layout.  If it is, we put that INDEX line into the master INDEX and append
173 # a new field with the disc number to the line.
174 def generate_index(index, layout, master_index):
175     for line in index:
176         pkg = line.split('|')[PACKAGE_COL]
177         if pkg in layout:
178             new_line = '%s|%d\n' % (line.splitlines()[0], layout[pkg])
179             master_index.write(new_line)
180
181 # Verify the command line arguments
182 if len(sys.argv) != 3:
183     sys.stderr.write('Invalid number of arguments\n')
184     sys.stderr.write('Usage: package-split.py <source INDEX> <master INDEX>\n')
185     sys.exit(1)
186
187 print "Loading %s..." % (sys.argv[1])
188 index = file(sys.argv[1])
189 (deps, pkgs) = load_index(index)
190 discs = desired_packages()
191 layout = layout_discs(discs, pkgs, deps)
192 index.seek(0)
193 print "Generating %s..." % (sys.argv[2])
194 master_index = file(sys.argv[2], 'w')
195 generate_index(index, layout, master_index)
196 index.close()
197 master_index.close()