Gentoo Archives: gentoo-commits

From: Arfrever Frehtes Taifersar Arahesis <arfrever@××××××.org>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/repoman/, pym/portage/repository/, pym/portage/dbapi/, bin/, misc/, ...
Date: Tue, 08 Dec 2015 07:14:10
Message-Id: 1449558745.2cde1f65e9c585e78415857fdcac1fe5deaa60da.arfrever@gentoo
1 commit: 2cde1f65e9c585e78415857fdcac1fe5deaa60da
2 Author: Arfrever Frehtes Taifersar Arahesis <Arfrever <AT> Apache <DOT> Org>
3 AuthorDate: Tue Dec 8 07:12:25 2015 +0000
4 Commit: Arfrever Frehtes Taifersar Arahesis <arfrever <AT> apache <DOT> org>
5 CommitDate: Tue Dec 8 07:12:25 2015 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=2cde1f65
7
8 portage.repository.config: Clean reading of repository names and drop support for repositories with missing or invalid names.
9
10 bin/emerge-webrsync | 4 +-
11 bin/portageq | 4 +
12 misc/emerge-delta-webrsync | 4 +-
13 pym/_emerge/actions.py | 33 ------
14 pym/portage/dbapi/porttree.py | 4 +-
15 pym/portage/repository/config.py | 229 +++++++++++++++++----------------------
16 pym/repoman/repos.py | 6 +-
17 7 files changed, 113 insertions(+), 171 deletions(-)
18
19 diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
20 index 9961ad8..fc5ab95 100755
21 --- a/bin/emerge-webrsync
22 +++ b/bin/emerge-webrsync
23 @@ -1,5 +1,5 @@
24 #!/bin/bash
25 -# Copyright 1999-2014 Gentoo Foundation
26 +# Copyright 1999-2015 Gentoo Foundation
27 # Distributed under the terms of the GNU General Public License v2
28 # Author: Karl Trygve Kalleberg <karltk@g.o>
29 # Rewritten from the old, Perl-based emerge-webrsync script
30 @@ -39,7 +39,7 @@ else
31 eecho "could not find 'portageq'; aborting"
32 exit 1
33 fi
34 -eval "$("${portageq}" envvar -v DISTDIR EPREFIX FEATURES \
35 +eval "$(PORTAGE_SYNC_MODE=1 "${portageq}" envvar -v DISTDIR EPREFIX FEATURES \
36 FETCHCOMMAND GENTOO_MIRRORS \
37 PORTAGE_BIN_PATH PORTAGE_CONFIGROOT PORTAGE_GPG_DIR \
38 PORTAGE_NICENESS PORTAGE_REPOSITORIES PORTAGE_RSYNC_EXTRA_OPTS \
39
40 diff --git a/bin/portageq b/bin/portageq
41 index 925640b..12886f0 100755
42 --- a/bin/portageq
43 +++ b/bin/portageq
44 @@ -66,6 +66,10 @@ def uses_eroot(function):
45 function.uses_eroot = True
46 return function
47
48 +# Workaround until emerge-webrsync and emerge-delta-webrsync are rewritten in Python.
49 +if os.environ.get("PORTAGE_SYNC_MODE") == "1":
50 + portage._sync_mode = True
51 +
52 # global to hold all function docstrings to be used for argparse help.
53 # Avoids python compilation level 2 optimization troubles.
54 docstrings = {}
55
56 diff --git a/misc/emerge-delta-webrsync b/misc/emerge-delta-webrsync
57 index f2dc822..1cc04bd 100755
58 --- a/misc/emerge-delta-webrsync
59 +++ b/misc/emerge-delta-webrsync
60 @@ -1,5 +1,5 @@
61 #!/bin/bash
62 -# Copyright 1999-2014 Gentoo Foundation
63 +# Copyright 1999-2015 Gentoo Foundation
64 # Distributed under the terms of the GNU General Public License v2
65 # Author: Brian Harring <ferringb@g.o>, karltk@g.o originally.
66 # Rewritten from the old, Perl-based emerge-webrsync script
67 @@ -36,7 +36,7 @@ else
68 eecho "could not find 'portageq'; aborting"
69 exit 1
70 fi
71 -eval "$("${portageq}" envvar -v DISTDIR EPREFIX FEATURES \
72 +eval "$(PORTAGE_SYNC_MODE=1 "${portageq}" envvar -v DISTDIR EPREFIX FEATURES \
73 FETCHCOMMAND GENTOO_MIRRORS \
74 PORTAGE_BIN_PATH PORTAGE_CONFIGROOT PORTAGE_GPG_DIR \
75 PORTAGE_NICENESS PORTAGE_REPOSITORIES PORTAGE_RSYNC_EXTRA_OPTS \
76
77 diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
78 index c3b0b98..a080ba4 100644
79 --- a/pym/_emerge/actions.py
80 +++ b/pym/_emerge/actions.py
81 @@ -2693,38 +2693,6 @@ def expand_set_arguments(myfiles, myaction, root_config):
82 newargs.append(a)
83 return (newargs, retval)
84
85 -def repo_name_check(trees):
86 - missing_repo_names = set()
87 - for root_trees in trees.values():
88 - porttree = root_trees.get("porttree")
89 - if porttree:
90 - portdb = porttree.dbapi
91 - missing_repo_names.update(portdb.getMissingRepoNames())
92 -
93 - # Skip warnings about missing repo_name entries for
94 - # /usr/local/portage (see bug #248603).
95 - try:
96 - missing_repo_names.remove('/usr/local/portage')
97 - except KeyError:
98 - pass
99 -
100 - if missing_repo_names:
101 - msg = []
102 - msg.append("WARNING: One or more repositories " + \
103 - "have missing repo_name entries:")
104 - msg.append("")
105 - for p in missing_repo_names:
106 - msg.append("\t%s/profiles/repo_name" % (p,))
107 - msg.append("")
108 - msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \
109 - "should be a plain text file containing a unique " + \
110 - "name for the repository on the first line.", 70))
111 - msg.append("\n")
112 - writemsg_level("".join("%s\n" % l for l in msg),
113 - level=logging.WARNING, noiselevel=-1)
114 -
115 - return bool(missing_repo_names)
116 -
117 def repo_name_duplicate_check(trees):
118 ignored_repos = {}
119 for root, root_trees in trees.items():
120 @@ -2842,7 +2810,6 @@ def run_action(emerge_config):
121 if "--quiet" not in emerge_config.opts:
122 portage.deprecated_profile_check(
123 settings=emerge_config.target_config.settings)
124 - repo_name_check(emerge_config.trees)
125 repo_name_duplicate_check(emerge_config.trees)
126 config_protect_check(emerge_config.trees)
127 check_procfs()
128
129 diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
130 index 23f3169..0b8034e 100644
131 --- a/pym/portage/dbapi/porttree.py
132 +++ b/pym/portage/dbapi/porttree.py
133 @@ -354,7 +354,9 @@ class portdbapi(dbapi):
134 """
135 Returns a list of repository paths that lack profiles/repo_name.
136 """
137 - return self.settings.repositories.missing_repo_names
138 + warnings.warn("portage.dbapi.porttree.portdbapi.getMissingRepoNames() is deprecated",
139 + DeprecationWarning, stacklevel=2)
140 + return frozenset()
141
142 def getIgnoredRepos(self):
143 """
144
145 diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
146 index b792d78..fbc1c14 100644
147 --- a/pym/portage/repository/config.py
148 +++ b/pym/portage/repository/config.py
149 @@ -21,6 +21,7 @@ import portage
150 from portage import eclass_cache, os
151 from portage.const import (MANIFEST2_HASH_FUNCTIONS, MANIFEST2_REQUIRED_HASH,
152 PORTAGE_BASE_PATH, REPO_NAME_LOC, USER_CONFIG_PATH)
153 +from portage.dep import _repo_name_re
154 from portage.eapi import eapi_allows_directories_on_profile_level_and_repository_level
155 from portage.env.loaders import KeyValuePairFileLoader
156 from portage.util import (normalize_path, read_corresponding_eapi_file, shlex_split,
157 @@ -52,6 +53,36 @@ _repo_name_sub_re = re.compile(r'[^\w-]')
158
159 _repo_attr_override_var_re = re.compile(r'^PORTAGE_REPOSITORY:([^:]+):([^:]+)$')
160
161 +def _read_repo_name(repo_location, quiet=False):
162 + layout_data = _read_layout_conf(repo_location)[0]
163 + repo_name = layout_data.get("repo-name")
164 + if repo_name is not None:
165 + if _repo_name_re.match(repo_name) is None:
166 + if not quiet:
167 + writemsg_level("!!! %s\n" % _("Repository name set in 'repo-name' attribute in %r is invalid: %r") %
168 + (os.path.join(repo_location, "metadata", "layout.conf"), repo_name), level=logging.ERROR, noiselevel=-1)
169 + return None
170 + return repo_name
171 +
172 + repo_name_file_location = os.path.join(repo_location, REPO_NAME_LOC)
173 + try:
174 + with io.open(_unicode_encode(repo_name_file_location, encoding=_encodings["fs"], errors="strict"),
175 + mode="r", encoding=_encodings["repo.content"], errors="replace") as f:
176 + repo_name = f.read()
177 + except EnvironmentError:
178 + repo_name = None
179 + if repo_name is not None:
180 + if repo_name.endswith("\n"):
181 + repo_name = repo_name[:-1]
182 + if _repo_name_re.match(repo_name) is None:
183 + if not quiet:
184 + writemsg_level("!!! %s\n" % _("Repository name set in %r is invalid: %r") %
185 + (repo_name_file_location, repo_name), level=logging.ERROR, noiselevel=-1)
186 + return None
187 + return repo_name
188 +
189 + return None
190 +
191 def _gen_valid_repo(name):
192 """
193 Substitute hyphen in place of characters that don't conform to PMS 3.1.5,
194 @@ -86,13 +117,13 @@ class RepoConfig(object):
195 'auto_sync', 'cache_formats', 'create_manifest', 'disable_manifest',
196 'eapi', 'eclass_db', 'eclass_locations', 'eclass_overrides',
197 'find_invalid_path_char', 'force', 'format', 'local_config', 'location',
198 - 'main_repo', 'manifest_hashes', 'masters', 'missing_repo_name',
199 + 'main_repo', 'manifest_hashes', 'masters', 'module_specific_options',
200 'name', 'portage1_profiles', 'portage1_profiles_compat', 'priority',
201 'profile_formats', 'sign_commit', 'sign_manifest',
202 'sync_depth', 'sync_hooks_only_on_change',
203 'sync_type', 'sync_umask', 'sync_uri', 'sync_user', 'thin_manifest',
204 'update_changelog', '_eapis_banned', '_eapis_deprecated',
205 - '_masters_orig', 'module_specific_options',
206 + '_invalid_config', '_masters_orig'
207 )
208
209 def __init__(self, name, repo_opts, local_config=True):
210 @@ -100,6 +131,57 @@ class RepoConfig(object):
211 Try to read repo_name in repository location, but if
212 it is not found use variable name as repository name"""
213
214 + self._invalid_config = False
215 +
216 + if name == "DEFAULT":
217 + self.location = None
218 + self.name = name
219 + else:
220 + location = repo_opts.get("location")
221 + if location is None:
222 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf is missing 'location' attribute") %
223 + name, level=logging.ERROR, noiselevel=-1)
224 + self._invalid_config = True
225 + else:
226 + if not os.path.isabs(location):
227 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has 'location' attribute set to "
228 + "relative path: %r") % (name, location), level=logging.ERROR, noiselevel=-1)
229 + self._invalid_config = True
230 + location = None
231 + elif not os.path.lexists(location):
232 + if not portage._sync_mode:
233 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has 'location' attribute set to "
234 + "nonexistent directory: %r") % (name, location), level=logging.ERROR, noiselevel=-1)
235 + self._invalid_config = True
236 + location = None
237 + elif not os.path.isdir(location):
238 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has 'location' attribute set to "
239 + "non-directory: %r") % (name, location), level=logging.ERROR, noiselevel=-1)
240 + self._invalid_config = True
241 + location = None
242 + elif not os.access(location, os.R_OK):
243 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has 'location' attribute set to "
244 + "nonreadable directory: %r") % (name, location), level=logging.ERROR, noiselevel=-1)
245 + self._invalid_config = True
246 + location = None
247 + else:
248 + location = os.path.realpath(location)
249 + self.location = location
250 +
251 + if self.location is None or portage._sync_mode:
252 + self.name = name
253 + else:
254 + self.name = _read_repo_name(location)
255 + if self.name is None:
256 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf refers to repository without repository name "
257 + "set in %r or in 'repo-name' attribute in %r") % (name, os.path.join(location, REPO_NAME_LOC),
258 + os.path.join(location, "metadata", "layout.conf")), level=logging.ERROR, noiselevel=-1)
259 + self._invalid_config = True
260 + elif name != self.name:
261 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has name different from repository name %r "
262 + "set inside repository") % (name, self.name), level=logging.ERROR, noiselevel=-1)
263 + self._invalid_config = True
264 +
265 force = repo_opts.get('force')
266 if force is not None:
267 force = tuple(force.split())
268 @@ -188,32 +270,7 @@ class RepoConfig(object):
269 format = format.strip()
270 self.format = format
271
272 - location = repo_opts.get('location')
273 - if location is not None and location.strip():
274 - if os.path.isdir(location) or portage._sync_mode:
275 - location = os.path.realpath(location)
276 - else:
277 - location = None
278 - self.location = location
279 -
280 - missing = True
281 - self.name = name
282 - if self.location is not None:
283 - self.name, missing = self._read_valid_repo_name(self.location)
284 - if missing:
285 - # The name from repos.conf has to be used here for
286 - # things like emerge-webrsync to work when the repo
287 - # is empty (bug #484950).
288 - if name is not None:
289 - self.name = name
290 - if portage._sync_mode:
291 - missing = False
292 -
293 - elif name == "DEFAULT":
294 - missing = False
295 -
296 self.eapi = None
297 - self.missing_repo_name = missing
298 # sign_commit is disabled by default, since it requires Git >=1.7.9,
299 # and key_id configured by `git config user.signingkey key_id`
300 self.sign_commit = False
301 @@ -249,13 +306,6 @@ class RepoConfig(object):
302 # them the ability to do incremental overrides
303 self.aliases = layout_data['aliases'] + tuple(aliases)
304
305 - if layout_data['repo-name']:
306 - # allow layout.conf to override repository name
307 - # useful when having two copies of the same repo enabled
308 - # to avoid modifying profiles/repo_name in one of them
309 - self.name = layout_data['repo-name']
310 - self.missing_repo_name = False
311 -
312 for value in ('allow-missing-manifest',
313 'allow-provide-virtual', 'cache-formats',
314 'create-manifest', 'disable-manifest', 'manifest-hashes',
315 @@ -343,15 +393,11 @@ class RepoConfig(object):
316 """Update repository with options in another RepoConfig"""
317
318 keys = set(self.__slots__)
319 - keys.discard("missing_repo_name")
320 for k in keys:
321 v = getattr(new_repo, k, None)
322 if v is not None:
323 setattr(self, k, v)
324
325 - if new_repo.name is not None:
326 - self.missing_repo_name = new_repo.missing_repo_name
327 -
328 @property
329 def writable(self):
330 """
331 @@ -363,42 +409,6 @@ class RepoConfig(object):
332 """
333 return os.access(first_existing(self.location), os.W_OK)
334
335 - @staticmethod
336 - def _read_valid_repo_name(repo_path):
337 - name, missing = RepoConfig._read_repo_name(repo_path)
338 - # We must ensure that the name conforms to PMS 3.1.5
339 - # in order to avoid InvalidAtom exceptions when we
340 - # use it to generate atoms.
341 - name = _gen_valid_repo(name)
342 - if not name:
343 - # name only contains invalid characters
344 - name = "x-" + os.path.basename(repo_path)
345 - name = _gen_valid_repo(name)
346 - # If basename only contains whitespace then the
347 - # end result is name = 'x-'.
348 - return name, missing
349 -
350 - @staticmethod
351 - def _read_repo_name(repo_path):
352 - """
353 - Read repo_name from repo_path.
354 - Returns repo_name, missing.
355 - """
356 - repo_name_path = os.path.join(repo_path, REPO_NAME_LOC)
357 - f = None
358 - try:
359 - f = io.open(
360 - _unicode_encode(repo_name_path,
361 - encoding=_encodings['fs'], errors='strict'),
362 - mode='r', encoding=_encodings['repo.content'],
363 - errors='replace')
364 - return f.readline().strip(), False
365 - except EnvironmentError:
366 - return "x-" + os.path.basename(repo_path), True
367 - finally:
368 - if f is not None:
369 - f.close()
370 -
371 def info_string(self):
372 """
373 Returns a formatted string containing informations about the repository.
374 @@ -604,6 +614,11 @@ class RepoConfigLoader(object):
375 parser.remove_section(deleted_repo)
376
377 for sname in parser.sections():
378 + if _repo_name_re.match(sname) is None:
379 + writemsg_level("!!! %s\n" % _("Section %r in repos.conf has invalid name") %
380 + sname, level=logging.ERROR, noiselevel=-1)
381 + continue
382 +
383 optdict = {}
384 for oname in parser.options(sname):
385 optdict[oname] = parser.get(sname, oname)
386 @@ -622,10 +637,8 @@ class RepoConfigLoader(object):
387 # Perform repos.conf sync variable validation
388 portage.sync.validate_config(repo, logging)
389
390 - # For backward compatibility with locations set via PORTDIR and
391 - # PORTDIR_OVERLAY, delay validation of the location and repo.name
392 - # until after PORTDIR and PORTDIR_OVERLAY have been processed.
393 - prepos[sname] = repo
394 + if not repo._invalid_config:
395 + prepos[sname] = repo
396
397 def __init__(self, paths, settings):
398 """Load config from files in paths"""
399 @@ -690,50 +703,10 @@ class RepoConfigLoader(object):
400 ignored_repos = tuple((repo_name, tuple(paths)) \
401 for repo_name, paths in ignored_map.items())
402
403 - self.missing_repo_names = frozenset(repo.location
404 - for repo in prepos.values()
405 - if repo.location is not None and repo.missing_repo_name)
406 -
407 # Do this before expanding aliases, so that location_map and
408 # treemap consistently map unaliased names whenever available.
409 for repo_name, repo in list(prepos.items()):
410 - if repo.location is None:
411 - if repo_name != 'DEFAULT':
412 - # Skip this warning for repoman (bug #474578).
413 - if settings.local_config and paths:
414 - writemsg_level("!!! %s\n" % _("Section '%s' in repos.conf is missing location attribute") %
415 - repo.name, level=logging.ERROR, noiselevel=-1)
416 - del prepos[repo_name]
417 - continue
418 - else:
419 - if not portage._sync_mode:
420 - if not isdir_raise_eaccess(repo.location):
421 - writemsg_level("!!! %s\n" % _("Section '%s' in repos.conf has location attribute set "
422 - "to nonexistent directory: '%s'") %
423 - (repo_name, repo.location), level=logging.ERROR, noiselevel=-1)
424 -
425 - # Ignore missing directory for 'gentoo' so that
426 - # first sync with emerge-webrsync is possible.
427 - if repo.name != 'gentoo':
428 - del prepos[repo_name]
429 - continue
430 -
431 - # After removing support for PORTDIR_OVERLAY, the following check can be:
432 - # if repo.missing_repo_name:
433 - if repo.missing_repo_name and repo.name != repo_name:
434 - writemsg_level("!!! %s\n" % _("Section '%s' in repos.conf refers to repository "
435 - "without repository name set in '%s'") %
436 - (repo_name, os.path.join(repo.location, REPO_NAME_LOC)), level=logging.ERROR, noiselevel=-1)
437 - del prepos[repo_name]
438 - continue
439 -
440 - if repo.name != repo_name:
441 - writemsg_level("!!! %s\n" % _("Section '%s' in repos.conf has name different "
442 - "from repository name '%s' set inside repository") %
443 - (repo_name, repo.name), level=logging.ERROR, noiselevel=-1)
444 - del prepos[repo_name]
445 - continue
446 -
447 + if repo_name != "DEFAULT":
448 location_map[repo.location] = repo_name
449 treemap[repo_name] = repo.location
450
451 @@ -1022,18 +995,20 @@ def load_repository_config(settings, extra_files=None):
452 def _get_repo_name(repo_location, cached=None):
453 if cached is not None:
454 return cached
455 - name, missing = RepoConfig._read_repo_name(repo_location)
456 - if missing:
457 - return None
458 - return name
459 -
460 -def parse_layout_conf(repo_location, repo_name=None):
461 - eapi = read_corresponding_eapi_file(os.path.join(repo_location, REPO_NAME_LOC))
462 + return _read_repo_name(repo_location, quiet=True)
463
464 +def _read_layout_conf(repo_location):
465 layout_filename = os.path.join(repo_location, "metadata", "layout.conf")
466 layout_file = KeyValuePairFileLoader(layout_filename, None, None)
467 layout_data, layout_errors = layout_file.load()
468
469 + return layout_data, layout_errors
470 +
471 +def parse_layout_conf(repo_location, repo_name=None):
472 + layout_data, layout_errors = _read_layout_conf(repo_location)
473 +
474 + eapi = read_corresponding_eapi_file(os.path.join(repo_location, REPO_NAME_LOC))
475 +
476 data = {}
477
478 # None indicates abscence of a masters setting, which later code uses
479 @@ -1062,8 +1037,6 @@ def parse_layout_conf(repo_location, repo_name=None):
480 data['thin-manifest'] = layout_data.get('thin-manifests', 'false').lower() \
481 == 'true'
482
483 - data['repo-name'] = _gen_valid_repo(layout_data.get('repo-name', ''))
484 -
485 manifest_policy = layout_data.get('use-manifests', 'strict').lower()
486 data['allow-missing-manifest'] = manifest_policy != 'strict'
487 data['create-manifest'] = manifest_policy != 'false'
488
489 diff --git a/pym/repoman/repos.py b/pym/repoman/repos.py
490 index 9a62e05..e7b8463 100644
491 --- a/pym/repoman/repos.py
492 +++ b/pym/repoman/repos.py
493 @@ -130,11 +130,7 @@ class RepoSettings(object):
494
495 def _add_repo(self, config_root, portdir_overlay):
496 self.repo_conf = portage.repository.config
497 - self.repo_name = self.repo_conf.RepoConfig._read_valid_repo_name(
498 - portdir_overlay)[0]
499 - self.layout_conf_data = self.repo_conf.parse_layout_conf(portdir_overlay)[0]
500 - if self.layout_conf_data['repo-name']:
501 - self.repo_name = self.layout_conf_data['repo-name']
502 + self.repo_name = self.repo_conf._read_repo_name(portdir_overlay, quiet=True)
503 tmp_conf_file = io.StringIO(textwrap.dedent("""
504 [%s]
505 location = %s