source.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. """ Queries related to source packages
  2. @contact: Debian FTPMaster <ftpmaster@debian.org>
  3. @copyright: 2014 Mark Hymers <mhy@debian.org>
  4. @copyright: 2014 Joerg Jaspert <joerg@debian.org>
  5. @license: GNU General Public License version 2 or later
  6. """
  7. from sqlalchemy import or_
  8. import bottle
  9. import json
  10. from daklib.dbconn import DBConn, DBSource, Suite, DSCFile, PoolFile, SourceMetadata, MetadataKey
  11. from dakweb.webregister import QueryRegister
  12. @bottle.route('/dsc_in_suite/<suite>/<source>')
  13. def dsc_in_suite(suite=None, source=None):
  14. """
  15. Find all dsc files for a given source package name in a given suite.
  16. @since: December 2014
  17. @type suite: string
  18. @param suite: Name of the suite.
  19. @see: L{I{suites}<dakweb.queries.suite.suites>} on how to receive a list of valid suites.
  20. @type source: string
  21. @param source: Source package to query for.
  22. @rtype: list of dictionaries
  23. @return: Dictionaries made out of
  24. - version
  25. - component
  26. - filename
  27. - filesize
  28. - sha256sum
  29. """
  30. if suite is None:
  31. return bottle.HTTPError(503, 'Suite not specified.')
  32. if source is None:
  33. return bottle.HTTPError(503, 'Source package not specified.')
  34. s = DBConn().session()
  35. q = s.query(DSCFile).join(PoolFile)
  36. q = q.join(DBSource).join(Suite, DBSource.suites)
  37. q = q.filter(or_(Suite.suite_name == suite, Suite.codename == suite))
  38. q = q.filter(DBSource.source == source)
  39. q = q.filter(PoolFile.filename.endswith('.dsc'))
  40. ret = []
  41. for p in q:
  42. ret.append({'version': p.source.version,
  43. 'component': p.poolfile.component.component_name,
  44. 'filename': p.poolfile.filename,
  45. 'filesize': p.poolfile.filesize,
  46. 'sha256sum': p.poolfile.sha256sum})
  47. s.close()
  48. bottle.response.content_type = 'application/json; charset=UTF-8'
  49. return json.dumps(ret)
  50. QueryRegister().register_path('/dsc_in_suite', dsc_in_suite)
  51. @bottle.route('/file_in_archive/<filepattern:path>')
  52. def file_in_archive(filepattern=None):
  53. """
  54. Check if a file pattern is known to the archive. Note that the
  55. patterns are matched against the location of the files in the
  56. pool, so for %tmux_2.3-1.dsc it will return t/tmux/tmux_2.3-1.dsc
  57. as filename.
  58. @since: October 2016
  59. @type filepattern: string
  60. @param filepattern: Pattern of the filenames to match. SQL LIKE
  61. statement wildcard matches are supported, that
  62. is % for zero, one or more characters, _ for a
  63. single character match.
  64. @rtype: list of dictionaries
  65. @return: Dictionaries made out of
  66. - filename
  67. - sha256sum
  68. - component
  69. """
  70. if filepattern is None:
  71. return bottle.HTTPError(503, 'Filepattern not specified.')
  72. s = DBConn().session()
  73. q = s.query(PoolFile)
  74. q = q.filter(PoolFile.filename.like(filepattern))
  75. ret = []
  76. for p in q:
  77. ret.append({'filename': p.filename,
  78. 'component': p.component.component_name,
  79. 'sha256sum': p.sha256sum})
  80. s.close()
  81. bottle.response.content_type = 'application/json; charset=UTF-8'
  82. return json.dumps(ret)
  83. QueryRegister().register_path('/file_in_archive', file_in_archive)
  84. @bottle.route('/sha256sum_in_archive/<sha256sum>')
  85. def sha256sum_in_archive(sha256sum=None):
  86. """
  87. Check if files with matching sha256sums are known to the archive.
  88. @since: June 2018
  89. @type sha256sum: string
  90. @param sha256sum: SHA256 sum of the file.
  91. @rtype: list of dictionaries
  92. @return: Dictionaries made out of
  93. - filename
  94. - sha256sum
  95. - component
  96. """
  97. if sha256sum is None:
  98. return bottle.HTTPError(503, 'sha256sum not specified.')
  99. s = DBConn().session()
  100. q = s.query(PoolFile)
  101. q = q.filter(PoolFile.sha256sum == sha256sum)
  102. ret = []
  103. for p in q:
  104. ret.append({'filename': p.filename,
  105. 'component': p.component.component_name,
  106. 'sha256sum': p.sha256sum})
  107. s.close()
  108. bottle.response.content_type = 'application/json; charset=UTF-8'
  109. return json.dumps(ret)
  110. QueryRegister().register_path('/sha256sum_in_archive', sha256sum_in_archive)
  111. @bottle.route('/sources_in_suite/<suite>')
  112. def sources_in_suite(suite=None):
  113. """
  114. Returns all source packages and their versions in a given suite.
  115. @since: December 2014
  116. @type suite: string
  117. @param suite: Name of the suite.
  118. @see: L{I{suites}<dakweb.queries.suite.suites>} on how to receive a list of valid suites.
  119. @rtype: list of dictionaries
  120. @return: Dictionaries made out of
  121. - source
  122. - version
  123. """
  124. if suite is None:
  125. return bottle.HTTPError(503, 'Suite not specified.')
  126. s = DBConn().session()
  127. q = s.query(DBSource).join(Suite, DBSource.suites)
  128. q = q.filter(or_(Suite.suite_name == suite, Suite.codename == suite))
  129. ret = []
  130. for p in q:
  131. ret.append({'source': p.source,
  132. 'version': p.version})
  133. s.close()
  134. bottle.response.content_type = 'application/json; charset=UTF-8'
  135. return json.dumps(ret)
  136. QueryRegister().register_path('/sources_in_suite', sources_in_suite)
  137. @bottle.route('/all_sources')
  138. def all_sources():
  139. """
  140. Returns all source packages and their versions known to the archive
  141. (this includes NEW).
  142. @rtype: list of dictionaries
  143. @return: Dictionaries made out of
  144. - source
  145. - version
  146. """
  147. s = DBConn().session()
  148. q = s.query(DBSource)
  149. ret = []
  150. for p in q:
  151. ret.append({'source': p.source,
  152. 'version': p.version})
  153. s.close()
  154. bottle.response.content_type = 'application/json; charset=UTF-8'
  155. return json.dumps(ret)
  156. QueryRegister().register_path('/all_sources', all_sources)
  157. @bottle.route('/source/by_metadata/<key>')
  158. def source_by_metadata(key=None):
  159. """
  160. Finds all Debian source packages which have the specified metadata set.
  161. E.g., to find out the Maintainer of all source packages, query
  162. /source/by_metadata/Maintainer.
  163. @type key: string
  164. @param key: Metadata key to search for.
  165. @rtype: dictionary
  166. @return: A list of dictionaries of
  167. - source
  168. - metadata value
  169. """
  170. if not key:
  171. return bottle.HTTPError(503, 'Metadata key not specified.')
  172. s = DBConn().session()
  173. q = s.query(DBSource.source, SourceMetadata.value)
  174. q = q.join(SourceMetadata).join(MetadataKey)
  175. q = q.filter(MetadataKey.key == key)
  176. ret = []
  177. for p in q:
  178. ret.append({'source': p.source,
  179. 'metadata_value': p.value})
  180. s.close()
  181. bottle.response.content_type = 'application/json; charset=UTF-8'
  182. return json.dumps(ret)
  183. QueryRegister().register_path('/source/by_metadata', source_by_metadata)