aboutsummaryrefslogtreecommitdiffstats
path: root/docs/bak/Developer_Info.rst
diff options
context:
space:
mode:
authorMax Benjamin <max.benjamin@att.com>2020-03-23 13:43:57 +0000
committerGerrit Code Review <gerrit@onap.org>2020-03-23 13:43:57 +0000
commit745c624081e15d018e221272c5be661d42bff8eb (patch)
tree9985a60f679764672117cfa6e6fc78b1d9bd7207 /docs/bak/Developer_Info.rst
parent41a79000737c08c6eac2b7f6faea747227678bba (diff)
parentfaf87b43c86213602d447a24a684ffe68466ab4f (diff)
Merge "remove duplicated and not used code"
Diffstat (limited to 'docs/bak/Developer_Info.rst')
0 files changed, 0 insertions, 0 deletions
'n174' href='#n174'>174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
#  ============LICENSE_START=======================================================
#  Copyright (C) 2022 Nordix Foundation
#  ================================================================================
#  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.
#
#  SPDX-License-Identifier: Apache-2.0
#  ============LICENSE_END=========================================================

import subprocess
import csv
import re
import datetime

#constants
import sys

COMMITTERS_CONFIG_FILE = ''
TEMPLATE_COPYRIGHT_FILE = ''
IGNORE_FILE = ''
if len(sys.argv) == 4:
    COMMITTERS_CONFIG_FILE = sys.argv[1]
    TEMPLATE_COPYRIGHT_FILE = sys.argv[2]
    IGNORE_FILE = sys.argv[3]

BANNER = '=' * 120

def main():
    print(BANNER + '\nCopyright Check Python Script:')
    PermissionsCheck()

    committerEmailExtension = GetCommitterEmailExtension()
    projectCommitters = ReadProjectCommittersConfigFile()

    CheckCommitterInConfigFile(committerEmailExtension, projectCommitters)

    alteredFiles = FindAlteredFiles()

    if alteredFiles:
        issueCounter = CheckCopyrightForFiles(alteredFiles, projectCommitters, committerEmailExtension)
    else:
        issueCounter = 0

    print(str(issueCounter) + ' issue(s) found after '+ str(len(alteredFiles)) + ' altered file(s) checked')
    print(BANNER)


