[license_checker] refactoring

This commit is contained in:
Aleksandr
2023-06-20 19:55:33 +03:00
parent 095bbc9d19
commit 41f1b76702
7 changed files with 152 additions and 150 deletions

View File

@ -56,13 +56,6 @@ save text files with reports.
"reportFolder": "build_tools/scripts/license_checker/reports"
```
* `licensePath` specifies the path to the license template.
**For example:**
```json
"licensePath": "build_tools/scripts/license_checker/license_template.txt"
```
* `printChecking` specifies whether to output
information about which file is
being checked to the console.
@ -104,6 +97,13 @@ Possible array values:
"dir": "sdkjs"
```
* `licensePath` specifies the path to the license template.
**For example:**
```json
"licensePath": "build_tools/scripts/license_checker/license_template.txt"
```
* `fileExtensions` file extensions to check.
**For example:**
@ -111,35 +111,6 @@ Possible array values:
"fileExtensions": [".js"]
```
* `startMultiComm` the line that starts the multiline comment.
**For example:**
```json
"startMultiComm": "/*"
```
* `endMultiComm` the line that ends the multiline comment.
You should carefully consider the formatting
of the string, all spaces are taken into account.
This affects how the license check works.
**For example:**
```json
"endMultiComm": " */"
```
Space at the beginning for a prettier comment.
* `prefix` the line on which each comment
line will begin, except for the
beginning and end.
**For example:**
```json
"prefix": " *"
```
Space at the beginning for a prettier comment.
* `ignoreListDir` folder paths to ignore.
**For example:**
@ -172,6 +143,15 @@ Possible array values:
]
```
* `allowListFile` file paths to allow (throw ignore paths).
**For example:**
```json
"allowListFile": [
"sdkjs/deploy/dontIgnoreMe.js"
]
```
Any number of configurations can be
specified, they can overlap
if we need to check

View File

@ -1,17 +1,14 @@
{
"basePath": "../../../",
"reportFolder": "build_tools/scripts/license_checker/reports",
"licensePath": "build_tools/scripts/license_checker/header.license",
"printChecking": false,
"printReports": false,
"fix": ["OUTDATED"],
"configs": [
{
"dir": "core",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".cs", ".js", ".m", ".mm", ".license"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"core/build",
"core/Common/cfcpp/test",
@ -58,10 +55,8 @@
},
{
"dir": "core-ext",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".m", ".mm"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"core-ext/AutoTester",
"core-ext/cell_android",
@ -82,10 +77,8 @@
},
{
"dir": "sdkjs",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"sdkjs/deploy",
"sdkjs/develop",
@ -105,10 +98,8 @@
},
{
"dir": "sdkjs-forms",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -116,10 +107,8 @@
},
{
"dir": "sdkjs-ooxml",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -127,10 +116,8 @@
},
{
"dir": "web-apps",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor",
@ -153,10 +140,8 @@
},
{
"dir": "web-apps-mobile",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"node_modules",
"vendor"
@ -164,10 +149,8 @@
},
{
"dir": "server",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
@ -177,10 +160,8 @@
},
{
"dir": "server-lockstorage",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
@ -190,10 +171,8 @@
},
{
"dir": "server-license",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".js"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDir": [
"server/FileConverter/bin"
],
@ -203,10 +182,8 @@
},
{
"dir": "editors-ios",
"licensePath": "build_tools/scripts/license_checker/licenses/header.license",
"fileExtensions": [".h", ".c", ".hpp", ".cpp", ".hxx", ".cxx", ".m", ".mm"],
"startMultiComm": "/*",
"endMultiComm": " */",
"prefix": " *",
"ignoreListDirName": [
"vendor",
"Vendor",
@ -218,6 +195,22 @@
"editors-ios/Vendor/ThreadSafeMutable/ThreadSafeMutableDictionary.h",
"editors-ios/Vendor/ThreadSafeMutable/ThreadSafeMutableDictionary.m"
]
},
{
"dir": "onlyoffice.github.io",
"isSingleYear": true,
"licensePath": "build_tools/scripts/license_checker/licenses/apache_js.license",
"fileExtensions": [".js"],
"ignoreListDirName": [
"vendor",
"thirdparty"
]
},
{
"dir": "onlyoffice.github.io",
"isSingleYear": true,
"licensePath": "build_tools/scripts/license_checker/licenses/apache_html.license",
"fileExtensions": [".html"]
}
]
}

View File

