pre-upload: automatically reject (c) in newer files
So I don't have to keep telling people.
BUG=None
TEST=`./pre-upload_unittest.py` passes
Change-Id: I85a2e95ea13a633c621a4a73aa6e9099eef97c69
Reviewed-on: https://chromium-review.googlesource.com/214582
Reviewed-by: Yu-Ju Hong <yjhong@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index adc4d82..9e6214c 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -63,6 +63,8 @@
# ignore profiles data (like overlay-tegra2/profiles)
r".*/overlay-.*/profiles/.*",
+ r"^profiles/.*$",
+
# ignore minified js and jquery
r".*\.min\.js",
r".*jquery.*\.js",
@@ -154,38 +156,6 @@
return filtered
-def _verify_header_content(commit, content, fail_msg):
- """Verify that file headers contain specified content.
-
- Args:
- commit: the affected commit.
- content: the content of the header to be verified.
- fail_msg: the first message to display in case of failure.
-
- Returns:
- The return value of HookFailure().
- """
- license_re = re.compile(content, re.MULTILINE)
- bad_files = []
- files = _filter_files(_get_affected_files(commit),
- COMMON_INCLUDED_PATHS,
- COMMON_EXCLUDED_PATHS)
-
- for f in files:
- # Ignore non-existant files and symlinks
- if os.path.exists(f) and not os.path.islink(f):
- contents = open(f).read()
- if not contents:
- # Ignore empty files
- continue
- if not license_re.search(contents):
- bad_files.append(f)
- if bad_files:
- msg = "%s:\n%s\n%s" % (fail_msg, license_re.pattern,
- "Found a bad header in these files:")
- return HookFailure(msg, bad_files)
-
-
# Git Helpers
@@ -736,18 +706,55 @@
def _check_license(_project, commit):
- """Verifies the license header."""
- LICENSE_HEADER = (
- r".* Copyright( \(c\))? 20[-0-9]{2,7} The Chromium OS Authors\. "
- "All rights reserved\." "\n"
- r".* Use of this source code is governed by a BSD-style license that can "
- "be\n"
- r".* found in the LICENSE file\."
- "\n"
- )
- FAIL_MSG = "License must match"
+ """Verifies the license/copyright header.
- return _verify_header_content(commit, LICENSE_HEADER, FAIL_MSG)
+ Should be following the spec:
+ http://dev.chromium.org/developers/coding-style#TOC-File-headers
+ """
+ # For older years, be a bit more flexible as our policy says leave them be.
+ LICENSE_HEADER = (
+ r'.* Copyright( \(c\))? 20[-0-9]{2,7} The Chromium OS Authors\. '
+ 'All rights reserved\.' '\n'
+ r'.* Use of this source code is governed by a BSD-style license that can '
+ 'be\n'
+ r'.* found in the LICENSE file\.'
+ '\n'
+ )
+ license_re = re.compile(LICENSE_HEADER, re.MULTILINE)
+
+ # For newer years, be stricter.
+ COPYRIGHT_LINE = (
+ r'.* Copyright \(c\) 20(1[5-9]|[2-9][0-9]) The Chromium OS Authors\. '
+ 'All rights reserved\.' '\n'
+ )
+ copyright_re = re.compile(COPYRIGHT_LINE)
+
+ bad_files = []
+ bad_copyright_files = []
+ files = _filter_files(_get_affected_files(commit, relative=True),
+ COMMON_INCLUDED_PATHS,
+ COMMON_EXCLUDED_PATHS)
+
+ for f in files:
+ contents = _get_file_content(f, commit)
+ if not contents:
+ # Ignore empty files.
+ continue
+
+ if not license_re.search(contents):
+ bad_files.append(f)
+ elif copyright_re.search(contents):
+ bad_copyright_files.append(f)
+
+ if bad_files:
+ msg = '%s:\n%s\n%s' % (
+ 'License must match', license_re.pattern,
+ 'Found a bad header in these files:')
+ return HookFailure(msg, bad_files)
+
+ if bad_copyright_files:
+ msg = 'Do not use (c) in copyright headers in new files:'
+ return HookFailure(msg, bad_copyright_files)
def _check_layout_conf(_project, commit):
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index feb4555..ffc4777 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -281,8 +281,10 @@
ret = pre_upload._check_ebuild_virtual_pv(self.PRIVATE_VARIANT_OVERLAY, 'H')
self.assertTrue(isinstance (ret, errors.HookFailure))
+
class CheckGitOutputParsing(cros_test_lib.MockTestCase):
"""Tests for git output parsing."""
+
def testParseAffectedFiles(self):
"""Test parsing git diff --raw output."""
# Sample from git diff --raw.
@@ -304,5 +306,49 @@
relative=True)
self.assertEqual(result, expected_modified_files_no_deletes)
+
+class CheckLicenseCopyrightHeader(cros_test_lib.MockTestCase):
+ """Tests for _check_license."""
+
+ def setUp(self):
+ self.file_mock = self.PatchObject(pre_upload, '_get_affected_files')
+ self.content_mock = self.PatchObject(pre_upload, '_get_file_content')
+
+ def testOldHeaders(self):
+ """Accept old header styles."""
+ HEADERS = (
+ ('#!/bin/sh\n'
+ '# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.\n'
+ '# Use of this source code is governed by a BSD-style license that'
+ ' can be\n'
+ '# found in the LICENSE file.\n'),
+ ('// Copyright 2010-13 The Chromium OS Authors. All rights reserved.\n'
+ '// Use of this source code is governed by a BSD-style license that'
+ ' can be\n'
+ '// found in the LICENSE file.\n'),
+ )
+ self.file_mock.return_value = ['file']
+ for header in HEADERS:
+ self.content_mock.return_value = header
+ self.assertEqual(None, pre_upload._check_license('proj', 'sha1'))
+
+ def testRejectC(self):
+ """Reject the (c) in newer headers."""
+ HEADERS = (
+ ('// Copyright (c) 2015 The Chromium OS Authors. All rights reserved.\n'
+ '// Use of this source code is governed by a BSD-style license that'
+ ' can be\n'
+ '// found in the LICENSE file.\n'),
+ ('// Copyright (c) 2020 The Chromium OS Authors. All rights reserved.\n'
+ '// Use of this source code is governed by a BSD-style license that'
+ ' can be\n'
+ '// found in the LICENSE file.\n'),
+ )
+ self.file_mock.return_value = ['file']
+ for header in HEADERS:
+ self.content_mock.return_value = header
+ self.assertNotEqual(None, pre_upload._check_license('proj', 'sha1'))
+
+
if __name__ == '__main__':
cros_test_lib.main()