~ubuntu-branches/ubuntu/gutsy/debootstrap/gutsy-backports

« back to all changes in this revision

Viewing changes to required-base.py

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, warty
  • Date: 2004-10-13 00:02:10 UTC
  • Revision ID: james.westby@ubuntu.com-20041013000210-6kxir6wy5l3x0qm0
Tags: 0.2.39ubuntu22
[warty] Remove pcmcia-cs from Base.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
 
 
3
"""Build a debootstrap script from a list of base packages and a control
 
4
file listing per-architecture overrides."""
 
5
 
 
6
import sys
 
7
import os
 
8
import string
 
9
import re
 
10
 
 
11
class RequiredPackageNotInBase(Exception): pass
 
12
 
 
13
class Base:
 
14
    def __init__(self):
 
15
        self.base = {}
 
16
 
 
17
    def read(self, f):
 
18
        """Read a file describing the base system on each architecture."""
 
19
        for line in f:
 
20
            line = line.rstrip()
 
21
            if line.startswith('#') or len(line) == 0:
 
22
                continue
 
23
 
 
24
            fields = line.split(':')
 
25
            if len(fields) != 2:
 
26
                continue
 
27
 
 
28
            name = fields[0]
 
29
            value = fields[1].strip()
 
30
            packages = value.split()
 
31
 
 
32
            if name.startswith('base-'):
 
33
                arch = name[5:]
 
34
                if arch not in self.base:
 
35
                    self.base[arch] = []
 
36
                self.base[arch].extend(packages)
 
37
 
 
38
        f.close()
 
39
 
 
40
class Overrides:
 
41
    def __init__(self):
 
42
        self.exclude = []
 
43
        self.required = []
 
44
 
 
45
        self.arch_exclude = {}
 
46
        self.arch_required = {}
 
47
 
 
48
    def read(self, f):
 
49
        """Read an overrides file."""
 
50
        for line in f:
 
51
            line = line.rstrip()
 
52
            if line.startswith('#') or len(line) == 0:
 
53
                continue
 
54
 
 
55
            fields = line.split(':')
 
56
            if len(fields) != 2:
 
57
                continue
 
58
 
 
59
            name = fields[0]
 
60
            value = fields[1].strip()
 
61
            packages = value.split()
 
62
 
 
63
            if name == 'exclude':
 
64
                # Exclude from all architectures (regular expressions)
 
65
                for expr in packages:
 
66
                    self.exclude.append(re.compile(expr))
 
67
            elif name.startswith('exclude-'):
 
68
                # Exclude from one architecture (regular expressions)
 
69
                arch = name[8:]
 
70
                if arch not in self.arch_exclude:
 
71
                    self.arch_exclude[arch] = []
 
72
                for expr in packages:
 
73
                    self.arch_exclude[arch].append(re.compile(expr))
 
74
            elif name == 'required':
 
75
                # Required in first stage on all architectures
 
76
                self.required.extend(packages)
 
77
            elif name.startswith('required-'):
 
78
                # Required in first stage on one architecture
 
79
                arch = name[9:]
 
80
                if arch not in self.arch_required:
 
81
                    self.arch_required[arch] = []
 
82
                self.arch_required[arch].extend(packages)
 
83
            elif name.startswith('base-'):
 
84
                # In base system (second stage) on one architecture
 
85
                arch = name[5:]
 
86
                if arch not in self.arch_base:
 
87
                    self.arch_base[arch] = []
 
88
                self.arch_base[arch].extend(packages)
 
89
 
 
90
        f.close()
 
91
 
 
92
def main():
 
93
    for dist in sys.argv[1:]:
 
94
        template_name = "%s.template" % dist
 
95
        base_name = "%s.base" % dist
 
96
        overrides_name = "%s.overrides" % dist
 
97
 
 
98
        # Read base system
 
99
        base = Base()
 
100
        if os.path.exists(base_name):
 
101
            base.read(open(base_name, 'r'))
 
102
 
 
103
        # Read overrides
 
104
        overrides = Overrides()
 
105
        if os.path.exists(overrides_name):
 
106
            overrides.read(open(overrides_name, 'r'))
 
107
 
 
108
        base_arch_indep = []
 
