blob: 6c92d5aa3a91f034c0f3b939d4373f631a4f75c1 [file] [log] [blame]
# Copyright (c) 2015 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 os
import re
import subprocess
import sys
from trace_viewer import trace_viewer_project
class AffectedFile(object):
def __init__(self, input_api, filename):
self._filename = filename
self._input_api = input_api
self._cached_contents = None
self._cached_changed_contents = None
self._cached_new_contents = None
def __repr__(self):
return self._filename
@property
def filename(self):
return self._filename
@property
def contents(self):
if self._cached_contents is None:
self._cached_contents = self._input_api._git(
['show', ':%s' % self._filename])
return self._cached_contents
@property
def is_added(self):
return self.fileame in self._input_api.added_files
@property
def contents_as_lines(self):
"""Returns an iterator over the lines in the new version of file.
The new version is the file in the user's workspace, i.e. the "right hand
side".
Contents will be empty if the file is a directory or does not exist.
Note: The carriage returns (LF or CR) are stripped off.
"""
if self._cached_new_contents is None:
self._cached_new_contents = self.contents.splitlines()
return self._cached_new_contents[:]
@property
def changed_lines(self):
"""Returns a list of tuples (line number, line text) of all new lines.
This relies on the scm diff output describing each changed code section
with a line of the form
^@@ <old line num>,<old size> <new line num>,<new size> @@$
"""
if self._cached_changed_contents is not None:
return self._cached_changed_contents[:]
self._cached_changed_contents = []
line_num = 0
for line in self.GenerateDiff().splitlines():
m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line)
if m:
line_num = int(m.groups(1)[0])
continue
if line.startswith('+') and not line.startswith('++'):
self._cached_changed_contents.append((line_num, line[1:]))
if not line.startswith('-'):
line_num += 1
return self._cached_changed_contents[:]
def GenerateDiff(self):
return self._input_api._git([
'diff', self._input_api.diff_base, '--cached', self.filename])
class InputAPI(object):
def __init__(self, tvp, diff_base):
self.DEFAULT_BLACK_LIST = []
self._tvp = tvp
self._filename_statuses = None
self._added_files = None
self.diff_base = diff_base
def _git(self, args):
assert isinstance(args, list)
args = ['git'] + args
p = subprocess.Popen(
args,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=self.repository_root)
res = p.communicate()
if p.wait() != 0:
raise Exception(res[1])
return res[0]
@property
def repository_root(self):
return self._tvp.trace_viewer_path
@property
def added_files(self):
if not self._added_files:
self._added_files = set()
for filename, status_char in filename_statuses:
if status_char == 'A':
self._added_files.Add(filename)
return self._added_files
@property
def affected_files(self):
return self.AffectedFiles(include_deletes=True)
def AffectedFiles(self,
include_deletes=False,
file_filter=lambda t: True):
filename_statuses = self._GetFilenameStatuses()
for filename, status_char in filename_statuses:
if status_char == 'D':
if include_deletes:
if file_filter(filename):
yield AffectedFile(self, filename)
else:
if file_filter(filename):
yield AffectedFile(self, filename)
def _GetFilenameStatuses(self):
if self._filename_statuses != None:
return self._filename_statuses
self._filename_statuses = []
stdout = self._git([
'diff', self.diff_base, '--cached', '--name-status'])
for line in stdout.split('\n'):
line = line.strip()
if len(line) == 0:
continue
m = re.match('([ACDMRTUXB])\s+(.+)', line)
if not m:
import pdb; pdb.set_trace()
assert m
status_char = m.group(1)
filename = m.group(2)
self._filename_statuses.append((filename, status_char))
return self._filename_statuses
def IsTestDataFile(self, affected_file):
full_path = os.path.join(self.repository_root, affected_file.filename)
return full_path.startswith(self._tvp.test_data_path)
def RunChecks(input_api):
results = []
from hooks import pre_commit_checks
results += pre_commit_checks.RunChecks(input_api)
from trace_viewer.build import check_gyp
err = check_gyp.GypCheck()
if err:
results += [err]
from trace_viewer.build import check_gn
err = check_gn.GnCheck()
if err:
results += [err]
from trace_viewer.build import check_modules
err = check_modules.CheckModules()
if err:
results += [err]
from hooks import js_checks
results += js_checks.RunChecks(input_api)
return results
def GetResults(diff_base):
tvp = trace_viewer_project.TraceViewerProject()
input_api = InputAPI(tvp, diff_base)
return RunChecks(input_api)
def Main(args):
results = GetResults('HEAD')
print '\n\n'.join(results)
if len(results):
return 255
return 0