[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[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: