]>
Commit | Line | Data |
---|---|---|
f6e6ff79 MT |
1 | #!/usr/bin/python |
2 | ||
01197c1d MT |
3 | import mimetypes |
4 | import os.path | |
f6e6ff79 MT |
5 | import tornado.web |
6 | ||
0919f216 | 7 | from . import base |
f6e6ff79 | 8 | |
2c909128 | 9 | from ..constants import BUFFER_SIZE |
01197c1d | 10 | |
b5800237 | 11 | class IndexHandler(base.BaseHandler): |
f6e6ff79 | 12 | def get(self): |
b5800237 MT |
13 | # Sort all packages in an array like "<first char>" --> [packages, ...] |
14 | # to print them in a table for each letter of the alphabet. | |
f6e6ff79 MT |
15 | packages = {} |
16 | ||
b5800237 MT |
17 | for pkg in self.backend.packages.get_list(): |
18 | c = pkg.name[0].lower() | |
f6e6ff79 | 19 | |
b5800237 MT |
20 | try: |
21 | packages[c].append(pkg) | |
22 | except KeyError: | |
23 | packages[c] = [pkg] | |
f6e6ff79 | 24 | |
b5800237 | 25 | self.render("packages/index.html", packages=packages) |
f6e6ff79 | 26 | |
f6e6ff79 | 27 | |
b5800237 MT |
28 | class PackageIDDetailHandler(base.BaseHandler): |
29 | def get(self, id): | |
30 | package = self.packages.get_by_id(id) | |
31 | if not package: | |
32 | return tornado.web.HTTPError(404, "Package not found: %s" % id) | |
f6e6ff79 | 33 | |
b5800237 | 34 | self.render("package-detail.html", package=package) |
f6e6ff79 MT |
35 | |
36 | ||
0919f216 | 37 | class PackageNameHandler(base.BaseHandler): |
f6e6ff79 | 38 | def get(self, name): |
47130fc1 | 39 | builds = self.backend.builds.get_active_builds(name) |
fd0e70ec | 40 | if not builds: |
f6e6ff79 MT |
41 | raise tornado.web.HTTPError(404, "Package '%s' was not found" % name) |
42 | ||
fd0e70ec MT |
43 | # Get the latest build to show the package meta information. |
44 | latest_build = builds[0] | |
f6e6ff79 MT |
45 | |
46 | # Get the latest bugs from bugzilla. | |
47130fc1 | 47 | bugs = self.backend.bugzilla.get_bugs_from_component(name) |
f6e6ff79 | 48 | |
fd0e70ec MT |
49 | self.render("package-detail-list.html", name=name, builds=builds, |
50 | latest_build=latest_build, pkg=latest_build.pkg, bugs=bugs) | |
f6e6ff79 MT |
51 | |
52 | ||
0919f216 | 53 | class PackageScratchBuildsHandler(base.BaseHandler): |
a15d6139 MT |
54 | def get(self, name): |
55 | offset = self.get_argument("offset", 0) | |
56 | limit = self.get_argument("limit", 10) | |
57 | ||
47130fc1 | 58 | scratch_builds = self.backend.builds.get_by_name(name, type="scratch", |
1104bcbf | 59 | limit=limit, offset=offset) |
a15d6139 MT |
60 | |
61 | if scratch_builds: | |
62 | latest_build = scratch_builds[0] | |
63 | else: | |
47130fc1 | 64 | release_builds = self.backend.builds.get_by_name(name, type="release", limit=1) |
a15d6139 MT |
65 | if not release_builds: |
66 | raise tornado.web.HTTPError(404, "Could not find any build with this name: %s" % name) | |
67 | ||
68 | latest_build = release_builds[0] | |
69 | ||
70 | self.render("packages/builds/scratch.html", builds=scratch_builds, | |
71 | pkg=latest_build.pkg) | |
72 | ||
73 | ||
0919f216 | 74 | class PackageChangelogHandler(base.BaseHandler): |
4b1e87c4 MT |
75 | def get(self, name): |
76 | limit = self.get_argument("limit", 10) | |
77 | try: | |
78 | limit = int(limit) | |
b5800237 | 79 | |
4b1e87c4 MT |
80 | except ValueError: |
81 | limit = 10 | |
82 | ||
83 | offset = self.get_argument("offset", 0) | |
84 | try: | |
85 | offset = int(offset) | |
86 | except ValueError: | |
87 | offset = 0 | |
88 | ||
89 | # Get one more build than requested to find out if there are more items | |
90 | # to display (next button). | |
47130fc1 | 91 | builds = self.backend.builds.get_changelog(name, limit=limit + 1, offset=offset) |
4b1e87c4 MT |
92 | |
93 | if len(builds) >= limit: | |
94 | have_next = True | |
95 | else: | |
96 | have_next = False | |
97 | ||
98 | if offset < limit: | |
99 | have_prev = False | |
100 | else: | |
101 | have_prev = True | |
102 | ||
103 | # Clip list to limit. | |
104 | builds = builds[:limit] | |
105 | ||
106 | self.render("packages/changelog.html", name=name, builds=builds, | |
107 | limit=limit, offset=offset, have_prev=have_prev, have_next=have_next) | |
108 | ||
109 | ||
0919f216 | 110 | class PackageDetailHandler(base.BaseHandler): |
f6e6ff79 | 111 | def get(self, uuid): |
47130fc1 | 112 | pkg = self.backend.packages.get_by_uuid(uuid) |
f6e6ff79 MT |
113 | if not pkg: |
114 | raise tornado.web.HTTPError(404, "Package not found: %s" % uuid) | |
115 | ||
116 | self.render("package-detail.html", pkg=pkg) | |
117 | ||
118 | @tornado.web.authenticated | |
119 | def post(self, name, epoch, version, release): | |
47130fc1 | 120 | pkg = self.backend.packages.get_by_tuple(name, epoch, version, release) |
f6e6ff79 MT |
121 | |
122 | action = self.get_argument("action", None) | |
123 | ||
124 | if action == "comment": | |
125 | vote = self.get_argument("vote", None) | |
126 | if not self.current_user.is_tester() and \ | |
127 | not self.current_user.is_admin(): | |
128 | vote = None | |
129 | ||
130 | pkg.comment(self.current_user.id, self.get_argument("text"), | |
131 | vote or "none") | |
132 | ||
133 | self.render("package-detail.html", pkg=pkg) | |
134 | ||
135 | ||
0919f216 | 136 | class PackagePropertiesHandler(base.BaseHandler): |
f6e6ff79 MT |
137 | @tornado.web.authenticated |
138 | def get(self, name): | |
47130fc1 | 139 | build = self.backend.builds.get_latest_by_name(name) |
f6e6ff79 MT |
140 | |
141 | if not build: | |
142 | raise tornado.web.HTTPError(404, "Package '%s' was not found" % name) | |
143 | ||
144 | # Check if the user has sufficient permissions. | |
145 | if not build.has_perm(self.current_user): | |
146 | raise tornado.web.HTTPError(403, "User %s is not allowed to manage build %s" \ | |
147 | % (self.current_user, build)) | |
148 | ||
149 | self.render("package-properties.html", build=build, | |
150 | pkg=build.pkg, properties=build.pkg.properties) | |
151 | ||
152 | @tornado.web.authenticated | |
153 | def post(self, name): | |
47130fc1 | 154 | build = self.backend.builds.get_latest_by_name(name) |
f6e6ff79 MT |
155 | |
156 | if not build: | |
157 | raise tornado.web.HTTPError(404, "Package '%s' was not found" % name) | |
158 | ||
159 | # Check if the user has sufficient permissions. | |
160 | if not build.has_perm(self.current_user): | |
161 | raise tornado.web.HTTPError(403, "User %s is not allowed to manage build %s" \ | |
162 | % (self.current_user, build)) | |
163 | ||
164 | critical_path = self.get_argument("critical_path", False) | |
165 | if critical_path: | |
166 | critical_path = True | |
167 | else: | |
168 | critical_path = False | |
169 | build.pkg.update_property("critical_path", critical_path) | |
01197c1d MT |
170 | |
171 | ||
0919f216 | 172 | class PackageFileDownloadHandler(base.BaseHandler): |
de4e09a5 | 173 | def get_file(self, pkg_uuid, filename): |
01197c1d | 174 | # Fetch package. |
47130fc1 | 175 | pkg = self.backend.packages.get_by_uuid(pkg_uuid) |
01197c1d MT |
176 | if not pkg: |
177 | raise tornado.web.HTTPError(404, "Package not found: %s" % pkg_uuid) | |
178 | ||
179 | # Check if the package has got a file with the given name. | |
6a6aaccd MT |
180 | file = pkg.get_file(filename) |
181 | if not file: | |
01197c1d MT |
182 | raise tornado.web.HTTPError(404, "Package %s does not contain file %s" % (pkg, filename)) |
183 | ||
184 | # Open the package in the filesystem. | |
6a6aaccd | 185 | pkg_file = pkg.open() |
01197c1d | 186 | if not pkg_file: |
e088f666 | 187 | raise tornado.web.HTTPError(404, "Could not open package %s" % pkg.path) |
01197c1d MT |
188 | |
189 | # Open the file to transfer it to the client. | |
190 | f = pkg_file.open_file(filename) | |
191 | if not f: | |
192 | raise tornado.web.HTTPError(404, "Package %s does not contain file %s" % (pkg_file, filename)) | |
193 | ||
01197c1d MT |
194 | # Guess the MIME type of the file. |
195 | (type, encoding) = mimetypes.guess_type(filename) | |
196 | if not type: | |
197 | type = "text/plain" | |
de4e09a5 MT |
198 | |
199 | return (pkg, f, type) | |
200 | ||
201 | def get(self, pkg_uuid, filename): | |
202 | pkg, f, mimetype = self.get_file(pkg_uuid, filename) | |
203 | ||
204 | # Send the filename and mimetype in header. | |
205 | self.set_header("Content-Disposition", "attachment; filename=%s" % os.path.basename(filename)) | |
206 | self.set_header("Content-Type", mimetype) | |
01197c1d MT |
207 | |
208 | # Transfer the content chunk by chunk. | |
209 | while True: | |
210 | buf = f.read(BUFFER_SIZE) | |
211 | if not buf: | |
212 | break | |
213 | ||
214 | self.write(buf) | |
215 | ||
216 | f.close() | |
217 | ||
218 | # Done. | |
219 | self.finish() | |
de4e09a5 MT |
220 | |
221 | ||
222 | class PackageFileViewHandler(PackageFileDownloadHandler): | |
223 | def get(self, pkg_uuid, filename): | |
224 | pkg, f, mimetype = self.get_file(pkg_uuid, filename) | |
225 | ||
226 | # Read in the data. | |
227 | content = f.read() | |
228 | f.close() | |
229 | ||
5669a87f | 230 | self.render("packages/view-file.html", pkg=pkg, filename=filename, |
de4e09a5 | 231 | mimetype=mimetype, content=content, filesize=f.size) |
bc293d03 MT |
232 | |
233 | ||
0919f216 | 234 | class PackageBuildsTimesHandler(base.BaseHandler): |
bc293d03 | 235 | def get(self, name): |
47130fc1 | 236 | latest_build = self.backend.builds.get_latest_by_name(name) |
bc293d03 MT |
237 | |
238 | # If no build with this name was found, we cannot go on. | |
239 | if not latest_build: | |
240 | raise tornado.web.HTTPError(404) | |
241 | ||
242 | # Get the summary stats. | |
47130fc1 | 243 | build_times_summary = self.backend.builds.get_build_times_summary(name) |
bc293d03 MT |
244 | |
245 | self.render("packages/builds/times.html", pkg=latest_build.pkg, | |
246 | build_times_summary=build_times_summary) |