109
        base_arch_dep = {}
 
110
        required_arch_indep = []
 
111
        required_arch_dep = {}
 
112
 
 
113
        for arch in base.base:
 
114
            base_arch_dep[arch] = []
 
115
            required_arch_dep[arch] = []
 
116
 
 
117
        # Process excludes first.
 
118
        for arch in base.base:
 
119
            excludes = list(overrides.exclude)
 
120
            if arch in overrides.arch_exclude:
 
121
                excludes.extend(overrides.arch_exclude[arch])
 
122
            new_base = []
 
123
            for package in base.base[arch]:
 
124
                for exclude in excludes:
 
125
                    if exclude.match(package):
 
126
                        break
 
127
                else:
 
128
                    new_base.append(package)
 
129
            base.base[arch] = new_base
 
130
 
 
131
        # Sketch out the whole base system.
 
132
        base_full = []
 
133
        for arch in base.base:
 
134
            for package in base.base[arch]:
 
135
                if package not in base_full:
 
136
                    base_full.append(package)
 
137
 
 
138
        # Which packages are in the base system on only some architectures?
 
139
        for package in base_full:
 
140
            for arch in base.base:
 
141
                if package not in base.base[arch]:
 
142
                    break
 
143
            else:
 
144
                base_arch_indep.append(package)
 
145
 
 
146
        # By set subtraction, get the architecture-dependent list for each
 
147
        # architecture.
 
148
        for arch in base.base:
 
149
            for package in base.base[arch]:
 
150
                if package not in base_arch_indep:
 
151
                    base_arch_dep[arch].append(package)
 
152
 
 
153
        # Move architecture-independent requires. If they actually aren't
 
154
        # available on all architectures, make them architecture-dependent
 
155
        # requires instead.
 
156
        for package in overrides.required:
 
157
            if package in base_arch_indep:
 
158
                base_arch_indep.remove(package)
 
159
                required_arch_indep.append(package)
 
160
            else:
 
161
                for arch in base_arch_dep:
 
162
                    if package in base_arch_dep[arch]:
 
163
                        base_arch_dep[arch].remove(package)
 
164
                        required_arch_dep[arch].append(package)
 
165
                # TODO: would like to raise an exception if it wasn't in
 
166
                # base_arch_dep at all
 
167
 
 
168
        # Move architecture-dependent requires.
 
169
        for arch in overrides.arch_required:
 
170
            for package in overrides.arch_required[arch]:
 
171
                if package in base_arch_indep:
 
172
                    # Required on one architecture; base elsewhere.
 
173
                    base_arch_indep.remove(package)
 
174
                    for otherarch in base_arch_dep:
 
175
                        if arch != otherarch:
 
176
                            base_arch_dep[otherarch].append(package)
 
177
                    required_arch_dep[arch].append(package)
 
178
                else:
 
179
                    # Required on one architecture; may or may not be base
 
180
                    # elsewhere, but we don't need to care.
 
181
                    if package in base_arch_dep[arch]:
 
182
                        base_arch_dep[arch].remove(package)
 
183
                        required_arch_dep[arch].append(package)
 
184
                    else:
 
185
                        raise RequiredPackageNotInBase, package
 
186
 
 
187
        # Make substitutions in the template
 
188
        template_handle = open(template_name, 'r')
 
189
        template = template_handle.read()
 
190
        template_handle.close()
 
191
 
 
192
        updist = dist.upper()
 
193
        template = template.replace("@%s_REQUIRED@" % updist, string.join(required_arch_indep))
 
194
        template = template.replace("@%s_BASE@" % updist, string.join(base_arch_indep))
 
195
        for arch in required_arch_dep:
 
196
            template = template.replace("@%s_REQUIRED_%s@" % (updist, arch.upper()), string.join(required_arch_dep[arch]))
 
197
        for arch in base_arch_dep:
 
198
            template = template.replace("@%s_BASE_%s@" % (updist, arch.upper()), string.join(base_arch_dep[arch]))
 
199
 
 
200
        output_handle = open(dist, 'w')
 
201
        output_handle.write(template)
 
202
        output_handle.close()
 
203
 
 
204
if __name__ == "__main__":
 
205
    main()