]>
git.ipfire.org Git - people/jschlag/pbs.git/blob - src/buildservice/packages.py
9 import pakfire
.packages
as packages
13 from . import database
17 from .constants
import *
19 class Packages(base
.Object
):
20 def _get_package(self
, query
, *args
):
21 res
= self
.db
.get(query
, *args
)
24 return Package(self
.backend
, res
.id, data
=res
)
26 def _get_packages(self
, query
, *args
):
27 res
= self
.db
.query(query
, *args
)
30 yield Package(self
.backend
, row
.id, data
=row
)
32 def get_by_id(self
, pkg_id
):
33 return self
._get
_package
("SELECT * FROM packages \
34 WHERE id = %s", pkg_id
)
36 def get_all_names(self
, user
=None, states
=None):
37 query
= "SELECT DISTINCT packages.name AS name, summary FROM packages \
38 JOIN builds ON builds.pkg_id = packages.id \
39 WHERE packages.type = 'source'"
44 if user
and not user
.is_admin():
45 conditions
.append("builds.owner_id = %s")
50 conditions
.append("builds.state = %s")
54 query
+= " AND (%s)" % " OR ".join(conditions
)
56 query
+= " ORDER BY packages.name"
58 return [(n
.name
, n
.summary
) for n
in self
.db
.query(query
, *args
)]
60 def get_by_uuid(self
, uuid
):
61 pkg
= self
.db
.get("SELECT * FROM packages WHERE uuid = %s LIMIT 1", uuid
)
65 return Package(self
.pakfire
, pkg
.id, pkg
)
67 def create(self
, path
):
68 # Just check if the file really exist
69 assert os
.path
.exists(path
)
71 _pkg
= packages
.open(pakfire
.PakfireServer(), None, path
)
73 hash_sha512
= misc
.calc_hash(path
, "sha512")
78 ("epoch", _pkg
.epoch
),
79 ("version", _pkg
.version
),
80 ("release", _pkg
.release
),
84 ("groups", " ".join(_pkg
.groups
)),
85 ("maintainer", _pkg
.maintainer
),
86 ("license", _pkg
.license
),
88 ("summary", _pkg
.summary
),
89 ("description", _pkg
.description
),
90 ("size", _pkg
.inst_size
),
94 ("build_id", _pkg
.build_id
),
95 ("build_host", _pkg
.build_host
),
96 ("build_time", datetime
.datetime
.utcfromtimestamp(_pkg
.build_time
)),
100 ("filesize", os
.path
.getsize(path
)),
101 ("hash_sha512", hash_sha512
),
104 if _pkg
.type == "source":
105 query
.append(("supported_arches", _pkg
.supported_arches
))
109 for key
, val
in query
:
113 _query
= "INSERT INTO packages(%s)" % ", ".join(keys
)
114 _query
+= " VALUES(%s) RETURNING *" % ", ".join("%s" for v
in vals
)
116 # Create package entry in the database.
117 pkg
= self
._get
_package
(_query
, *vals
)
119 # Dependency information.
120 for d
in _pkg
.prerequires
:
121 pkg
.add_dependency("prerequires", d
)
123 for d
in _pkg
.requires
:
124 pkg
.add_dependency("requires", d
)
126 for d
in _pkg
.provides
:
127 pkg
.add_dependency("provides", d
)
129 for d
in _pkg
.conflicts
:
130 pkg
.add_dependency("conflicts", d
)
132 for d
in _pkg
.obsoletes
:
133 pkg
.add_dependency("obsoletes", d
)
135 # Add all files to filelists table
136 for f
in _pkg
.filelist
:
137 pkg
.add_file(f
.name
, f
.size
, f
.hash1
, f
.type, f
.config
, f
.mode
,
138 f
.user
, f
.group
, f
.mtime
, f
.capabilities
)
140 # Return the newly created object
143 def search(self
, pattern
, limit
=None):
145 Searches for packages that do match the query.
147 This function does not work for UUIDs or filenames.
149 query
= "SELECT * FROM packages \
150 WHERE type = %s AND ( \
153 description LIKE %s \
157 pattern
= "%%%s%%" % pattern
158 args
= ("source", pattern
, pattern
, pattern
)
160 res
= self
.db
.query(query
, *args
)
164 pkg
= Package(self
.pakfire
, row
.id, row
)
167 if limit
and len(pkgs
) >= limit
:
172 def search_by_filename(self
, filename
, limit
=None):
173 query
= "SELECT filelists.* FROM filelists \
174 JOIN packages ON filelists.pkg_id = packages.id \
175 WHERE filelists.name = %s ORDER BY packages.build_time DESC"
183 for result
in self
.db
.query(query
, *args
):
184 pkg
= Package(self
.pakfire
, result
.pkg_id
)
185 files
.append((pkg
, result
))
189 def autocomplete(self
, query
, limit
=8):
190 res
= self
.db
.query("SELECT DISTINCT name FROM packages \
191 WHERE packages.name LIKE %s AND packages.type = %s \
192 ORDER BY packages.name LIMIT %s", "%%%s%%" % query
, "source", limit
)
194 return [row
.name
for row
in res
]
197 class Package(base
.Object
):
198 def __init__(self
, pakfire
, id, data
=None):
199 base
.Object
.__init
__(self
, pakfire
)
201 # The ID of the package.
207 self
._filelist
= None
210 self
._properties
= None
211 self
._maintainer
= None
214 return "<%s %s>" % (self
.__class
__.__name
__, self
.friendly_name
)
216 def __cmp__(self
, other
):
217 return pakfire
.util
.version_compare(self
.pakfire
,
218 self
.friendly_name
, other
.friendly_name
)
221 self
.db
.execute("INSERT INTO queue_delete(path) VALUES(%s)", self
.path
)
223 # Delete all files from the filelist.
224 self
.db
.execute("DELETE FROM filelists WHERE pkg_id = %s", self
.id)
226 # Delete the package.
227 self
.db
.execute("DELETE FROM packages WHERE id = %s", self
.id)
229 # Remove cached data.
234 if self
._data
is None:
236 self
.db
.get("SELECT * FROM packages WHERE id = %s", self
.id)
237 assert self
._data
, "Cannot fetch package %s: %s" % (self
.id, self
._data
)
243 return self
.data
.uuid
247 return self
.data
.name
251 return self
.data
.epoch
255 return self
.data
.version
259 return self
.data
.release
263 return self
.data
.arch
267 return self
.data
.type
270 def friendly_name(self
):
271 return "%s-%s.%s" % (self
.name
, self
.friendly_version
, self
.arch
)
274 def friendly_version(self
):
275 s
= "%s-%s" % (self
.version
, self
.release
)
278 s
= "%d:%s" % (self
.epoch
, s
)
284 return self
.data
.groups
.split()
287 def maintainer(self
):
288 if self
._maintainer
is None:
289 self
._maintainer
= self
.data
.maintainer
291 # Search if there is a user account for this person.
292 user
= self
.pakfire
.users
.find_maintainer(self
._maintainer
)
294 self
._maintainer
= user
296 return self
._maintainer
300 return self
.data
.license
308 return self
.data
.summary
311 def description(self
):
312 return self
.data
.description
315 def supported_arches(self
):
316 return self
.data
.supported_arches
320 return self
.data
.size
322 def add_dependency(self
, type, what
):
323 self
.db
.execute("INSERT INTO packages_deps(pkg_id, type, what) \
324 VALUES(%s, %s, %s)", self
.id, type, what
)
328 Returns True if the package has got dependencies.
330 Always filter out the uuid provides.
332 return len(self
.deps
) > 1
336 if self
._deps
is None:
337 query
= self
.db
.query("SELECT type, what FROM packages_deps WHERE pkg_id = %s", self
.id)
341 self
._deps
.append((row
.type, row
.what
))
346 def prerequires(self
):
347 return [d
[1] for d
in self
.deps
if d
[0] == "prerequires"]
351 return [d
[1] for d
in self
.deps
if d
[0] == "requires"]
355 return [d
[1] for d
in self
.deps
if d
[0] == "provides" and not d
[1].startswith("uuid(")]
359 return [d
[1] for d
in self
.deps
if d
[0] == "conflicts"]
363 return [d
[1] for d
in self
.deps
if d
[0] == "obsoletes"]
367 return [d
[1] for d
in self
.deps
if d
[0] == "suggests"]
370 def recommends(self
):
371 return [d
[1] for d
in self
.deps
if d
[0] == "recommends"]
375 return self
.data
.commit_id
377 def get_commit(self
):
378 if not self
.commit_id
:
381 if self
._commit
is None:
382 self
._commit
= sources
.Commit(self
.pakfire
, self
.commit_id
)
386 def set_commit(self
, commit
):
387 self
.db
.execute("UPDATE packages SET commit_id = %s WHERE id = %s",
389 self
._commit
= commit
391 commit
= property(get_commit
, set_commit
)
398 # XXX THIS CANNOT RETURN None
400 return self
.commit
.distro
404 return self
.data
.build_id
407 def build_host(self
):
408 return self
.data
.build_host
411 def build_time(self
):
412 return self
.data
.build_time
416 return self
.data
.path
419 def hash_sha512(self
):
420 return self
.data
.hash_sha512
424 return self
.data
.filesize
426 def move(self
, target_dir
):
427 # Create directory if it does not exist, yet.
428 if not os
.path
.exists(target_dir
):
429 os
.makedirs(target_dir
)
431 # Make full path where to put the file.
432 target
= os
.path
.join(target_dir
, os
.path
.basename(self
.path
))
434 # Copy the file to the target directory (keeping metadata).
435 shutil
.move(self
.path
, target
)
437 # Update file path in the database.
438 self
.db
.execute("UPDATE packages SET path = %s WHERE id = %s",
439 os
.path
.relpath(target
, PACKAGES_DIR
), self
.id)
440 self
._data
["path"] = target
445 return self
.job
.build
447 build
= self
.db
.get("SELECT id FROM builds \
448 WHERE type = 'release' AND pkg_id = %s", self
.id)
451 return self
.pakfire
.builds
.get_by_id(build
.id)
455 if self
._job
is None:
456 job
= self
.db
.get("SELECT job_id AS id FROM jobs_packages \
457 WHERE pkg_id = %s", self
.id)
460 self
._job
= self
.pakfire
.jobs
.get_by_id(job
.id)
466 if self
._filelist
is None:
469 for f
in self
.db
.query("SELECT * FROM filelists WHERE pkg_id = %s ORDER BY name", self
.id):
470 f
= File(self
.pakfire
, f
)
471 self
._filelist
.append(f
)
473 return self
._filelist
475 def add_file(self
, name
, size
, hash_sha512
, type, config
, mode
, user
, group
, mtime
, capabilities
):
476 # Convert mtime from seconds since epoch to datetime
477 mtime
= datetime
.datetime
.utcfromtimestamp(float(mtime
))
479 self
.db
.execute("INSERT INTO filelists(pkg_id, name, size, hash_sha512, type, config, mode, \
480 \"user\", \"group\", mtime, capabilities) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
481 self
.id, name
, size
, hash_sha512
, type, config
, mode
, user
, group
, mtime
, capabilities
)
484 path
= os
.path
.join(PACKAGES_DIR
, self
.path
)
486 if os
.path
.exists(path
):
487 return pakfire
.packages
.open(None, None, path
)
491 _default_properties
= {
492 "critical_path" : False,
496 def update_property(self
, key
, value
):
497 assert self
._default
_properties
.has_key(key
), "Unknown key: %s" % key
499 #print self.db.execute("UPDATE packages_properties SET
502 def properties(self
):
503 if self
._properties
is None:
505 self
.db
.get("SELECT * FROM packages_properties WHERE name = %s", self
.name
)
507 if not self
._properties
:
508 self
._properties
= database
.Row(self
._default
_properties
)
510 return self
._properties
513 def critical_path(self
):
514 return self
.properties
.get("critical_path", "N") == "Y"
517 class File(base
.Object
):
518 def __init__(self
, pakfire
, data
):
519 base
.Object
.__init
__(self
, pakfire
)
523 def __getattr__(self
, attr
):
525 return self
.data
[attr
]
527 raise AttributeError, attr
530 def downloadable(self
):
531 # All regular files are downloadable.
532 return self
.type == 0
536 # Empty files cannot be viewed.
540 for ext
in FILE_EXTENSIONS_VIEWABLE
:
541 if self
.name
.endswith(ext
):