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
    ]
    return markdownBlock


def hasKeySequence(inputfile, key_message):
66
    line_cnt = 0
Ted Themistokleous's avatar
Ted Themistokleous committed
67
    line_limit = 5
Ted Themistokleous's avatar
Ted Themistokleous committed
68

Ted Themistokleous's avatar
Ted Themistokleous committed
69
70
    lines = inputfile.split("\n")
    for line in lines:
71
        if key_message in line:
Ted Themistokleous's avatar
Ted Themistokleous committed
72
            return [True, line_cnt]
73
74
75

        if line_cnt >= line_limit:
            break
Ted Themistokleous's avatar
Ted Themistokleous committed
76
77
        line_cnt = line_cnt + 1

Ted Themistokleous's avatar
Ted Themistokleous committed
78
    return [False, -1]
79
80
81
82
83
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


# 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

119
120
121
122
    current_year = str(datetime.date.today().year)
    needs_update = False
    update_line = -1

123
124
125
126
127
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
    #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
156
                #print(save)
157
158
159
160
161

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

Ted Themistokleous's avatar
Ted Themistokleous committed
162
                #print(save)
Ted Themistokleous's avatar
Ted Themistokleous committed
163

164
                #Check if we have a licence stamp already
165
166
167
168
                if hasAmdLic[0] or hasOtherLic[0] is True:
                    hasOldAmdLic = hasKeySequence(
                        save, "2015-" + current_year +
                        " Advanced Micro Devices, Inc. All rights reserved.")
Ted Themistokleous's avatar
Ted Themistokleous committed
169
170
                    print(hasOldAmdLic)
                    if hasOldAmdLic[1] != -1 and hasOtherLic[0] is False:
171
172
173
174
175
176
177
178
                        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 ")
179

180
181
                        contents.close()
                        return
182
183
184
185
186
187
188
189

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


190
    if needs_update is True and update_line > -1:
Ted Themistokleous's avatar
Ted Themistokleous committed
191
192
        if debug is True:
            print("...Updating header\n", end='')
193

Ted Themistokleous's avatar
Ted Themistokleous committed
194
195
196
197
198
199
200
201
202
203
204
205
#
#        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)
206
207

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

211
212
        with open(filename, 'w') as contents:
            #append the licence to the top of the file
213

214
215
216
            #Append shebang before license
            if add_shebang is True:
                contents.write(saved_shebang + "\n")
217

218
219
220
            #Append markdown hooks before license
            if modify_markdown is True:
                contents.write(''.join(str(x) for x in save_markdown_lines))
221

222
223
224
225
            delim = topHeader(commentChar)
            if delim is not None:
                contents.write(delim)
                #print(delim)
226

227
228
229
230
231
232
            if modify_markdown is False:
                for line in message:
                    if line != '':
                        contents.write(commentChar + " " + line + "\n")
                    else:
                        contents.write(commentChar + "\n")
233

234
235
236
            delim = bottomFooter(commentChar)
            if delim is not None:
                contents.write(delim)
237

238
239
            #write remaining contents
            contents.write(save)
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    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": "#",
258
259
        ".sh": "#",
        ".cmake": "#"
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    }
    listOfKeys = delimiterDict.keys()
    delimiter = None

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

    return delimiter


def main():

274
    message = open(os.path.join(__repo_dir__, 'LICENSE')).read()
275
276
277
278
279
280

    #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,
281
282
                          stdout=subprocess.PIPE,
                          cwd=__repo_dir__)
283
284
285
    fileList = proc.stdout.decode().split('\n')
    message = message.split('\n')

Ted Themistokleous's avatar
Ted Themistokleous committed
286
287
288
    #if debug is True:
    #print("Target file list:\n" + str(fileList))
    #print("Output Message:\n" + str(message))
289

290
291
    for rfile in fileList:
        file = os.path.join(__repo_dir__, rfile)
292
293
294
295
296
297
298
299
        #print(file)
        commentDelim = getDelimiter(file)
        if commentDelim is not None:
            openAndWriteFile(file, message, commentDelim)


if __name__ == "__main__":
    main()