pre-upload: Add AOSP license check.
The Apache2 license header used in AOSP can be enabled adding a
PRESUBMIT.cfg file with the following contents:
[Hook Overrides]
cros_license_check: false
aosp_license_check: true
BUG=None
TEST=Tested commits on update_engine repo.
Change-Id: Ida6ed02904517a45c728d3eb96d1d7d440dee7e5
Reviewed-on: https://chromium-review.googlesource.com/295454
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Alex Deymo <deymo@chromium.org>
Trybot-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index 5e34329..5432d40 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -902,8 +902,8 @@
MAX_FIRST_LINE_LEN)
-def _check_license(_project, commit):
- """Verifies the license/copyright header.
+def _check_cros_license(_project, commit):
+ """Verifies the Chromium OS license/copyright header.
Should be following the spec:
http://dev.chromium.org/developers/coding-style#TOC-File-headers
@@ -954,6 +954,53 @@
return HookFailure(msg, bad_copyright_files)
+def _check_aosp_license(_project, commit):
+ """Verifies the AOSP license/copyright header.
+
+ AOSP uses the Apache2 License:
+ https://source.android.com/source/licenses.html
+ """
+ LICENSE_HEADER = (
+ r"""^[#/\*]*
+[#/\*]* ?Copyright( \([cC]\))? 20[-0-9]{2,7} The Android Open Source Project
+[#/\*]* ?
+[#/\*]* ?Licensed under the Apache License, Version 2.0 \(the "License"\);
+[#/\*]* ?you may not use this file except in compliance with the License\.
+[#/\*]* ?You may obtain a copy of the License at
+[#/\*]* ?
+[#/\*]* ? http://www\.apache\.org/licenses/LICENSE-2\.0
+[#/\*]* ?
+[#/\*]* ?Unless required by applicable law or agreed to in writing, software
+[#/\*]* ?distributed under the License is distributed on an "AS IS" BASIS,
+[#/\*]* ?WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or """
+ r"""implied\.
+[#/\*]* ?See the License for the specific language governing permissions and
+[#/\*]* ?limitations under the License\.
+[#/\*]*$
+"""
+ )
+ license_re = re.compile(LICENSE_HEADER, re.MULTILINE)
+
+ files = _filter_files(_get_affected_files(commit, relative=True),
+ COMMON_INCLUDED_PATHS,
+ COMMON_EXCLUDED_PATHS)
+
+ bad_files = []
+ 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)
+
+ if bad_files:
+ msg = ('License must match:\n%s\nFound a bad header in these files:' %
+ license_re.pattern)
+ return HookFailure(msg, bad_files)
+
+
def _check_layout_conf(_project, commit):
"""Verifies the metadata/layout.conf file."""
repo_name = 'profiles/repo_name'
@@ -1192,7 +1239,7 @@
_check_for_uprev,
_check_gofmt,
_check_layout_conf,
- _check_license,
+ _check_cros_license,
_check_no_long_lines,
_check_no_stray_whitespace,
_check_no_tabs,
@@ -1216,7 +1263,8 @@
'stray_whitespace_check': _check_no_stray_whitespace,
'json_check': _run_json_check,
'long_line_check': _check_no_long_lines,
- 'cros_license_check': _check_license,
+ 'cros_license_check': _check_cros_license,
+ 'aosp_license_check': _check_aosp_license,
'tab_check': _check_no_tabs,
'branch_check': _check_change_has_branch_field,
'signoff_check': _check_change_has_signoff_field,
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index 57642fd..890a3e5 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -448,8 +448,8 @@
self.assertTrue(isinstance(ret, errors.HookFailure))
-class CheckLicenseCopyrightHeader(cros_test_lib.MockTestCase):
- """Tests for _check_license."""
+class CheckCrosLicenseCopyrightHeader(cros_test_lib.MockTestCase):
+ """Tests for _check_cros_license."""
def setUp(self):
self.file_mock = self.PatchObject(pre_upload, '_get_affected_files')
@@ -471,7 +471,7 @@
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'))
+ self.assertEqual(None, pre_upload._check_cros_license('proj', 'sha1'))
def testRejectC(self):
"""Reject the (c) in newer headers."""
@@ -488,7 +488,79 @@
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'))
+ self.assertNotEqual(None, pre_upload._check_cros_license('proj', 'sha1'))
+
+
+class CheckAOSPLicenseCopyrightHeader(cros_test_lib.MockTestCase):
+ """Tests for _check_aosp_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 testHeaders(self):
+ """Accept old header styles."""
+ HEADERS = (
+ """//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+""",
+ """#
+# Copyright (c) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+""",
+ )
+ self.file_mock.return_value = ['file']
+ for header in HEADERS:
+ self.content_mock.return_value = header
+ self.assertEqual(None, pre_upload._check_aosp_license('proj', 'sha1'))
+
+ def testRejectNoLinesAround(self):
+ """Reject headers missing the empty lines before/after the license."""
+ HEADERS = (
+ """# Copyright (c) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+""",
+ )
+ self.file_mock.return_value = ['file']
+ for header in HEADERS:
+ self.content_mock.return_value = header
+ self.assertNotEqual(None, pre_upload._check_aosp_license('proj', 'sha1'))
class CheckLayoutConfTestCase(cros_test_lib.MockTestCase):