]>
git.ipfire.org Git - people/jschlag/pbs.git/blob - src/buildservice/packages.py
9 import pakfire
.packages
as packages
12 from . import database
15 from .constants
import *
16 from .decorators
import *
18 class Packages(base
.Object
):
19 def _get_package(self
, query
, *args
):
20 res
= self
.db
.get(query
, *args
)
23 return Package(self
.backend
, res
.id, data
=res
)
25 def _get_packages(self
, query
, *args
):
26 res
= self
.db
.query(query
, *args
)
29 yield Package(self
.backend
, row
.id, data
=row
)
31 def get_by_id(self
, pkg_id
):
32 return self
._get
_package
("SELECT * FROM packages \
33 WHERE id = %s", pkg_id
)
35 def get_all_names(self
, user
=None, states
=None):
36 query
= "SELECT DISTINCT packages.name AS name, summary FROM packages \
37 JOIN builds ON builds.pkg_id = packages.id \
38 WHERE packages.type = 'source'"
43 if user
and not user
.is_admin():
44 conditions
.append("builds.owner_id = %s")
49 conditions
.append("builds.state = %s")
53 query
+= " AND (%s)" % " OR ".join(conditions
)
55 query
+= " ORDER BY packages.name"
57 return [(n
.name
, n
.summary
) for n
in self
.db
.query(query
, *args
)]
59 def get_by_uuid(self
, uuid
):
60 pkg
= self
.db
.get("SELECT * FROM packages WHERE uuid = %s LIMIT 1", uuid
)
64 return Package(self
.backend
, pkg
.id, pkg
)
66 def create(self
, path
):
67 # Just check if the file really exist
68 assert os
.path
.exists(path
)
70 _pkg
= packages
.open(pakfire
.PakfireServer(), None, path
)
72 hash_sha512
= misc
.calc_hash(path
, "sha512")
77 ("epoch", _pkg
.epoch
),
78 ("version", _pkg
.version
),
79 ("release", _pkg
.release
),
83 ("groups", " ".join(_pkg
.groups
)),
84 ("maintainer", _pkg
.maintainer
),
85 ("license", _pkg
.license
),
87 ("summary", _pkg
.summary
),
88 ("description", _pkg
.description
),
89 ("size", _pkg
.inst_size
),
93 ("build_id", _pkg
.build_id
),
94 ("build_host", _pkg
.build_host
),
95 ("build_time", datetime
.datetime
.utcfromtimestamp(_pkg
.build_time
)),
99 ("filesize", os
.path
.getsize(path
)),
100 ("hash_sha512", hash_sha512
),
103 if _pkg
.type == "source":
104 query
.append(("supported_arches", _pkg
.supported_arches
))
108 for key
, val
in query
:
112 _query
= "INSERT INTO packages(%s)" % ", ".join(keys
)
113 _query
+= " VALUES(%s) RETURNING *" % ", ".join("%s" for v
in vals
)
115 # Create package entry in the database.
116 pkg
= self
._get
_package
(_query
, *vals
)
118 # Dependency information.
119 for d
in _pkg
.prerequires
:
120 pkg
.add_dependency("prerequires", d
)
122 for d
in _pkg
.requires
:
123 pkg
.add_dependency("requires", d
)
125 for d
in _pkg
.provides
:
126 pkg
.add_dependency("provides", d
)
128 for d
in _pkg
.conflicts
:
129 pkg
.add_dependency("conflicts", d
)
131 for d
in _pkg
.obsoletes
:
132 pkg
.add_dependency("obsoletes", d
)
134 # Add all files to filelists table
135 for f
in _pkg
.filelist
:
136 pkg
.add_file(f
.name
, f
.size
, f
.hash1
, f
.type, f
.config
, f
.mode
,
137 f
.user
, f
.group
, f
.mtime
, f
.capabilities
)
139 # Return the newly created object
142 def search(self
, pattern
, limit
=None):
144 Searches for packages that do match the query.
146 This function does not work for UUIDs or filenames.
148 query
= "SELECT * FROM packages \
149 WHERE type = %s AND ( \
152 description LIKE %s \
156 pattern
= "%%%s%%" % pattern
157 args
= ("source", pattern
, pattern
, pattern
)
159 res
= self
.db
.query(query
, *args
)
163 pkg
= Package(self
.backend
, row
.id, row
)
166 if limit
and len(pkgs
) >= limit
:
171 def search_by_filename(self
, filename
, limit
=None):
172 query
= "SELECT filelists.* FROM filelists \
173 JOIN packages ON filelists.pkg_id = packages.id \
174 WHERE filelists.name = %s ORDER BY packages.build_time DESC"
182 for result
in self
.db
.query(query
, *args
):
183 pkg
= Package(self
.backend
, result
.pkg_id
)
184 files
.append((pkg
, result
))
188 def autocomplete(self
, query
, limit
=8):
189 res
= self
.db
.query("SELECT DISTINCT name FROM packages \
190 WHERE packages.name LIKE %s AND packages.type = %s \
191 ORDER BY packages.name LIMIT %s", "%%%s%%" % query
, "source", limit
)
193 return [row
.name
for row
in res
]
196 class Package(base
.DataObject
):
200 return "<%s %s>" % (self
.__class
__.__name
__, self
.friendly_name
)
202 def __eq__(self
, other
):
203 if isinstance(other
, self
.__class
__):
204 return self
.id == other
.id
206 def __lt__(self
, other
):
207 if isinstance(other
, self
.__class
__):
208 return pakfire
.util
.version_compare(self
.backend
, self
.friendly_name
, other
.friendly_name
) < 0
211 self
.db
.execute("INSERT INTO queue_delete(path) VALUES(%s)", self
.path
)
213 # Delete all files from the filelist.
214 self
.db
.execute("DELETE FROM filelists WHERE pkg_id = %s", self
.id)
216 # Delete the package.
217 self
.db
.execute("DELETE FROM packages WHERE id = %s", self
.id)
221 return self
.data
.uuid
225 return self
.data
.name
229 return self
.data
.epoch
233 return self
.data
.version
237 return self
.data
.release
241 return self
.data
.arch
245 return self
.data
.type
248 def friendly_name(self
):
249 return "%s-%s.%s" % (self
.name
, self
.friendly_version
, self
.arch
)
252 def friendly_version(self
):
253 s
= "%s-%s" % (self
.version
, self
.release
)
256 s
= "%s:%s" % (self
.epoch
, s
)
262 return self
.data
.groups
.split()
265 def maintainer(self
):
266 return self
.backend
.users
.find_maintainer(self
.data
.maintainer
) or self
.data
.maintainer
270 return self
.data
.license
278 return self
.data
.summary
281 def description(self
):
282 return self
.data
.description
285 def supported_arches(self
):
286 return self
.data
.supported_arches
290 return self
.data
.size
292 def add_dependency(self
, type, what
):
293 self
.db
.execute("INSERT INTO packages_deps(pkg_id, type, what) \
294 VALUES(%s, %s, %s)", self
.id, type, what
)
296 self
.deps
.append((type, what
))
300 Returns True if the package has got dependencies.
302 Always filter out the uuid provides.
304 return len(self
.deps
) > 1
308 res
= self
.db
.query("SELECT type, what FROM packages_deps \
309 WHERE pkg_id = %s", self
.id)
313 ret
.append((row
.type, row
.what
))
318 def prerequires(self
):
319 return [d
[1] for d
in self
.deps
if d
[0] == "prerequires"]
323 return [d
[1] for d
in self
.deps
if d
[0] == "requires"]
327 return [d
[1] for d
in self
.deps
if d
[0] == "provides" and not d
[1].startswith("uuid(")]
331 return [d
[1] for d
in self
.deps
if d
[0] == "conflicts"]
335 return [d
[1] for d
in self
.deps
if d
[0] == "obsoletes"]
339 return [d
[1] for d
in self
.deps
if d
[0] == "suggests"]
342 def recommends(self
):
343 return [d
[1] for d
in self
.deps
if d
[0] == "recommends"]
345 def get_commit(self
):
346 if self
.data
.commit_id
:
347 return self
.backend
.sources
.get_commit_by_id(self
.data
.commit_id
)
349 def set_commit(self
, commit
):
350 self
._set
_attribute
("commit_id", commit
.id)
352 commit
= lazy_property(get_commit
, set_commit
)
356 # XXX THIS CANNOT RETURN None
359 return self
.commit
.distro
363 return self
.data
.build_id
366 def build_host(self
):
367 return self
.data
.build_host
370 def build_time(self
):
371 return self
.data
.build_time
375 return self
.data
.path
378 def hash_sha512(self
):
379 return self
.data
.hash_sha512
383 return self
.data
.filesize
385 def move(self
, target_dir
):
386 # Create directory if it does not exist, yet.
387 if not os
.path
.exists(target_dir
):
388 os
.makedirs(target_dir
)
390 # Make full path where to put the file.
391 target
= os
.path
.join(target_dir
, os
.path
.basename(self
.path
))
393 # Copy the file to the target directory (keeping metadata).
394 shutil
.move(self
.path
, target
)
396 # Update file path in the database.
397 self
._set
_attribute
("path", os
.path
.relpath(target
, PACKAGES_DIR
))
402 return self
.job
.build
404 return self
.backend
.builds
._get
_build
("SELECT * FROM builds \
405 WHERE pkg_id = %s" % self
.id)
409 return self
.backend
.jobs
._get
_job
("SELECT jobs.* FROM jobs \
410 LEFT JOIN jobs_packages pkgs ON jobs.id = pkgs.job_id \
411 WHERE pkgs.pkg_id = %s", self
.id)
415 res
= self
.db
.query("SELECT * FROM filelists \
416 WHERE pkg_id = %s ORDER BY name", self
.id)
420 f
= File(self
.backend
, row
)
425 def get_file(self
, filename
):
426 res
= self
.db
.get("SELECT * FROM filelists \
427 WHERE pkg_id = %s AND name = %s", self
.id, filename
)
430 return File(self
.backend
, res
)
432 def add_file(self
, name
, size
, hash_sha512
, type, config
, mode
, user
, group
, mtime
, capabilities
):
433 # Convert mtime from seconds since epoch to datetime
434 mtime
= datetime
.datetime
.utcfromtimestamp(float(mtime
))
436 self
.db
.execute("INSERT INTO filelists(pkg_id, name, size, hash_sha512, type, config, mode, \
437 \"user\", \"group\", mtime, capabilities) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
438 self
.id, name
, size
, hash_sha512
, type, config
, mode
, user
, group
, mtime
, capabilities
)
441 path
= os
.path
.join(PACKAGES_DIR
, self
.path
)
443 if os
.path
.exists(path
):
444 return pakfire
.packages
.open(None, None, path
)
448 def update_property(self
, key
, value
):
450 self
.db
.execute("UPDATE packages_properties SET %s = %%s WHERE name = %%s" % key
, value
, self
.name
)
452 self
.db
.execute("INSERT INTO packages_properties(name, %s) VALUES(%%s, %%s)" % key
, self
.name
, value
)
455 self
.property[key
] = value
458 def properties(self
):
459 res
= self
.db
.get("SELECT * FROM packages_properties WHERE name = %s", self
.name
)
465 if key
in ("id", "name"):
473 def critical_path(self
):
474 return self
.properties
.get("critical_path", False)
477 class File(base
.Object
):
478 def init(self
, data
):
481 def __getattr__(self
, attr
):
483 return self
.data
[attr
]
485 raise AttributeError(attr
)
488 def downloadable(self
):
489 # All regular files are downloadable.
490 return self
.type == 0
494 # Empty files cannot be viewed.
498 for ext
in FILE_EXTENSIONS_VIEWABLE
:
499 if self
.name
.endswith(ext
):