# Check that Script has access to command line functions to use git
def PermissionsCheck():
   if 'permission denied' in subprocess.run('git', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8').lower():
       print('Error, I may not have the necessary permissions. Exiting...')
       print(BANNER)
       sys.exit()
   else:
       return

# Returns List of Strings of file tracked by git which have been changed/added
def FindAlteredFiles():
    ignoreFilePaths = GetIgnoredFiles()

    #Before Stage lower case d removes deleted files
    stream = subprocess.run('git diff --name-only --diff-filter=d', shell=True, stdout=subprocess.PIPE)
    fileNames = stream.stdout.decode('utf-8')
    #Staged
    stream = subprocess.run('git diff --name-only --cached --diff-filter=d', shell=True, stdout=subprocess.PIPE)
    fileNames += '\n' + stream.stdout.decode('utf-8')
    #New committed
    stream = subprocess.run('git diff --name-only HEAD^ HEAD --diff-filter=d', shell=True, stdout=subprocess.PIPE)
    fileNames += '\n' + stream.stdout.decode('utf-8')

    #String to list of strings
    alteredFiles = fileNames.split("\n")

    #Remove duplicates
    alteredFiles = list(dict.fromkeys(alteredFiles))

    #Remove blank string(s)
    alteredFiles = list(filter(None, alteredFiles))

    #Remove ignored-extensions
    alteredFiles = list(filter(lambda fileName: not re.match("|".join(ignoreFilePaths), fileName), alteredFiles))

    return alteredFiles

# Get the email of the most recent committer
def GetCommitterEmailExtension():
    email = subprocess.run('git show -s --format=\'%ce\'', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8').rstrip('\n')
    return email[email.index('@'):]

# Read the config file with names of companies and respective email extensions
def ReadProjectCommittersConfigFile():
    try:
        with open(COMMITTERS_CONFIG_FILE, 'r') as file:
            reader = csv.reader(file, delimiter=',')
            projectCommitters = {row[0]:row[1] for row in reader}
        projectCommitters.pop('email')  #Remove csv header
    except FileNotFoundError:
        print('Unable to open Project Committers Config File, have the command line arguments been set?')
        print(BANNER)
        sys.exit()
    return projectCommitters

def CheckCommitterInConfigFile(committerEmailExtension, projectCommitters):
    if not committerEmailExtension in projectCommitters:
        print('Error, Committer email is not included in config file.')
        print('If your company is new to the project please make appropriate changes to project-committers-config.csv')
        print('for Copyright Check to work.')
        print('Exiting...')
        print(BANNER)
        sys.exit()
    else:
        return True

# Read config file with list of files to ignore
def GetIgnoredFiles():
    try:
        with open(IGNORE_FILE, 'r') as file:
            reader = csv.reader(file)
            ignoreFilePaths = [row[0] for row in reader]
        ignoreFilePaths.pop(0)  #Remove csv header
        ignoreFilePaths = [filePath.replace('*', '.*') for filePath in ignoreFilePaths]
    except FileNotFoundError:
        print('Unable to open File Ignore Config File, have the command line arguments been set?')
        print(BANNER)
        sys.exit()
    return ignoreFilePaths

# Read the template copyright file
def GetCopyrightTemplate():
    try:
        with open(TEMPLATE_COPYRIGHT_FILE, 'r') as file:
            copyrightTemplate = file.readlines()
    except FileNotFoundError:
        print('Unable to open Template Copyright File, have the command line arguments been set?')
        print(BANNER)
        sys.exit()
    return copyrightTemplate

def GetProjectRootDir():
    return subprocess.run('git rev-parse --show-toplevel', shell=True, stdout=subprocess.PIPE).stdout.decode('utf-8').rstrip('\n') + '/'

# Get the Copyright from the altered file
def ParseFileCopyright(fileObject):
    global issueCounter
    copyrightFlag = False
    copyrightInFile = {}
    lineNumber = 1
    for line in fileObject:
        if 'LICENSE_START' in line:
            copyrightFlag = True
        if copyrightFlag:
            copyrightInFile[lineNumber] = line
        if 'LICENSE_END' in line:
            break
        lineNumber += 1

    if not copyrightFlag:
        print(fileObject.name + ' | no copyright found')
        return {}, {}

    copyrightSignatures = {}
    copyrightLineNumbers = list(copyrightInFile.keys())
    #Capture signature lines after LICENSE_START line
    for lineNumber in copyrightLineNumbers:
        if '=' not in copyrightInFile[lineNumber]:
            copyrightSignatures[lineNumber] = copyrightInFile[lineNumber]
            copyrightInFile.pop(lineNumber)
        elif 'LICENSE_START' not in copyrightInFile[lineNumber]:
            break

    return (copyrightInFile, copyrightSignatures)

# Remove the Block comment syntax
def RemoveCommentBlock(fileCopyright):
    # Comment Characters can very depending on file # *..
    endOfCommentsIndex = list(fileCopyright.values())[0].index('=')
    for key in fileCopyright:
        fileCopyright[key] = fileCopyright[key][endOfCommentsIndex:]
        if fileCopyright[key] == '':
            fileCopyright[key] = '\n'

    return fileCopyright

def CheckCopyrightForFiles(alteredFiles, projectCommitters, committerEmailExtension):
    issueCounter = 0
    templateCopyright = GetCopyrightTemplate() #Get Copyright Template
    projectRootDir = GetProjectRootDir()

    for fileName in alteredFiles: # Not removed files
        try:
            with open(projectRootDir + fileName, 'r') as fileObject:
                (fileCopyright, fileSignatures) = ParseFileCopyright(fileObject)

            #Empty dict evaluates to false
            if fileCopyright and fileSignatures:
                fileCopyright = RemoveCommentBlock(fileCopyright)
                issueCounter += CheckCopyrightFormat(fileCopyright, templateCopyright, projectRootDir + fileName)
                committerCompany = projectCommitters[committerEmailExtension]
                issueCounter += CheckCopyrightSignature(fileSignatures, committerCompany, projectRootDir + fileName)
            else:
                issueCounter += 1

        except FileNotFoundError:
            issueCounter += 1
            print('Unable to find file ' + projectRootDir + fileName)
    return issueCounter

# Check that the filecopyright matches the template copyright and print comparison
def CheckCopyrightFormat(copyrightInFile, templateCopyright, filePath):
    issueCounter = 0
    errorWithComparison = ''
    for copyrightInFileKey, templateLine in zip(copyrightInFile, templateCopyright):
        if copyrightInFile[copyrightInFileKey] != templateLine:
            issueCounter += 1
            errorWithComparison += filePath + ' | line ' + '{:2}'.format(copyrightInFileKey) + ' read \t ' + repr(copyrightInFile[copyrightInFileKey]) + '\n'
            errorWithComparison += filePath + ' | line ' + '{:2}'.format(copyrightInFileKey) + ' expected ' + repr(templateLine) + '\n'
    if errorWithComparison != '':
        print(errorWithComparison.rstrip('\n'))
    return issueCounter

# Check the signatures and compare with committer signature and current year
def CheckCopyrightSignature(copyrightSignatures, committerCompany, filePath):
    issueCounter = 0
    errorWithSignature = ''
    signatureExists = False #signatureExistsForCommitter
    afterFirstLine = False #afterFirstCopyright
    for key in copyrightSignatures:
        if afterFirstLine and 'Modifications Copyright' not in copyrightSignatures[key]:
            issueCounter += 1
            errorWithSignature += filePath + ' | line ' + str(key) + ' expected Modifications Copyright\n'
        elif not afterFirstLine and 'Copyright' not in copyrightSignatures[key]:
            issueCounter += 1
            errorWithSignature += filePath + ' | line ' + str(key) + ' expected Copyright\n'
        if committerCompany in copyrightSignatures[key]:
            signatureExists = True
            signatureYear = int(re.findall(r'\d+', copyrightSignatures[key])[-1])
            currentYear = datetime.date.today().year
            if signatureYear != currentYear:
                issueCounter += 1
                errorWithSignature += filePath + ' | line ' + str(key) + ' update year to include ' + str(currentYear) + '\n'
        afterFirstLine = True

    if not signatureExists:
        issueCounter += 1
        errorWithSignature += filePath + ' | missing company name and year for ' + committerCompany

    if errorWithSignature != '':
        print(errorWithSignature.rstrip('\n'))

    return issueCounter

if __name__ == '__main__':
    main()