[snapshot/master] Implement search for binary packages (Re: #577658)
---
API | 28 +++++++++
web/app/snapshot/config/routing.py | 5 ++
web/app/snapshot/controllers/archive.py | 4 +-
web/app/snapshot/controllers/package.py | 74 ++++++++++++++++++++++--
web/app/snapshot/model/snapshotmodel.py | 12 ++++-
web/app/snapshot/templates/package-binary.mako | 15 +++++
web/app/snapshot/templates/root.mako | 10 +++-
7 files changed, 139 insertions(+), 9 deletions(-)
create mode 100644 web/app/snapshot/templates/package-binary.mako
diff --git a/API b/API
index 258c499..a1cdda7 100644
--- a/API
+++ b/API
@@ -112,6 +112,34 @@ summary: list all files associated with this source package at that version
}
}
+URL: /mr/binary/<binary>/
+http status codes: 200 500 404 304
+summary: find binary package versions and corresponding source names and versions
+{ '_comment': "foo",
+ 'binary': "keylookup",
+ 'result': [ {
+ 'name': "keylookup",
+ 'binary_version': "2.0-2",
+ 'source': "keylookup",
+ 'version': "2.0-2"},
+ {
+ 'name': "keylookup",
+ 'binary_version': "2.2-2",
+ 'source': "keylookup",
+ 'version': "2.2-2"},
+ {
+ 'name': "keylookup",
+ 'binary_version': "3.0-1",
+ 'source': "signing-party",
+ 'version': "0.4.2-1"},
+ ...
+ ]
+}
+
+
+
+
+
URL: /file/<hash>
http status codes: 200 500 404 403 304
[return the file]
diff --git a/web/app/snapshot/config/routing.py b/web/app/snapshot/config/routing.py
index 2c05351..83ea049 100644
--- a/web/app/snapshot/config/routing.py
+++ b/web/app/snapshot/config/routing.py
@@ -32,6 +32,9 @@ def make_map():
map.connect('/package/{source}/', controller='package', action='source')
map.connect('/package/{source}/{version}/', controller='package', action='source_version')
+ map.connect('/binary/', controller='package', action='binary_root')
+ map.connect('/binary/{binary}/', controller='package', action='binary')
+
map.connect('/mr/package/', controller='package', action='mr_list')
map.connect('/mr/package/{source}/', controller='package', action='mr_source')
map.connect('/mr/package/{source}/{version}/srcfiles', controller='package', action='mr_source_version_srcfiles')
@@ -39,6 +42,8 @@ def make_map():
map.connect('/mr/package/{source}/{version}/binfiles/{binary}/{binary_version}', controller='package', action='mr_source_version_binfiles')
map.connect('/mr/package/{source}/{version}/allfiles', controller='package', action='mr_source_version_allfiles')
+ map.connect('/mr/binary/{binary}/', controller='package', action='mr_binary')
+
map.connect('/file/{hash}', controller='archive', action='file')
map.connect('/mr/file/{hash}/info', controller='package', action='mr_fileinfo')
diff --git a/web/app/snapshot/controllers/archive.py b/web/app/snapshot/controllers/archive.py
index 89f4728..7c95e1b 100644
--- a/web/app/snapshot/controllers/archive.py
+++ b/web/app/snapshot/controllers/archive.py
@@ -130,7 +130,9 @@ class ArchiveController(BaseController):
crumbs = []
url = request.environ.get('SCRIPT_NAME') + "/"
- crumbs.append( { 'url': url, 'name': 'snapshot.debian.org' });
+ crumbs.append( { 'url': url, 'name': 'snapshot.debian.org', 'sep': '|' });
+
+ crumbs.append( { 'url': None, 'name': 'archive:', 'sep': '' });
url += 'archive/' + archive + "/"
crumbs.append( { 'url': url, 'name': archive, 'sep': '' });
diff --git a/web/app/snapshot/controllers/package.py b/web/app/snapshot/controllers/package.py
index 7bb664f..b9e86c7 100644
--- a/web/app/snapshot/controllers/package.py
+++ b/web/app/snapshot/controllers/package.py
@@ -27,11 +27,17 @@ class PackageController(BaseController):
if not self.db is None:
self.db.close()
- def _build_crumbs(self, srcpkg=None, version=None, start=None):
+ def _make_crumbs_base(self):
crumbs = []
url = urllib.quote(request.environ.get('SCRIPT_NAME')) + "/"
- crumbs.append( { 'url': url, 'name': 'snapshot.debian.org' });
+ crumbs.append( { 'url': url, 'name': 'snapshot.debian.org', 'sep': '|' });
+
+ return (url, crumbs)
+
+ def _build_crumbs(self, srcpkg=None, version=None, start=None):
+ (url, crumbs) = self._make_crumbs_base()
+ crumbs.append( { 'url': None, 'name': 'source package:', 'sep': '' });
if not start:
if srcpkg.startswith('lib') and len(srcpkg) >= 4:
@@ -114,7 +120,7 @@ class PackageController(BaseController):
set_expires(int(config['app_conf']['expires.package.source_version']))
sourcefiles = g.shm.packages_get_source_files(self._db(), source, version)
- binpkgs = g.shm.packages_get_binpkgs(self._db(), source, version)
+ binpkgs = g.shm.packages_get_binpkgs_from_source(self._db(), source, version)
# we may have binaries without sources.
if len(sourcefiles) == 0 and len(binpkgs) == 0:
@@ -150,8 +156,51 @@ class PackageController(BaseController):
finally:
self._db_close()
+ def binary_root(self):
+ if 'bin' in request.params:
+ url = url_quote(request.params['bin'] + "/")
+ return redirect_to(url)
+ else:
+ return redirect_to("../")
+ def binary(self, binary):
+ try:
+ # Package names are ascii.
+ # Check that before passing it on to postgres since the DB
+ # will just whine about not being able to convert the string
+ # anyway.
+ # If the passed string is not ascii, then the package name
+ # simply does not exist.
+ try:
+ binary.encode('ascii')
+ except UnicodeEncodeError:
+ abort(404, 'No such binary package')
+ #etag_cache( g.shm.packages_get_etag(self._db()) )
+ set_expires(int(config['app_conf']['expires.package.source']))
+
+ binaryversions = g.shm.packages_get_binary_versions_by_name(self._db(), binary)
+
+ if len(binaryversions) == 0:
+ abort(404, 'No such binary package')
+
+ binaryversions = map(lambda b: dict(b), binaryversions)
+ for b in binaryversions:
+ b['link'] = url_quote('../../package/%s/%s/'%(b['source'], b['version']))
+ b['escaped_name'] = self._attribute_escape(b['name'])
+ b['escaped_version'] = self._attribute_escape(b['version'])
+
+ url, crumbs = self._make_crumbs_base()
+ crumbs.append( { 'url': None, 'name': 'binary package:', 'sep': '' });
+ crumbs.append( { 'url': None, 'name': binary });
+
+ c.binary = binary
+ c.binaryversions = binaryversions
+ c.breadcrumbs = crumbs
+ c.title = binary
+ return render('/package-binary.mako')
+ finally:
+ self._db_close()
def _get_fileinfo_for_mr_one(self, hash):
@@ -207,7 +256,7 @@ class PackageController(BaseController):
def mr_source_version_binpackages(self, source, version):
try:
set_expires(int(config['app_conf']['expires.package.mr.source_version']))
- binpkgs = g.shm.packages_get_binpkgs(self._db(), source, version)
+ binpkgs = g.shm.packages_get_binpkgs_from_source(self._db(), source, version)
if len(binpkgs) == 0: abort(404, 'No such source package or no binary packages found')
binpkgs = map(lambda b: { 'name': b['name'],
'version': b['version'] }, binpkgs)
@@ -242,7 +291,7 @@ class PackageController(BaseController):
try:
set_expires(int(config['app_conf']['expires.package.mr.source_version']))
sourcefiles = g.shm.packages_get_source_files(self._db(), source, version)
- binpkgs = g.shm.packages_get_binpkgs(self._db(), source, version)
+ binpkgs = g.shm.packages_get_binpkgs_from_source(self._db(), source, version)
# we may have binaries without sources.
if len(sourcefiles) == 0 and len(binpkgs) == 0:
abort(404, 'No source or binary packages found')
@@ -266,6 +315,21 @@ class PackageController(BaseController):
self._db_close()
@jsonify
+ def mr_binary(self, binary):
+ try:
+ set_expires(int(config['app_conf']['expires.package.mr.source']))
+ binaryversions = g.shm.packages_get_binary_versions_by_name(self._db(), binary)
+ binaryversions = map(lambda b: dict(b), binaryversions)
+ if len(binaryversions) == 0: abort(404, 'No such binary package')
+ r = { '_comment': "foo",
+ 'binary': binary,
+ 'result': binaryversions }
+ return r
+ finally:
+ self._db_close()
+
+
+ @jsonify
def mr_fileinfo(self, hash):
if not re.match('[0-9a-f]{40}$', hash): # match matches only at start of string
abort(404, 'Invalid hash format.')
diff --git a/web/app/snapshot/model/snapshotmodel.py b/web/app/snapshot/model/snapshotmodel.py
index a5cb7e1..07bf332 100644
--- a/web/app/snapshot/model/snapshotmodel.py
+++ b/web/app/snapshot/model/snapshotmodel.py
@@ -264,7 +264,7 @@ class SnapshotModel:
return map(lambda x: x['hash'], rows)
- def packages_get_binpkgs(self, db, source, version):
+ def packages_get_binpkgs_from_source(self, db, source, version):
rows = db.query("""SELECT name, version, binpkg_id
FROM binpkg
WHERE srcpkg_id = (SELECT srcpkg_id FROM srcpkg WHERE name=%(source)s AND version=%(version)s)
@@ -273,6 +273,16 @@ class SnapshotModel:
'version': version} )
return rows
+ def packages_get_binary_versions_by_name(self, db, binary):
+ rows = db.query("""SELECT binpkg.name AS name, binpkg.version AS binary_version, srcpkg.name AS source, srcpkg.version AS version
+ FROM binpkg
+ JOIN srcpkg
+ ON binpkg.srcpkg_id=srcpkg.srcpkg_id
+ WHERE binpkg.name=%(binary)s
+ ORDER BY binpkg.version""",
+ { 'binary': binary} )
+ return rows
+
def packages_get_binary_files_from_id(self, db, binpkg_id):
rows = db.query("""SELECT hash, architecture
FROM file_binpkg_mapping
diff --git a/web/app/snapshot/templates/package-binary.mako b/web/app/snapshot/templates/package-binary.mako
new file mode 100644
index 0000000..a894d58
--- /dev/null
+++ b/web/app/snapshot/templates/package-binary.mako
@@ -0,0 +1,15 @@
+<%inherit file="/page.mako" />
+
+<h1>Binary package ${c.binary}</h1>
+<p>
+Available versions:
+</p>
+<ul>
+ %for entry in c.binaryversions:
+ <li><a href="${entry['link']}#${entry['escaped_name']}_${entry['escaped_version']}">${entry['binary_version']} (source: ${entry['source']} ${entry['version']})</a></li>
+ %endfor
+</ul>
+
+## vim:syn=html
+## vim:set ts=4:
+## vim:set shiftwidth=4:
diff --git a/web/app/snapshot/templates/root.mako b/web/app/snapshot/templates/root.mako
index a9c4f99..2dc1f4b 100644
--- a/web/app/snapshot/templates/root.mako
+++ b/web/app/snapshot/templates/root.mako
@@ -16,7 +16,7 @@
<h1>Packages</h1>
-Search in the index:<br />
+Search in the index of source packages:<br />
<ul class="inlineList">
%for letter in c.srcstarts:
<li><a href="package/?cat=${letter['quoted']}">${letter['raw']}</a></li>
@@ -24,7 +24,13 @@ Search in the index:<br />
</ul>
<form action="package/">
-<p>Or enter a source package name directly: <input name="src" /> <input type="submit" value="Submit" /></p>
+<p>Or enter a <strong>source</strong> package name directly: <input name="src" /> <input type="submit" value="Submit" /></p>
+</form>
+
+<h2>Binary packages</h2>
+
+<form action="binary/">
+<p>Search for a <strong>binary</strong> package name: <input name="bin" /> <input type="submit" value="Submit" /></p>
</form>
<h1>Miscellaneous</h1>
--
1.5.6.5
Reply to: