Chromium Code Reviews| Index: appengine/findit/common/repo_util.py |
| diff --git a/appengine/findit/common/repo_util.py b/appengine/findit/common/repo_util.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..78662f91565b4b483345d3dd20abc927235bf625 |
| --- /dev/null |
| +++ b/appengine/findit/common/repo_util.py |
| @@ -0,0 +1,85 @@ |
| +# Copyright 2016 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +import json |
| +import re |
| +import urllib2 |
| + |
| +CODE_REVIEW_URL_PATTERN = re.compile( |
| + '^(?:Review URL|Review-Url): (.*\d+).*$', re.IGNORECASE) |
| +COMMIT_POSITION_PATTERN = re.compile( |
| + '^Cr-Commit-Position: refs/heads/master@{#(\d+)}$', re.IGNORECASE) |
| +REVERTED_REVISION_PATTERN = re.compile( |
| + '^> Committed: https://.+/([0-9a-fA-F]{40})$', re.IGNORECASE) |
| + |
| + |
| +def ExtractCommitPositionAndCodeReviewUrl(message): |
| + """Returns the commit position and code review url in the commit message. |
| + |
| + A "commit position" is something similar to SVN version ids; i.e., |
| + numeric identifiers which are issued in sequential order. The reason |
| + we care about them is that they're easier for humans to read than |
| + the hashes that Git uses internally for identifying commits. We |
| + should never actually use them for *identifying* commits; they're |
| + only for pretty printing to humans. |
| + |
| + Returns: |
| + (commit_position, code_review_url) |
| + """ |
| + if not message: |
| + return (None, None) |
| + |
| + commit_position = None |
| + code_review_url = None |
| + |
| + # Commit position and code review url are in the last 5 lines. |
| + lines = message.strip().split('\n')[-5:] |
|
lijeffrey
2016/10/20 23:31:32
move this to a constant
Sharu Jiang
2016/10/21 01:07:42
Cannot think of a good name except a extremely lon
wrengr
2016/10/28 18:15:36
START_OF_CR_COMMIT_POSITION (or expand "CR" if pre
Sharu Jiang
2016/10/28 21:05:36
Sounds good :)
|
| + lines.reverse() |
| + |
| + for line in lines: |
| + if commit_position is None: |
| + match = COMMIT_POSITION_PATTERN.match(line) |
| + if match: |
| + commit_position = int(match.group(1)) |
| + |
| + if code_review_url is None: |
| + match = CODE_REVIEW_URL_PATTERN.match(line) |
| + if match: |
| + code_review_url = match.group(1) |
| + return (commit_position, code_review_url) |
| + |
| + |
| +def NormalizeEmail(email): |
| + """Normalizes the email from git repo. |
| + |
| + Some email is like: test@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538. |
| + """ |
| + parts = email.split('@') |
| + return '@'.join(parts[0:2]) |
| + |
| + |
| +def GetRevertedRevision(message): |
| + """Parse message to get the reverted revision if there is one.""" |
| + lines = message.strip().splitlines() |
| + if not lines[0].lower().startswith('revert'): |
| + return None |
| + |
| + for line in reversed(lines): # pragma: no cover |
| + # TODO: Handle cases where no reverted_revision in reverting message. |
| + reverted_revision_match = REVERTED_REVISION_PATTERN.match(line) |
| + if reverted_revision_match: |
| + return reverted_revision_match.group(1) |
| + |
| + |
| +def GetRepoToCloneUrlDict(host_url): |
| + # Gerrit prepends )]}' to json-formatted response. |
| + content = urllib2.urlopen('%s?format=json' % host_url).read() |
| + prefix = ')]}\'\n' |
| + repo_infos = json.loads(content[len(prefix):]) |
| + |
| + repo_to_clone_url = {} |
| + for repo, repo_info in repo_infos.iteritems(): |
| + repo_to_clone_url[repo] = repo_info['clone_url'] |
| + |
| + return repo_to_clone_url |