]>
git.ipfire.org Git - people/jschlag/pbs.git/blob - src/buildservice/packages.py
9 import pakfire
.packages
as packages
18 from constants
import *
20 class Packages(base
.Object
):
21 def get_all_names(self
, public
=None, user
=None, states
=None):
22 query
= "SELECT DISTINCT name, summary FROM packages \
23 JOIN builds ON builds.pkg_id = packages.id \
24 WHERE packages.type = 'source'"
29 if public
in (True, False):
35 conditions
.append("builds.public = %s")
38 if user
and not user
.is_admin():
39 conditions
.append("builds.owner_id = %s")
44 conditions
.append("builds.state = %s")
48 query
+= " AND (%s)" % " OR ".join(conditions
)
50 query
+= " ORDER BY packages.name"
52 return [(n
.name
, n
.summary
) for n
in self
.db
.query(query
, *args
)]
54 def get_by_uuid(self
, uuid
):
55 pkg
= self
.db
.get("SELECT * FROM packages WHERE uuid = %s LIMIT 1", uuid
)
59 return Package(self
.pakfire
, pkg
.id, pkg
)
61 def search(self
, pattern
, limit
=None):
63 Searches for packages that do match the query.
65 This function does not work for UUIDs or filenames.
67 query
= "SELECT * FROM packages \
68 WHERE type = %s AND ( \
75 pattern
= "%%%s%%" % pattern
76 args
= ("source", pattern
, pattern
, pattern
)
78 res
= self
.db
.query(query
, *args
)
82 pkg
= Package(self
.pakfire
, row
.id, row
)
85 if limit
and len(pkgs
) >= limit
:
90 def search_by_filename(self
, filename
, limit
=None):
91 query
= "SELECT filelists.* FROM filelists \
92 JOIN packages ON filelists.pkg_id = packages.id \
93 WHERE filelists.name = %s ORDER BY packages.build_time DESC"
101 for result
in self
.db
.query(query
, *args
):
102 pkg
= Package(self
.pakfire
, result
.pkg_id
)
103 files
.append((pkg
, result
))
107 def autocomplete(self
, query
, limit
=8):
108 res
= self
.db
.query("SELECT DISTINCT name FROM packages \
109 WHERE packages.name LIKE %s AND packages.type = %s \
110 ORDER BY packages.name LIMIT %s", "%%%s%%" % query
, "source", limit
)
112 return [row
.name
for row
in res
]
115 class Package(base
.Object
):
116 def __init__(self
, pakfire
, id, data
=None):
117 base
.Object
.__init
__(self
, pakfire
)
119 # The ID of the package.
126 self
._filelist
= None
129 self
._properties
= None
130 self
._maintainer
= None
133 return "<%s %s>" % (self
.__class
__.__name
__, self
.friendly_name
)
135 def __cmp__(self
, other
):
136 return pakfire
.util
.version_compare(self
.pakfire
,
137 self
.friendly_name
, other
.friendly_name
)
140 def open(cls
, _pakfire
, path
):
141 # Just check if the file really does exist.
142 assert os
.path
.exists(path
)
144 p
= pakfire
.PakfireServer()
145 file = packages
.open(p
, None, path
)
147 # Get architecture from the database.
148 arch
= _pakfire
.arches
.get_by_name(file.arch
)
149 assert arch
, "Unknown architecture: %s" % file.arch
151 hash_sha512
= misc
.calc_hash(path
, "sha512")
156 ("epoch", file.epoch
),
157 ("version", file.version
),
158 ("release", file.release
),
162 ("groups", " ".join(file.groups
)),
163 ("maintainer", file.maintainer
),
164 ("license", file.license
),
166 ("summary", file.summary
),
167 ("description", file.description
),
168 ("size", file.inst_size
),
172 ("build_id", file.build_id
),
173 ("build_host", file.build_host
),
174 ("build_time", datetime
.datetime
.utcfromtimestamp(file.build_time
)),
178 ("filesize", os
.path
.getsize(path
)),
179 ("hash_sha512", hash_sha512
),
182 if file.type == "source":
183 query
.append(("supported_arches", file.supported_arches
))
187 for key
, val
in query
:
188 keys
.append("`%s`" % key
)
191 _query
= "INSERT INTO packages(%s)" % ", ".join(keys
)
192 _query
+= " VALUES(%s)" % ", ".join("%s" for v
in vals
)
194 # Create package entry in the database.
195 id = _pakfire
.db
.execute(_query
, *vals
)
197 # Dependency information.
199 for d
in file.prerequires
:
200 deps
.append((id, "prerequires", d
))
202 for d
in file.requires
:
203 deps
.append((id, "requires", d
))
205 for d
in file.provides
:
206 deps
.append((id, "provides", d
))
208 for d
in file.conflicts
:
209 deps
.append((id, "conflicts", d
))
211 for d
in file.obsoletes
:
212 deps
.append((id, "obsoletes", d
))
215 _pakfire
.db
.executemany("INSERT INTO packages_deps(pkg_id, type, what) \
216 VALUES(%s, %s, %s)", deps
)
218 # Add all files to filelists table.
220 for f
in file.filelist
:
226 # Convert mtime to integer.
232 filelist
.append((id, f
.name
, f
.size
, f
.hash1
, f
.type, config
, f
.mode
,
233 f
.user
, f
.group
, datetime
.datetime
.utcfromtimestamp(mtime
),
236 _pakfire
.db
.executemany("INSERT INTO filelists(pkg_id, name, size, hash_sha512, \
237 type, config, mode, user, `group`, mtime, capabilities) \
238 VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", filelist
)
240 # Return the newly created object.
241 return cls(_pakfire
, id)
244 self
.db
.execute("INSERT INTO queue_delete(path) VALUES(%s)", self
.path
)
246 # Delete all files from the filelist.
247 self
.db
.execute("DELETE FROM filelists WHERE pkg_id = %s", self
.id)
249 # Delete the package.
250 self
.db
.execute("DELETE FROM packages WHERE id = %s", self
.id)
252 # Remove cached data.
257 if self
._data
is None:
259 self
.db
.get("SELECT * FROM packages WHERE id = %s", self
.id)
260 assert self
._data
, "Cannot fetch package %s: %s" % (self
.id, self
._data
)
266 return self
.data
.uuid
270 return self
.data
.name
274 return self
.data
.epoch
278 return self
.data
.version
282 return self
.data
.release
286 if self
._arch
is None:
287 self
._arch
= self
.pakfire
.arches
.get_by_id(self
.data
.arch
)
294 return self
.data
.type
297 def friendly_name(self
):
298 return "%s-%s.%s" % (self
.name
, self
.friendly_version
, self
.arch
.name
)
301 def friendly_version(self
):
302 s
= "%s-%s" % (self
.version
, self
.release
)
305 s
= "%d:%s" % (self
.epoch
, s
)
311 return self
.data
.groups
.split()
314 def maintainer(self
):
315 if self
._maintainer
is None:
316 self
._maintainer
= self
.data
.maintainer
318 # Search if there is a user account for this person.
319 user
= self
.pakfire
.users
.find_maintainer(self
._maintainer
)
321 self
._maintainer
= user
323 return self
._maintainer
327 return self
.data
.license
335 return self
.data
.summary
338 def description(self
):
339 return self
.data
.description
342 def supported_arches(self
):
343 return self
.data
.supported_arches
347 return self
.data
.size
351 Returns True if the package has got dependencies.
353 Always filter out the uuid provides.
355 return len(self
.deps
) > 1
359 if self
._deps
is None:
360 query
= self
.db
.query("SELECT type, what FROM packages_deps WHERE pkg_id = %s", self
.id)
364 self
._deps
.append((row
.type, row
.what
))
369 def prerequires(self
):
370 return [d
[1] for d
in self
.deps
if d
[0] == "prerequires"]
374 return [d
[1] for d
in self
.deps
if d
[0] == "requires"]
378 return [d
[1] for d
in self
.deps
if d
[0] == "provides" and not d
[1].startswith("uuid(")]
382 return [d
[1] for d
in self
.deps
if d
[0] == "conflicts"]
386 return [d
[1] for d
in self
.deps
if d
[0] == "obsoletes"]
390 return [d
[1] for d
in self
.deps
if d
[0] == "suggests"]
393 def recommends(self
):
394 return [d
[1] for d
in self
.deps
if d
[0] == "recommends"]
398 return self
.data
.commit_id
400 def get_commit(self
):
401 if not self
.commit_id
:
404 if self
._commit
is None:
405 self
._commit
= sources
.Commit(self
.pakfire
, self
.commit_id
)
409 def set_commit(self
, commit
):
410 self
.db
.execute("UPDATE packages SET commit_id = %s WHERE id = %s",
412 self
._commit
= commit
414 commit
= property(get_commit
, set_commit
)
421 # XXX THIS CANNOT RETURN None
423 return self
.commit
.distro
427 return self
.data
.build_id
430 def build_host(self
):
431 return self
.data
.build_host
434 def build_time(self
):
435 return self
.data
.build_time
439 return self
.data
.path
442 def hash_sha512(self
):
443 return self
.data
.hash_sha512
447 return self
.data
.filesize
449 def move(self
, target_dir
):
450 # Create directory if it does not exist, yet.
451 if not os
.path
.exists(target_dir
):
452 os
.makedirs(target_dir
)
454 # Make full path where to put the file.
455 target
= os
.path
.join(target_dir
, os
.path
.basename(self
.path
))
457 # Copy the file to the target directory (keeping metadata).
458 shutil
.move(self
.path
, target
)
460 # Update file path in the database.
461 self
.db
.execute("UPDATE packages SET path = %s WHERE id = %s",
462 os
.path
.relpath(target
, PACKAGES_DIR
), self
.id)
463 self
._data
["path"] = target
468 return self
.job
.build
470 build
= self
.db
.get("SELECT id FROM builds \
471 WHERE type = 'release' AND pkg_id = %s", self
.id)
474 return builds
.Build(self
.pakfire
, build
.id)
478 if self
._job
is None:
479 job
= self
.db
.get("SELECT job_id AS id FROM jobs_packages \
480 WHERE pkg_id = %s", self
.id)
483 self
._job
= builds
.Job(self
.pakfire
, job
.id)
489 if self
._filelist
is None:
492 for f
in self
.db
.query("SELECT * FROM filelists WHERE pkg_id = %s ORDER BY name", self
.id):
493 f
= File(self
.pakfire
, f
)
494 self
._filelist
.append(f
)
496 return self
._filelist
499 path
= os
.path
.join(PACKAGES_DIR
, self
.path
)
501 if os
.path
.exists(path
):
502 return pakfire
.packages
.open(None, None, path
)
506 _default_properties
= {
507 "critical_path" : False,
511 def update_property(self
, key
, value
):
512 assert self
._default
_properties
.has_key(key
), "Unknown key: %s" % key
514 #print self.db.execute("UPDATE packages_properties SET
517 def properties(self
):
518 if self
._properties
is None:
520 self
.db
.get("SELECT * FROM packages_properties WHERE name = %s", self
.name
)
522 if not self
._properties
:
523 self
._properties
= database
.Row(self
._default
_properties
)
525 return self
._properties
528 def critical_path(self
):
529 return self
.properties
.get("critical_path", "N") == "Y"
532 class File(base
.Object
):
533 def __init__(self
, pakfire
, data
):
534 base
.Object
.__init
__(self
, pakfire
)
538 def __getattr__(self
, attr
):
540 return self
.data
[attr
]
542 raise AttributeError, attr
545 def downloadable(self
):
546 # All regular files are downloadable.
547 return self
.type == 0
551 # Empty files cannot be viewed.
555 for ext
in FILE_EXTENSIONS_VIEWABLE
:
556 if self
.name
.endswith(ext
):