|
1 #!/usr/bin/python |
|
2 # |
|
3 # Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 # All rights reserved. |
|
5 # This component and the accompanying materials are made available |
|
6 # under the terms of "Eclipse Public License v1.0" |
|
7 # which accompanies this distribution, and is available |
|
8 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
9 # |
|
10 # Initial Contributors: |
|
11 # Nokia Corporation - initial contribution. |
|
12 # |
|
13 # Contributors: |
|
14 # |
|
15 # Description: |
|
16 # |
|
17 # Checks filenames in specified paths for maximum path length, illegal |
|
18 # characters, uppercase characters and unknown filename extensions. |
|
19 # |
|
20 # http://developer.symbian.org/wiki/index.php/Coding_Standards_and_Conventions#File_and_Directory |
|
21 # |
|
22 |
|
23 import os, re, sys, traceback |
|
24 from optparse import OptionParser |
|
25 |
|
26 # Patterns for matching illegal characters: |
|
27 # & ^ + - @ $ % * ( ) | / [ ] { } < > ? ; : , " ' |
|
28 # Space and dash omitted: |
|
29 re_illegal_chars = re.compile( |
|
30 ".*[\&\^\+\@\$\%\*\(\)\|\[\]\{\}\<\>\?\;\:\,\"\'].*") |
|
31 # Space and dash included: |
|
32 re_illegal_strictchars = re.compile( |
|
33 ".*[\s\&\^\+\-\@\$\%\*\(\)\|\[\]\{\}\<\>\?\;\:\,\"\'].*") |
|
34 |
|
35 # List of known filename extensions in lowercase and in alphabetical order. |
|
36 known_exts = [ |
|
37 ".3gp", |
|
38 ".bat", ".bin", ".bmp", |
|
39 ".c", ".cat", ".cer", ".cfg", ".class", ".classpath", |
|
40 ".classpath_qt", ".classpath_qt_j2me", |
|
41 ".cmd", ".comp", ".conf", ".css", ".confml", ".cpp", ".cproject", ".crml", |
|
42 ".cvsignore", ".dat", ".dcf", ".def", ".defs", ".dll", ".der", ".doc", |
|
43 ".dr", ".dso", ".dsp", ".dsw", ".dtd", |
|
44 ".emx", ".exe", ".flm", ".gcfml", ".gif", |
|
45 ".h", ".hrh", ".html", ".iby", ".inf", ".ini", ".inl", |
|
46 ".jad", ".jar", ".java", ".javaversion", ".jpeg", ".jpg", ".js", ".jsp", ".jupiter", |
|
47 ".key", ".ks", ".launch", ".lib", ".loc", ".log", |
|
48 ".mak", ".make", "makefile", "makefile_akn", "makefile_qt", "manifest", ".mbm", ".mdl", |
|
49 ".meta", ".metadata", ".metaxml", ".mf", ".mif", ".mk", ".mmh", ".mmp", |
|
50 ".m3g", ".nonqt", ".odc", |
|
51 ".pem", ".pkg", ".pl", ".plugin", ".png", ".prefs", ".prf", ".pri", ".pro", |
|
52 ".project", ".project_classpath_builder", ".project_normal", ".mtj", |
|
53 ".eclipseme", ".properties", ".py", |
|
54 "readme", ".reg", ".result", ".review", ".rh", ".rsg", ".rss", |
|
55 ".ser", ".sh", ".sis", ".sisx", |
|
56 ".sps", ".subsystem", ".svg", ".svgb", ".s60", |
|
57 ".template", ".txt", ".vcf", ".vcs", |
|
58 ".wav", ".xls", ".xml", ".xpf", ".xsl", ".zip", |
|
59 ".rm", ".aac", ".amr", ".awb", ".au", ".jts", ".mid", ".mp3", ".mp4", |
|
60 ".ra", ".wma", ".mpg", |
|
61 # Peculiar filenames under jrt/tools directory: |
|
62 "exemakefile", "ijg_readme", "objmakefile", "staticlibmakefile", "testexemakefile", |
|
63 "findtr", "syncqt", "new", |
|
64 # Other peculiar filenames: |
|
65 "installerodclist", "installerodclist30", "midpodclist", "midpodclist30", |
|
66 "notice", "package-list", "tckrunnerodclist", "tckrunnerodclist30", "unknowncert", |
|
67 ] |
|
68 |
|
69 # Command line options. |
|
70 opts = None |
|
71 # Status code to be returned when script exits. |
|
72 status_code = 0 |
|
73 |
|
74 def main(): |
|
75 global opts, status_code |
|
76 # Parse command line options and arguments. |
|
77 parser = OptionParser( |
|
78 usage = "python -u %prog [options] <path> ...", |
|
79 description = "Checks filenames in specified paths for maximum " + \ |
|
80 "path length, illegal characters, uppercase characters and " + \ |
|
81 "unknown filename extensions. By default makes --length, --chars " + \ |
|
82 "and --exts checks.") |
|
83 parser.add_option("--length", dest="length", |
|
84 action="store_true", default=False, |
|
85 help="check path lengths") |
|
86 parser.add_option("--chars", dest="chars", |
|
87 action="store_true", default=False, |
|
88 help="check for illegal characters, ignoring spaces and dashes") |
|
89 parser.add_option("--strictchars", dest="strictchars", |
|
90 action="store_true", default=False, |
|
91 help="check for all illegal characters") |
|
92 parser.add_option("--uppercase", dest="uppercase", |
|
93 action="store_true", default=False, |
|
94 help="check for uppercase characters") |
|
95 parser.add_option("--exts", dest="exts", |
|
96 action="store_true", default=False, |
|
97 help="check for unknown filename extensions") |
|
98 (opts, args) = parser.parse_args() |
|
99 if not (opts.length or opts.chars or opts.strictchars or \ |
|
100 opts.uppercase or opts.exts): |
|
101 # No checks specified, make all checks except uppercase and strictchars. |
|
102 opts.length = True |
|
103 opts.chars = True |
|
104 opts.strictchars = False |
|
105 opts.uppercase = False |
|
106 opts.exts = True |
|
107 paths = [] |
|
108 for arg in args: |
|
109 paths += [arg] |
|
110 |
|
111 try: |
|
112 # Check all filenames under paths that were given as arguments. |
|
113 prefix_path = "jrt" |
|
114 for path in paths: |
|
115 check_filenames(prefix_path, path) |
|
116 except: |
|
117 print "ERROR: Unexpected exception" |
|
118 traceback.print_exc() |
|
119 sys.exit(1) |
|
120 |
|
121 # If no exceptions occurred, exit with status_code. |
|
122 sys.exit(status_code) |
|
123 |
|
124 def check_filenames(prefix_path, path): |
|
125 for root, dirs, files in os.walk(path): |
|
126 if root.find(path + os.sep) == 0: |
|
127 repl_prefix = path + os.sep |
|
128 else: |
|
129 repl_prefix = path |
|
130 dir_path = os.path.join(prefix_path, root.replace(repl_prefix, "")) |
|
131 for dir in dirs: |
|
132 dp_path = os.path.join(dir_path, dir, "distribution.policy.s60") |
|
133 if not os.path.exists(dp_path): |
|
134 check_filename(dp_path) |
|
135 check_dirname(os.path.join(root, dir)) |
|
136 for file in files: |
|
137 file_path = os.path.join(dir_path, file) |
|
138 check_filename(file_path) |
|
139 |
|
140 def check_dirname(dirname): |
|
141 # Ignore .svn paths. |
|
142 if dirname.find(os.sep + ".svn" + os.sep) != -1: |
|
143 return |
|
144 global status_code |
|
145 if not os.listdir(dirname): |
|
146 print "Empty directory " + dirname |
|
147 status_code = 1 |
|
148 |
|
149 def check_filename(filename): |
|
150 # Ignore .svn paths. |
|
151 if filename.find(os.sep + ".svn" + os.sep) != -1: |
|
152 return |
|
153 global opts, re_illegal_chars, re_illegal_strictchars, known_exts, status_code |
|
154 if opts.length: |
|
155 # Check maximum path length. |
|
156 l = len(filename) |
|
157 if l > 140: |
|
158 print "Too long path (" + str(l) + "): " + filename |
|
159 status_code = 1 |
|
160 if opts.strictchars: |
|
161 # Check for all illegal characters. |
|
162 if re_illegal_strictchars.match(filename): |
|
163 print "Illegal character: " + filename |
|
164 status_code = 1 |
|
165 elif opts.chars: |
|
166 # Check for illegal characters. |
|
167 if re_illegal_chars.match(filename): |
|
168 print "Illegal character: " + filename |
|
169 status_code = 1 |
|
170 path = os.path.dirname(filename) |
|
171 (root, ext) = os.path.splitext(filename) |
|
172 if opts.uppercase: |
|
173 if ext == ".java" or ext == ".class": |
|
174 # Check for uppercase characters in dir name. |
|
175 if path.lower() != path: |
|
176 print "Uppercase character: " + filename |
|
177 status_code = 1 |
|
178 else: |
|
179 # Check for uppercase characters. |
|
180 if filename.lower() != filename: |
|
181 print "Uppercase character: " + filename |
|
182 status_code = 1 |
|
183 if opts.exts: |
|
184 # Check for unknown extensions. |
|
185 if ext == "": |
|
186 ext = os.path.basename(filename) |
|
187 if not ext.lower() in known_exts: |
|
188 print "Unknown extension: " + filename |
|
189 status_code = 1 |
|
190 |
|
191 if __name__ == "__main__": |
|
192 main() |