blob: f73f306f9b5f7c9880891d3297c3713d9c368c0a [file] [log] [blame]
Chris Craik93216d02015-03-05 13:58:42 -08001# Copyright (c) 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.
4import os
5import re
6import subprocess
7import sys
8
9from trace_viewer import trace_viewer_project
10
11class AffectedFile(object):
12 def __init__(self, input_api, filename):
13 self._filename = filename
14 self._input_api = input_api
15 self._cached_contents = None
16 self._cached_changed_contents = None
17 self._cached_new_contents = None
18
19 def __repr__(self):
20 return self._filename
21
22 @property
23 def filename(self):
24 return self._filename
25
26 @property
27 def contents(self):
28 if self._cached_contents is None:
29 self._cached_contents = self._input_api._git(
30 ['show', ':%s' % self._filename])
31 return self._cached_contents
32
33 @property
34 def is_added(self):
35 return self.fileame in self._input_api.added_files
36
37 @property
38 def contents_as_lines(self):
39 """Returns an iterator over the lines in the new version of file.
40
41 The new version is the file in the user's workspace, i.e. the "right hand
42 side".
43
44 Contents will be empty if the file is a directory or does not exist.
45 Note: The carriage returns (LF or CR) are stripped off.
46 """
47 if self._cached_new_contents is None:
48 self._cached_new_contents = self.contents.splitlines()
49 return self._cached_new_contents[:]
50
51 @property
52 def changed_lines(self):
53 """Returns a list of tuples (line number, line text) of all new lines.
54
55 This relies on the scm diff output describing each changed code section
56 with a line of the form
57
58 ^@@ <old line num>,<old size> <new line num>,<new size> @@$
59 """
60 if self._cached_changed_contents is not None:
61 return self._cached_changed_contents[:]
62 self._cached_changed_contents = []
63 line_num = 0
64
65 for line in self.GenerateDiff().splitlines():
66 m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line)
67 if m:
68 line_num = int(m.groups(1)[0])
69 continue
70 if line.startswith('+') and not line.startswith('++'):
71 self._cached_changed_contents.append((line_num, line[1:]))
72 if not line.startswith('-'):
73 line_num += 1
74 return self._cached_changed_contents[:]
75
76 def GenerateDiff(self):
77 return self._input_api._git(['diff', '--cached', self.filename])
78
79
80class InputAPI(object):
81 def __init__(self, tvp):
82 self.DEFAULT_BLACK_LIST = []
83 self._tvp = tvp
84 self._filename_statuses = None
85 self._added_files = None
86
87 def _git(self, args):
88 assert isinstance(args, list)
89 args = ['git'] + args
90 p = subprocess.Popen(
91 args,
92 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
93 cwd=self.repository_root)
94 res = p.communicate()
95 if p.wait() != 0:
96 raise Exception(res[1])
97 return res[0]
98
99 @property
100 def repository_root(self):
101 return self._tvp.trace_viewer_path
102
103 @property
104 def added_files(self):
105 if not self._added_files:
106 self._added_files = set()
107 for filename, status_char in filename_statuses:
108 if status_char == 'A':
109 self._added_files.Add(filename)
110 return self._added_files
111
112 @property
113 def affected_files(self):
114 return self.AffectedFiles(include_deletes=True)
115
116 def AffectedFiles(self,
117 include_deletes=False,
118 file_filter=lambda t: True):
119 filename_statuses = self._GetFilenameStatuses()
120 for filename, status_char in filename_statuses:
121 if status_char == 'D':
122 if include_deletes:
123 if file_filter(filename):
124 yield AffectedFile(self, filename)
125 else:
126 if file_filter(filename):
127 yield AffectedFile(self, filename)
128
129 def _GetFilenameStatuses(self):
130 if self._filename_statuses != None:
131 return self._filename_statuses
132
133 self._filename_statuses = []
134 stdout = self._git(['diff', '--cached', '--name-status'])
135 for line in stdout.split('\n'):
136 line = line.strip()
137 if len(line) == 0:
138 continue
139 m = re.match('([ACDMRTUXB])\s+(.+)', line)
140 if not m:
141 import pdb; pdb.set_trace()
142 assert m
143
144 status_char = m.group(1)
145 filename = m.group(2)
146 self._filename_statuses.append((filename, status_char))
147 return self._filename_statuses
148
149
150def RunChecks(input_api):
151 results = []
152
153 from hooks import pre_commit_checks
154 results += pre_commit_checks.RunChecks(input_api)
155
156 from trace_viewer.build import check_gyp
157 err = check_gyp.GypCheck()
158 if err:
159 results += [err]
160
161 from trace_viewer.build import check_gn
162 err = check_gn.GnCheck()
163 if err:
164 results += [err]
165
166 from trace_viewer.build import check_modules
167 err = check_modules.CheckModules()
168 if err:
169 results += [err]
170
171 from hooks import js_checks
172 results += js_checks.RunChecks(input_api)
173
174 return results
175
176
177def Main(args):
178 tvp = trace_viewer_project.TraceViewerProject()
179 input_api = InputAPI(tvp)
180 results = RunChecks(input_api)
181 print '\n\n'.join(results)
182
183 if len(results):
184 return 255
185 return 0