| Index: chrome/common/extensions/docs/server2/gitiles_file_system.py
|
| diff --git a/chrome/common/extensions/docs/server2/gitiles_file_system.py b/chrome/common/extensions/docs/server2/gitiles_file_system.py
|
| index df907e6b08ab83d9783629f476654cda8230aa7e..8470affd80c96e38aeca637c45b413300ad92db7 100644
|
| --- a/chrome/common/extensions/docs/server2/gitiles_file_system.py
|
| +++ b/chrome/common/extensions/docs/server2/gitiles_file_system.py
|
| @@ -2,14 +2,17 @@
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| +
|
| from base64 import b64decode
|
| from itertools import izip
|
| +import logging
|
| import json
|
| import posixpath
|
| +import time
|
| import traceback
|
|
|
| from appengine_url_fetcher import AppEngineUrlFetcher
|
| -from appengine_wrappers import IsDownloadError
|
| +from appengine_wrappers import IsDownloadError, app_identity
|
| from docs_server_utils import StringIdentity
|
| from file_system import (FileNotFoundError,
|
| FileSystem,
|
| @@ -18,8 +21,9 @@ from file_system import (FileNotFoundError,
|
| from future import All, Future
|
| from path_util import AssertIsValid, IsDirectory, ToDirectory
|
| from third_party.json_schema_compiler.memoize import memoize
|
| -from url_constants import GITILES_BASE, GITILES_BRANCH_BASE
|
| -
|
| +from url_constants import (GITILES_BASE,
|
| + GITILES_BRANCH_BASE,
|
| + GITILES_OAUTH2_SCOPE)
|
|
|
| _JSON_FORMAT = '?format=JSON'
|
| _TEXT_FORMAT = '?format=TEXT'
|
| @@ -66,9 +70,12 @@ class GitilesFileSystem(FileSystem):
|
| need to use posixpath.join.
|
| '''
|
| AssertIsValid(url)
|
| - return self._fetcher.FetchAsync('%s/%s' % (self._base_url, url))
|
| + access_token, _ = app_identity.get_access_token(GITILES_OAUTH2_SCOPE)
|
| + return self._fetcher.FetchAsync('%s/%s' % (self._base_url, url),
|
| + access_token=access_token)
|
|
|
| - def _ResolveFetchContent(self, path, fetch_future, skip_not_found=False):
|
| + def _ResolveFetchContent(self, path, fetch_future, retry,
|
| + skip_not_found=False):
|
| '''Returns a future to cleanly resolve |fetch_future|.
|
| '''
|
| def handle(e):
|
| @@ -84,11 +91,17 @@ class GitilesFileSystem(FileSystem):
|
| return None
|
| raise FileNotFoundError('Got 404 when fetching %s for Get from %s' %
|
| (path, self._base_url))
|
| + if result.status_code == 429:
|
| + logging.warning('Access throttled when fetching %s for Get from %s' %
|
| + (path, self._base_url))
|
| + time.sleep(30)
|
| + return retry().Then(get_content, handle)
|
| if result.status_code != 200:
|
| raise FileSystemError(
|
| 'Got %s when fetching %s for Get from %s, content %s' %
|
| (result.status_code, path, self._base_url, result.content))
|
| return result.content
|
| +
|
| return fetch_future.Then(get_content, handle)
|
|
|
| def Read(self, paths, skip_not_found=False):
|
| @@ -118,8 +131,11 @@ class GitilesFileSystem(FileSystem):
|
| return path + (_JSON_FORMAT if IsDirectory(path) else _TEXT_FORMAT)
|
|
|
| # A list of tuples of the form (path, Future).
|
| - fetches = ((path, self._FetchAsync(fixup_url_format(path)))
|
| - for path in paths)
|
| + fetches = []
|
| + for path in paths:
|
| + def make_fetch_future():
|
| + return self._FetchAsync(fixup_url_format(path))
|
| + fetches.append((path, make_fetch_future(), make_fetch_future))
|
|
|
| def parse_contents(results):
|
| value = {}
|
| @@ -130,8 +146,9 @@ class GitilesFileSystem(FileSystem):
|
| # http://tools.ietf.org/html/rfc4648 for info about base64).
|
| value[path] = (list_dir if IsDirectory(path) else b64decode)(content)
|
| return value
|
| - return All(self._ResolveFetchContent(path, future, skip_not_found)
|
| - for path, future in fetches).Then(parse_contents)
|
| +
|
| + return All(self._ResolveFetchContent(path, future, factory, skip_not_found)
|
| + for path, future, factory in fetches).Then(parse_contents)
|
|
|
| def Refresh(self):
|
| return Future(value=())
|
| @@ -166,8 +183,15 @@ class GitilesFileSystem(FileSystem):
|
| # different from '<gitiles_url>/<branch>/?format=JSON': the latter serves
|
| # the root directory JSON content, whereas the former serves the branch
|
| # commit info JSON content.
|
| - fetch_future = self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT)
|
| - content_future = self._ResolveFetchContent(self._base_url, fetch_future)
|
| +
|
| + def make_fetch_future():
|
| + access_token, _ = app_identity.get_access_token(GITILES_OAUTH2_SCOPE)
|
| + return self._fetcher.FetchAsync(self._base_url + _JSON_FORMAT,
|
| + access_token = access_token)
|
| +
|
| + fetch_future = make_fetch_future()
|
| + content_future = self._ResolveFetchContent(self._base_url, fetch_future,
|
| + make_fetch_future)
|
| return content_future.Then(lambda json: _ParseGitilesJson(json)[key])
|
|
|
| def GetCommitID(self):
|
| @@ -175,6 +199,11 @@ class GitilesFileSystem(FileSystem):
|
| '''
|
| return self._GetCommitInfo('commit')
|
|
|
| + def GetPreviousCommitID(self):
|
| + '''Returns a future that resolves to the previous commit ID for this branch.
|
| + '''
|
| + return self._GetCommitInfo('parents').Then(lambda parents: parents[0])
|
| +
|
| def StatAsync(self, path):
|
| dir_, filename = posixpath.split(path)
|
| def stat(content):
|
| @@ -187,8 +216,13 @@ class GitilesFileSystem(FileSystem):
|
| raise FileNotFoundError(
|
| '%s from %s was not in child versions for Stat' % (filename, path))
|
| return StatInfo(stat_info.child_versions[filename])
|
| - fetch_future = self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT)
|
| - return self._ResolveFetchContent(path, fetch_future).Then(stat)
|
| +
|
| + def make_fetch_future():
|
| + return self._FetchAsync(ToDirectory(dir_) + _JSON_FORMAT)
|
| +
|
| + fetch_future = make_fetch_future()
|
| + return self._ResolveFetchContent(path, fetch_future,
|
| + make_fetch_future).Then(stat)
|
|
|
| def GetIdentity(self):
|
| # NOTE: Do not use commit information to create the string identity.
|
|
|