blob: 60c49be0e9982a7d2529dbf9c007494520650012 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001from abc import ABCMeta, abstractmethod
2import os
3import re
4import bb
5
6
Patrick Williamsc0f7c042017-02-23 20:41:17 -06007class Manifest(object, metaclass=ABCMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -05008 """
9 This is an abstract class. Do not instantiate this directly.
10 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011
12 PKG_TYPE_MUST_INSTALL = "mip"
13 PKG_TYPE_MULTILIB = "mlp"
14 PKG_TYPE_LANGUAGE = "lgp"
15 PKG_TYPE_ATTEMPT_ONLY = "aop"
16
17 MANIFEST_TYPE_IMAGE = "image"
18 MANIFEST_TYPE_SDK_HOST = "sdk_host"
19 MANIFEST_TYPE_SDK_TARGET = "sdk_target"
20
21 var_maps = {
22 MANIFEST_TYPE_IMAGE: {
23 "PACKAGE_INSTALL": PKG_TYPE_MUST_INSTALL,
24 "PACKAGE_INSTALL_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY,
25 "LINGUAS_INSTALL": PKG_TYPE_LANGUAGE
26 },
27 MANIFEST_TYPE_SDK_HOST: {
28 "TOOLCHAIN_HOST_TASK": PKG_TYPE_MUST_INSTALL,
29 "TOOLCHAIN_HOST_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
30 },
31 MANIFEST_TYPE_SDK_TARGET: {
32 "TOOLCHAIN_TARGET_TASK": PKG_TYPE_MUST_INSTALL,
33 "TOOLCHAIN_TARGET_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
34 }
35 }
36
37 INSTALL_ORDER = [
38 PKG_TYPE_LANGUAGE,
39 PKG_TYPE_MUST_INSTALL,
40 PKG_TYPE_ATTEMPT_ONLY,
41 PKG_TYPE_MULTILIB
42 ]
43
44 initial_manifest_file_header = \
45 "# This file was generated automatically and contains the packages\n" \
46 "# passed on to the package manager in order to create the rootfs.\n\n" \
47 "# Format:\n" \
48 "# <package_type>,<package_name>\n" \
49 "# where:\n" \
50 "# <package_type> can be:\n" \
51 "# 'mip' = must install package\n" \
52 "# 'aop' = attempt only package\n" \
53 "# 'mlp' = multilib package\n" \
54 "# 'lgp' = language package\n\n"
55
56 def __init__(self, d, manifest_dir=None, manifest_type=MANIFEST_TYPE_IMAGE):
57 self.d = d
58 self.manifest_type = manifest_type
59
60 if manifest_dir is None:
61 if manifest_type != self.MANIFEST_TYPE_IMAGE:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050062 self.manifest_dir = self.d.getVar('SDK_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050063 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050064 self.manifest_dir = self.d.getVar('WORKDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050065 else:
66 self.manifest_dir = manifest_dir
67
68 bb.utils.mkdirhier(self.manifest_dir)
69
70 self.initial_manifest = os.path.join(self.manifest_dir, "%s_initial_manifest" % manifest_type)
71 self.final_manifest = os.path.join(self.manifest_dir, "%s_final_manifest" % manifest_type)
72 self.full_manifest = os.path.join(self.manifest_dir, "%s_full_manifest" % manifest_type)
73
74 # packages in the following vars will be split in 'must install' and
75 # 'multilib'
76 self.vars_to_split = ["PACKAGE_INSTALL",
77 "TOOLCHAIN_HOST_TASK",
78 "TOOLCHAIN_TARGET_TASK"]
79
80 """
81 This creates a standard initial manifest for core-image-(minimal|sato|sato-sdk).
82 This will be used for testing until the class is implemented properly!
83 """
84 def _create_dummy_initial(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050085 image_rootfs = self.d.getVar('IMAGE_ROOTFS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086 pkg_list = dict()
87 if image_rootfs.find("core-image-sato-sdk") > 0:
88 pkg_list[self.PKG_TYPE_MUST_INSTALL] = \
89 "packagegroup-core-x11-sato-games packagegroup-base-extended " \
90 "packagegroup-core-x11-sato packagegroup-core-x11-base " \
91 "packagegroup-core-sdk packagegroup-core-tools-debug " \
92 "packagegroup-core-boot packagegroup-core-tools-testapps " \
93 "packagegroup-core-eclipse-debug packagegroup-core-qt-demoapps " \
94 "apt packagegroup-core-tools-profile psplash " \
95 "packagegroup-core-standalone-sdk-target " \
96 "packagegroup-core-ssh-openssh dpkg kernel-dev"
97 pkg_list[self.PKG_TYPE_LANGUAGE] = \
98 "locale-base-en-us locale-base-en-gb"
99 elif image_rootfs.find("core-image-sato") > 0:
100 pkg_list[self.PKG_TYPE_MUST_INSTALL] = \
101 "packagegroup-core-ssh-dropbear packagegroup-core-x11-sato-games " \
102 "packagegroup-core-x11-base psplash apt dpkg packagegroup-base-extended " \
103 "packagegroup-core-x11-sato packagegroup-core-boot"
104 pkg_list['lgp'] = \
105 "locale-base-en-us locale-base-en-gb"
106 elif image_rootfs.find("core-image-minimal") > 0:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500107 pkg_list[self.PKG_TYPE_MUST_INSTALL] = "packagegroup-core-boot"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500108
109 with open(self.initial_manifest, "w+") as manifest:
110 manifest.write(self.initial_manifest_file_header)
111
112 for pkg_type in pkg_list:
113 for pkg in pkg_list[pkg_type].split():
114 manifest.write("%s,%s\n" % (pkg_type, pkg))
115
116 """
117 This will create the initial manifest which will be used by Rootfs class to
118 generate the rootfs
119 """
120 @abstractmethod
121 def create_initial(self):
122 pass
123
124 """
125 This creates the manifest after everything has been installed.
126 """
127 @abstractmethod
128 def create_final(self):
129 pass
130
131 """
132 This creates the manifest after the package in initial manifest has been
133 dummy installed. It lists all *to be installed* packages. There is no real
134 installation, just a test.
135 """
136 @abstractmethod
137 def create_full(self, pm):
138 pass
139
140 """
141 The following function parses an initial manifest and returns a dictionary
142 object with the must install, attempt only, multilib and language packages.
143 """
144 def parse_initial_manifest(self):
145 pkgs = dict()
146
147 with open(self.initial_manifest) as manifest:
148 for line in manifest.read().split('\n'):
149 comment = re.match("^#.*", line)
150 pattern = "^(%s|%s|%s|%s),(.*)$" % \
151 (self.PKG_TYPE_MUST_INSTALL,
152 self.PKG_TYPE_ATTEMPT_ONLY,
153 self.PKG_TYPE_MULTILIB,
154 self.PKG_TYPE_LANGUAGE)
155 pkg = re.match(pattern, line)
156
157 if comment is not None:
158 continue
159
160 if pkg is not None:
161 pkg_type = pkg.group(1)
162 pkg_name = pkg.group(2)
163
164 if not pkg_type in pkgs:
165 pkgs[pkg_type] = [pkg_name]
166 else:
167 pkgs[pkg_type].append(pkg_name)
168
169 return pkgs
170
171 '''
172 This following function parses a full manifest and return a list
173 object with packages.
174 '''
175 def parse_full_manifest(self):
176 installed_pkgs = list()
177 if not os.path.exists(self.full_manifest):
178 bb.note('full manifest not exist')
179 return installed_pkgs
180
181 with open(self.full_manifest, 'r') as manifest:
182 for pkg in manifest.read().split('\n'):
183 installed_pkgs.append(pkg.strip())
184
185 return installed_pkgs
186
187
188class RpmManifest(Manifest):
189 """
190 Returns a dictionary object with mip and mlp packages.
191 """
192 def _split_multilib(self, pkg_list):
193 pkgs = dict()
194
195 for pkg in pkg_list.split():
196 pkg_type = self.PKG_TYPE_MUST_INSTALL
197
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500198 ml_variants = self.d.getVar('MULTILIB_VARIANTS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500199
200 for ml_variant in ml_variants:
201 if pkg.startswith(ml_variant + '-'):
202 pkg_type = self.PKG_TYPE_MULTILIB
203
204 if not pkg_type in pkgs:
205 pkgs[pkg_type] = pkg
206 else:
207 pkgs[pkg_type] += " " + pkg
208
209 return pkgs
210
211 def create_initial(self):
212 pkgs = dict()
213
214 with open(self.initial_manifest, "w+") as manifest:
215 manifest.write(self.initial_manifest_file_header)
216
217 for var in self.var_maps[self.manifest_type]:
218 if var in self.vars_to_split:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500219 split_pkgs = self._split_multilib(self.d.getVar(var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500220 if split_pkgs is not None:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600221 pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500222 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500223 pkg_list = self.d.getVar(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500224 if pkg_list is not None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500225 pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500226
227 for pkg_type in pkgs:
228 for pkg in pkgs[pkg_type].split():
229 manifest.write("%s,%s\n" % (pkg_type, pkg))
230
231 def create_final(self):
232 pass
233
234 def create_full(self, pm):
235 pass
236
237
238class OpkgManifest(Manifest):
239 """
240 Returns a dictionary object with mip and mlp packages.
241 """
242 def _split_multilib(self, pkg_list):
243 pkgs = dict()
244
245 for pkg in pkg_list.split():
246 pkg_type = self.PKG_TYPE_MUST_INSTALL
247
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500248 ml_variants = self.d.getVar('MULTILIB_VARIANTS').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500249
250 for ml_variant in ml_variants:
251 if pkg.startswith(ml_variant + '-'):
252 pkg_type = self.PKG_TYPE_MULTILIB
253
254 if not pkg_type in pkgs:
255 pkgs[pkg_type] = pkg
256 else:
257 pkgs[pkg_type] += " " + pkg
258
259 return pkgs
260
261 def create_initial(self):
262 pkgs = dict()
263
264 with open(self.initial_manifest, "w+") as manifest:
265 manifest.write(self.initial_manifest_file_header)
266
267 for var in self.var_maps[self.manifest_type]:
268 if var in self.vars_to_split:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500269 split_pkgs = self._split_multilib(self.d.getVar(var))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500270 if split_pkgs is not None:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600271 pkgs = dict(list(pkgs.items()) + list(split_pkgs.items()))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500272 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500273 pkg_list = self.d.getVar(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500274 if pkg_list is not None:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500275 pkgs[self.var_maps[self.manifest_type][var]] = self.d.getVar(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500276
277 for pkg_type in pkgs:
278 for pkg in pkgs[pkg_type].split():
279 manifest.write("%s,%s\n" % (pkg_type, pkg))
280
281 def create_final(self):
282 pass
283
284 def create_full(self, pm):
285 if not os.path.exists(self.initial_manifest):
286 self.create_initial()
287
288 initial_manifest = self.parse_initial_manifest()
289 pkgs_to_install = list()
290 for pkg_type in initial_manifest:
291 pkgs_to_install += initial_manifest[pkg_type]
292 if len(pkgs_to_install) == 0:
293 return
294
295 output = pm.dummy_install(pkgs_to_install)
296
297 with open(self.full_manifest, 'w+') as manifest:
298 pkg_re = re.compile('^Installing ([^ ]+) [^ ].*')
299 for line in set(output.split('\n')):
300 m = pkg_re.match(line)
301 if m:
302 manifest.write(m.group(1) + '\n')
303
304 return
305
306
307class DpkgManifest(Manifest):
308 def create_initial(self):
309 with open(self.initial_manifest, "w+") as manifest:
310 manifest.write(self.initial_manifest_file_header)
311
312 for var in self.var_maps[self.manifest_type]:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500313 pkg_list = self.d.getVar(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500314
315 if pkg_list is None:
316 continue
317
318 for pkg in pkg_list.split():
319 manifest.write("%s,%s\n" %
320 (self.var_maps[self.manifest_type][var], pkg))
321
322 def create_final(self):
323 pass
324
325 def create_full(self, pm):
326 pass
327
328
329def create_manifest(d, final_manifest=False, manifest_dir=None,
330 manifest_type=Manifest.MANIFEST_TYPE_IMAGE):
331 manifest_map = {'rpm': RpmManifest,
332 'ipk': OpkgManifest,
333 'deb': DpkgManifest}
334
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500335 manifest = manifest_map[d.getVar('IMAGE_PKGTYPE')](d, manifest_dir, manifest_type)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336
337 if final_manifest:
338 manifest.create_final()
339 else:
340 manifest.create_initial()
341
342
343if __name__ == "__main__":
344 pass