LEFT | RIGHT |
1 # Copyright 2010 The Go Authors. All rights reserved. | 1 # Copyright 2010 The Go Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style | 2 # Use of this source code is governed by a BSD-style |
3 # license that can be found in the LICENSE file. | 3 # license that can be found in the LICENSE file. |
4 | 4 |
5 # This is the server part of the package dashboard. | 5 # This is the server part of the package dashboard. |
6 # It must be run by App Engine. | 6 # It must be run by App Engine. |
7 | 7 |
8 from google.appengine.api import memcache | 8 from google.appengine.api import memcache |
9 from google.appengine.runtime import DeadlineExceededError | 9 from google.appengine.runtime import DeadlineExceededError |
10 from google.appengine.ext import db | 10 from google.appengine.ext import db |
(...skipping 14 matching lines...) Expand all Loading... |
25 # Storage model for package info recorded on server. | 25 # Storage model for package info recorded on server. |
26 # Just path, count, and time of last install. | 26 # Just path, count, and time of last install. |
27 class Package(db.Model): | 27 class Package(db.Model): |
28 path = db.StringProperty() | 28 path = db.StringProperty() |
29 web_url = db.StringProperty() # derived from path | 29 web_url = db.StringProperty() # derived from path |
30 count = db.IntegerProperty() | 30 count = db.IntegerProperty() |
31 last_install = db.DateTimeProperty() | 31 last_install = db.DateTimeProperty() |
32 | 32 |
33 re_bitbucket = re.compile(r'^bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$') | 33 re_bitbucket = re.compile(r'^bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$') |
34 re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$') | 34 re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$') |
35 re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+\.git$') | 35 re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$') |
36 | 36 |
37 MaxPathLength = 100 | 37 MaxPathLength = 100 |
38 | 38 |
39 class PackagePage(webapp.RequestHandler): | 39 class PackagePage(webapp.RequestHandler): |
40 def get(self): | 40 def get(self): |
41 if self.request.get('fmt') == 'json': | 41 if self.request.get('fmt') == 'json': |
42 return self.json() | 42 return self.json() |
43 | 43 |
44 q = Package.all() | 44 q = Package.all() |
45 q.order('-last_install') | 45 q.order('-last_install') |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 key = 'pkg-' + path | 87 key = 'pkg-' + path |
88 p = Package.get_by_key_name(key) | 88 p = Package.get_by_key_name(key) |
89 if p is None: | 89 if p is None: |
90 # not in datastore - verify URL before creating | 90 # not in datastore - verify URL before creating |
91 if re_bitbucket.match(path): | 91 if re_bitbucket.match(path): |
92 check_url = 'http://' + path + '/?cmd=heads' | 92 check_url = 'http://' + path + '/?cmd=heads' |
93 web = 'http://' + path + '/' | 93 web = 'http://' + path + '/' |
94 elif re_github.match(path): | 94 elif re_github.match(path): |
95 # github doesn't let you fetch the .git directory anymore. | 95 # github doesn't let you fetch the .git directory anymore. |
96 # fetch .git/info/refs instead, like git clone would. | 96 # fetch .git/info/refs instead, like git clone would. |
97 check_url = 'http://'+path+'/info/refs' | 97 check_url = 'http://'+path+'.git/info/refs' |
98 web = 'http://' + path[:-4] # drop .git | 98 web = 'http://' + path |
99 elif re_googlecode.match(path): | 99 elif re_googlecode.match(path): |
100 check_url = 'http://'+path | 100 check_url = 'http://'+path |
101 web = 'http://code.google.com/p/' + path[:path.index('.')] | 101 web = 'http://code.google.com/p/' + path[:path.index('.')] |
102 else: | 102 else: |
103 logging.error('unrecognized path: %s', path) | 103 logging.error('unrecognized path: %s', path) |
104 return False | 104 return False |
105 if not self.can_get_url(check_url): | 105 if not self.can_get_url(check_url): |
106 logging.error('cannot get %s', check_url) | 106 logging.error('cannot get %s', check_url) |
107 return False | 107 return False |
108 p = Package(key_name = key, path = path, count = 0, web_url = web) | 108 p = Package(key_name = key, path = path, count = 0, web_url = web) |
(...skipping 14 matching lines...) Expand all Loading... |
123 logging.error('invalid path in post: %s', path) | 123 logging.error('invalid path in post: %s', path) |
124 self.response.set_status(500) | 124 self.response.set_status(500) |
125 self.response.out.write('not ok') | 125 self.response.out.write('not ok') |
126 | 126 |
127 def main(): | 127 def main(): |
128 app = webapp.WSGIApplication([('/package', PackagePage)], debug=True) | 128 app = webapp.WSGIApplication([('/package', PackagePage)], debug=True) |
129 run_wsgi_app(app) | 129 run_wsgi_app(app) |
130 | 130 |
131 if __name__ == '__main__': | 131 if __name__ == '__main__': |
132 main() | 132 main() |
LEFT | RIGHT |