1
0
mirror of https://github.com/golang/go synced 2024-11-21 21:04:41 -07:00

dashboard: more aggressive caching for project/package pages

Plus automatic package<->project association script.
(This is just a helper script for now. I intend to fully automate
the associations further down the track.)

R=rsc
CC=golang-dev
https://golang.org/cl/1715054
This commit is contained in:
Andrew Gerrand 2010-07-27 15:02:44 +10:00
parent 711f075987
commit fc5a835b2e

View File

@ -17,6 +17,7 @@ from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users from google.appengine.api import users
from google.appengine.api import mail from google.appengine.api import mail
from google.appengine.api import urlfetch
import binascii import binascii
import datetime import datetime
import hashlib import hashlib
@ -50,36 +51,91 @@ re_bitbucket = re.compile(r'^bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$') re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$')
re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$') re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
def vc_to_web(path):
if re_bitbucket.match(path):
check_url = 'http://' + path + '/?cmd=heads'
web = 'http://' + path + '/'
elif re_github.match(path):
# github doesn't let you fetch the .git directory anymore.
# fetch .git/info/refs instead, like git clone would.
check_url = 'http://'+path+'.git/info/refs'
web = 'http://' + path
elif re_googlecode.match(path):
check_url = 'http://'+path
web = 'http://code.google.com/p/' + path[:path.index('.')]
else:
return False, False
return web, check_url
re_bitbucket_web = re.compile(r'bitbucket\.org/([a-z0-9A-Z_.\-]+)/([a-z0-9A-Z_.\-]+)')
re_googlecode_web = re.compile(r'code.google.com/p/([a-z0-9\-]+)')
re_github_web = re.compile(r'github\.com/([a-z0-9A-Z_.\-]+)/([a-z0-9A-Z_.\-]+)')
re_striphttp = re.compile(r'http://(www\.)?')
def web_to_vc(url):
url = re_striphttp.sub('', url)
m = re_bitbucket_web.match(url)
if m:
return 'bitbucket.org/'+m.group(1)+'/'+m.group(2)
m = re_github_web.match(url)
if m:
return 'github.com/'+m.group(1)+'/'+m.group(2)
m = re_googlecode_web.match(url)
if m:
path = m.group(1)+'.googlecode.com/'
# perform http request to path/hg to check if they're using mercurial
vcs = 'svn'
try:
response = urlfetch.fetch('http://'+path+'hg', deadline=1)
if response.status_code == 200:
vcs = 'hg'
except: pass
return path + vcs
return False
MaxPathLength = 100 MaxPathLength = 100
CacheTimeout = 3600
class PackagePage(webapp.RequestHandler): class PackagePage(webapp.RequestHandler):
def get(self): def get(self):
if self.request.get('fmt') == 'json': if self.request.get('fmt') == 'json':
return self.json() return self.json()
q = Package.all() html = memcache.get('view-package')
q.order('-last_install') if not html:
by_time = q.fetch(100) q = Package.all()
q.order('-last_install')
by_time = q.fetch(100)
q = Package.all() q = Package.all()
q.order('-count') q.order('-count')
by_count = q.fetch(100) by_count = q.fetch(100)
self.response.headers['Content-Type'] = 'text/html; charset=utf-8' self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
path = os.path.join(os.path.dirname(__file__), 'package.html') path = os.path.join(os.path.dirname(__file__), 'package.html')
self.response.out.write(template.render(path, {"by_time": by_time, "by_count": by_count})) html = template.render(
path,
{"by_time": by_time, "by_count": by_count}
)
memcache.set('view-package', html, time=CacheTimeout)
self.response.out.write(html)
def json(self): def json(self):
self.response.set_status(200) json = memcache.get('view-package-json')
self.response.headers['Content-Type'] = 'text/plain; charset=utf-8' if not json:
q = Package.all() self.response.set_status(200)
s = '{"packages": [' self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
sep = '' q = Package.all()
for r in q.fetch(1000): s = '{"packages": ['
s += '%s\n\t{"path": "%s", "last_install": "%s", "count": "%s"}' % (sep, r.path, r.last_install, r.count) sep = ''
sep = ',' for r in q.fetch(1000):
s += '\n]}\n' s += '%s\n\t{"path": "%s", "last_install": "%s", "count": "%s"}' % (sep, r.path, r.last_install, r.count)
self.response.out.write(s) sep = ','
s += '\n]}\n'
json = s
memcache.set('view-package-json', json, time=CacheTimeoout)
self.response.out.write(json)
def can_get_url(self, url): def can_get_url(self, url):
try: try:
@ -104,18 +160,8 @@ class PackagePage(webapp.RequestHandler):
p = Package.get_by_key_name(key) p = Package.get_by_key_name(key)
if p is None: if p is None:
# not in datastore - verify URL before creating # not in datastore - verify URL before creating
if re_bitbucket.match(path): web, check_url = vc_to_web(path)
check_url = 'http://' + path + '/?cmd=heads' if not web:
web = 'http://' + path + '/'
elif re_github.match(path):
# github doesn't let you fetch the .git directory anymore.
# fetch .git/info/refs instead, like git clone would.
check_url = 'http://'+path+'.git/info/refs'
web = 'http://' + path
elif re_googlecode.match(path):
check_url = 'http://'+path
web = 'http://code.google.com/p/' + path[:path.index('.')]
else:
logging.error('unrecognized path: %s', path) logging.error('unrecognized path: %s', path)
return False return False
if not self.can_get_url(check_url): if not self.can_get_url(check_url):
@ -150,9 +196,27 @@ class ProjectPage(webapp.RequestHandler):
self.redirect(users.create_logout_url("/project")) self.redirect(users.create_logout_url("/project"))
elif self.request.path == "/project/edit" and admin: elif self.request.path == "/project/edit" and admin:
self.edit() self.edit()
elif self.request.path == "/project/assoc" and admin:
self.assoc()
else: else:
self.list() self.list()
def assoc(self):
projects = Project.all()
for p in projects:
if p.package:
continue
path = web_to_vc(p.web_url)
if not path:
continue
pkg = Package.get_by_key_name("pkg-"+path)
if not pkg:
self.response.out.write('no: %s %s<br>' % (p.web_url, path))
continue
p.package = pkg
p.put()
self.response.out.write('yes: %s %s<br>' % (p.web_url, path))
def post(self): def post(self):
if self.request.path == "/project/edit": if self.request.path == "/project/edit":
self.edit(True) self.edit(True)
@ -177,30 +241,37 @@ class ProjectPage(webapp.RequestHandler):
self.list({"submitMsg": "Your project has been submitted."}) self.list({"submitMsg": "Your project has been submitted."})
def list(self, data={}): def list(self, additional_data={}):
projects = Project.all().order('category').order('name') data = memcache.get('view-project-data')
admin = users.is_current_user_admin() admin = users.is_current_user_admin()
if not admin: if admin or not data:
projects = projects.filter('approved =', True) projects = Project.all().order('category').order('name')
if not admin:
projects = projects.filter('approved =', True)
projects = list(projects)
projects = list(projects) tags = sets.Set()
for p in projects:
for t in p.tags:
tags.add(t)
tags = sets.Set() tag = self.request.get('tag', None)
for p in projects: if tag:
for t in p.tags: projects = filter(lambda x: tag in x.tags, projects)
tags.add(t)
tag = self.request.get("tag", None) data = {}
if tag: data['tag'] = tag
projects = filter(lambda x: tag in x.tags, projects) data['tags'] = tags
data['projects'] = projects
data['admin']= admin
if not admin:
memcache.set('view-project-data', data, time=CacheTimeout)
for k, v in additional_data.items():
data[k] = v
self.response.headers['Content-Type'] = 'text/html; charset=utf-8' self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
path = os.path.join(os.path.dirname(__file__), 'project.html') path = os.path.join(os.path.dirname(__file__), 'project.html')
data["tag"] = tag
data["tags"] = tags
data["projects"] = projects
data["admin"] = admin
self.response.out.write(template.render(path, data)) self.response.out.write(template.render(path, data))
def edit(self, save=False): def edit(self, save=False):
@ -228,7 +299,8 @@ class ProjectPage(webapp.RequestHandler):
p.approved = self.request.get("approved") == "1" p.approved = self.request.get("approved") == "1"
p.tags = filter(lambda x: x, self.request.get("tags", "").split(",")) p.tags = filter(lambda x: x, self.request.get("tags", "").split(","))
p.put() p.put()
self.redirect("/project") memcache.delete('view-project-data')
self.redirect('/project')
return return
# get all project categories and tags # get all project categories and tags