]>
Commit | Line | Data |
---|---|---|
028b2057 MT |
1 | #!/usr/bin/python3 |
2 | ||
22a89cd7 | 3 | import asyncio |
da4b4f45 | 4 | import collections |
73747ff6 | 5 | import configparser |
1af8c243 | 6 | import io |
028b2057 | 7 | import logging |
da4b4f45 | 8 | import logging.handlers |
028b2057 | 9 | import pakfire |
028b2057 MT |
10 | |
11 | from . import base | |
12 | ||
13 | # Setup logging | |
6acc7746 | 14 | log = logging.getLogger("pbs.config") |
028b2057 MT |
15 | |
16 | class PakfireConfig(base.Object): | |
cd8c247d | 17 | def init(self, distro=None, repos=None, vendor=None, contact=None, |
46124b3a | 18 | arch=None, include_source=False, mirrored=True, build=None, logger=None): |
028b2057 MT |
19 | self.distro = distro |
20 | self.repos = set() | |
21 | ||
c7c90543 MT |
22 | # Overwritten for user repositories |
23 | self.vendor = vendor | |
24 | self.contact = contact | |
25 | ||
cd8c247d MT |
26 | # Architecture |
27 | self.arch = arch | |
28 | ||
316ffaa3 MT |
29 | # Should the configuration include the source repositories? |
30 | self.include_source = include_source | |
31 | ||
91fb1718 MT |
32 | # Should the repositories use any mirrors? |
33 | self.mirrored = mirrored | |
34 | ||
46124b3a MT |
35 | # Is this for a build? |
36 | self.build = build | |
37 | ||
da4b4f45 MT |
38 | # Log messages to here |
39 | self.logger = logger | |
40 | ||
028b2057 | 41 | # Add all repositories belonging to the distribution |
c7d2517e MT |
42 | if self.distro: |
43 | for repo in self.distro.repos: | |
44 | self.add_repo(repo) | |
028b2057 MT |
45 | |
46 | # Add any repositories | |
47 | if repos: | |
48 | for repo in repos: | |
49 | self.add_repo(repo) | |
50 | ||
51 | def __str__(self): | |
1af8c243 | 52 | config = self._make_config() |
6b441548 MT |
53 | |
54 | return self._to_string(config) | |
55 | ||
56 | def _to_string(self, config): | |
57 | buffer = io.StringIO() | |
1af8c243 MT |
58 | config.write(buffer) |
59 | ||
60 | return buffer.getvalue() | |
028b2057 | 61 | |
db548d43 MT |
62 | def _log(self, level, message): |
63 | # Remove any trailing newline (but only one) | |
64 | if message: | |
65 | message = message.removesuffix("\n") | |
66 | ||
da4b4f45 MT |
67 | # Log to the logger if configured |
68 | if self.logger: | |
69 | return self.logger(level, message) | |
70 | ||
db548d43 MT |
71 | return log.log(level, message) |
72 | ||
028b2057 MT |
73 | # Repositories |
74 | ||
75 | def add_repo(self, repo): | |
76 | """ | |
77 | Adds a repository to this configuration | |
78 | """ | |
79 | self.repos.add(repo) | |
80 | ||
81 | # Add any sibling repositories | |
dc433969 | 82 | self.repos.update(repo.parents) |
028b2057 MT |
83 | |
84 | # Context | |
85 | ||
22a89cd7 | 86 | async def __aenter__(self): |
5ca2b3bb MT |
87 | f = io.StringIO() |
88 | ||
028b2057 MT |
89 | # Make configuration |
90 | config = self._make_config(local=True) | |
91 | ||
5ca2b3bb MT |
92 | # Write the configuration to the buffer |
93 | config.write(f) | |
94 | f.seek(0) | |
028b2057 | 95 | |
5ca2b3bb | 96 | log.debug("Launching Pakfire with configuration:\n%s", f.getvalue()) |
028b2057 | 97 | |
5ca2b3bb | 98 | # Launch a new Pakfire instance (in a separate thread) |
6c7bb702 MT |
99 | async with self.backend.tempdir() as d: |
100 | return await asyncio.to_thread(pakfire.Pakfire, path=d, arch=self.arch, | |
101 | conf=f, logger=self._log, offline=False) | |
22a89cd7 MT |
102 | |
103 | async def __aexit__(self, type, value, traceback): | |
028b2057 MT |
104 | pass |
105 | ||
106 | def _make_config(self, local=False): | |
107 | """ | |
108 | Generates the configuration file | |
109 | """ | |
73747ff6 MT |
110 | config = configparser.ConfigParser(interpolation=None, |
111 | default_section="general") | |
112 | ||
113 | # Apply some general settings | |
deecf10c MT |
114 | if local: |
115 | config["general"] = { | |
116 | "cache_path" : self.backend.path(".cache"), | |
117 | } | |
028b2057 MT |
118 | |
119 | # Add the distro configuration | |
c7d2517e | 120 | if self.distro: |
73747ff6 | 121 | self.distro.write_config(config, local=local, |
c7c90543 | 122 | vendor=self.vendor, contact=self.contact) |
028b2057 MT |
123 | |
124 | # Add the repository configurations | |
125 | for repo in self.repos: | |
46124b3a MT |
126 | repo.write_config(config, local=local, include_source=self.include_source, |
127 | mirrored=self.mirrored, build=self.build) | |
028b2057 | 128 | |
73747ff6 | 129 | return config |
da4b4f45 MT |
130 | |
131 | ||
132 | class PakfireLogger(object): | |
133 | """ | |
134 | This is a simple logger instance which collects all log | |
135 | messages which can in the end be exported to for example being stored in the database. | |
136 | """ | |
137 | id = 0 | |
138 | ||
139 | class QueueHandler(logging.handlers.QueueHandler): | |
140 | """ | |
141 | This calls overwrites the enqueue() method so that | |
142 | we can use an alternative queue which allows us to | |
143 | iterate over its data without removing anything. | |
144 | """ | |
145 | def enqueue(self, record): | |
146 | self.queue.append(record) | |
147 | ||
148 | def __init__(self, level=logging.DEBUG): | |
149 | # Create a new child logger | |
150 | self.log = log.getChild("logger-%s" % self.id) | |
151 | self.log.setLevel(level) | |
152 | ||
153 | # Increment the ID | |
154 | self.id += 1 | |
155 | ||
156 | # Propagate messages to the parent logger | |
157 | self.log.propagate = True | |
158 | ||
159 | # Create a new queue to buffer any messages | |
160 | self.queue = collections.deque() | |
161 | ||
162 | # Create a log formatter | |
163 | formatter = logging.Formatter( | |
164 | "%(asctime)s %(levelname)-8s %(message)s" | |
165 | ) | |
166 | ||
167 | # Create a queue handler | |
168 | handler = self.QueueHandler(self.queue) | |
169 | handler.setFormatter(formatter) | |
170 | ||
171 | # Register the queue with the logger | |
172 | self.log.addHandler(handler) | |
173 | ||
174 | def __call__(self, *args, **kwargs): | |
175 | """ | |
176 | Logs a message | |
177 | """ | |
178 | return self.log.log(*args, **kwargs) | |
179 | ||
180 | def __str__(self): | |
181 | """ | |
182 | Returns the entire log as a string | |
183 | """ | |
184 | return "\n".join((record.getMessage() for record in self.queue)) |