blob: 95f5e72b5c8c33493a59d12d058687a8657f37e1 [file] [log] [blame]
Ryan Cui1562fb82011-05-09 11:01:31 -07001# Copyright (c) 2011 The Chromium OS 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
Mike Frysingerae409522014-02-01 03:16:11 -05005"""Common errors thrown when repo presubmit checks fail."""
6
Mike Frysinger09d6a3d2013-10-08 22:21:03 -04007from __future__ import print_function
8
Ryan Cui1562fb82011-05-09 11:01:31 -07009import re
10import sys
11
12
13class VerifyException(Exception):
Mike Frysingerae409522014-02-01 03:16:11 -050014 """Basic sanity checks failed."""
Ryan Cui1562fb82011-05-09 11:01:31 -070015
16
17class HookFailure(object):
18 """Contains an error message and a list of error details."""
19 def __init__(self, msg, items=None):
20 self.msg = msg
21 self.items = items
22
Daniel Erat9d203ff2015-02-17 10:12:21 -070023 def __str__(self):
24 return _FormatHookFailure(self)
25
Ryan Cui1562fb82011-05-09 11:01:31 -070026
27_INDENT = ' ' * 4
28_PROJECT_INFO = 'Errors in PROJECT *%s*!'
29
Mike Frysingerae409522014-02-01 03:16:11 -050030
Ryan Cui1562fb82011-05-09 11:01:31 -070031def _PrintWithIndent(msg, indent_level):
32 """Print a block of text with a specified indent level to stderr.
33
34 Args:
35 msg: A string to print (may contain newlines).
36 indent_level: The number of indents to prefix each line with. Each indent
37 is four characters wide.
38 """
39 regex = re.compile(r'^', re.M)
40 msg = regex.sub(_INDENT * indent_level, msg)
Mike Frysinger09d6a3d2013-10-08 22:21:03 -040041 print(msg, file=sys.stderr)
Ryan Cui1562fb82011-05-09 11:01:31 -070042
43
44def _FormatCommitDesc(desc):
45 """Returns the properly prefixed commit description."""
46 regex = re.compile(r'^', re.M)
47 return regex.sub('>', desc)
48
49
50def _FormatHookFailure(hook_failure):
51 """Returns the properly formatted VerifyException as a string."""
52 item_prefix = '\n%s* ' % _INDENT
53 formatted_items = ''
54 if hook_failure.items:
55 formatted_items = item_prefix + item_prefix.join(hook_failure.items)
56 return '* ' + hook_failure.msg + formatted_items
57
58
59def PrintErrorForProject(project, error):
60 """Prints the project and its error.
61
62 Args:
63 project: project name
64 error: An instance of the HookFailure class
65 """
66 _PrintWithIndent(_PROJECT_INFO % project, 0)
67 _PrintWithIndent(_FormatHookFailure(error), 1)
Mike Frysinger09d6a3d2013-10-08 22:21:03 -040068 print('', file=sys.stderr)
Ryan Cui1562fb82011-05-09 11:01:31 -070069
70
71def PrintErrorsForCommit(project, commit, commit_desc, error_list):
72 """Prints the hook error to stderr with project and commit context
73
74 A sample error output for a project would be:
75 ----------------------------------------------------------------------------
76 Errors in PROJECT *chromiumos/repohooks*!
77 COMMIT 10041758:
78 Description:
79 >staged
80 >
81 >TEST=some
82 >Change-Id: I2c4f545a20a659541c02be16aa9dc440c876a604
83 >
84 Errors:
85 * Changelist description needs BUG field (after first line)
86 * Found line ending with white space in:
87 * src/repohooks/pre-upload.py, line 307
88 * Found lines longer than 80 characters (first 5 shown):
89 * src/repohooks/pre-upload.py, line 335, 85 chars
90 ----------------------------------------------------------------------------
91
92 Args:
93 project: project name
94 commit: the commit hash the errors belong to
95 commit_desc: a string containing the commit message
96 error_list: a list of HookFailure instances
97 """
98 _PrintWithIndent(_PROJECT_INFO % project, 0)
99
100 formatted_desc = _FormatCommitDesc(commit_desc)
101 _PrintWithIndent('COMMIT %s:' % commit[:8], 1)
102 _PrintWithIndent('Description:', 2)
103 _PrintWithIndent(formatted_desc, 3)
104 _PrintWithIndent('Errors:', 2)
105
106 for error in error_list:
107 _PrintWithIndent(_FormatHookFailure(error), 3)
108
Mike Frysinger09d6a3d2013-10-08 22:21:03 -0400109 print('', file=sys.stderr)