Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Implementation of package repository service. | 5 """Implementation of package repository service. |
| 6 | 6 |
| 7 Package and PackageInstance | 7 Package and PackageInstance |
| 8 --------------------------- | 8 --------------------------- |
| 9 | 9 |
| 10 Definitions: | 10 Definitions: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 ACL changes are applied atomically (e.g. multiple ACLs can be changed all at | 76 ACL changes are applied atomically (e.g. multiple ACLs can be changed all at |
| 77 once or none at all), but checks are still only eventually consistent (for | 77 once or none at all), but checks are still only eventually consistent (for |
| 78 performance and code simplicity). | 78 performance and code simplicity). |
| 79 | 79 |
| 80 TODO(vadimsh): Add fine grain ACL for tags. Tags that are set by Buildbot | 80 TODO(vadimsh): Add fine grain ACL for tags. Tags that are set by Buildbot |
| 81 builders should not be allowed to set by other WRITERs. | 81 builders should not be allowed to set by other WRITERs. |
| 82 """ | 82 """ |
| 83 | 83 |
| 84 import collections | 84 import collections |
| 85 import hashlib | 85 import hashlib |
| 86 import itertools | |
| 86 import json | 87 import json |
| 87 import logging | 88 import logging |
| 88 import re | 89 import re |
| 89 import webapp2 | 90 import webapp2 |
| 90 | 91 |
| 91 from google.appengine import runtime | 92 from google.appengine import runtime |
| 92 from google.appengine.api import datastore_errors | 93 from google.appengine.api import datastore_errors |
| 93 from google.appengine.ext import ndb | 94 from google.appengine.ext import ndb |
| 94 | 95 |
| 95 from components import auth | 96 from components import auth |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 """Returns Package entity if it exists. | 159 """Returns Package entity if it exists. |
| 159 | 160 |
| 160 Args: | 161 Args: |
| 161 package_name: name of the package, e.g. 'infra/tools/cipd'. | 162 package_name: name of the package, e.g. 'infra/tools/cipd'. |
| 162 | 163 |
| 163 Returns: | 164 Returns: |
| 164 Package or None. | 165 Package or None. |
| 165 """ | 166 """ |
| 166 return package_key(package_name).get() | 167 return package_key(package_name).get() |
| 167 | 168 |
| 169 @staticmethod | |
| 170 def _is_in_directory(directory, path, recursive): | |
| 171 """Tests is the path is under the given directory. | |
|
Vadim Sh.
2015/06/23 00:08:34
typo: if
estaab
2015/06/23 02:26:13
Done.
| |
| 172 | |
| 173 This assumes directory is a prefix of path. | |
| 174 | |
| 175 Args: | |
| 176 directory: String, directory the path should fall under. | |
|
Vadim Sh.
2015/06/23 00:08:35
nit: start arg desc with lower case letter
estaab
2015/06/23 02:26:13
Done.
| |
| 177 path: String, full path to test. | |
| 178 recursive: Whether the path can be in a subdirectory. | |
| 179 | |
| 180 Returns: | |
| 181 True if the path is under the directory. | |
| 182 """ | |
| 183 start = len(directory) | |
| 184 logging.info('processing %s in %s', path, directory) | |
|
Vadim Sh.
2015/06/23 00:08:34
remove logging if it doesn't provide any additiona
estaab
2015/06/23 02:26:13
Sorry, also not supposed to be in the CL.
| |
| 185 | |
| 186 # The directory itself or anything shorter is not a match. | |
| 187 if len(path) <= start: | |
| 188 logging.info('shorter.') | |
| 189 return False | |
| 190 | |
| 191 # The root doesn't begin with slash so only check non-root searches. | |
| 192 if start: | |
| 193 if path[start] != '/': | |
| 194 logging.info('next isnt /.') | |
| 195 return False | |
| 196 start += 1 | |
| 197 | |
| 198 # A subdirectory was found and we're not looking for recursive matches. | |
| 199 if not recursive and '/' in path[start:]: | |
| 200 logging.info('next after is /.') | |
| 201 return False | |
| 202 return True | |
| 203 | |
| 204 def list_packages(self, dir_path, recursive): | |
| 205 """Returns lists of package names and directory names with the given prefix. | |
| 206 | |
| 207 Args: | |
| 208 dir_path: string directory from which to list packages. | |
| 209 recursive: boolean whether to list contents of subdirectories. | |
| 210 | |
| 211 Returns: | |
| 212 [package name, ...], [directory name, ...] | |
| 213 """ | |
| 214 query = Package.query() | |
| 215 | |
| 216 # Normalize directory to simplify matching logic later. | |
| 217 dir_path = dir_path.rstrip('/') | |
| 218 | |
| 219 # Only apply the filtering if a prefix was given. The empty string isn't a | |
| 220 # valid key and will result in an exception. | |
| 221 if dir_path: | |
| 222 query = query.filter( | |
| 223 # Prefix match using the operators available to us. Packages can only | |
| 224 # contain lowercase ascii, numbers, and '/' so '\uffff' will always | |
| 225 # be larger. | |
| 226 ndb.AND(Package.key >= ndb.Key(Package, dir_path), | |
| 227 Package.key <= ndb.Key(Package, dir_path + u'\uffff'))) | |
| 228 pkgs = [] | |
| 229 dirs = set() | |
| 230 for key in query.iter(keys_only=True): | |
|
Vadim Sh.
2015/06/23 00:08:35
non-ancestor queries are eventually consistent: th
estaab
2015/06/23 02:26:13
Good to know, done. I couldn't think of an easy wa
| |
| 231 pkg = key.string_id() | |
| 232 pkgs.append(pkg) | |
| 233 | |
| 234 # Add in directories derived from full package path if it's not an exact | |
| 235 # match. | |
| 236 if '/' in pkg and len(dir_path) != len(pkg): | |
|
Vadim Sh.
2015/06/23 00:08:35
I don't understand len(dir_path) != len(pkg) condi
estaab
2015/06/23 02:26:13
Removed, this was from some older logic.
| |
| 237 parts = pkg.split('/') | |
| 238 dirs.update('/'.join(parts[:n]) for n in xrange(1, len(parts))) | |
| 239 logging.info(str(['/'.join(parts[:n]) for n in xrange(1, len(parts))])) | |
|
Vadim Sh.
2015/06/23 00:08:34
remove logging, it's probably not helpful in relea
estaab
2015/06/23 02:26:13
Done, also a mistake.
| |
| 240 | |
| 241 dirs = [d for d in dirs if self._is_in_directory(dir_path, d, recursive)] | |
| 242 pkgs = [p for p in pkgs if self._is_in_directory(dir_path, p, recursive) | |
| 243 or len(dir_path) == len(p)] | |
| 244 return pkgs, dirs | |
| 245 | |
| 168 def get_processing_result(self, package_name, instance_id, processor_name): | 246 def get_processing_result(self, package_name, instance_id, processor_name): |
| 169 """Returns results of some asynchronous processor or None if not ready. | 247 """Returns results of some asynchronous processor or None if not ready. |
| 170 | 248 |
| 171 Args: | 249 Args: |
| 172 package_name: name of the package, e.g. 'infra/tools/cipd'. | 250 package_name: name of the package, e.g. 'infra/tools/cipd'. |
| 173 instance_id: identifier of the package instance (SHA1 of package file). | 251 instance_id: identifier of the package instance (SHA1 of package file). |
| 174 processor_name: name of the processor to retrieve results of. | 252 processor_name: name of the processor to retrieve results of. |
| 175 | 253 |
| 176 Returns: | 254 Returns: |
| 177 ProcessingResult entity or None. | 255 ProcessingResult entity or None. |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 processors=payload['processors']) | 857 processors=payload['processors']) |
| 780 | 858 |
| 781 | 859 |
| 782 def get_backend_routes(): # pragma: no cover | 860 def get_backend_routes(): # pragma: no cover |
| 783 """Returns a list of webapp2.Route to add to backend WSGI app.""" | 861 """Returns a list of webapp2.Route to add to backend WSGI app.""" |
| 784 return [ | 862 return [ |
| 785 webapp2.Route( | 863 webapp2.Route( |
| 786 r'/internal/taskqueue/cipd-process/<instance_id:.+>', | 864 r'/internal/taskqueue/cipd-process/<instance_id:.+>', |
| 787 ProcessTaskQueueHandler), | 865 ProcessTaskQueueHandler), |
| 788 ] | 866 ] |
| OLD | NEW |