#!/usr/bin/env python3 # # BLIS # An object-based framework for developing high-performance BLAS-like # libraries. # # Copyright (C) 2018, The University of Texas at Austin # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # - Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # - Neither the name(s) of the copyright holder(s) nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # # Import modules import os import sys import getopt import re import subprocess import datetime def print_usage(): my_print( " " ) my_print( " %s" % script_name ) my_print( " " ) my_print( " Field G. Van Zee" ) my_print( " " ) my_print( " Update copyright lines of all created or modified source files currently" ) my_print( " staged in the git index, and also insert new copyright lines where they" ) my_print( " currently are missing. This script targets copyright lines for one" ) my_print( " organization at a time." ) my_print( " " ) my_print( " Usage:" ) my_print( " " ) my_print( " %s [options]" % script_name ) my_print( " " ) my_print( " Arguments:" ) my_print( " " ) my_print( " " ) my_print( " The following options are accepted:" ) my_print( " " ) my_print( " -o org organization name" ) my_print( " Update and add copyrights for an organization named ." ) my_print( " By default, is 'Advanced Micro Devices, Inc.'" ) my_print( " " ) my_print( " -u update only" ) my_print( " Update existing copyrights to reflect the current year," ) my_print( " but do not add any additional copyright lines. With this" ) my_print( " option, the script still only updates copyright lines for" ) my_print( " the specified (or default) organization. The default is" ) my_print( " to update but also add copyright lines where missing." ) my_print( " " ) my_print( " -d dry run" ) my_print( " Go through all of the motions, but don't actually modify" ) my_print( " any files. The default behavior is to not enable dry run." ) my_print( " " ) my_print( " -q quiet" ) my_print( " Do not output feedback while processing each file. The" ) my_print( " default behavior is to output one line of text to stdout" ) my_print( " per file updated." ) my_print( " " ) my_print( " -h help" ) my_print( " Output this information and exit." ) my_print( " " ) # ------------------------------------------------------------------------------ def my_print( s ): sys.stdout.write( "%s\n" % s ) #sys.stdout.flush() def my_echo( s ): if not quiet: sys.stdout.write( "%s: %s\n" % ( output_name, s ) ) #sys.stdout.flush() # ------------------------------------------------------------------------------ def main(): global script_name global output_name global quiet # Obtain the script name. path, script_name = os.path.split(sys.argv[0]) output_name = script_name # Default values for optional arguments. the_org = 'Advanced Micro Devices, Inc.' update_only = False dry_run = False quiet = False # Process our command line options. try: opts, args = getopt.getopt( sys.argv[1:], "do:uhq" ) except getopt.GetoptError as err: # print help information and exit: my_print( str(err) ) # will print something like "option -a not recognized" print_usage() sys.exit(2) for opt, optarg in opts: if opt == "-o": the_org = optarg elif opt == "-u": update_only = True elif opt == "-d": dry_run = True elif opt == "-q": quiet = True elif opt == "-h": print_usage() sys.exit() else: print_usage() sys.exit() # Print usage if we don't have exactly zero arguments. if len( args ) != 0: print_usage() sys.exit() # Acquire our only mandatory argument. #driverfile = args[0] # Query the current year. the_time = datetime.datetime.now() cur_year = str(the_time.year) # We run 'git status' with --porcelain to make the output easily parseable. gitstatus = 'git status --porcelain' # Run the 'git status' command and capture the output. p = subprocess.run( gitstatus, stdout=subprocess.PIPE, shell=True ) git_lines = p.stdout.decode().splitlines() git_num_lines = int( len( git_lines ) ) # Consider each line of output from 'git status' for i in range( git_num_lines ): # Parse the current line to find the performance value. git_line = git_lines[i] git_words = git_line.split() mod_char = git_line[0] # Check the first character of the git output. We want to only update # files that are new ('A'), modified ('M'), or renamed ('R'). if mod_char != 'A' and \ mod_char != 'M' and \ mod_char != 'R': continue # Identify the filename for the current line of 'git status' output. if mod_char == 'R': # For renamed files, we need to reference them by their new names, # which appear after the "->" char sequence in git_words[2]. filename = git_words[3] else: filename = git_words[1] #my_echo( "-debug---- %s" % filename ) # Start by opening the file. (We can assume it exists since it # was found by 'git status', so no need to check for existence.) # Read all lines in the file and then close it. f = open( filename, "r" ) file_lines = f.readlines() f.close() # Concatenate all lines in the file into one string. file_string = "".join( file_lines ) # Search for an existing copyright line. has_cr = re.search( 'Copyright \(C\)', file_string ) # If the file does not have any copyright notice in it already, we # assume we don't need to update it. if not has_cr: my_echo( "[nocrline] %s" % filename ) continue # Check whether the file already has a copyright for the_org. We may # need to use this information later. has_org_cr = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), %s' % the_org, file_string ) # Initialize the list of processed (potentially modified) file lines. mod_file_lines = [] # At this point we know that the file has at least one copyright, and # has_org_cr encodes whether it already has a copyright for the_org. # We process the files that we know already have copyrights for the_org # differently from the files that do not yet have them. if has_org_cr: # Iterate through the lines in the current file. for line in file_lines: result = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), %s' % the_org, line ) # If the current line matches a copyright line for the_org... if result: # Extract the year saved as the first/only group in the # regular expression. old_year = result.group(1) # Don't need to update the year if it's already up-to-date. if old_year != cur_year: # Substitute the old year for the current year. find_line = ' %s, ' % old_year repl_line = ' %s, ' % cur_year line_ny = re.sub( find_line, repl_line, line ) my_echo( "[updated ] %s" % filename ) # Add the updated line to the running list. mod_file_lines += line_ny else: my_echo( "[up2date ] %s" % filename ) # Add the unchanged line to the running list. mod_file_lines += line else: # Add the unchanged line to the running list. mod_file_lines += line # endif result # endfor else: # Don't go any further if we're only updating existing copyright # lines. if update_only: my_echo( "[nocrline] %s" % filename ) continue num_file_lines = len( file_lines ) # Iterate through the lines in the current file. for i in range( int(num_file_lines) ): line = file_lines[i] # Only look at the next line if we are not at the last line. if i < int(num_file_lines) - 1: line_next = file_lines[i+1] else: line_next = file_lines[i] # Try to match both the current line and the next line. result = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), (.*)', line ) resnext = re.search( 'Copyright \(C\) ([0-9][0-9][0-9][0-9]), (.*)', line_next ) # Parse the results. if result: if resnext: # The current line matches but so does the next. Add the # current line unchanged to the running list. mod_file_lines += line else: # The current line matches but the next does not. Thus, # this branch only executes for the *last* copyright line # in the file. # Extract the year and organization from the matched # string. old_year = result.group(1) old_org = result.group(2) # Set up search/replace strings to convert the current # line into one that serves as copyright for the_org. find_line = '%s, %s' % (old_year, old_org) repl_line = '%s, %s' % (cur_year, the_org) line_nyno = re.sub( find_line, repl_line, line ) # Add the current line and then also insert our new # copyright line for the_org into the running list. mod_file_lines += line mod_file_lines += line_nyno my_echo( "[added ] %s" % filename ) # endif resnext else: # The current line does not match. Pass it through unchanged. mod_file_lines += line # endif result # endfor # endif has_org_cr if not dry_run: # Open the file for writing. f = open( filename, "w" ) # Join the modified file lines into a single string. final_string = "".join( mod_file_lines ) # Write the lines to the file. f.write( final_string ) # Close the file. f.close() # endif not dry_run # Return from main(). return 0 if __name__ == "__main__": main()