| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import json |
| 6 |
| 7 from appengine_url_fetcher import AppEngineUrlFetcher |
| 8 from appengine_wrappers import GetAppVersion |
| 9 from object_store_creator import ObjectStoreCreator |
| 10 #from servlet import Servlet |
| 11 import svn_constants |
| 12 import url_constants |
| 13 |
| 14 PATCH_BASEURL = '_patch/' |
| 15 PATCH_CHANNEL_NAME = 'trunk' |
| 16 CHROMIUM_REPO_BASEURLS = [ |
| 17 'https://src.chromium.org/svn/trunk/src/', |
| 18 'http://src.chromium.org/svn/trunk/src/', |
| 19 'svn://svn.chromium.org/chrome/trunk/src', |
| 20 'https://chromium.googlesource.com/chromium/src.git@master', |
| 21 'http://git.chromium.org/chromium/src.git@master', |
| 22 ] |
| 23 DOCS_PATHS = [ |
| 24 svn_constants.API_PATH, |
| 25 svn_constants.INTRO_PATH, |
| 26 svn_constants.ARTICLE_PATH, |
| 27 svn_constants.PUBLIC_TEMPLATE_PATH, |
| 28 svn_constants.PRIVATE_TEMPLATE_PATH, |
| 29 svn_constants.JSON_PATH, |
| 30 svn_constants.STATIC_PATH |
| 31 ] |
| 32 RIETVELD_ISSUE_JSON = 'api/%s' |
| 33 RIETVELD_PATCHSET_JSON = 'api/%s/%s' |
| 34 |
| 35 class PatchData(object): |
| 36 _object_store = None |
| 37 |
| 38 def __init__(self, issue, patchset, files): |
| 39 self.issue = issue |
| 40 self.patchset = patchset |
| 41 self.files = files |
| 42 |
| 43 @staticmethod |
| 44 def Create(issue): |
| 45 fetcher = AppEngineUrlFetcher(url_constants.CODEREVIEW_SERVER) |
| 46 object_store = PatchData._GetOrCreateObjectStore() |
| 47 patchset = PatchData._GetPatchsetFromIssue(issue, fetcher, object_store) |
| 48 if patchset is None: |
| 49 return None |
| 50 files = PatchData._GetPatchsetFiles(issue, patchset, fetcher, object_store) |
| 51 if len(files) == 0: |
| 52 return None |
| 53 return PatchData(issue, patchset, files) |
| 54 |
| 55 @staticmethod |
| 56 def _GetPatchsetFromIssue(issue, fetcher, object_store): |
| 57 patchset = object_store.Get(issue).Get() |
| 58 if patchset is not None: |
| 59 return patchset |
| 60 |
| 61 try: |
| 62 issue_json = json.loads(fetcher.Fetch( |
| 63 RIETVELD_ISSUE_JSON % issue).content) |
| 64 except Exception as e: |
| 65 return None |
| 66 |
| 67 if issue_json.get('closed'): |
| 68 return None |
| 69 |
| 70 patchsets = issue_json.get('patchsets') |
| 71 if not isinstance(patchsets, list) or len(patchsets) == 0: |
| 72 return None |
| 73 |
| 74 if not issue_json.get('base_url') in CHROMIUM_REPO_BASEURLS: |
| 75 return None |
| 76 |
| 77 patchset = patchsets[-1] |
| 78 object_store.Set(issue, patchset) |
| 79 return patchset |
| 80 |
| 81 @staticmethod |
| 82 def _GetPatchsetFiles(issue, patchset, fetcher, object_store): |
| 83 key = '%s.%s' % (issue, patchset) |
| 84 docs_files = object_store.Get(key).Get() |
| 85 if docs_files is not None: |
| 86 return docs_files |
| 87 |
| 88 try: |
| 89 patchset_json = json.loads(fetcher.Fetch( |
| 90 RIETVELD_PATCHSET_JSON % (issue, patchset)).content) |
| 91 except Exception as e: |
| 92 return [] |
| 93 |
| 94 files = patchset_json.get('files') |
| 95 if files is None or not isinstance(files, dict): |
| 96 return [] |
| 97 |
| 98 docs_files = [] |
| 99 for f in files: |
| 100 f = f.split(svn_constants.EXTENSIONS_PATH + '/', 1)[1] |
| 101 if (f.startswith(svn_constants.DOCS_PATH) or |
| 102 f.startswith(svn_constants.API_PATH)): |
| 103 docs_files.append(f) |
| 104 if len(docs_files) == 0: |
| 105 return [] |
| 106 |
| 107 object_store.Set(key, docs_files) |
| 108 return docs_files |
| 109 |
| 110 @staticmethod |
| 111 def _GetOrCreateObjectStore(): |
| 112 if PatchData._object_store is None: |
| 113 PatchData._object_store = (ObjectStoreCreator.SharedFactory( |
| 114 GetAppVersion()).Create(PatchData).Create()) |
| 115 return PatchData._object_store |
| 116 |
| 117 class PatchServlet(object): |
| 118 '''Servlet which renders patched docs. |
| 119 ''' |
| 120 @staticmethod |
| 121 def SplitPatchFromPath(path): |
| 122 if path.startswith(PATCH_BASEURL): |
| 123 remaining_path = path.split(PATCH_BASEURL, 1)[1] |
| 124 if not '/' in remaining_path: |
| 125 return (None, None, None) |
| 126 issue, real_path = remaining_path.split('/', 1) |
| 127 if not issue.isdigit() or len(real_path) == 0: |
| 128 return (None, None, None) |
| 129 return (PATCH_CHANNEL_NAME, issue, real_path) |
| 130 else: |
| 131 return (None, None, None) |
| OLD | NEW |