]>
Commit | Line | Data |
---|---|---|
9137135a MT |
1 | #!/usr/bin/python |
2 | ||
f6e6ff79 MT |
3 | import os.path |
4 | ||
2c909128 MT |
5 | from . import base |
6 | from . import logs | |
9137135a | 7 | |
e459cbba MT |
8 | from .decorators import * |
9 | ||
9137135a | 10 | class Repositories(base.Object): |
e459cbba MT |
11 | def _get_repository(self, query, *args): |
12 | res = self.db.get(query, *args) | |
9137135a | 13 | |
e459cbba MT |
14 | if res: |
15 | return Repository(self.backend, res.id, data=res) | |
9137135a | 16 | |
e459cbba MT |
17 | def _get_repositories(self, query, *args): |
18 | res = self.db.query(query, *args) | |
19 | ||
20 | for row in res: | |
21 | yield Repository(self.backend, row.id, data=row) | |
22 | ||
23 | def __iter__(self): | |
24 | repositories = self._get_repositories("SELECT * FROM repositories \ | |
8cb14e63 | 25 | WHERE deleted IS FALSE ORDER BY distro_id, name") |
9137135a | 26 | |
e459cbba MT |
27 | return iter(repositories) |
28 | ||
d629da45 MT |
29 | def create(self, distro, name, description): |
30 | return self._get_repository("INSERT INTO repositories(distro_id, name, description) \ | |
31 | VALUES(%s, %s, %s) RETURNING *", distro.id, name, description) | |
32 | ||
e459cbba MT |
33 | def get_by_id(self, repo_id): |
34 | return self._get_repository("SELECT * FROM repositories \ | |
35 | WHERE id = %s", repo_id) | |
9137135a MT |
36 | |
37 | def get_needs_update(self, limit=None): | |
38 | query = "SELECT id FROM repositories WHERE needs_update = 'Y'" | |
39 | query += " ORDER BY last_update ASC" | |
40 | ||
41 | # Append limit if any | |
42 | if limit: | |
43 | query += " LIMIT %d" % limit | |
44 | ||
45 | repos = self.db.query(query) | |
46 | ||
47 | return [Repository(self.pakfire, r.id) for r in repos] | |
48 | ||
f6e6ff79 MT |
49 | def get_history(self, limit=None, offset=None, build=None, repo=None, user=None): |
50 | query = "SELECT * FROM repositories_history" | |
51 | args = [] | |
9137135a | 52 | |
f6e6ff79 | 53 | query += " ORDER BY time DESC" |
9137135a | 54 | |
f6e6ff79 MT |
55 | if limit: |
56 | if offset: | |
57 | query += " LIMIT %s,%s" | |
58 | args += [offset, limit,] | |
59 | else: | |
60 | query += " LIMIT %s" | |
61 | args += [limit,] | |
9137135a | 62 | |
f6e6ff79 MT |
63 | entries = [] |
64 | for entry in self.db.query(query, *args): | |
65 | entry = logs.RepositoryLogEntry(self.pakfire, entry) | |
66 | entries.append(entry) | |
9137135a | 67 | |
f6e6ff79 | 68 | return entries |
9137135a MT |
69 | |
70 | ||
d629da45 MT |
71 | class Repository(base.DataObject): |
72 | table = "repositories" | |
f6e6ff79 | 73 | |
d629da45 MT |
74 | def __eq__(self, other): |
75 | if isinstance(other, self.__class__): | |
76 | return self.id == other.id | |
f6e6ff79 | 77 | |
d629da45 MT |
78 | def __lt__(self, other): |
79 | if isinstance(other, self.__class__): | |
80 | return self.parent_id == other.id | |
9137135a | 81 | |
d629da45 MT |
82 | def __iter__(self): |
83 | builds = self.backend.builds._get_builds("SELECT builds.* FROM repositories_builds \ | |
84 | LEFT JOIN builds ON repositories_builds.build_id = builds.id \ | |
78f9cb76 | 85 | WHERE repositories_builds.repo_id = %s", self.id) |
9137135a | 86 | |
d629da45 | 87 | return iter(builds) |
f6e6ff79 | 88 | |
d629da45 MT |
89 | def __len__(self): |
90 | res = self.db.get("SELECT COUNT(*) AS len FROM repositories_builds \ | |
91 | WHERE repo_id = %s", self.id) | |
9137135a | 92 | |
d629da45 | 93 | return res.len |
9137135a | 94 | |
d629da45 | 95 | @lazy_property |
9137135a | 96 | def next(self): |
d629da45 MT |
97 | return self.backend.repos._get_repository("SELECT * FROM repositories \ |
98 | WHERE parent_id = %s", self.id) | |
9137135a | 99 | |
d629da45 | 100 | @lazy_property |
f6e6ff79 | 101 | def parent(self): |
d629da45 MT |
102 | if self.data.parent_id: |
103 | return self.backend.repos._get_repository("SELECT * FROM repositories \ | |
104 | WHERE id = %s", self.data.parent_id) | |
9137135a | 105 | |
e459cbba | 106 | @lazy_property |
9137135a | 107 | def distro(self): |
e459cbba | 108 | return self.backend.distros.get_by_id(self.data.distro_id) |
9137135a MT |
109 | |
110 | @property | |
111 | def info(self): | |
112 | return { | |
113 | "id" : self.id, | |
114 | "distro" : self.distro.info, | |
115 | "name" : self.name, | |
116 | "arches" : self.arches, | |
117 | } | |
118 | ||
119 | @property | |
f6e6ff79 MT |
120 | def url(self): |
121 | url = os.path.join( | |
122 | self.settings.get("repository_baseurl", "http://pakfire.ipfire.org/repositories/"), | |
123 | self.distro.identifier, | |
124 | self.identifier, | |
125 | "%{arch}" | |
126 | ) | |
127 | ||
128 | return url | |
129 | ||
130 | @property | |
131 | def mirrorlist(self): | |
132 | url = os.path.join( | |
133 | self.settings.get("mirrorlist_baseurl", "https://pakfire.ipfire.org/"), | |
134 | "distro", self.distro.identifier, | |
135 | "repo", self.identifier, | |
136 | "mirrorlist?arch=%{arch}" | |
137 | ) | |
138 | ||
139 | return url | |
140 | ||
141 | def get_conf(self): | |
142 | prioritymap = { | |
143 | "stable" : 500, | |
144 | "unstable" : 200, | |
145 | "testing" : 100, | |
146 | } | |
147 | ||
148 | try: | |
149 | priority = prioritymap[self.type] | |
150 | except KeyError: | |
151 | priority = None | |
152 | ||
153 | lines = [ | |
154 | "[repo:%s]" % self.identifier, | |
155 | "description = %s - %s" % (self.distro.name, self.summary), | |
156 | "enabled = 1", | |
157 | "baseurl = %s" % self.url, | |
158 | "mirrors = %s" % self.mirrorlist, | |
159 | ] | |
160 | ||
161 | if priority: | |
162 | lines.append("priority = %s" % priority) | |
163 | ||
164 | return "\n".join(lines) | |
9137135a MT |
165 | |
166 | @property | |
167 | def name(self): | |
168 | return self.data.name | |
169 | ||
170 | @property | |
f6e6ff79 MT |
171 | def identifier(self): |
172 | return self.name.lower() | |
9137135a MT |
173 | |
174 | @property | |
f6e6ff79 MT |
175 | def type(self): |
176 | return self.data.type | |
9137135a MT |
177 | |
178 | @property | |
f6e6ff79 MT |
179 | def summary(self): |
180 | lines = self.description.splitlines() | |
9137135a | 181 | |
f6e6ff79 MT |
182 | if lines: |
183 | return lines[0] | |
9137135a | 184 | |
f6e6ff79 | 185 | return "N/A" |
9137135a | 186 | |
f6e6ff79 MT |
187 | @property |
188 | def description(self): | |
189 | return self.data.description or "" | |
9137135a | 190 | |
f6e6ff79 MT |
191 | @property |
192 | def parent_id(self): | |
193 | return self.data.parent_id | |
9137135a | 194 | |
d629da45 | 195 | @lazy_property |
f6e6ff79 MT |
196 | def key(self): |
197 | if not self.data.key_id: | |
198 | return | |
9137135a | 199 | |
d629da45 | 200 | return self.pakfire.keys.get_by_id(self.data.key_id) |
9137135a | 201 | |
f6e6ff79 MT |
202 | @property |
203 | def arches(self): | |
204 | return self.distro.arches | |
205 | ||
206 | @property | |
207 | def mirrored(self): | |
d629da45 | 208 | return self.data.mirrored |
9137135a | 209 | |
f6e6ff79 | 210 | def set_enabled_for_builds(self, state): |
d629da45 | 211 | self._set_attribute("enabled_for_builds", state) |
9137135a | 212 | |
d629da45 | 213 | enabled_for_builds = property(lambda s: s.data.enabled_for_builds, set_enabled_for_builds) |
9137135a MT |
214 | |
215 | @property | |
f6e6ff79 MT |
216 | def score_needed(self): |
217 | return self.data.score_needed | |
9137135a MT |
218 | |
219 | @property | |
f6e6ff79 MT |
220 | def time_min(self): |
221 | return self.data.time_min | |
9137135a MT |
222 | |
223 | @property | |
f6e6ff79 MT |
224 | def time_max(self): |
225 | return self.data.time_max | |
9137135a | 226 | |
f6e6ff79 MT |
227 | def _log_build(self, action, build, from_repo=None, to_repo=None, user=None): |
228 | user_id = None | |
229 | if user: | |
230 | user_id = user.id | |
9137135a | 231 | |
f6e6ff79 MT |
232 | from_repo_id = None |
233 | if from_repo: | |
234 | from_repo_id = from_repo.id | |
9137135a | 235 | |
f6e6ff79 MT |
236 | to_repo_id = None |
237 | if to_repo: | |
238 | to_repo_id = to_repo.id | |
9137135a | 239 | |
f6e6ff79 MT |
240 | self.db.execute("INSERT INTO repositories_history(action, build_id, from_repo_id, to_repo_id, user_id, time) \ |
241 | VALUES(%s, %s, %s, %s, %s, NOW())", action, build.id, from_repo_id, to_repo_id, user_id) | |
9137135a | 242 | |
f6e6ff79 MT |
243 | def add_build(self, build, user=None, log=True): |
244 | self.db.execute("INSERT INTO repositories_builds(repo_id, build_id, time_added)" | |
245 | " VALUES(%s, %s, NOW())", self.id, build.id) | |
9137135a | 246 | |
f6e6ff79 MT |
247 | # Update bug status. |
248 | build._update_bugs_helper(self) | |
9137135a | 249 | |
f6e6ff79 MT |
250 | if log: |
251 | self._log_build("added", build, to_repo=self, user=user) | |
9137135a | 252 | |
f6e6ff79 MT |
253 | def rem_build(self, build, user=None, log=True): |
254 | self.db.execute("DELETE FROM repositories_builds \ | |
255 | WHERE repo_id = %s AND build_id = %s", self.id, build.id) | |
9137135a | 256 | |
f6e6ff79 MT |
257 | if log: |
258 | self._log_build("removed", build, from_repo=self, user=user) | |
9137135a | 259 | |
f6e6ff79 MT |
260 | def move_build(self, build, to_repo, user=None, log=True): |
261 | self.db.execute("UPDATE repositories_builds SET repo_id = %s, time_added = NOW() \ | |
262 | WHERE repo_id = %s AND build_id = %s", to_repo.id, self.id, build.id) | |
9137135a | 263 | |
f6e6ff79 MT |
264 | # Update bug status. |
265 | build._update_bugs_helper(to_repo) | |
9137135a | 266 | |
f6e6ff79 MT |
267 | if log: |
268 | self._log_build("moved", build, from_repo=self, to_repo=to_repo, | |
269 | user=user) | |
9137135a | 270 | |
f6e6ff79 MT |
271 | def get_builds(self, limit=None, offset=None): |
272 | query = "SELECT build_id AS id FROM repositories_builds \ | |
273 | WHERE repo_id = %s ORDER BY time_added DESC" | |
274 | args = [self.id,] | |
9137135a | 275 | |
f6e6ff79 MT |
276 | if limit: |
277 | if offset: | |
278 | query += " LIMIT %s,%s" | |
279 | args += [offset, limit,] | |
280 | else: | |
281 | query += " LIMIT %s" | |
282 | args += [limit,] | |
283 | ||
284 | _builds = [] | |
285 | for build in self.db.query(query, *args): | |
2c909128 | 286 | build = self.pakfire.builds.get_by_id(build.id) |
f6e6ff79 MT |
287 | build._repo = self |
288 | ||
289 | _builds.append(build) | |
290 | ||
291 | return _builds | |
292 | ||
83be3106 | 293 | def _get_packages(self, arch): |
f6e6ff79 | 294 | if arch.name == "src": |
83be3106 | 295 | pkgs = self.db.query("SELECT packages.id AS id, packages.path AS path FROM packages \ |
f6e6ff79 MT |
296 | JOIN builds ON builds.pkg_id = packages.id \ |
297 | JOIN repositories_builds ON builds.id = repositories_builds.build_id \ | |
298 | WHERE packages.arch = %s AND repositories_builds.repo_id = %s", | |
22b715d7 | 299 | arch.name, self.id) |
9137135a | 300 | |
f6e6ff79 | 301 | else: |
83be3106 | 302 | pkgs = self.db.query("SELECT packages.id AS id, packages.path AS path FROM packages \ |
f6e6ff79 MT |
303 | JOIN jobs_packages ON jobs_packages.pkg_id = packages.id \ |
304 | JOIN jobs ON jobs_packages.job_id = jobs.id \ | |
305 | JOIN builds ON builds.id = jobs.build_id \ | |
306 | JOIN repositories_builds ON builds.id = repositories_builds.build_id \ | |
22b715d7 | 307 | WHERE (jobs.arch = %s OR jobs.arch = %s) AND \ |
f6e6ff79 | 308 | repositories_builds.repo_id = %s", |
d1a95124 | 309 | arch.name, "noarch", self.id) |
9137135a | 310 | |
83be3106 MT |
311 | return pkgs |
312 | ||
313 | def get_packages(self, arch): | |
2c909128 | 314 | pkgs = [self.pakfire.packages.get_by_id(p.id) for p in self._get_packages(arch)] |
83be3106 MT |
315 | pkgs.sort() |
316 | ||
317 | return pkgs | |
318 | ||
319 | def get_paths(self, arch): | |
320 | paths = [p.path for p in self._get_packages(arch)] | |
321 | paths.sort() | |
322 | ||
323 | return paths | |
f6e6ff79 MT |
324 | |
325 | @property | |
326 | def packages(self): | |
327 | return self.get_packages() | |
9137135a | 328 | |
f6e6ff79 MT |
329 | def get_unpushed_builds(self): |
330 | query = self.db.query("SELECT build_id FROM repositories_builds \ | |
331 | WHERE repo_id = %s AND \ | |
332 | time_added > (SELECT last_update FROM repositories WHERE id = %s)", | |
333 | self.id, self.id) | |
334 | ||
335 | ret = [] | |
336 | for row in query: | |
2c909128 | 337 | b = self.pakfire.builds.get_by_id(row.build_id) |
f6e6ff79 MT |
338 | ret.append(b) |
339 | ||
340 | return ret | |
341 | ||
342 | def get_obsolete_builds(self): | |
f6e6ff79 MT |
343 | return self.pakfire.builds.get_obsolete(self) |
344 | ||
345 | def needs_update(self): | |
346 | if self.get_unpushed_builds: | |
9137135a MT |
347 | return True |
348 | ||
9137135a MT |
349 | return False |
350 | ||
f6e6ff79 MT |
351 | def updated(self): |
352 | self.db.execute("UPDATE repositories SET last_update = NOW() \ | |
353 | WHERE id = %s", self.id) | |
9137135a | 354 | |
f6e6ff79 MT |
355 | def get_history(self, **kwargs): |
356 | kwargs.update({ | |
357 | "repo" : self, | |
358 | }) | |
9137135a | 359 | |
f6e6ff79 | 360 | return self.pakfire.repos.get_history(**kwargs) |
9137135a | 361 | |
f6e6ff79 | 362 | def get_build_times(self): |
f6e6ff79 | 363 | times = [] |
e459cbba MT |
364 | for arch in self.arches: |
365 | time = self.db.get("SELECT SUM(jobs.time_finished - jobs.time_started) AS time FROM jobs \ | |
f6e6ff79 MT |
366 | JOIN builds ON builds.id = jobs.build_id \ |
367 | JOIN repositories_builds ON builds.id = repositories_builds.build_id \ | |
e459cbba | 368 | WHERE (jobs.arch = %s OR jobs.arch = %s) AND \ |
a577f40c | 369 | jobs.type = 'build' AND \ |
e459cbba | 370 | repositories_builds.repo_id = %s", arch, "noarch", self.id) |
f6e6ff79 | 371 | |
e459cbba | 372 | times.append((arch, time.time.total_seconds())) |
f6e6ff79 MT |
373 | |
374 | return times | |
9137135a | 375 | |
9137135a | 376 | |
d629da45 MT |
377 | class RepositoryAux(base.DataObject): |
378 | table = "repositories_aux" | |
f6e6ff79 MT |
379 | |
380 | @property | |
381 | def name(self): | |
382 | return self.data.name | |
383 | ||
384 | @property | |
385 | def description(self): | |
386 | return self.data.description or "" | |
387 | ||
388 | @property | |
389 | def url(self): | |
390 | return self.data.url | |
391 | ||
392 | @property | |
393 | def identifier(self): | |
394 | return self.name.lower() | |
395 | ||
396 | @property | |
397 | def distro(self): | |
d629da45 | 398 | return self.pakfire.distros.get_by_id(self.data.distro_id) |
f6e6ff79 MT |
399 | |
400 | def get_conf(self): | |
401 | lines = [ | |
402 | "[repo:%s]" % self.identifier, | |
403 | "description = %s - %s" % (self.distro.name, self.name), | |
404 | "enabled = 1", | |
405 | "baseurl = %s" % self.url, | |
406 | "priority = 0", | |
407 | ] | |
408 | ||
409 | return "\n".join(lines) |