1# Copyright 2015 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"""Functions for getting commit information from Gitiles.""" 5from __future__ import print_function 6from __future__ import division 7from __future__ import absolute_import 8 9import base64 10 11from dashboard.services import gerrit_service 12from dashboard.services import request 13 14NotFoundError = request.NotFoundError 15 16 17def CommitInfo(repository_url, git_hash): 18 """Fetches information about a commit. 19 20 Args: 21 repository_url: The url of the git repository. 22 git_hash: The git hash of the commit. 23 24 Returns: 25 A dictionary containing the author, message, time, file changes, and other 26 information. See gitiles_service_test.py for an example. 27 28 Raises: 29 NotFoundError: The repository or commit was not found in Gitiles. 30 httplib.HTTPException: A network or HTTP error occurred. 31 """ 32 # TODO: Update the docstrings in this file. 33 url = '%s/+/%s?format=JSON' % (repository_url, git_hash) 34 return request.RequestJson( 35 url, 36 use_cache=IsHash(git_hash), 37 use_auth=True, 38 scope=gerrit_service.GERRIT_SCOPE) 39 40 41def CommitRange(repository_url, first_git_hash, last_git_hash): 42 """Fetches the commits in between first and last, including the latter. 43 44 Args: 45 repository_url: The git url of the repository. 46 first_git_hash: The git hash of the earliest commit in the range. 47 last_git_hash: The git hash of the latest commit in the range. 48 49 Returns: 50 A list of dictionaries, one for each commit after the first commit up to 51 and including the last commit. For each commit, its dictionary will 52 contain information about the author and the comitter and the commit itself. 53 See gitiles_service_test.py for an example. The list is in order from newest 54 to oldest. 55 56 Raises: 57 NotFoundError: The repository or a commit was not found in Gitiles. 58 httplib.HTTPException: A network or HTTP error occurred. 59 """ 60 commits = [] 61 while last_git_hash: 62 url = '%s/+log/%s..%s?format=JSON' % (repository_url, first_git_hash, 63 last_git_hash) 64 use_cache = IsHash(first_git_hash) and IsHash(last_git_hash) 65 response = request.RequestJson( 66 url, 67 use_cache=use_cache, 68 use_auth=True, 69 scope=gerrit_service.GERRIT_SCOPE) 70 commits += response['log'] 71 last_git_hash = response.get('next') 72 return commits 73 74 75def FileContents(repository_url, git_hash, path): 76 """Fetches the contents of a file at a particular commit. 77 78 Args: 79 repository_url: The git url of the repository. 80 git_hash: The git hash of the commit, or "HEAD". 81 path: The path in the repository to the file. 82 83 Returns: 84 A string containing the file contents. 85 86 Raises: 87 NotFoundError: The repository, commit, or file was not found in Gitiles. 88 httplib.HTTPException: A network or HTTP error occurred. 89 """ 90 url = '%s/+/%s/%s?format=TEXT' % (repository_url, git_hash, path) 91 response = request.Request( 92 url, 93 use_cache=IsHash(git_hash), 94 use_auth=True, 95 scope=gerrit_service.GERRIT_SCOPE) 96 return base64.b64decode(response) 97 98 99def IsHash(git_hash): 100 """Returns True iff git_hash is a full SHA-1 hash. 101 102 Commits keyed by full git hashes are guaranteed to not change. It's unsafe 103 to cache things that can change (e.g. `HEAD`, `master`, tag names) 104 """ 105 return git_hash.isalnum() and len(git_hash) == 40 106