2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
29 import pakfire
.packages
as packages
31 from pakfire
.constants
import *
32 from pakfire
.i18n
import _
34 class Cursor(sqlite3
.Cursor
):
35 def execute(self
, *args
, **kwargs
):
36 # For debugging of SQL queries.
39 return sqlite3
.Cursor
.execute(self
, *args
, **kwargs
)
42 class Database(object):
43 def __init__(self
, pakfire
, filename
):
44 self
.pakfire
= pakfire
45 self
.filename
= filename
62 logging
.debug("Open database %s" % self
.filename
)
64 dirname
= os
.path
.dirname(self
.filename
)
65 if not os
.path
.exists(dirname
):
68 database_exists
= os
.path
.exists(self
.filename
)
70 # Make a connection to the database.
71 self
._db
= sqlite3
.connect(self
.filename
)
72 self
._db
.row_factory
= sqlite3
.Row
74 # In the case, the database was not existant, it is
75 # filled with content. In case it has been there
76 # we call the migrate method to update it if neccessary.
91 return self
._db
.cursor(Cursor
)
93 def executescript(self
, *args
, **kwargs
):
95 return self
._db
.executescript(*args
, **kwargs
)
98 class DatabaseLocal(Database
):
99 def __init__(self
, pakfire
, repo
):
102 # Generate filename for package database
103 filename
= os
.path
.join(pakfire
.path
, PACKAGES_DB
)
105 # Cache format number.
108 Database
.__init
__(self
, pakfire
, filename
)
110 # Check if we actually can open the database.
111 if not self
.format
in DATABASE_FORMATS_SUPPORTED
:
112 raise DatabaseFormatError
, _("The format of the database is not supported by this version of pakfire.")
118 c
.execute("SELECT COUNT(*) AS count FROM packages")
127 if self
.__format
is None:
130 c
.execute("SELECT val FROM settings WHERE key = 'version' LIMIT 1")
133 self
.__format
= int(row
["val"])
145 CREATE TABLE settings(
149 INSERT INTO settings(key, val) VALUES('version', '%s');
152 id INTEGER PRIMARY KEY,
166 CREATE TABLE packages(
167 id INTEGER PRIMARY KEY,
195 CREATE TABLE scriptlets(
196 id INTEGER PRIMARY KEY,
202 CREATE TABLE triggers(
203 id INTEGER PRIMARY KEY,
208 """ % DATABASE_FORMAT
)
209 # XXX add some indexes here
214 # If we have already the latest version, there is nothing to do.
215 if self
.format
== DATABASE_FORMAT
:
218 # Check if database version is supported.
219 if self
.format
> DATABASE_FORMAT
:
220 raise DatabaseError
, _("Cannot use database with version greater than %s.") % DATABASE_FORMAT
222 logging
.info(_("Migrating database from format %s to %s.") % (self
.format
, DATABASE_FORMAT
))
224 # Get a database cursor.
227 # 1) The vendor column was added.
229 c
.execute("ALTER TABLE packages ADD COLUMN vendor TEXT AFTER uuid")
232 c
.execute("ALTER TABLE files ADD COLUMN `config` INTEGER")
233 c
.execute("ALTER TABLE files ADD COLUMN `mode` INTEGER")
234 c
.execute("ALTER TABLE files ADD COLUMN `user` TEXT")
235 c
.execute("ALTER TABLE files ADD COLUMN `group` TEXT")
236 c
.execute("ALTER TABLE files ADD COLUMN `mtime` INTEGER")
239 c
.execute("ALTER TABLE files ADD COLUMN `capabilities` TEXT")
241 # In the end, we can easily update the version of the database.
242 c
.execute("UPDATE settings SET val = ? WHERE key = 'version'", (DATABASE_FORMAT
,))
243 self
.__format
= DATABASE_FORMAT
248 def add_package(self
, pkg
, reason
=None):
249 logging
.debug("Adding package to database: %s" % pkg
.friendly_name
)
255 INSERT INTO packages(
281 ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
288 " ".join(pkg
.groups
),
292 " ".join(pkg
.provides
),
293 " ".join(pkg
.requires
),
294 " ".join(pkg
.conflicts
),
295 " ".join(pkg
.obsoletes
),
313 c
.executemany("INSERT INTO files(`name`, `pkg`, `size`, `config`, `type`, `hash1`, `mode`, `user`, `group`, `mtime`, `capabilities`)"
314 " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
315 ((f
.name
, pkg_id
, f
.size
, f
.is_config(), f
.type, f
.hash1
, f
.mode
, f
.user
, f
.group
, f
.mtime
, f
.capabilities
or "") for f
in pkg
.filelist
))
325 def rem_package(self
, pkg
):
326 logging
.debug("Removing package from database: %s" % pkg
.friendly_name
)
330 # Get the ID of the package in the database.
332 #c.execute("SELECT id FROM packages WHERE uuid = ? LIMIT 1", (pkg.uuid,))
333 c
.execute("SELECT id FROM packages WHERE name = ? AND epoch = ? AND version = ?"
334 " AND release = ? LIMIT 1", (pkg
.name
, pkg
.epoch
, pkg
.version
, pkg
.release
,))
342 # First, delete all files from the database and then delete the pkg itself.
343 c
.execute("DELETE FROM files WHERE pkg = ?", (id,))
344 c
.execute("DELETE FROM packages WHERE id = ?", (id,))
349 def get_package_by_id(self
, id):
351 c
.execute("SELECT * FROM packages WHERE id = ?", (id,))
355 return packages
.DatabasePackage(self
.pakfire
, self
.repo
, self
, row
)
364 c
.execute("SELECT * FROM packages ORDER BY name")
367 yield packages
.DatabasePackage(self
.pakfire
, self
.repo
, self
, row
)
371 def get_package_from_solv(self
, solv_pkg
):
373 c
.execute("SELECT * FROM packages WHERE uuid = ? LIMIT 1", (solv_pkg
.uuid
,))
377 return packages
.DatabasePackage(self
.pakfire
, self
.repo
, self
, row
)