[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | """Top-level presubmit script for Chromium. |
| 7 | |
| 8 | See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for |
| 9 | details on the presubmit API built into gcl. |
| 10 | """ |
| 11 | |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 12 | EXCLUDED_PATHS = ( |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 13 | r"breakpad[\\\/].*", |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 14 | r"skia[\\\/].*", |
[email protected] | 3347870 | 2009-03-05 14:03:14 | [diff] [blame] | 15 | r"v8[\\\/].*", |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 16 | ) |
[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 17 | |
[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 18 | |
[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 19 | def CheckChangeOnUpload(input_api, output_api): |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame] | 20 | results = [] |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 21 | # What does this code do? |
| 22 | # It loads the default black list (e.g. third_party, experimental, etc) and |
| 23 | # add our black list (breakpad, skia and v8 are still not following |
| 24 | # google style and are not really living this repository). |
| 25 | # See presubmit_support.py InputApi.FilterSourceFile for the (simple) usage. |
| 26 | black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS |
| 27 | sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list) |
| 28 | results.extend(input_api.canned_checks.CheckLongLines( |
| 29 | input_api, output_api, sources)) |
| 30 | results.extend(input_api.canned_checks.CheckChangeHasNoTabs( |
| 31 | input_api, output_api, sources)) |
| 32 | results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace( |
| 33 | input_api, output_api, sources)) |
| 34 | results.extend(input_api.canned_checks.CheckChangeHasBugField( |
| 35 | input_api, output_api)) |
| 36 | results.extend(input_api.canned_checks.CheckChangeHasTestField( |
| 37 | input_api, output_api)) |
| 38 | results.extend(input_api.canned_checks.CheckChangeSvnEolStyle( |
| 39 | input_api, output_api, sources)) |
[email protected] | 40cdf8b3 | 2009-06-26 23:00:37 | [diff] [blame] | 40 | results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( |
| 41 | input_api, output_api)) |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame] | 42 | return results |
[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 43 | |
| 44 | |
| 45 | def CheckChangeOnCommit(input_api, output_api): |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame] | 46 | results = [] |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 47 | black_list = input_api.DEFAULT_BLACK_LIST + EXCLUDED_PATHS |
| 48 | sources = lambda x: input_api.FilterSourceFile(x, black_list=black_list) |
| 49 | results.extend(input_api.canned_checks.CheckLongLines( |
| 50 | input_api, output_api, sources)) |
| 51 | results.extend(input_api.canned_checks.CheckChangeHasNoTabs( |
| 52 | input_api, output_api, sources)) |
| 53 | results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace( |
| 54 | input_api, output_api, sources)) |
| 55 | results.extend(input_api.canned_checks.CheckChangeHasBugField( |
| 56 | input_api, output_api)) |
| 57 | results.extend(input_api.canned_checks.CheckChangeHasTestField( |
| 58 | input_api, output_api)) |
| 59 | results.extend(input_api.canned_checks.CheckChangeSvnEolStyle( |
| 60 | input_api, output_api, sources)) |
[email protected] | 40cdf8b3 | 2009-06-26 23:00:37 | [diff] [blame] | 61 | results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( |
| 62 | input_api, output_api)) |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame] | 63 | # Make sure the tree is 'open'. |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 64 | # TODO(maruel): Run it in a separate thread to parallelize checks? |
[email protected] | 04a39f7c | 2009-06-11 00:41:32 | [diff] [blame] | 65 | results.extend(CheckTreeIsOpen(input_api, output_api, |
| 66 | 'http://chromium-status.appspot.com/status', |
| 67 | '0', |
| 68 | 'http://chromium-status.appspot.com/current')) |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 69 | results.extend(CheckTryJobExecution(input_api, output_api)) |
[email protected] | fe5f57c5 | 2009-06-05 14:25:54 | [diff] [blame] | 70 | return results |
[email protected] | ca8d198 | 2009-02-19 16:33:12 | [diff] [blame] | 71 | |
| 72 | |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 73 | def CheckTryJobExecution(input_api, output_api): |
[email protected] | 430641764 | 2009-06-11 00:33:40 | [diff] [blame] | 74 | outputs = [] |
| 75 | if not input_api.change.issue or not input_api.change.patchset: |
| 76 | return outputs |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 77 | url = "http://codereview.chromium.org/%d/get_build_results/%d" % ( |
| 78 | input_api.change.issue, input_api.change.patchset) |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 79 | try: |
| 80 | connection = input_api.urllib2.urlopen(url) |
| 81 | # platform|status|url |
| 82 | values = [item.split('|', 2) for item in connection.read().splitlines()] |
| 83 | connection.close() |
| 84 | statuses = map(lambda x: x[1], values) |
[email protected] | 7230383 | 2009-07-10 19:09:08 | [diff] [blame] | 85 | message = None |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 86 | if 'failure' in statuses: |
| 87 | failures = filter(lambda x: x[1] != 'success', values) |
| 88 | long_text = '\n'.join("% 5s: % 7s %s" % (item[0], item[1], item[2]) |
| 89 | for item in failures) |
[email protected] | 7230383 | 2009-07-10 19:09:08 | [diff] [blame] | 90 | message = 'You had try job failures. Are you sure you want to check-in?\n' |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 91 | elif 'pending' in statuses or len(values) != 3: |
| 92 | long_text = '\n'.join("% 5s: % 7s %s" % (item[0], item[1], item[2]) |
| 93 | for item in values) |
[email protected] | 7230383 | 2009-07-10 19:09:08 | [diff] [blame] | 94 | message = 'You should try the patch first (and wait for it to finish).\n' |
| 95 | if message: |
| 96 | message += ( |
| 97 | 'Is try server wrong or broken? Please notify [email protected]. ' |
| 98 | 'Thanks.\n') |
| 99 | outputs.append(output_api.PresubmitPromptWarning(message=message, |
| 100 | long_text=long_text)) |
[email protected] | 70ac498 | 2009-06-08 17:31:51 | [diff] [blame] | 101 | except input_api.urllib2.HTTPError, e: |
| 102 | if e.code == 404: |
| 103 | # Fallback to no try job. |
| 104 | # TODO(maruel): Change to a PresubmitPromptWarning once the try server is |
| 105 | # stable enough and it seems to work fine. |
| 106 | outputs.append(output_api.PresubmitNotifyResult( |
| 107 | 'You should try the patch first.')) |
| 108 | else: |
| 109 | # Another HTTP error happened, warn the user. |
| 110 | # TODO(maruel): Change to a PresubmitPromptWarning once it deemed to work |
| 111 | # fine. |
| 112 | outputs.append(output_api.PresubmitNotifyResult( |
| 113 | 'Got %s while looking for try job status.' % str(e))) |
| 114 | return outputs |
[email protected] | 04a39f7c | 2009-06-11 00:41:32 | [diff] [blame] | 115 | |
| 116 | |
| 117 | def CheckTreeIsOpen(input_api, output_api, url, closed, url_text): |
| 118 | """Similar to the one in presubmit_canned_checks except it shows an helpful |
| 119 | status text instead. |
| 120 | """ |
| 121 | assert(input_api.is_committing) |
| 122 | try: |
| 123 | connection = input_api.urllib2.urlopen(url) |
| 124 | status = connection.read() |
| 125 | connection.close() |
| 126 | if input_api.re.match(closed, status): |
| 127 | long_text = status + '\n' + url |
| 128 | try: |
| 129 | connection = input_api.urllib2.urlopen(url_text) |
| 130 | text = connection.read() |
| 131 | connection.close() |
| 132 | match = input_api.re.search(r"\<div class\=\"Notice\"\>(.*)\<\/div\>", |
| 133 | text) |
| 134 | if match: |
| 135 | long_text = match.group(1).strip() |
| 136 | except IOError: |
| 137 | pass |
[email protected] | b3fbe1c | 2009-07-29 18:44:39 | [diff] [blame^] | 138 | return [output_api.PresubmitError("The tree is closed.", |
| 139 | long_text=long_text)] |
[email protected] | 04a39f7c | 2009-06-11 00:41:32 | [diff] [blame] | 140 | except IOError: |
| 141 | pass |
| 142 | return [] |