license_stamper.py 10.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python3
#####################################################################################
#  The MIT License (MIT)
#
#  Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved.
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in
#  all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#  THE SOFTWARE.
#####################################################################################
25
import subprocess, os
26
import datetime
27
28

#Debug flag
Ted Themistokleous's avatar
Ted Themistokleous committed
29
debug = True
30

31
32
33
__repo_dir__ = os.path.normpath(
    os.path.join(os.path.realpath(__file__), '..', '..'))

34
35
36
37
38

# Markdown code blob we should use to insert into notebook files
def getipynb_markdownBlockAsList():
    markdownBlock = [
        '\t{\n'
39
40
41
        '\t\t"cell_type": "code",\n', '\t\t"execution_count": null,\n',
        '\t\t"metadata": {},\n', '\t\t"outputs": [],\n', '\t\t"source": [\n',
        '\t\t\t\"#  The MIT License (MIT)\\n\",\n', '\t\t\t\"#\\n\",\n',
Ted Themistokleous's avatar
test  
Ted Themistokleous committed
42
        '\t\t\t\"#  Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.\\n\",\n',
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        '\t\t\t\"#\\n\",\n',
        '\t\t\t\"#  Permission is hereby granted, free of charge, to any person obtaining a copy\\n\",\n',
        '\t\t\t\"#  of this software and associated documentation files (the \'Software\'), to deal\\n\",\n',
        '\t\t\t\"#  in the Software without restriction, including without limitation the rights\\n\",\n',
        '\t\t\t\"#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\\n\",\n',
        '\t\t\t\"#  copies of the Software, and to permit persons to whom the Software is\\n\",\n',
        '\t\t\t\"#  furnished to do so, subject to the following conditions:\\n\",\n',
        '\t\t\t\"#\\n\",\n',
        '\t\t\t\"#  The above copyright notice and this permission notice shall be included in\\n\",\n',
        '\t\t\t\"#  all copies or substantial portions of the Software.\\n\",\n',
        '\t\t\t\"#\\n\",\n',
        '\t\t\t\"#  THE SOFTWARE IS PROVIDED \'AS IS\', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\n\",\n',
        '\t\t\t\"#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\\n\",\n',
        '\t\t\t\"#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\\n\",\n',
        '\t\t\t\"#  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\\n\",\n',
        '\t\t\t\"#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\\n\",\n',
        '\t\t\t\"#  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\\n\",\n',
        '\t\t\t\"#  THE SOFTWARE.\\n\"\n', '\t\t]\n', '\t},'
61
62
63
64
65
66
    ]
    return markdownBlock


def hasKeySequence(inputfile, key_message):
    result = False
67
68
    line_cnt = 0
    line_limit = 10
69
    target_line = -1
70

Ted Themistokleous's avatar
Ted Themistokleous committed
71
72
    for line in inputfile.split("\n"):

73
74
        if key_message in line:
            result = True
75
            target_line = line_cnt
76
77
78
79
            break

        if line_cnt >= line_limit:
            break
80

Ted Themistokleous's avatar
Ted Themistokleous committed
81
82
        line_cnt = line_cnt + 1

83
    return [result, target_line]
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123


# Header and footer of the comment block
# modify these if we want some different style
def topHeader(commentChar):
    delim = None

    #Early return
    if "//" in commentChar:
        delim = getipynb_markdownBlockAsList()
        delim.append("\n")
        return ''.join(str(x) for x in delim)

    if "*" in commentChar:
        delim = "/*\n"
    if "#" in commentChar:
        delim = "#####################################################################################\n"
    return delim


def bottomFooter(commentChar):
    delim = None
    #Early return - no footer handled by
    if "//" in commentChar:
        return delim

    if "*" in commentChar:
        delim = "*/\n"
    if "#" in commentChar:
        delim = "#####################################################################################\n"
    return delim


#Simple just open and write stuff to each file with the license stamp
def openAndWriteFile(filename, message, commentChar):
    add_shebang = False
    #markdown file stamping for .ipynb
    save_markdown_lines = []
    modify_markdown = False

124
125
126
127
    current_year = str(datetime.date.today().year)
    needs_update = False
    update_line = -1

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
    #open save old contents and append things here
    if debug is True:
        print("Open", filename, end='')

    #with open(filename, 'r') as contents:
    #    save = contents.read()
    try:
        file = open(filename, 'r')
    except OSError as e:
        if debug is True:
            print(str(e) + "....Open Error: Skipping  file ")
        file.close()
        return
    else:
        with file as contents:
            try:
                if commentChar != "//":
                    saved_shebang = contents.readline()
                    add_shebang = hasKeySequence(saved_shebang, "#!")

                    # No shebang so start at beginning line
                    if add_shebang is False:
                        contents.seek(0)

                # Get the first tags in notebook before we insert license into a cell as a comment block
                if commentChar == "//":
                    save_markdown_lines.extend(contents.readline())  # { tag
                    save_markdown_lines.extend(
                        contents.readline())  # "cells": [ tag
                    modify_markdown = True

                #read remaining lines in the original file
                save = contents.read()
