]>
Commit | Line | Data |
---|---|---|
47a4cb89 | 1 | #!/usr/bin/python |
b792d887 MT |
2 | ############################################################################### |
3 | # # | |
4 | # Pakfire - The IPFire package management system # | |
5 | # Copyright (C) 2011 Pakfire development team # | |
6 | # # | |
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. # | |
11 | # # | |
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. # | |
16 | # # | |
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/>. # | |
19 | # # | |
20 | ############################################################################### | |
47a4cb89 MT |
21 | |
22 | import logging | |
23 | import os | |
5cc35aa4 | 24 | import random |
2568a6d1 | 25 | import shutil |
47a4cb89 | 26 | import sqlite3 |
66af936c | 27 | import time |
47a4cb89 | 28 | |
c605d735 MT |
29 | import pakfire.packages as packages |
30 | ||
a2d1644c | 31 | from pakfire.constants import * |
66af936c | 32 | |
b6da0663 MT |
33 | class Cursor(sqlite3.Cursor): |
34 | def execute(self, *args, **kwargs): | |
35 | # For debugging of SQL queries. | |
36 | #print args, kwargs | |
37 | ||
38 | return sqlite3.Cursor.execute(self, *args, **kwargs) | |
39 | ||
40 | ||
47a4cb89 | 41 | class Database(object): |
3723913b MT |
42 | def __init__(self, pakfire, filename): |
43 | self.pakfire = pakfire | |
5cc35aa4 MT |
44 | self.filename = filename |
45 | ||
c605d735 | 46 | self._db = None |
47a4cb89 MT |
47 | |
48 | def __del__(self): | |
49 | if self._db: | |
47a4cb89 | 50 | self._db.close() |
c605d735 | 51 | self._db = None |
47a4cb89 MT |
52 | |
53 | def create(self): | |
54 | pass | |
55 | ||
56 | def open(self): | |
c605d735 | 57 | if self._db is None: |
47a4cb89 MT |
58 | logging.debug("Open database %s" % self.filename) |
59 | ||
5cc35aa4 MT |
60 | dirname = os.path.dirname(self.filename) |
61 | if not os.path.exists(dirname): | |
62 | os.makedirs(dirname) | |
47a4cb89 | 63 | |
5cc35aa4 | 64 | database_exists = os.path.exists(self.filename) |
47a4cb89 MT |
65 | |
66 | # Make a connection to the database. | |
67 | self._db = sqlite3.connect(self.filename) | |
68 | self._db.row_factory = sqlite3.Row | |
69 | ||
70 | # Create the database if it was not there, yet. | |
71 | if not database_exists: | |
72 | self.create() | |
73 | ||
74 | def close(self): | |
c605d735 | 75 | self.__del__() |
5cc35aa4 | 76 | |
47a4cb89 | 77 | def commit(self): |
c605d735 | 78 | self.open() |
47a4cb89 MT |
79 | self._db.commit() |
80 | ||
81 | def cursor(self): | |
c605d735 | 82 | self.open() |
b6da0663 | 83 | return self._db.cursor(Cursor) |
47a4cb89 | 84 | |
a2d1644c | 85 | def executescript(self, *args, **kwargs): |
c605d735 | 86 | self.open() |
a2d1644c MT |
87 | return self._db.executescript(*args, **kwargs) |
88 | ||
2568a6d1 | 89 | |
c605d735 MT |
90 | class DatabaseLocal(Database): |
91 | def __init__(self, pakfire, repo): | |
92 | self.repo = repo | |
2568a6d1 | 93 | |
c605d735 MT |
94 | # Generate filename for package database |
95 | filename = os.path.join(pakfire.path, PACKAGES_DB) | |
96 | ||
97 | Database.__init__(self, pakfire, filename) | |
98 | ||
99 | def __len__(self): | |
100 | count = 0 | |
47a4cb89 | 101 | |
47a4cb89 | 102 | c = self.cursor() |
c605d735 MT |
103 | c.execute("SELECT COUNT(*) AS count FROM packages") |
104 | for row in c: | |
105 | count = row["count"] | |
106 | c.close() | |
47a4cb89 | 107 | |
c605d735 MT |
108 | return count |
109 | ||
110 | def create(self): | |
111 | c = self.cursor() | |
47a4cb89 | 112 | c.executescript(""" |
c605d735 MT |
113 | CREATE TABLE settings( |
114 | key TEXT, | |
115 | val TEXT | |
116 | ); | |
117 | INSERT INTO settings(key, val) VALUES('version', '0'); | |
118 | ||
47a4cb89 MT |
119 | CREATE TABLE files( |
120 | name TEXT, | |
121 | pkg INTEGER, | |
122 | size INTEGER, | |
123 | type INTEGER, | |
66af936c | 124 | hash1 TEXT |
47a4cb89 MT |
125 | ); |
126 | ||
127 | CREATE TABLE packages( | |
128 | id INTEGER PRIMARY KEY, | |
129 | name TEXT, | |
130 | epoch INTEGER, | |
131 | version TEXT, | |
132 | release TEXT, | |
c560c27a | 133 | arch TEXT, |
8537c16d | 134 | groups TEXT, |
fa6d335b | 135 | filename TEXT, |
ba8c383d | 136 | size INTEGER, |
47a4cb89 MT |
137 | hash1 TEXT, |
138 | provides TEXT, | |
139 | requires TEXT, | |
140 | conflicts TEXT, | |
141 | obsoletes TEXT, | |
142 | license TEXT, | |
143 | summary TEXT, | |
144 | description TEXT, | |
1317485d | 145 | uuid TEXT, |
47a4cb89 MT |
146 | build_id TEXT, |
147 | build_host TEXT, | |
0c665250 | 148 | build_date TEXT, |
c605d735 MT |
149 | build_time INTEGER, |
150 | installed INT, | |
151 | reason TEXT, | |
152 | repository TEXT, | |
153 | scriptlet TEXT, | |
154 | triggers TEXT | |
47a4cb89 MT |
155 | ); |
156 | """) | |
157 | # XXX add some indexes here | |
47a4cb89 MT |
158 | self.commit() |
159 | c.close() | |
160 | ||
66af936c | 161 | def add_package(self, pkg, reason=None): |
fa6d335b MT |
162 | logging.debug("Adding package to database: %s" % pkg.friendly_name) |
163 | ||
164 | c = self.cursor() | |
fa6d335b | 165 | |
c605d735 MT |
166 | try: |
167 | c.execute(""" | |
168 | INSERT INTO packages( | |
169 | name, | |
170 | epoch, | |
171 | version, | |
172 | release, | |
173 | arch, | |
174 | groups, | |
175 | filename, | |
176 | size, | |
177 | hash1, | |
178 | provides, | |
179 | requires, | |
180 | conflicts, | |
181 | obsoletes, | |
182 | license, | |
183 | summary, | |
184 | description, | |
185 | uuid, | |
186 | build_id, | |
187 | build_host, | |
188 | build_date, | |
189 | build_time, | |
190 | installed, | |
191 | repository, | |
192 | reason, | |
193 | scriptlet, | |
194 | triggers | |
195 | ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", | |
196 | ( | |
197 | pkg.name, | |
198 | pkg.epoch, | |
199 | pkg.version, | |
200 | pkg.release, | |
201 | pkg.arch, | |
202 | " ".join(pkg.groups), | |
203 | pkg.filename, | |
204 | pkg.size, | |
205 | pkg.hash1, | |
206 | " ".join(pkg.provides), | |
207 | " ".join(pkg.requires), | |
208 | " ".join(pkg.conflicts), | |
209 | " ".join(pkg.obsoletes), | |
210 | pkg.license, | |
211 | pkg.summary, | |
212 | pkg.description, | |
213 | pkg.uuid, | |
214 | pkg.build_id, | |
215 | pkg.build_host, | |
216 | pkg.build_date, | |
217 | pkg.build_time, | |
218 | time.time(), | |
219 | pkg.repo.name, | |
220 | reason or "", | |
221 | pkg.scriptlet, | |
222 | " ".join(pkg.triggers) | |
223 | ) | |
224 | ) | |
66af936c | 225 | |
c605d735 | 226 | pkg_id = c.lastrowid |
66af936c | 227 | |
c605d735 MT |
228 | c.executemany("INSERT INTO files(name, pkg) VALUES(?, ?)", |
229 | ((file, pkg_id) for file in pkg.filelist)) | |
66af936c | 230 | |
c605d735 MT |
231 | except: |
232 | raise | |
66af936c | 233 | |
c605d735 MT |
234 | else: |
235 | self.commit() | |
66af936c | 236 | |
66af936c | 237 | c.close() |
fa6d335b | 238 | |
e871a081 MT |
239 | def rem_package(self, pkg): |
240 | logging.debug("Removing package from database: %s" % pkg.friendly_name) | |
241 | ||
242 | assert pkg.uuid | |
243 | ||
244 | # Get the ID of the package in the database. | |
245 | c = self.cursor() | |
246 | c.execute("SELECT id FROM packages WHERE uuid = ? LIMIT 1", (pkg.uuid,)) | |
247 | ||
248 | id = None | |
249 | for row in c: | |
250 | id = row["id"] | |
251 | break | |
252 | assert id | |
253 | ||
254 | # First, delete all files from the database and then delete the pkg itself. | |
255 | c.execute("DELETE FROM files WHERE pkg = ?", (id,)) | |
256 | c.execute("DELETE FROM packages WHERE id = ?", (id,)) | |
257 | ||
258 | c.close() | |
259 | self.commit() | |
260 | ||
c605d735 MT |
261 | @property |
262 | def packages(self): | |
47a4cb89 MT |
263 | c = self.cursor() |
264 | ||
c605d735 | 265 | c.execute("SELECT * FROM packages ORDER BY name") |
47a4cb89 | 266 | |
c605d735 MT |
267 | for row in c: |
268 | yield packages.DatabasePackage(self.pakfire, self.repo, self, row) | |
47a4cb89 | 269 | |
66af936c | 270 | c.close() |
6ee3d6b9 MT |
271 | |
272 | def get_package_from_solv(self, solv_pkg): | |
273 | c = self.cursor() | |
274 | c.execute("SELECT * FROM packages WHERE uuid = ? LIMIT 1", (solv_pkg.uuid,)) | |
275 | ||
276 | try: | |
277 | for row in c: | |
278 | return packages.DatabasePackage(self.pakfire, self.repo, self, row) | |
279 | ||
280 | finally: | |
281 | c.close() |