Merge "Build and package Layer Management service binaries." into tizen
[profile/ivi/layer-management.git] / scripts / check_license.py
1 #!/usr/bin/python
2
3 ###########################################################################
4 #
5 # Copyright 2013 BMW Car IT GmbH
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 #        http://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19 ###########################################################################
20
21 import sys, re, string
22 from common_modules.common import *
23 from common_modules.config import G_LICENSE_TEMPLATES
24
25
26 def clean_comment_chars(s):
27     """
28     Removes comment characters from a string
29
30     """
31     s = string.replace(s, "/", "")
32     s = string.replace(s, "*", "")
33     s = string.replace(s, "#", "")
34     return s
35
36 def make_license_re(license_text):
37     """
38     Makes a regular expression for every line in the license, this would match the license
39     text tolerating extra spaces
40
41     """
42     license_lines = license_text.split("\n")
43     license_lines_re = {}
44     for i in range(len(license_lines)):
45         license_line = license_lines[i]
46         re_text = clean_comment_chars(license_line)
47         #remove white space paddings
48         re_text = re_text.strip(" \n\t\r\f")
49         #replace special characters
50         re_text = string.replace(re_text, "(", "\(")
51         re_text = string.replace(re_text, ")", "\)")
52         re_text = string.replace(re_text, " ", "(\s+)")
53         re_text = string.replace(re_text, "\n", "(\s*)")
54         re_text = string.replace(re_text, "\t", "(\s+)")
55         re_text = string.replace(re_text, ".", "\.")
56
57         #this replaces the text [YYYY] with a regex that mathces years in one of the following forms:
58         #2013 or 2000-2013 or 2000 or 2000, 2001, 2002, 2013
59         re_text = string.replace(re_text, "[YYYY]", r"(\d{4})(((-(\d{4}))|(((\s*),(\s*)\d{4})+))?)")
60
61         if len(re_text) > 0:
62             re_text = "(\s*)" + re_text + "(\s*)"
63             current_text = ""
64             #remove unneeded space matches
65             while current_text != re_text:
66                 current_text = re_text
67                 re_text = string.replace(re_text, "(\s*)(\s*)", "(\s*)")
68                 re_text = string.replace(re_text, "(\s+)(\s+)", "(\s+)")
69                 re_text = string.replace(re_text, "(\s*)(\s+)", "(\s+)")
70
71             license_lines_re[i] = re_text
72
73     return license_lines_re
74
75 def check_specific_license_in_file(filename, clean_file_contents, license_text):
76     """
77     Checks if the file contains a valid license according to the license template provided
78
79     """
80     license_lines = license_text.split("\n")
81
82     license_re = make_license_re(license_text)
83
84     #search for the first line of the license in the target file
85     line_re = re.compile(license_re.values()[0])
86     found_match = line_re.search(clean_file_contents)
87
88     if found_match:
89         clean_file_contents = clean_file_contents[found_match.start():]
90
91     #check that license exists without any added or removed words
92     for (line_num, line_re_text) in license_re.items():
93         line_re = re.compile(line_re_text)
94         found_match = line_re.match(clean_file_contents)
95
96         if found_match:
97             clean_file_contents = clean_file_contents[found_match.end():]
98         else:
99             #log_warning(filename, 1, "license does not match at", license_lines[line_num])
100             return (line_num, license_lines[line_num])
101
102     return None # success
103
104 def check_license_in_file(filename, file_contents):
105     """
106     Checks if the file contains a valid license.
107     It tries to find a match inside the file with any of the licenses configured
108
109     """
110     clean_file_contents = clean_comment_chars(file_contents)
111
112     #license that had the best match with the file
113     best_match = (-1, None)
114
115     #try to match with every license
116     for license in G_LICENSE_TEMPLATES:
117         call_result = check_specific_license_in_file(filename, clean_file_contents, license)
118
119         #if match is found just return
120         if call_result == None:
121             return None
122
123         #if no match found check if this license was a good candidate for the match
124         else:
125             best_match = call_result if call_result[0] > best_match[0] else best_match
126
127     #(this else clause is executed if the for loop exists naturally)
128     #if loop ended without return, this means no license matched
129     else:
130         #if no license matched at all
131         if best_match[1] == None:
132             log_warning(filename, 1, "no license found")
133
134         #get the license with the best match
135         else:
136             log_warning(filename, 1, "license does not match at", best_match[1])
137
138 if __name__ == "__main__":
139     targets = sys.argv[1:]
140     targets = get_all_files(targets)
141
142     if len(targets) == 0:
143         print """
144 \t**** No input provided ****
145 \tTakes a list of files/directories as input and performs specific style checking on all files/directories.
146
147 \tGives warnings if the file does not contain a valid license text. It does not check if Copyright statements are included.
148 """
149         exit(0)
150
151     for t in targets:
152         file_contents, _, _, _ = read_file(t)
153         check_license_in_file(t, file_contents)