@ -1,28 +0,0 @@
(c) Copyright Ascensio System SIA 2010-2023
This program is a free software product. You can redistribute it and/or
modify it under the terms of the GNU Affero General Public License (AGPL)
version 3 as published by the Free Software Foundation. In accordance with
Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
that Ascensio System SIA expressly excludes the warranty of non-infringement
of any third-party rights.
This program is distributed WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
street, Riga, Latvia, EU, LV-1050.
The interactive user interfaces in modified source and object code versions
of the Program must display Appropriate Legal Notices, as required under
Section 5 of the GNU AGPL version 3.
Pursuant to Section 7(b) of the License you must retain the original Product
logo when distributing the program. Pursuant to Section 7(e) we decline to
grant you any rights under trademark law for use of our trademarks.
All the Product's GUI elements, including illustrations and icon sets, as
well as technical writing content are licensed under the terms of the
Creative Commons Attribution-ShareAlike 4.0 International. See the License
terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode

View File

@ -19,15 +19,20 @@ FIX_TYPES = {
'LEN_MISMATCH': ErrorType.LEN_MISMATCH
}
def getLicense(path: str) -> list[str]:
"""Returns a license from file"""
with open(path, 'r') as f:
license: list[str] = f.readlines()
if not license:
raise Exception(f'Error getting license template. Cannot read {path} file. Is not it empty?')
return license
class Config(object):
"""
License checker configuration.
Attributes:
dir: Directory to check.
fileExtensions: file extensions to check.
startMultiComm: characters to start a multi-line comment.
endMultiComm: characters to end a multi-line comment.
prefix: prefix for multiline comments
ignoreListDir: Ignored folder paths.
ignoreListDirName: Ignored folder names.
ignoreListFile: Ignored file paths.
@ -36,34 +41,27 @@ class Config(object):
def __init__(self,
dir: str,
fileExtensions: list[str],
startMultiComm: str,
endMultiComm: str,
prefix: str = '',
allowListFile: list[str] = [],
ignoreListDir: list[str] = [],
ignoreListDirName: list[str] = [],
ignoreListFile: list[str] = []) -> None:
ignoreListFile: list[str] = [],
licensePath: str = '',
isSingleYear: bool = False) -> None:
self._dir = dir
self._fileExtensions = fileExtensions
self._startMultiComm = startMultiComm
self._endMultiComm = endMultiComm
self._prefix = prefix
self._allowListFile = allowListFile
self._ignoreListDir = ignoreListDir
self._ignoreListDirName = ignoreListDirName
self._ignoreListFile = ignoreListFile
self._licensePath = licensePath
self._isSingleYear = isSingleYear
self._license = getLicense(licensePath)
def getDir(self) -> str:
return self._dir
def getFileExtensions(self) -> list[str]:
return self._fileExtensions
def getStartMultiComm(self) -> str:
return self._startMultiComm
def getEndMultiComm(self) -> str:
return self._endMultiComm
def getPrefix(self) -> str:
return self._prefix
def getAllowListFile(self) -> list[str]:
return self._allowListFile
def getIgnoreListDir(self) -> list[str]:
@ -72,12 +70,16 @@ class Config(object):
return self._ignoreListDirName
def getIgnoreListFile(self) -> list[str]:
return self._ignoreListFile
def getLicense(self) -> str:
return self._license
def getIsSingleYear(self) -> bool:
return self._isSingleYear
with open(CONFIG_PATH, 'r') as j:
_json: dict = json.load(j)
BASE_PATH: str = _json.get('basePath') or '../../../'
os.chdir(BASE_PATH)
REPORT_FOLDER: str = _json.get('reportFolder') or 'build_tools/scripts/license_checker/reports'
LICENSE_TEMPLATE_PATH: str = _json.get('licensePath') or 'build_tools/scripts/license_checker/header.license'
if (_json.get('fix')):
try:
FIX: list[ErrorType] = list(map(lambda x: FIX_TYPES[x], _json.get('fix')))
@ -91,25 +93,6 @@ with open(CONFIG_PATH, 'r') as j:
for i in _json.get('configs'):
CONFIGS.append(Config(**i))
os.chdir(BASE_PATH)
with open(LICENSE_TEMPLATE_PATH, 'r') as f:
LICENSE: list[str] = f.readlines()
if not LICENSE:
raise Exception(f'Error getting license template. Cannot read {LICENSE_TEMPLATE_PATH} file. Is not it empty?')
def getLicense(start: str, prefix: str, end: str) -> list[str]:
"""Returns a valid license for any kind of comment prefix."""
result = [start]
for i in LICENSE:
if i == '\n':
result.append(prefix)
else:
result.append(f'{" ".join([prefix, i.strip()])}')
result.append(prefix)
result.append(end)
return result
class Error(object):
def __init__(self, errorType: ErrorType) -> None:
self._errorType = errorType
@ -144,8 +127,6 @@ class Checker(object):
self._reports: list[Report] = []
def getReports(self):
return self._reports
def getLicense(self):
return getLicense(start=self._config.getStartMultiComm(), prefix=self._config.getPrefix(), end=self._config.getEndMultiComm())
def _checkLine(self, line: str, prefix: str) -> bool:
"""Checks if a line has a prefix."""
"""Trim to catch invalid license without leading spaces"""
@ -154,16 +135,28 @@ class Checker(object):
return True
else:
return False
def getCommaOperator(self, line: str, reverse: bool = False) -> str:
r = r'\W'
result = ''
line = reversed(line) if reverse else line
for char in line:
if re.search(r, char) and not re.search(r'\s', char):
result = char + result if reverse else result + char
else:
break
return result
def findLicense(self, lines: list[str]) -> list[str]:
"""Looks for consecutive comments in a list of strings."""
result = []
isStarted = False
license = self._config.getLicense()
startComma = self.getCommaOperator(license[0])
endComma = self.getCommaOperator(license[-1], True)
for line in lines:
if line == '\n': continue
if (self._checkLine(line=line, prefix=self._config.getStartMultiComm())):
if (self._checkLine(line=line, prefix=startComma)):
result.append(line)
isStarted = True
elif(self._checkLine(line=line, prefix=self._config.getEndMultiComm())):
elif(self._checkLine(line=line, prefix=endComma)):
result.append(line)
break
elif (isStarted):
@ -172,7 +165,7 @@ class Checker(object):
break
return result
def _checkLicense(self, test: list[str], pathToFile: str) -> Report:
license = self.getLicense()
license = self._config.getLicense()
if len(license) != len(test):
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.LEN_MISMATCH),
@ -180,11 +173,11 @@ class Checker(object):
invalidLinesCount = 0
lastWrongLine = 0
for i in range(len(license)):
if (license[i] != test[i].strip('\n')):
if (license[i].strip('\n') != test[i].strip('\n')):
invalidLinesCount += 1
lastWrongLine = i
if (invalidLinesCount == 1):
r = r'\d\d\d\d\-\d\d\d\d'
r = r'\d\d\d\d' if self._config.getIsSingleYear() else r'\d\d\d\d\-\d\d\d\d'
testDate = re.search(r, test[lastWrongLine])
licenseDate = re.search(r, license[lastWrongLine])
@ -194,10 +187,10 @@ class Checker(object):
else:
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.INVALID_LICENSE),
message=f'Something wrong...')
message=f'Invalid line number: {lastWrongLine}')
testLastYear = testDate.split('-')[1]
licenseLastYear = licenseDate.split('-')[1]
testLastYear = testDate if self._config.getIsSingleYear() else testDate.split('-')[1]
licenseLastYear = licenseDate if self._config.getIsSingleYear() else licenseDate.split('-')[1]
if (int(testLastYear) < int(licenseLastYear)):
return Report(pathToFile=pathToFile,
error=Error(errorType=ErrorType.OUTDATED),
@ -258,7 +251,6 @@ class Walker(object):
for file in files:
if (PRINT_CHECKING):
print(f'Checking {file}...')
# self._checker.checkFile(file)
try:
self._checker.checkFile(file)
except Exception as e:
@ -286,8 +278,9 @@ class Fixer(object):
with open(pathToFile, 'r', encoding="utf8") as file:
buffer = file.readlines()
with open(pathToFile, 'w', encoding="utf8") as file:
license = self._checker.getLicense()
file.writelines(map(lambda x: "".join([x, '\n']), license))
license = self._checker._config.getLicense()
file.writelines(license)
file.write('\n')
file.writelines(buffer)
return
def _fixLicense(self, pathToFile: str):
@ -301,8 +294,9 @@ class Fixer(object):
for i in oldLicense:
buffer.remove(i)
with open(pathToFile, 'w', encoding=writeEncoding) as file:
license = self._checker.getLicense()
file.writelines(map(lambda x: "".join([x, '\n']), license))
license = self._checker._config.getLicense()
file.writelines(license)
file.write('\n')
file.writelines(buffer)
return

View File

@ -0,0 +1,15 @@
<!--
(c) Copyright Ascensio System SIA 2023
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.
-->

View File

@ -0,0 +1,17 @@
/**
*
* (c) Copyright Ascensio System SIA 2023
*
* 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.
*
*/

View File

@ -0,0 +1,31 @@
/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/