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