summaryrefslogtreecommitdiff
path: root/webapp.py
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2013-09-07 21:04:40 +0200
committerHelmut Grohne <helmut@subdivi.de>2013-09-07 21:04:40 +0200
commit7f3d8c5098d23bb43b86e060700170cc41cd22aa (patch)
tree5e0ee4d269259b4b0d205d1f89895d8f46cccf93 /webapp.py
parent49cac8bdae0ec787372d227545411ef14905d6a8 (diff)
downloaddebian-dedup-7f3d8c5098d23bb43b86e060700170cc41cd22aa.tar.gz
permit multiple architectures per package
While the importer can easily cope with this change, the web presentation still needs fixing. It works somewhat now.
Diffstat (limited to 'webapp.py')
-rwxr-xr-xwebapp.py82
1 files changed, 56 insertions, 26 deletions
diff --git a/webapp.py b/webapp.py
index d5f076e..2819a83 100755
--- a/webapp.py
+++ b/webapp.py
@@ -60,6 +60,11 @@ def html_response(unicode_iterator, max_age=24 * 60 * 60):
resp.expires = datetime.datetime.now() + datetime.timedelta(seconds=max_age)
return resp
+class InternalRedirect(Exception):
+ def __init__(self, target):
+ Exception.__init__(self)
+ self.target = target
+
class Application(object):
def __init__(self, db):
self.db = db
@@ -83,9 +88,8 @@ class Application(object):
elif endpoint == "hash":
if args["function"] == "image_sha512":
# backwards compatibility
- raise RequestRedirect("%s/hash/png_sha512/%s" %
- (request.environ["SCRIPT_NAME"],
- args["hashvalue"]))
+ raise InternalRedirect("/hash/png_sha512/%s" %
+ args["hashvalue"])
return self.show_hash(args["function"], args["hashvalue"])
elif endpoint == "index":
if not request.environ["PATH_INFO"]:
@@ -94,28 +98,33 @@ class Application(object):
elif endpoint == "source":
return self.show_source(args["package"])
raise NotFound()
+ except InternalRedirect as r:
+ return RequestRedirect(request.environ["SCRIPT_NAME"] + r.target)
except HTTPException as e:
return e
- def get_details(self, package):
+ def guess_package(self, package):
cur = self.db.cursor()
- cur.execute("SELECT id, version, architecture FROM package WHERE name = ?;",
+ cur.execute("SELECT architecture, id FROM package WHERE name = ?;",
(package,))
+ ret = dict(cur.fetchall())
+ if not ret:
+ raise NotFound()
+ return ret
+
+ def get_details(self, package, architecture):
+ cur = self.db.cursor()
+ cur.execute("SELECT package.id, package.version, package.architecture, count(content.filename), sum(content.size) FROM package JOIN content ON package.id = content.pid WHERE name = ? AND architecture = ? GROUP BY package.id;",
+ (package, architecture))
row = cur.fetchone()
if not row:
raise NotFound()
- pid, version, architecture = row
- details = dict(pid=pid,
- package=package,
- version=version,
- architecture=architecture)
- cur.execute("SELECT count(filename), sum(size) FROM content WHERE pid = ?;",
- (pid,))
- num_files, total_size = cur.fetchone()
+ pid, version, architecture, num_files, total_size = row
if total_size is None:
total_size = 0
- details.update(dict(num_files=num_files, total_size=total_size))
- return details
+ return dict(pid=pid, package=package, version=version,
+ architecture=architecture, num_files=num_files,
+ total_size=total_size)
def get_dependencies(self, pid):
cur = self.db.cursor()
@@ -126,18 +135,24 @@ class Application(object):
def cached_sharedstats(self, pid):
cur = self.db.cursor()
sharedstats = {}
- cur.execute("SELECT pid2, package.name, f1.name, f2.name, files, size FROM sharing JOIN package ON sharing.pid2 = package.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE pid1 = ? AND f1.eqclass = f2.eqclass;",
+ cur.execute("SELECT pid2, package.name, package.architecture, f1.name, f2.name, files, size FROM sharing JOIN package ON sharing.pid2 = package.id JOIN function AS f1 ON sharing.fid1 = f1.id JOIN function AS f2 ON sharing.fid2 = f2.id WHERE pid1 = ? AND f1.eqclass = f2.eqclass;",
(pid,))
- for pid2, package2, func1, func2, files, size in fetchiter(cur):
+ for pid2, package2, architecture2, func1, func2, files, size in fetchiter(cur):
curstats = sharedstats.setdefault(
function_combination(func1, func2), list())
if pid2 == pid:
package2 = None
- curstats.append(dict(package=package2, duplicate=files, savable=size))
+ architecture2 = None
+ curstats.append(dict(package=package2, architecture=architecture2, duplicate=files, savable=size))
return sharedstats
def show_package(self, package):
- params = self.get_details(package)
+ if ':' in package:
+ package, architecture = package.split(':', 1)
+ else:
+ architecture = min(self.guess_package(package))
+ raise InternalRedirect("/binary/%s:%s" % (package, architecture))
+ params = self.get_details(package, architecture)
params["dependencies"] = self.get_dependencies(params["pid"])
params["shared"] = self.cached_sharedstats(params["pid"])
params["urlroot"] = ".."
@@ -193,9 +208,24 @@ class Application(object):
yield entry
def show_detail(self, package1, package2):
- details1 = details2 = self.get_details(package1)
- if package1 != package2:
- details2 = self.get_details(package2)
+ guessed = False
+ if ':' in package1:
+ package1, architecture1 = package1.split(':', 1)
+ else:
+ architecture1 = min(self.guess_package(package1))
+ guessed = True
+ if ':' in package2:
+ package2, architecture2 = package2.split(':', 1)
+ else:
+ architecture2 = min(self.guess_package(package2))
+ guessed = True
+ if guessed:
+ raise InternalRedirect("/compare/%s:%s/%s:%s" %
+ (package1, architecture1, package2,
+ architecture2))
+ details1 = details2 = self.get_details(package1, architecture1)
+ if package1 != package2 or architecture1 != architecture2:
+ details2 = self.get_details(package2, architecture2)
shared = self.compute_comparison(details1["pid"], details2["pid"])
params = dict(
@@ -207,11 +237,11 @@ class Application(object):
def show_hash(self, function, hashvalue):
cur = self.db.cursor()
- cur.execute("SELECT package.name, content.filename, content.size, f2.name FROM hash JOIN content ON hash.cid = content.id JOIN package ON content.pid = package.id JOIN function AS f2 ON hash.fid = f2.id JOIN function AS f1 ON f2.eqclass = f1.eqclass WHERE f1.name = ? AND hash = ?;",
+ cur.execute("SELECT package.name, package.architecture, content.filename, content.size, f2.name FROM hash JOIN content ON hash.cid = content.id JOIN package ON content.pid = package.id JOIN function AS f2 ON hash.fid = f2.id JOIN function AS f1 ON f2.eqclass = f1.eqclass WHERE f1.name = ? AND hash = ?;",
(function, hashvalue,))
- entries = [dict(package=package, filename=filename, size=size,
- function=otherfunc)
- for package, filename, size, otherfunc in fetchiter(cur)]
+ entries = [dict(package=package, architecture=architecture,
+ filename=filename, size=size, function=otherfunc)
+ for package, architecture, filename, size, otherfunc in fetchiter(cur)]
if not entries:
raise NotFound()
params = dict(function=function, hashvalue=hashvalue, entries=entries,