1""" Queries related to source packages
3@contact: Debian FTPMaster <ftpmaster@debian.org>
4@copyright: 2014 Mark Hymers <mhy@debian.org>
5@copyright: 2014 Joerg Jaspert <joerg@debian.org>
6@license: GNU General Public License version 2 or later
7"""
9from sqlalchemy import or_
10import bottle
11import json
12from typing import Optional
14from daklib.dbconn import DBConn, DBSource, Suite, DSCFile, PoolFile, SourceMetadata, MetadataKey
15from dakweb.webregister import QueryRegister
18@bottle.route('/dsc_in_suite/<suite>/<source>')
19def dsc_in_suite(suite: Optional[str] = None, source: Optional[str] = None) -> str:
20 """
21 Find all dsc files for a given source package name in a given suite.
23 .. versionadded: December 2014
25 :param suite: Name of the suite.
26 :param source: Source package to query for.
27 :return: List of dictionaries made out of
28 - version
29 - component
30 - filename
31 - filesize
32 - sha256sum
34 .. seealso:: :func:`~dakweb.queries.suite.suites` on how to receive a list of valid suites.
35 """
36 if suite is None:
37 return bottle.HTTPError(503, 'Suite not specified.')
38 if source is None:
39 return bottle.HTTPError(503, 'Source package not specified.')
41 s = DBConn().session()
42 q = s.query(DSCFile).join(PoolFile)
43 q = q.join(DBSource).join(Suite, DBSource.suites)
44 q = q.filter(or_(Suite.suite_name == suite, Suite.codename == suite))
45 q = q.filter(DBSource.source == source)
46 q = q.filter(PoolFile.filename.endswith('.dsc'))
47 ret = []
48 for p in q:
49 ret.append({'version': p.source.version,
50 'component': p.poolfile.component.component_name,
51 'filename': p.poolfile.filename,
52 'filesize': p.poolfile.filesize,
53 'sha256sum': p.poolfile.sha256sum})
55 s.close()
57 bottle.response.content_type = 'application/json; charset=UTF-8'
58 return json.dumps(ret)
61QueryRegister().register_path('/dsc_in_suite', dsc_in_suite)
64@bottle.route('/file_in_archive/<filepattern:path>')
65def file_in_archive(filepattern: Optional[str] = None) -> str:
66 """
67 Check if a file pattern is known to the archive. Note that the
68 patterns are matched against the location of the files in the
69 pool, so for %tmux_2.3-1.dsc it will return t/tmux/tmux_2.3-1.dsc
70 as filename.
72 .. versionadded:: October 2016
74 :param filepattern: Pattern of the filenames to match. SQL LIKE
75 statement wildcard matches are supported, that
76 is % for zero, one or more characters, _ for a
77 single character match.
78 :return: List of dictionaries made out of
79 - filename
80 - sha256sum
81 - component
82 """
83 if filepattern is None:
84 return bottle.HTTPError(503, 'Filepattern not specified.')
86 s = DBConn().session()
87 q = s.query(PoolFile)
88 q = q.filter(PoolFile.filename.like(filepattern))
89 ret = []
91 for p in q:
92 ret.append({'filename': p.filename,
93 'component': p.component.component_name,
94 'sha256sum': p.sha256sum})
96 s.close()
98 bottle.response.content_type = 'application/json; charset=UTF-8'
99 return json.dumps(ret)
102QueryRegister().register_path('/file_in_archive', file_in_archive)
105@bottle.route('/sha256sum_in_archive/<sha256sum>')
106def sha256sum_in_archive(sha256sum: Optional[str] = None) -> str:
107 """
108 Check if files with matching sha256sums are known to the archive.
110 .. versionadded:: June 2018
112 :param sha256sum: SHA256 sum of the file.
113 :return: List of dictionaries made out of
114 - filename
115 - sha256sum
116 - component
117 """
118 if sha256sum is None:
119 return bottle.HTTPError(503, 'sha256sum not specified.')
121 s = DBConn().session()
122 q = s.query(PoolFile)
123 q = q.filter(PoolFile.sha256sum == sha256sum)
124 ret = []
126 for p in q:
127 ret.append({'filename': p.filename,
128 'component': p.component.component_name,
129 'sha256sum': p.sha256sum})
131 s.close()
133 bottle.response.content_type = 'application/json; charset=UTF-8'
134 return json.dumps(ret)
137QueryRegister().register_path('/sha256sum_in_archive', sha256sum_in_archive)
140@bottle.route('/sources_in_suite/<suite>')
141def sources_in_suite(suite: Optional[str] = None) -> str:
142 """
143 Returns all source packages and their versions in a given suite.
145 .. versionadded:: December 2014
147 :param suite: Name of the suite.
148 :return: List of dictionaries made out of
149 - source
150 - version
152 .. seealso:: :func:`~dakweb.queries.suite.suites` on how to receive a list of valid suites.
153 """
154 if suite is None:
155 return bottle.HTTPError(503, 'Suite not specified.')
157 s = DBConn().session()
158 q = s.query(DBSource).join(Suite, DBSource.suites)
159 q = q.filter(or_(Suite.suite_name == suite, Suite.codename == suite))
160 ret = []
161 for p in q:
162 ret.append({'source': p.source,
163 'version': p.version})
165 s.close()
167 bottle.response.content_type = 'application/json; charset=UTF-8'
168 return json.dumps(ret)
171QueryRegister().register_path('/sources_in_suite', sources_in_suite)
174@bottle.route('/all_sources')
175def all_sources() -> str:
176 """
177 Returns all source packages and their versions known to the archive
178 (this includes NEW).
180 :return: List of dictionaries made out of
181 - source
182 - version
183 """
185 s = DBConn().session()
186 q = s.query(DBSource)
187 ret = []
188 for p in q:
189 ret.append({'source': p.source,
190 'version': p.version})
192 s.close()
194 bottle.response.content_type = 'application/json; charset=UTF-8'
195 return json.dumps(ret)
198QueryRegister().register_path('/all_sources', all_sources)
201@bottle.route('/source/by_metadata/<key>')
202def source_by_metadata(key: Optional[str] = None) -> str:
203 """
205 Finds all Debian source packages which have the specified metadata set.
207 E.g., to find out the Maintainer of all source packages, query
208 /source/by_metadata/Maintainer.
210 :param key: Metadata key to search for.
211 :return: A list of dictionaries of
212 - source
213 - metadata value
214 """
216 if not key:
217 return bottle.HTTPError(503, 'Metadata key not specified.')
219 s = DBConn().session()
220 q = s.query(DBSource.source, SourceMetadata.value)
221 q = q.join(SourceMetadata).join(MetadataKey)
222 q = q.filter(MetadataKey.key == key)
223 ret = []
224 for p in q:
225 ret.append({'source': p.source,
226 'metadata_value': p.value})
227 s.close()
229 bottle.response.content_type = 'application/json; charset=UTF-8'
230 return json.dumps(ret)
233QueryRegister().register_path('/source/by_metadata', source_by_metadata)