]>
Commit | Line | Data |
---|---|---|
9137135a MT |
1 | #!/usr/bin/python |
2 | ||
3 | import datetime | |
4 | import logging | |
5 | import os | |
13b9276e MT |
6 | import pakfire |
7 | import pakfire.config | |
8 | import shutil | |
9137135a | 9 | import subprocess |
13b9276e | 10 | import tempfile |
9137135a | 11 | |
2c909128 | 12 | from . import base |
7ad79344 | 13 | from . import git |
9137135a | 14 | |
29e226fc | 15 | from .constants import * |
78366294 MT |
16 | from .decorators import * |
17 | ||
9137135a | 18 | class Sources(base.Object): |
78366294 MT |
19 | def _get_source(self, query, *args): |
20 | res = self.db.get(query, *args) | |
21 | ||
22 | if res: | |
23 | return Source(self.backend, res.id, data=res) | |
24 | ||
25 | def _get_sources(self, query, *args): | |
26 | res = self.db.query(query, *args) | |
27 | ||
28 | for row in res: | |
29 | yield Source(self.backend, row.id, data=row) | |
30 | ||
31 | def _get_commit(self, query, *args): | |
32 | res = self.db.get(query, *args) | |
33 | ||
34 | if res: | |
35 | return Commit(self.backend, res.id, data=res) | |
36 | ||
37 | def _get_commits(self, query, *args): | |
38 | res = self.db.query(query, *args) | |
9137135a | 39 | |
78366294 MT |
40 | for row in res: |
41 | yield Commit(self.backend, row.id, data=row) | |
42 | ||
43 | def __iter__(self): | |
44 | return self._get_sources("SELECT * FROM sources") | |
9137135a MT |
45 | |
46 | def get_by_id(self, id): | |
78366294 MT |
47 | return self._get_source("SELECT * FROM sources \ |
48 | WHERE id = %s", id) | |
9137135a MT |
49 | |
50 | def get_by_distro(self, distro): | |
78366294 MT |
51 | return self._get_sources("SELECT * FROM sources \ |
52 | WHERE distro_id = %s", distro.id) | |
9137135a MT |
53 | |
54 | def update_revision(self, source_id, revision): | |
55 | query = "UPDATE sources SET revision = %s WHERE id = %s" | |
56 | ||
57 | return self.db.execute(query, revision, source_id) | |
58 | ||
f6e6ff79 MT |
59 | def get_commit_by_id(self, commit_id): |
60 | commit = self.db.get("SELECT id FROM sources_commits WHERE id = %s", commit_id) | |
61 | ||
62 | if commit: | |
63 | return Commit(self.pakfire, commit.id) | |
64 | ||
7ad79344 | 65 | def pull(self): |
78366294 | 66 | for source in self: |
29e226fc MT |
67 | with git.Repo(self.backend, source, mode="mirror") as repo: |
68 | # Fetch the latest updates | |
7ad79344 MT |
69 | repo.fetch() |
70 | ||
29e226fc MT |
71 | # Import all new revisions |
72 | repo.import_revisions() | |
7ad79344 | 73 | |
13b9276e | 74 | def dist(self): |
99fc0667 MT |
75 | # Walk through all source repositories |
76 | for source in self: | |
77 | # Get access to the git repo | |
78 | with git.Repo(self.pakfire, source) as repo: | |
79 | # Walk through all pending commits | |
80 | for commit in source.pending_commits: | |
81 | commit.state = "running" | |
13b9276e | 82 | |
99fc0667 | 83 | logging.debug("Processing commit %s: %s" % (commit.revision, commit.subject)) |
13b9276e | 84 | |
99fc0667 MT |
85 | # Navigate to the right revision. |
86 | repo.checkout(commit.revision) | |
29e226fc | 87 | |
99fc0667 MT |
88 | # Get all changed makefiles. |
89 | deleted_files = [] | |
90 | updated_files = [] | |
29e226fc | 91 | |
99fc0667 MT |
92 | for file in repo.changed_files(commit.revision): |
93 | # Don't care about files that are not a makefile. | |
94 | if not file.endswith(".%s" % MAKEFILE_EXTENSION): | |
95 | continue | |
29e226fc | 96 | |
99fc0667 MT |
97 | if os.path.exists(file): |
98 | updated_files.append(file) | |
99 | else: | |
100 | deleted_files.append(file) | |
29e226fc | 101 | |
99fc0667 MT |
102 | if updated_files: |
103 | # Create a temporary directory where to put all the files | |
104 | # that are generated here. | |
105 | pkg_dir = tempfile.mkdtemp() | |
29e226fc | 106 | |
99fc0667 MT |
107 | try: |
108 | config = pakfire.config.Config(["general.conf",]) | |
109 | config.parse(source.distro.get_config()) | |
29e226fc | 110 | |
99fc0667 | 111 | p = pakfire.PakfireServer(config=config) |
29e226fc | 112 | |
99fc0667 MT |
113 | pkgs = [] |
114 | for file in updated_files: | |
115 | try: | |
116 | pkg_file = p.dist(file, pkg_dir) | |
117 | pkgs.append(pkg_file) | |
118 | except: | |
119 | raise | |
29e226fc | 120 | |
99fc0667 MT |
121 | # Import all packages in one swoop. |
122 | for pkg in pkgs: | |
e153d3f6 MT |
123 | with self.db.transaction(): |
124 | self.backend.builds.create_from_source_package(pkg, | |
125 | source.distro, commit=commit, type="release") | |
29e226fc | 126 | |
99fc0667 MT |
127 | except: |
128 | if commit: | |
129 | commit.state = "failed" | |
29e226fc | 130 | |
99fc0667 | 131 | raise |
29e226fc | 132 | |
99fc0667 MT |
133 | finally: |
134 | if os.path.exists(pkg_dir): | |
135 | shutil.rmtree(pkg_dir) | |
29e226fc | 136 | |
99fc0667 MT |
137 | for file in deleted_files: |
138 | # Determine the name of the package. | |
139 | name = os.path.basename(file) | |
140 | name = name[:len(MAKEFILE_EXTENSION) + 1] | |
29e226fc | 141 | |
99fc0667 | 142 | source.distro.delete_package(name) |
29e226fc | 143 | |
99fc0667 MT |
144 | if commit: |
145 | commit.state = "finished" | |
13b9276e | 146 | |
f6e6ff79 | 147 | |
78366294 MT |
148 | class Commit(base.DataObject): |
149 | table = "sources_commits" | |
9137135a | 150 | |
f6e6ff79 MT |
151 | @property |
152 | def revision(self): | |
153 | return self.data.revision | |
154 | ||
78366294 | 155 | @lazy_property |
f6e6ff79 | 156 | def source(self): |
78366294 | 157 | return self.backend.sources.get_by_id(self.data.source_id) |
f6e6ff79 MT |
158 | |
159 | @property | |
160 | def distro(self): | |
161 | """ | |
162 | A shortcut to the distribution this commit | |
163 | belongs to. | |
164 | """ | |
165 | return self.source.distro | |
9137135a | 166 | |
f6e6ff79 | 167 | def set_state(self, state): |
78366294 | 168 | self._set_attribute("state", state) |
9137135a | 169 | |
78366294 | 170 | state = property(lambda s: s.data.state, set_state) |
9137135a | 171 | |
f6e6ff79 MT |
172 | @property |
173 | def author(self): | |
174 | return self.data.author | |
175 | ||
176 | @property | |
177 | def committer(self): | |
178 | return self.data.committer | |
179 | ||
180 | @property | |
181 | def subject(self): | |
b9d096e0 | 182 | return self.data.subject.strip() |
f6e6ff79 MT |
183 | |
184 | @property | |
185 | def message(self): | |
186 | return self.data.body.strip() | |
187 | ||
4b1e87c4 MT |
188 | @property |
189 | def message_full(self): | |
190 | msg = [self.subject, ""] + self.message.splitlines() | |
191 | ||
192 | return "\n".join(msg) | |
193 | ||
f6e6ff79 MT |
194 | @property |
195 | def date(self): | |
196 | return self.data.date | |
197 | ||
78366294 | 198 | @lazy_property |
f6e6ff79 | 199 | def packages(self): |
78366294 MT |
200 | return self.backend.packages._get_packages("SELECT * FROM packages \ |
201 | WHERE commit_id = %s", self.id) | |
f6e6ff79 MT |
202 | |
203 | def reset(self): | |
9137135a | 204 | """ |
f6e6ff79 MT |
205 | Removes all packages that have been created by this commit and |
206 | resets the state so it will be processed again. | |
9137135a | 207 | """ |
f6e6ff79 MT |
208 | # Remove all packages and corresponding builds. |
209 | for pkg in self.packages: | |
210 | # Check if there is a build associated with the package. | |
211 | # If so, the whole build will be deleted. | |
212 | if pkg.build: | |
213 | pkg.build.delete() | |
9137135a | 214 | |
f6e6ff79 MT |
215 | else: |
216 | # Delete the package. | |
217 | pkg.delete() | |
218 | ||
219 | # Clear the cache. | |
78366294 | 220 | del self.packages |
9137135a | 221 | |
f6e6ff79 MT |
222 | # Reset the state to 'pending'. |
223 | self.state = "pending" | |
9137135a | 224 | |
9137135a | 225 | |
78366294 MT |
226 | class Source(base.DataObject): |
227 | table = "sources" | |
f6e6ff79 | 228 | |
78366294 MT |
229 | def __eq__(self, other): |
230 | return self.id == other.id | |
f6e6ff79 | 231 | |
78366294 MT |
232 | def __len__(self): |
233 | ret = self.db.get("SELECT COUNT(*) AS len FROM sources_commits \ | |
234 | WHERE source_id = %s", self.id) | |
f6e6ff79 | 235 | |
78366294 | 236 | return ret.len |
9137135a | 237 | |
78366294 MT |
238 | def create_commit(self, revision, author, committer, subject, body, date): |
239 | commit = self.backend.sources._get_commit("INSERT INTO sources_commits(source_id, \ | |
86d8598e MT |
240 | revision, author, committer, subject, body, date) VALUES(%s, %s, %s, %s, %s, %s, %s) \ |
241 | RETURNING *", self.id, revision, author, committer, subject, body, date) | |
9137135a | 242 | |
78366294 MT |
243 | # Commit |
244 | commit.source = self | |
9137135a | 245 | |
78366294 | 246 | return commit |
9137135a | 247 | |
f6e6ff79 MT |
248 | @property |
249 | def info(self): | |
250 | return { | |
251 | "id" : self.id, | |
252 | "name" : self.name, | |
253 | "url" : self.url, | |
254 | "path" : self.path, | |
255 | "targetpath" : self.targetpath, | |
256 | "revision" : self.revision, | |
257 | "branch" : self.branch, | |
258 | } | |
9137135a | 259 | |
9137135a MT |
260 | @property |
261 | def name(self): | |
f6e6ff79 | 262 | return self.data.name |
9137135a MT |
263 | |
264 | @property | |
f6e6ff79 MT |
265 | def identifier(self): |
266 | return self.data.identifier | |
9137135a MT |
267 | |
268 | @property | |
f6e6ff79 MT |
269 | def url(self): |
270 | return self.data.url | |
9137135a MT |
271 | |
272 | @property | |
f6e6ff79 MT |
273 | def gitweb(self): |
274 | return self.data.gitweb | |
9137135a MT |
275 | |
276 | @property | |
277 | def revision(self): | |
f6e6ff79 | 278 | return self.data.revision |
9137135a MT |
279 | |
280 | @property | |
281 | def branch(self): | |
f6e6ff79 | 282 | return self.data.branch |
9137135a MT |
283 | |
284 | @property | |
285 | def builds(self): | |
286 | return self.pakfire.builds.get_by_source(self.id) | |
287 | ||
78366294 | 288 | @lazy_property |
9137135a | 289 | def distro(self): |
f6e6ff79 MT |
290 | return self.pakfire.distros.get_by_id(self.data.distro_id) |
291 | ||
292 | @property | |
293 | def start_revision(self): | |
294 | return self.data.revision | |
295 | ||
78366294 | 296 | @lazy_property |
f6e6ff79 | 297 | def head_revision(self): |
a7d966df | 298 | return self.backend.sources._get_commit("SELECT * FROM sources_commits \ |
78366294 | 299 | WHERE source_id = %s ORDER BY id DESC LIMIT 1", self.id) |
f6e6ff79 MT |
300 | |
301 | def get_commits(self, limit=None, offset=None): | |
a7d966df | 302 | return self.backend.sources._get_commits("SELECT * FROM sources_commits \ |
78366294 | 303 | WHERE source_id = %s ORDER BY id DESC LIMIT %s OFFSET %s", limit, offset) |
f6e6ff79 MT |
304 | |
305 | def get_commit(self, revision): | |
a7d966df | 306 | commit = self.backend.sources._get_commit("SELECT * FROM sources_commits \ |
78366294 | 307 | WHERE source_id = %s AND revision = %s", self.id, revision) |
f6e6ff79 | 308 | |
78366294 MT |
309 | if commit: |
310 | commit.source = self | |
311 | return commit | |
99fc0667 MT |
312 | |
313 | @property | |
314 | def pending_commits(self): | |
315 | return self.backend.sources._get_commits("SELECT * FROM sources_commits \ | |
316 | WHERE state = %s ORDER BY imported_at", "pending") |