Gentoo Archives: gentoo-catalyst

From: Felix Bier <Felix.Bier@×××××××××××××.com>
To: "gentoo-catalyst@l.g.o" <gentoo-catalyst@l.g.o>
Subject: Re: [Newsletter] Re: [gentoo-catalyst] Re: [PATCH 2/2] Move from PORTDIR_OVERLAY to repos.conf
Date: Tue, 10 Nov 2020 01:03:10
Message-Id: c5d97ab825f781441680f614d02033f65422574b.camel@rohde-schwarz.com
In Reply to: Re: [gentoo-catalyst] Re: [PATCH 2/2] Move from PORTDIR_OVERLAY to repos.conf by Matt Turner
1 This commit fixes the following issues:
2
3 * The PORTDIR_OVERLAY variable has been deprecated by Gentoo.
4
5 With this commit, the variable is no longer written to the
6 generated make.conf. Instead, a config file
7 /etc/portage/repos.conf/<repo-name>.conf
8 is generated for each overlay. The repo name is read from the
9 overlay using the portage API. Internally, portage parses
10 metadata/layout.conf and profiles/repo_name to obtain the name.
11
12 References:
13 https://wiki.gentoo.org/wiki//etc/portage/make.conf
14 https://wiki.gentoo.org/wiki//etc/portage/repos.conf
15
16 * All overlays were copied into the same target directory. If the
17 same file name occurred in multiple overlays, the last overlay
18 would overwrite all previous files with this name. In particular,
19 only the metadata/layout.conf of the last overlay was retained,
20 so it was not possible to reference the other overlays e.g. via
21 the masters entry in the layout.conf or the portage-2 syntax
22 for specifying a parent profile from another overlay. Also,
23 this created problems when the overlays contained ebuilds
24 for the same package, but with differing versions, because
25 after copying, the target directory contained both versions of the
26 ebuild but only the manifest file of the last overlay.
27
28 With this commit, each overlay is copied into a separate
29 sub-directory, e.g. /var/db/repos/<repo-name>.
30 This directory is referenced via the location entry in the
31 generated /etc/portage/repos.conf/<repo-name>.conf.
32
33 Signed-off-by: Felix Bier <felix.bier@×××××××××××××.com>
34 ---
35 catalyst/base/stagebase.py | 84 ++++++++++++++++++++++++++++----------
36 catalyst/defaults.py | 2 +-
37 catalyst/support.py | 18 ++++++++
38 3 files changed, 81 insertions(+), 23 deletions(-)
39
40 diff --git a/catalyst/base/stagebase.py b/catalyst/base/stagebase.py
41 index 21cf96a0..fe79b55a 100644
42 --- a/catalyst/base/stagebase.py
43 +++ b/catalyst/base/stagebase.py
44 @@ -1,4 +1,5 @@
45
46 +import configparser
47 import copy
48 import os
49 import platform
50 @@ -19,8 +20,8 @@ from catalyst import log
51 from catalyst.context import namespace
52 from catalyst.defaults import (confdefaults, MOUNT_DEFAULTS, PORT_LOGDIR_CLEAN)
53 from catalyst.support import (CatalystError, file_locate, normpath,
54 - cmd, read_makeconf, ismount, file_check,
55 - sanitize_name)
56 + cmd, read_makeconf, get_repo_name, ismount,
57 + file_check, sanitize_name)
58 from catalyst.base.targetbase import TargetBase
59 from catalyst.base.clearbase import ClearBase
60 from catalyst.base.genbase import GenBase
61 @@ -786,17 +787,55 @@ class StageBase(TargetBase, ClearBase, GenBase):
62 env=self.env)
63 self.resume.enable("setup_confdir")
64
65 + def to_chroot(self, path):
66 + """ Prepend chroot path to the given path. """
67 +
68 + chroot = Path(self.settings['chroot_path'])
69 + return chroot / path.relative_to(path.anchor)
70 +
71 + def get_repo_conf_path(self, repo_name):
72 + """ Construct repo conf path: {repos_conf}/{name}.conf """
73 + return Path(self.settings['repos_conf'], repo_name + ".conf")
74 +
75 + def get_repo_location(self, repo_name):
76 + """ Construct overlay repo path: {repo_basedir}/{name} """
77 + return Path(self.settings['repo_basedir'], repo_name)
78 +
79 + def write_repo_conf(self, repo_name, config):
80 + """ Write ConfigParser to {chroot}/{repos_conf}/{name}.conf """
81 +
82 + repo_conf = self.get_repo_conf_path(repo_name)
83 +
84 + repo_conf_chroot = self.to_chroot(repo_conf)
85 + repo_conf_chroot.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
86 +
87 + log.info(f'Creating repo config {repo_conf_chroot}.')
88 +
89 + try:
90 + with open(repo_conf_chroot, 'w') as f:
91 + config.write(f)
92 + except OSError as e:
93 + raise CatalystError(f'Could not write {repo_conf_chroot}: {e}') from e
94 +
95 def portage_overlay(self):
96 - """ We copy the contents of our overlays to /usr/local/portage """
97 + """ We copy the contents of our repos to get_repo_location(repo_name) """
98 if "portage_overlay" in self.settings:
99 for x in self.settings["portage_overlay"]:
100 if os.path.exists(x):
101 - log.info('Copying overlay dir %s', x)
102 - ensure_dirs(
103 - self.settings['chroot_path'] + self.settings['local_overlay'])
104 - cmd("cp -a " + x + "/* " + self.settings["chroot_path"] +
105 - self.settings["local_overlay"],
106 - env=self.env)
107 + name = get_repo_name(x)
108 +
109 + location = self.get_repo_location(name)
110 + config = configparser.ConfigParser()
111 + config[name] = {'location': location}
112 + self.write_repo_conf(name, config)
113 +
114 + location_chroot = self.to_chroot(location)
115 + location_chroot.mkdir(mode=0o755, parents=True, exist_ok=True)
116 +
117 + log.info(f'Copying overlay dir {x} to {location_chroot}')
118 + cmd(f'cp -a {x}/* {location_chroot}', env=self.env)
119 + else:
120 + log.warning(f'Skipping missing overlay {x}.')
121
122 def root_overlay(self):
123 """ Copy over the root_overlay """
124 @@ -852,8 +891,8 @@ class StageBase(TargetBase, ClearBase, GenBase):
125 cxt = libmount.Context(source=source, target=target,
126 fstype=fstype, options=options)
127 cxt.mount()
128 - except OSError as e:
129 - raise CatalystError(f"Couldn't mount: {source}, {e.strerror}")
130 + except Exception as e:
131 + raise CatalystError(f"Couldn't mount: {source}, {e}")
132
133 def chroot_setup(self):
134 self.makeconf = read_makeconf(normpath(self.settings["chroot_path"] +
135 @@ -1018,12 +1057,6 @@ class StageBase(TargetBase, ClearBase, GenBase):
136 varname = x.split('_')[1].upper()
137 myf.write(f'{varname}="{self.settings[x]}"\n')
138
139 - if setup:
140 - # Setup the portage overlay
141 - if "portage_overlay" in self.settings:
142 - myf.write('PORTDIR_OVERLAY="%s"\n' %
143 - self.settings["local_overlay"])
144 -
145 # Set default locale for system responses. #478382
146 myf.write(
147 '\n'
148 @@ -1097,11 +1130,18 @@ class StageBase(TargetBase, ClearBase, GenBase):
149 log.warning("You've been hacking. Clearing target patches: %s", target)
150 clear_path(target)
151
152 - # Remove our overlay
153 - overlay = normpath(
154 - self.settings["chroot_path"] + self.settings["local_overlay"])
155 - if os.path.exists(overlay):
156 - clear_path(overlay)
157 + # Remove our overlays
158 + if "portage_overlay" in self.settings:
159 + for repo_path in self.settings["portage_overlay"]:
160 + repo_name = get_repo_name(repo_path)
161 +
162 + repo_conf = self.get_repo_conf_path(repo_name)
163 + chroot_repo_conf = self.to_chroot(repo_conf)
164 + chroot_repo_conf.unlink()
165 +
166 + location = self.get_repo_location(repo_name)
167 + chroot_location = self.to_chroot(location)
168 + clear_path(str(chroot_location))
169
170 if "sticky-config" not in self.settings["options"]:
171 # re-write the make.conf to be sure it is clean
172 diff --git a/catalyst/defaults.py b/catalyst/defaults.py
173 index 0f399b56..3f12b8d5 100644
174 --- a/catalyst/defaults.py
175 +++ b/catalyst/defaults.py
176 @@ -38,9 +38,9 @@ confdefaults = {
177 "distdir": portage.settings['DISTDIR'],
178 "icecream": "/var/cache/icecream",
179 'list_xattrs_opt': LIST_XATTRS_OPTIONS['linux'],
180 - "local_overlay": "/var/db/repos/local",
181 "port_conf": "/etc/portage",
182 "make_conf": "%(port_conf)s/make.conf",
183 + "repos_conf": "%(port_conf)s/repos.conf",
184 "options": set(),
185 "pkgdir": "/var/cache/binpkgs",
186 "port_tmpdir": "/var/tmp/portage",
187 diff --git a/catalyst/support.py b/catalyst/support.py
188 index ddbd9ab9..f3a865a7 100644
189 --- a/catalyst/support.py
190 +++ b/catalyst/support.py
191 @@ -10,6 +10,8 @@ from subprocess import Popen
192
193 import libmount
194
195 +from portage.repository.config import RepoConfig
196 +
197 from catalyst import log
198
199 BASH_BINARY = "/bin/bash"
200 @@ -182,6 +184,22 @@ def read_makeconf(mymakeconffile):
201 return makeconf
202
203
204 +def get_repo_name(repo_path):
205 + """ Get the name of the repo at the given repo_path.
206 +
207 + References:
208 + https://wiki.gentoo.org/wiki/Repository_format/profiles/repo_name
209 + https://wiki.gentoo.org/wiki/Repository_format/metadata/layout.conf#repo-name
210 + """
211 +
212 + repo_config = RepoConfig(None, {"location": repo_path})
213 +
214 + if repo_config.missing_repo_name:
215 + raise CatalystError(f"Missing name in repository {repo_path}")
216 +
217 + return repo_config.name
218 +
219 +
220 def ismount(path):
221 """Like os.path.ismount, but also support bind mounts"""
222 path = Path(path)
223 --
224 2.29.2