Ted Themistokleous's avatar
Ted Themistokleous committed
161
                print(save)
162
163
164
165
166

                hasAmdLic = hasKeySequence(
                    save, "Advanced Micro Devices, Inc. All rights reserved")
                hasOtherLic = hasKeySequence(save, "Software License")

Ted Themistokleous's avatar
Ted Themistokleous committed
167
168
                print(save)

169
                #Check if we have a licence stamp already
170
171
172
173
174
175
176
177
178
179
180
181
182
                if hasAmdLic[0] or hasOtherLic[0] is True:
                    hasOldAmdLic = hasKeySequence(
                        save, "2015-" + current_year +
                        " Advanced Micro Devices, Inc. All rights reserved.")
                    if hasOldAmdLic[0] is True and hasOtherLic[0] is False:
                        if debug is True:
                            print("....License Out of Date: Updating file ")
                        needs_update = True
                        update_line = hasOldAmdLic[1]

                    else:
                        if debug is True:
                            print("....Already Stamped: Skipping  file ")
183

184
185
                        contents.close()
                        return
186
187
188
189
190
191
192
193

            except UnicodeDecodeError as eu:
                if debug is True:
                    print(str(eu) + "...Skipping binary file ")
                contents.close()
                return


194
    if needs_update is True and update_line > -1:
Ted Themistokleous's avatar
Ted Themistokleous committed
195
196
        if debug is True:
            print("...Updating header\n", end='')
197

Ted Themistokleous's avatar
Ted Themistokleous committed
198
199
200
201
202
203
204
205
206
207
208
209
210
#           print(save)
#
#        index = data[update_line + 1].find("2015-")
#        if index != -1:
#            save[update_line + 1] = save[
#                update_line+1][:index + 5] + current_year + save[update_line+1][index + 9:]
#
#        print(str(data))
#
#        with open(filename, 'w') as contents:
#            #write remaining contents
#            contents.seek(0)
#            contents.write(save)
211
212

    elif needs_update is False:
Ted Themistokleous's avatar
Ted Themistokleous committed
213
214
        if debug is True:
            print("...Writing header", end='')
Ted Themistokleous's avatar
Ted Themistokleous committed
215

216
217
        with open(filename, 'w') as contents:
            #append the licence to the top of the file
218

219
220
221
            #Append shebang before license
            if add_shebang is True:
                contents.write(saved_shebang + "\n")
222

223
224
225
            #Append markdown hooks before license
            if modify_markdown is True:
                contents.write(''.join(str(x) for x in save_markdown_lines))
226

227
228
229
230
            delim = topHeader(commentChar)
            if delim is not None:
                contents.write(delim)
                #print(delim)
231

232
233
234
235
236
237
            if modify_markdown is False:
                for line in message:
                    if line != '':
                        contents.write(commentChar + " " + line + "\n")
                    else:
                        contents.write(commentChar + "\n")
238

239
240
241
            delim = bottomFooter(commentChar)
            if delim is not None:
                contents.write(delim)
242

243
244
            #write remaining contents
            contents.write(save)
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    if debug is True:
        print("...done")


# Get the file type based on what we care about to tag with our licence
# file. Otherwise return None for the delimiter and skip the file


def getDelimiter(filename):

    delimiterDict = {
        ".cpp": "*",
        ".hpp": "*",
        ".h": "*",
        ".ipynb": "//",
        ".py": "#",
        ".txt": "#",
        ".bsh": "#",
263
264
        ".sh": "#",
        ".cmake": "#"
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    }
    listOfKeys = delimiterDict.keys()
    delimiter = None

    for extension in listOfKeys:
        if extension in filename:
            delimiter = delimiterDict[extension]
            break

    return delimiter


def main():

279
    message = open(os.path.join(__repo_dir__, 'LICENSE')).read()
280
281
282
283
284
285

    #Get a list of all the files in our git repo
    #bashCommand = "git ls-files --exclude-standard"
    #print (bashCommand.split())
    proc = subprocess.run("git ls-files --exclude-standard",
                          shell=True,
286
287
                          stdout=subprocess.PIPE,
                          cwd=__repo_dir__)
288
289
290
    fileList = proc.stdout.decode().split('\n')
    message = message.split('\n')

Ted Themistokleous's avatar
Ted Themistokleous committed
291
292
293
    #if debug is True:
    #print("Target file list:\n" + str(fileList))
    #print("Output Message:\n" + str(message))
294

295
296
    for rfile in fileList:
        file = os.path.join(__repo_dir__, rfile)
297
298
299
300
301
302
303
304
        #print(file)
        commentDelim = getDelimiter(file)
        if commentDelim is not None:
            openAndWriteFile(file, message, commentDelim)


if __name__ == "__main__":
    main()