File: generate_file_headers.py

package info (click to toggle)
vite 1.4-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,112 kB
  • sloc: cpp: 30,167; makefile: 467; sh: 233; python: 140; ansic: 67
file content (191 lines) | stat: -rw-r--r-- 7,138 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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
119
120
121
122
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
"""
 @file generation_utils.py

 @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
                      Univ. Bordeaux. All rights reserved.

 @author Camille Ordronneau

 @date 2024-07-16
 
 Script to automatically update the header of every files in the project
"""
import time
import subprocess

# Normalized author names in the format : Login -> Firstname Lastname
authors_name_dict = {
    "Arthur CHEVALIER"          : "Arthur Chevalier",
    "Arthur Redondy"            : "Arthur Redondy",
    "Augustin Degomme"          : "Augustin Degomme",
    "augustin"                  : "Augustin Gauchet",
    "Camille Ordronneau"        : "Camille Ordronneau",
    "Ordronneau Camille"        : "Camille Ordronneau",
    "Cédric Augonnet"           : "Cedric Augonnet",
    "Clément Vuchener"          : "Clement Vuchener",
    "Florent Pruvost"           : "Florent Pruvost",
    "Francois Broquedis"        : "Francois Broquedis",
    "François Trahay"           : "Francois Trahay",
    "Francois Trahay"           : "Francois Trahay",
    "francois.trahay"           : "Francois Trahay",
    "BENMENDIL Hamza"           : "Hamza Benmendil",
    "BAHHOU Houssam"            : "Houssam Bahhou",
    "Elomariismail00"           : "Ismail Elomari Alaoui",
    "Jean-Alexandre Collin"     : "Jean-Alexandre Collin",
    "Jérémie Gaidamour"         : "Jeremie Gaidamour",
    "Laszlo Joel"               : "Joel Laszlo",
    "Johnny Jazeix"             : "Johnny Jazeix",
    "Jonnhy Jazeix"             : "Johnny Jazeix",
    "Jule Marcoueille"          : "Jule Marcoueille",
    "Kevin Coulomb"             : "Kevin Coulomb",
    "DIEU Killian"              : "Killian Dieu",
    "Killian Dieu"              : "Killian Dieu",
    "Tackwin"                   : "Luca Bourroux",
    "Luca Bourroux"             : "Luca Bourroux",
    "GUEDON Lucas"              : "Lucas Guedon",
    "Lucas G"                   : "Lucas Guedon",
    "CANNAROZZO Luigi"          : "Luigi Cannarozzo",
    "THIOLIERE Martin"          : "Martin Thioliere",
    "Mathieu Faverge"           : "Mathieu Faverge",
    "BOULLIT Mohamed_Faycal"    : "Mohamed Faycal Boullit",
    "Nicolas Richart"           : "Nicolas Richart",
    "nbredel"                   : "Nolan Bredel",
    "Olivier Lagrasse"          : "Olivier Lagrasse",
    "Pascal Noisette"           : "Pascal Noisette",
    "Philippe SWARTVAGHER"      : "Philippe Swartvagher",
    "Samuel Thibault"           : "Samuel Thibault",
    "Thibault Soucarre"         : "Thibault Soucarre",
    "Thomas Herault"            : "Thomas Herault",
    "Xavier Lacoste"            : "Xavier Lacoste",
    ""                          : "",
}

def file_authors(filepath):
    '''
        Return authors of a file
    '''

    # Get every line changes -> Get author -> Remove duplicate -> Remove first word "author" to only get the author name
    command = f'git blame "{filepath}" --porcelain | grep  "^author " | sort -u | cut -d " " -f 2-'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    authors = result.stdout.strip().split("\n")

    if "Not Committed Yet" in authors:
        authors.remove("Not Committed Yet")

    if "root" in authors:
        authors.remove("root")

    # Convert to real normalized names
    authors = [authors_name_dict[a] for a in authors]

    # Remove duplicate
    authors = list(set(authors))

    authors_list_string = ""

    for a in authors:
        authors_list_string += " * @author "
        authors_list_string += a
        authors_list_string += "\n"

    return authors_list_string

def file_date(filepath):
    '''
        Return date of last modification
    '''

    command = f'git log -1 --pretty="format:%cs" {filepath}'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    return result.stdout.strip()

def create_header(filepath):
    command = f'git log -1 --pretty="format:%cs" "{filepath}" | cut -c-4'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    last_change_year = result.stdout.strip()
    return '''/**
 *
 * @file '''+ filepath +'''
 *
 * @copyright 2008-'''+ last_change_year +''' Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
''' + file_authors(filepath) + ''' *
 * @date ''' + file_date(filepath) + '''
 */'''

def update_header(filepath):
    global file_error_list
    with open(filepath, 'r') as file:
        lines = file.readlines()
    

    if lines[0].strip() != "/**" :
        print("\n[ERROR] : File " + filepath + " has not the right header format")
        print("It seems like the file " + filepath + " does not already contains any header in the current project format.")
        print("This could be because the file has seen its header removed or is a new file.\n")
        print("If you want to take into account this file in the header update please put :\n/**\n *\n */\n\nAt the beginning of the file.")
        print("If you want to remove this error without updating the file :")
        print("  - Go to file " + __file__ + " and edit the 'command' variable inside the 'project_file_list' function.\n")
        file_error_list.append(filepath)
        return

    if is_file_up_to_date(filepath):
        return

    # Take the first line equal to "*/"
    header_end_line = 0
    for i, line in enumerate(lines):
        if line.strip() == "*/" :
            header_end_line = i + 1
            break
    
    # Format the header to a list of lines
    header = create_header(filepath).split("\n")
    header = [line + "\n" for line in header]

    # Put in place the new header
    new_file_content = header + lines[header_end_line:]

    # Write it to the file
    with open(filepath, 'w') as file:
        file.writelines(new_file_content)

def is_file_up_to_date(filepath):

    command = f'git log -1 --pretty="format:%cs" {filepath}'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    last_change_date = result.stdout.strip()

    command = f'grep "@date" {filepath} | cut -d \' \' -f 4'
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    header_date = result.stdout.strip()

    return header_date == last_change_date

def project_file_list():
    '''
        Return authors of a file
    '''

    command = f'''
    git ls-files '*.cpp' '*.hpp' '*.c' '*.h'    |
    grep -v "externals/*"                       |
    grep -v "src/trace/portable_*"              |
    grep -v "src/core/getopt.*"                      
    '''
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
    file_list = result.stdout.strip().split("\n")

    return file_list

file_error_list = []

for filepath in project_file_list():
    update_header(filepath)

if file_error_list != []:
    print("File that caused an error :")
    for file in file_error_list:
        print("  - " + file)