]> git.ipfire.org Git - pbs.git/blame - src/buildservice/config.py
config: Create a temporary directory
[pbs.git] / src / buildservice / config.py
CommitLineData
028b2057
MT
1#!/usr/bin/python3
2
22a89cd7 3import asyncio
da4b4f45 4import collections
73747ff6 5import configparser
1af8c243 6import io
028b2057 7import logging
da4b4f45 8import logging.handlers
028b2057 9import pakfire
028b2057
MT
10
11from . import base
12
13# Setup logging
6acc7746 14log = logging.getLogger("pbs.config")
028b2057
MT
15
16class 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
132class 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))