comparison mxtool/mx.py @ 15274:1ea79f17ab95

mx: generalized workaround for system command line length limits and used it to fix issue with eclipseformat command
author Doug Simon <doug.simon@oracle.com>
date Wed, 23 Apr 2014 00:54:41 +0200
parents 7be43cbf3568
children 43aa6a7e60bd
comparison
equal deleted inserted replaced
15273:dec74cb2ec27 15274:1ea79f17ab95
2056 2056
2057 if suppliedParser: 2057 if suppliedParser:
2058 return args 2058 return args
2059 return None 2059 return None
2060 2060
2061 def _chunk_files_for_command_line(files, limit=None, pathFunction=None):
2062 """
2063 Returns a generator for splitting up a list of files into chunks such that the
2064 size of the space separated file paths in a chunk is less than a given limit.
2065 This is used to work around system command line length limits.
2066 """
2067 chunkSize = 0
2068 chunkStart = 0
2069 if limit is None:
2070 commandLinePrefixAllowance = 3000
2071 if get_os() == 'windows':
2072 # The CreateProcess function on Windows limits the length of a command line to
2073 # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx)
2074 limit = 32768 - commandLinePrefixAllowance
2075 else:
2076 # Using just SC_ARG_MAX without extra downwards adjustment
2077 # results in "[Errno 7] Argument list too long" on MacOS.
2078 syslimit = os.sysconf('SC_ARG_MAX') - 20000
2079 limit = syslimit - commandLinePrefixAllowance
2080 for i in range(len(files)):
2081 path = files[i] if pathFunction is None else pathFunction(files[i])
2082 size = len(path) + 1
2083 if chunkSize + size < limit:
2084 chunkSize += size
2085 else:
2086 assert i > chunkStart
2087 yield files[chunkStart:i]
2088 chunkStart = i
2089 chunkSize = 0
2090 if chunkStart == 0:
2091 assert chunkSize < limit
2092 yield files
2093
2061 def eclipseformat(args): 2094 def eclipseformat(args):
2062 """run the Eclipse Code Formatter on the Java sources 2095 """run the Eclipse Code Formatter on the Java sources
2063 2096
2064 The exit code 1 denotes that at least one file was modified.""" 2097 The exit code 1 denotes that at least one file was modified."""
2065 2098
2158 2191
2159 res = batches.setdefault(batch.settings(), batch) 2192 res = batches.setdefault(batch.settings(), batch)
2160 if res is not batch: 2193 if res is not batch:
2161 res.javafiles = res.javafiles + batch.javafiles 2194 res.javafiles = res.javafiles + batch.javafiles
2162 2195
2163 print "we have: " + str(len(batches)) + " batches" 2196 log("we have: " + str(len(batches)) + " batches")
2164 for batch in batches.itervalues(): 2197 for batch in batches.itervalues():
2165 run([args.eclipse_exe, 2198 for chunk in _chunk_files_for_command_line(batch.javafiles, pathFunction=lambda f: f.path):
2166 '-nosplash', 2199 run([args.eclipse_exe,
2167 '-application', 2200 '-nosplash',
2168 'org.eclipse.jdt.core.JavaCodeFormatter', 2201 '-application',
2169 '-vm', java(batch.javaCompliance).java, 2202 'org.eclipse.jdt.core.JavaCodeFormatter',
2170 '-config', batch.path] 2203 '-vm', java(batch.javaCompliance).java,
2171 + [f.path for f in batch.javafiles]) 2204 '-config', batch.path]
2172 for fi in batch.javafiles: 2205 + [f.path for f in chunk])
2173 if fi.update(batch.removeTrailingWhitespace): 2206 for fi in chunk:
2174 modified.append(fi) 2207 if fi.update(batch.removeTrailingWhitespace):
2208 modified.append(fi)
2175 2209
2176 log('{0} files were modified'.format(len(modified))) 2210 log('{0} files were modified'.format(len(modified)))
2177 2211
2178 if len(modified) != 0: 2212 if len(modified) != 0:
2179 arcbase = _primary_suite.dir 2213 arcbase = _primary_suite.dir
2501 2535
2502 auditfileName = join(p.dir, 'checkstyleOutput.txt') 2536 auditfileName = join(p.dir, 'checkstyleOutput.txt')
2503 log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config)) 2537 log('Running Checkstyle on {0} using {1}...'.format(sourceDir, config))
2504 2538
2505 try: 2539 try:
2506 2540 for chunk in _chunk_files_for_command_line(javafilelist):
2507 # Checkstyle is unable to read the filenames to process from a file, and the
2508 # CreateProcess function on Windows limits the length of a command line to
2509 # 32,768 characters (http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx)
2510 # so calling Checkstyle must be done in batches.
2511 while len(javafilelist) != 0:
2512 i = 0
2513 size = 0
2514 while i < len(javafilelist):
2515 s = len(javafilelist[i]) + 1
2516 if size + s < 30000:
2517 size += s
2518 i += 1
2519 else:
2520 break
2521
2522 batch = javafilelist[:i]
2523 javafilelist = javafilelist[i:]
2524 try: 2541 try:
2525 run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + batch, nonZeroIsFatal=False) 2542 run_java(['-Xmx1g', '-jar', library('CHECKSTYLE').get_path(True), '-f', 'xml', '-c', config, '-o', auditfileName] + chunk, nonZeroIsFatal=False)
2526 finally: 2543 finally:
2527 if exists(auditfileName): 2544 if exists(auditfileName):
2528 errors = [] 2545 errors = []
2529 source = [None] 2546 source = [None]
2530 def start_element(name, attrs): 2547 def start_element(name, attrs):