summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
authorFredrik Gustafsson <fredrik.gustafsson@axis.com>2020-07-24 16:42:35 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-07-27 19:58:10 +0100
commit6fd8b177480719f6dec6bdde15d01d19dbfb00c7 (patch)
tree858cad6d27177e797becc66c7beb8ab45a356ba0 /meta/lib
parent873aee855f196cba43bed5201e7b30ba74a2b255 (diff)
downloadpoky-6fd8b177480719f6dec6bdde15d01d19dbfb00c7.tar.gz
deb: Move rootfs to its own dir
This is a part of a refactor that will split the package manager code so that it's possible to use other package managers in other layers. (From OE-Core rev: abadf053371ce863bf21b4a9474eb61761545de1) Signed-off-by: Fredrik Gustafsson <fredrigu@axis.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oe/package_manager/deb/rootfs.py209
-rw-r--r--meta/lib/oe/rootfs.py201
2 files changed, 211 insertions, 199 deletions
diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py
new file mode 100644
index 0000000000..0661ee7c5b
--- /dev/null
+++ b/meta/lib/oe/package_manager/deb/rootfs.py
@@ -0,0 +1,209 @@
1#
2# SPDX-License-Identifier: GPL-2.0-only
3#
4
5from oe.rootfs import Rootfs
6from oe.package_manager import DpkgPM
7from oe.manifest import Manifest
8from oe.utils import execute_pre_post_process
9from oe.package_manager.deb.manifest import DpkgManifest
10import re
11
12class DpkgOpkgRootfs(Rootfs):
13 def __init__(self, d, progress_reporter=None, logcatcher=None):
14 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
15
16 def _get_pkgs_postinsts(self, status_file):
17 def _get_pkg_depends_list(pkg_depends):
18 pkg_depends_list = []
19 # filter version requirements like libc (>= 1.1)
20 for dep in pkg_depends.split(', '):
21 m_dep = re.match(r"^(.*) \(.*\)$", dep)
22 if m_dep:
23 dep = m_dep.group(1)
24 pkg_depends_list.append(dep)
25
26 return pkg_depends_list
27
28 pkgs = {}
29 pkg_name = ""
30 pkg_status_match = False
31 pkg_depends = ""
32
33 with open(status_file) as status:
34 data = status.read()
35 status.close()
36 for line in data.split('\n'):
37 m_pkg = re.match(r"^Package: (.*)", line)
38 m_status = re.match(r"^Status:.*unpacked", line)
39 m_depends = re.match(r"^Depends: (.*)", line)
40
41 #Only one of m_pkg, m_status or m_depends is not None at time
42 #If m_pkg is not None, we started a new package
43 if m_pkg is not None:
44 #Get Package name
45 pkg_name = m_pkg.group(1)
46 #Make sure we reset other variables
47 pkg_status_match = False
48 pkg_depends = ""
49 elif m_status is not None:
50 #New status matched
51 pkg_status_match = True
52 elif m_depends is not None:
53 #New depends macthed
54 pkg_depends = m_depends.group(1)
55 else:
56 pass
57
58 #Now check if we can process package depends and postinst
59 if "" != pkg_name and pkg_status_match:
60 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
61 else:
62 #Not enough information
63 pass
64
65 # remove package dependencies not in postinsts
66 pkg_names = list(pkgs.keys())
67 for pkg_name in pkg_names:
68 deps = pkgs[pkg_name][:]
69
70 for d in deps:
71 if d not in pkg_names:
72 pkgs[pkg_name].remove(d)
73
74 return pkgs
75
76 def _get_delayed_postinsts_common(self, status_file):
77 def _dep_resolve(graph, node, resolved, seen):
78 seen.append(node)
79
80 for edge in graph[node]:
81 if edge not in resolved:
82 if edge in seen:
83 raise RuntimeError("Packages %s and %s have " \
84 "a circular dependency in postinsts scripts." \
85 % (node, edge))
86 _dep_resolve(graph, edge, resolved, seen)
87
88 resolved.append(node)
89
90 pkg_list = []
91
92 pkgs = None
93 if not self.d.getVar('PACKAGE_INSTALL').strip():
94 bb.note("Building empty image")
95 else:
96 pkgs = self._get_pkgs_postinsts(status_file)
97 if pkgs:
98 root = "__packagegroup_postinst__"
99 pkgs[root] = list(pkgs.keys())
100 _dep_resolve(pkgs, root, pkg_list, [])
101 pkg_list.remove(root)
102
103 if len(pkg_list) == 0:
104 return None
105
106 return pkg_list
107
108 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
109 if bb.utils.contains("IMAGE_FEATURES", "package-management",
110 True, False, self.d):
111 return
112 num = 0
113 for p in self._get_delayed_postinsts():
114 bb.utils.mkdirhier(dst_postinst_dir)
115
116 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
117 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
118 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
119
120 num += 1
121
122class DpkgRootfs(DpkgOpkgRootfs):
123 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
124 super(DpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
125 self.log_check_regex = '^E:'
126 self.log_check_expected_regexes = \
127 [
128 "^E: Unmet dependencies."
129 ]
130
131 bb.utils.remove(self.image_rootfs, True)
132 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
133 self.manifest = DpkgManifest(d, manifest_dir)
134 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
135 d.getVar('PACKAGE_ARCHS'),
136 d.getVar('DPKG_ARCH'))
137
138
139 def _create(self):
140 pkgs_to_install = self.manifest.parse_initial_manifest()
141 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
142 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
143
144 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
145 bb.utils.mkdirhier(alt_dir)
146
147 # update PM index files
148 self.pm.write_index()
149
150 execute_pre_post_process(self.d, deb_pre_process_cmds)
151
152 if self.progress_reporter:
153 self.progress_reporter.next_stage()
154 # Don't support incremental, so skip that
155 self.progress_reporter.next_stage()
156
157 self.pm.update()
158
159 if self.progress_reporter:
160 self.progress_reporter.next_stage()
161
162 for pkg_type in self.install_order:
163 if pkg_type in pkgs_to_install:
164 self.pm.install(pkgs_to_install[pkg_type],
165 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
166 self.pm.fix_broken_dependencies()
167
168 if self.progress_reporter:
169 # Don't support attemptonly, so skip that
170 self.progress_reporter.next_stage()
171 self.progress_reporter.next_stage()
172
173 self.pm.install_complementary()
174
175 if self.progress_reporter:
176 self.progress_reporter.next_stage()
177
178 self._setup_dbg_rootfs(['/var/lib/dpkg'])
179
180 self.pm.fix_broken_dependencies()
181
182 self.pm.mark_packages("installed")
183
184 self.pm.run_pre_post_installs()
185
186 execute_pre_post_process(self.d, deb_post_process_cmds)
187
188 if self.progress_reporter:
189 self.progress_reporter.next_stage()
190
191 @staticmethod
192 def _depends_list():
193 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
194
195 def _get_delayed_postinsts(self):
196 status_file = self.image_rootfs + "/var/lib/dpkg/status"
197 return self._get_delayed_postinsts_common(status_file)
198
199 def _save_postinsts(self):
200 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
201 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
202 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
203
204 def _log_check(self):
205 self._log_check_warn()
206 self._log_check_error()
207
208 def _cleanup(self):
209 pass
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index 062ea7f335..17ca323588 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -354,208 +354,10 @@ class Rootfs(object, metaclass=ABCMeta):
354 self.image_rootfs, "-D", devtable]) 354 self.image_rootfs, "-D", devtable])
355 355
356 356
357class DpkgOpkgRootfs(Rootfs):
358 def __init__(self, d, progress_reporter=None, logcatcher=None):
359 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
360
361 def _get_pkgs_postinsts(self, status_file):
362 def _get_pkg_depends_list(pkg_depends):
363 pkg_depends_list = []
364 # filter version requirements like libc (>= 1.1)
365 for dep in pkg_depends.split(', '):
366 m_dep = re.match(r"^(.*) \(.*\)$", dep)
367 if m_dep:
368 dep = m_dep.group(1)
369 pkg_depends_list.append(dep)
370
371 return pkg_depends_list
372
373 pkgs = {}
374 pkg_name = ""
375 pkg_status_match = False
376 pkg_depends = ""
377
378 with open(status_file) as status:
379 data = status.read()
380 status.close()
381 for line in data.split('\n'):
382 m_pkg = re.match(r"^Package: (.*)", line)
383 m_status = re.match(r"^Status:.*unpacked", line)
384 m_depends = re.match(r"^Depends: (.*)", line)
385
386 #Only one of m_pkg, m_status or m_depends is not None at time
387 #If m_pkg is not None, we started a new package
388 if m_pkg is not None:
389 #Get Package name
390 pkg_name = m_pkg.group(1)
391 #Make sure we reset other variables
392 pkg_status_match = False
393 pkg_depends = ""
394 elif m_status is not None:
395 #New status matched
396 pkg_status_match = True
397 elif m_depends is not None:
398 #New depends macthed
399 pkg_depends = m_depends.group(1)
400 else:
401 pass
402
403 #Now check if we can process package depends and postinst
404 if "" != pkg_name and pkg_status_match:
405 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
406 else:
407 #Not enough information
408 pass
409
410 # remove package dependencies not in postinsts
411 pkg_names = list(pkgs.keys())
412 for pkg_name in pkg_names:
413 deps = pkgs[pkg_name][:]
414
415 for d in deps:
416 if d not in pkg_names:
417 pkgs[pkg_name].remove(d)
418
419 return pkgs
420
421 def _get_delayed_postinsts_common(self, status_file):
422 def _dep_resolve(graph, node, resolved, seen):
423 seen.append(node)
424
425 for edge in graph[node]:
426 if edge not in resolved:
427 if edge in seen:
428 raise RuntimeError("Packages %s and %s have " \
429 "a circular dependency in postinsts scripts." \
430 % (node, edge))
431 _dep_resolve(graph, edge, resolved, seen)
432
433 resolved.append(node)
434
435 pkg_list = []
436
437 pkgs = None
438 if not self.d.getVar('PACKAGE_INSTALL').strip():
439 bb.note("Building empty image")
440 else:
441 pkgs = self._get_pkgs_postinsts(status_file)
442 if pkgs:
443 root = "__packagegroup_postinst__"
444 pkgs[root] = list(pkgs.keys())
445 _dep_resolve(pkgs, root, pkg_list, [])
446 pkg_list.remove(root)
447
448 if len(pkg_list) == 0:
449 return None
450
451 return pkg_list
452
453 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
454 if bb.utils.contains("IMAGE_FEATURES", "package-management",
455 True, False, self.d):
456 return
457 num = 0
458 for p in self._get_delayed_postinsts():
459 bb.utils.mkdirhier(dst_postinst_dir)
460
461 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
462 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
463 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
464
465 num += 1
466
467class DpkgRootfs(DpkgOpkgRootfs):
468 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
469 super(DpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
470 self.log_check_regex = '^E:'
471 self.log_check_expected_regexes = \
472 [
473 "^E: Unmet dependencies."
474 ]
475
476 bb.utils.remove(self.image_rootfs, True)
477 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
478 self.manifest = DpkgManifest(d, manifest_dir)
479 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
480 d.getVar('PACKAGE_ARCHS'),
481 d.getVar('DPKG_ARCH'))
482
483
484 def _create(self):
485 pkgs_to_install = self.manifest.parse_initial_manifest()
486 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
487 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
488
489 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
490 bb.utils.mkdirhier(alt_dir)
491
492 # update PM index files
493 self.pm.write_index()
494
495 execute_pre_post_process(self.d, deb_pre_process_cmds)
496
497 if self.progress_reporter:
498 self.progress_reporter.next_stage()
499 # Don't support incremental, so skip that
500 self.progress_reporter.next_stage()
501
502 self.pm.update()
503
504 if self.progress_reporter:
505 self.progress_reporter.next_stage()
506
507 for pkg_type in self.install_order:
508 if pkg_type in pkgs_to_install:
509 self.pm.install(pkgs_to_install[pkg_type],
510 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
511 self.pm.fix_broken_dependencies()
512
513 if self.progress_reporter:
514 # Don't support attemptonly, so skip that
515 self.progress_reporter.next_stage()
516 self.progress_reporter.next_stage()
517
518 self.pm.install_complementary()
519
520 if self.progress_reporter:
521 self.progress_reporter.next_stage()
522
523 self._setup_dbg_rootfs(['/var/lib/dpkg'])
524
525 self.pm.fix_broken_dependencies()
526
527 self.pm.mark_packages("installed")
528
529 self.pm.run_pre_post_installs()
530
531 execute_pre_post_process(self.d, deb_post_process_cmds)
532
533 if self.progress_reporter:
534 self.progress_reporter.next_stage()
535
536 @staticmethod
537 def _depends_list():
538 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
539
540 def _get_delayed_postinsts(self):
541 status_file = self.image_rootfs + "/var/lib/dpkg/status"
542 return self._get_delayed_postinsts_common(status_file)
543
544 def _save_postinsts(self):
545 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
546 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
547 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
548
549 def _log_check(self):
550 self._log_check_warn()
551 self._log_check_error()
552
553 def _cleanup(self):
554 pass
555
556def get_class_for_type(imgtype): 357def get_class_for_type(imgtype):
557 from oe.package_manager.rpm.rootfs import RpmRootfs 358 from oe.package_manager.rpm.rootfs import RpmRootfs
558 from oe.package_manager.ipk.rootfs import OpkgRootfs 359 from oe.package_manager.ipk.rootfs import OpkgRootfs
360 from oe.package_manager.deb.rootfs import DpkgRootfs
559 return {"rpm": RpmRootfs, 361 return {"rpm": RpmRootfs,
560 "ipk": OpkgRootfs, 362 "ipk": OpkgRootfs,
561 "deb": DpkgRootfs}[imgtype] 363 "deb": DpkgRootfs}[imgtype]
@@ -570,6 +372,7 @@ def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None)
570 372
571 from oe.package_manager.rpm.rootfs import RpmRootfs 373 from oe.package_manager.rpm.rootfs import RpmRootfs
572 from oe.package_manager.ipk.rootfs import OpkgRootfs 374 from oe.package_manager.ipk.rootfs import OpkgRootfs
375 from oe.package_manager.deb.rootfs import DpkgRootfs
573 img_type = d.getVar('IMAGE_PKGTYPE') 376 img_type = d.getVar('IMAGE_PKGTYPE')
574 if img_type == "rpm": 377 if img_type == "rpm":
575 RpmRootfs(d, manifest_dir, progress_reporter, logcatcher).create() 378 RpmRootfs(d, manifest_dir, progress_reporter, logcatcher).create()