1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
# Copyright 2020-2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from collections import OrderedDict
from collections.abc import Mapping
from hashlib import md5
from portage.localization import _
from portage.util import _recursive_file_list, writemsg
from portage.util.configparser import SafeConfigParser, ConfigParserError, read_configs
class BinRepoConfig:
__slots__ = (
"frozen",
"name",
"name_fallback",
"fetchcommand",
"priority",
"resumecommand",
"sync_uri",
)
_bool_opts = ("frozen",)
def __init__(self, opts):
"""
Create a BinRepoConfig with options in opts.
"""
for k in self.__slots__:
setattr(self, k, opts.get(k.replace("_", "-")))
for k in self._bool_opts:
if isinstance(getattr(self, k, None), str):
setattr(self, k, getattr(self, k).lower() in ("true", "yes"))
def info_string(self):
"""
Returns a formatted string containing information about the repository.
Used by emerge --info.
"""
indent = " " * 4
repo_msg = []
repo_msg.append(self.name or self.name_fallback)
if self.priority is not None:
repo_msg.append(indent + "priority: " + str(self.priority))
repo_msg.append(indent + "sync-uri: " + self.sync_uri)
if self.frozen:
repo_msg.append(f"{indent}frozen: {str(self.frozen).lower()}")
repo_msg.append("")
return "\n".join(repo_msg)
class BinRepoConfigLoader(Mapping):
def __init__(self, paths, settings):
"""Load config from files in paths"""
# Defaults for value interpolation.
parser_defaults = {
"frozen": "false",
"EPREFIX": settings["EPREFIX"],
"EROOT": settings["EROOT"],
"PORTAGE_CONFIGROOT": settings["PORTAGE_CONFIGROOT"],
"ROOT": settings["ROOT"],
}
try:
parser = self._parse(paths, parser_defaults)
except ConfigParserError as e:
writemsg(
_("!!! Error while reading binrepo config file: %s\n") % e,
noiselevel=-1,
)
parser = SafeConfigParser(defaults=parser_defaults)
repos = []
sync_uris = []
for section_name in parser.sections():
repo_data = dict(parser[section_name].items())
repo_data["name"] = section_name
repo = BinRepoConfig(repo_data)
if repo.sync_uri is None:
writemsg(
_("!!! Missing sync-uri setting for binrepo %s\n") % (repo.name,),
noiselevel=-1,
)
continue
sync_uri = self._normalize_uri(repo.sync_uri)
sync_uris.append(sync_uri)
repo.sync_uri = sync_uri
if repo.priority is not None:
try:
repo.priority = int(repo.priority)
except ValueError:
repo.priority = None
repos.append(repo)
sync_uris = set(sync_uris)
current_priority = 0
for sync_uri in reversed(settings.get("PORTAGE_BINHOST", "").split()):
sync_uri = self._normalize_uri(sync_uri)
if sync_uri not in sync_uris:
current_priority += 1
sync_uris.add(sync_uri)
repos.append(
BinRepoConfig(
{
"name-fallback": self._digest_uri(sync_uri),
"name": None,
"priority": current_priority,
"sync-uri": sync_uri,
}
)
)
self._data = OrderedDict(
(repo.name or repo.name_fallback, repo)
for repo in sorted(
repos,
key=lambda repo: (repo.priority or 0, repo.name or repo.name_fallback),
)
)
@staticmethod
def _digest_uri(uri):
return md5(uri.encode("utf_8")).hexdigest()
@staticmethod
def _normalize_uri(uri):
return uri.rstrip("/")
@staticmethod
def _parse(paths, defaults):
parser = SafeConfigParser(defaults=defaults)
recursive_paths = []
for p in paths:
if isinstance(p, str):
recursive_paths.extend(_recursive_file_list(p))
else:
recursive_paths.append(p)
read_configs(parser, recursive_paths)
return parser
def __iter__(self):
return iter(self._data)
def __contains__(self, key):
return key in self._data
def __getitem__(self, key):
return self._data[key]
def __len__(self):
return len(self._data)
|