summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/package_manager
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/oe/package_manager
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/oe/package_manager')
-rw-r--r--meta/lib/oe/package_manager/deb/rootfs.py209
1 files changed, 209 insertions, 0 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