regression.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. # Copyright (c) MetaCommunications, Inc. 2003-2005
  2. #
  3. # Distributed under the Boost Software License, Version 1.0.
  4. # (See accompanying file LICENSE_1_0.txt or copy at
  5. # http://www.boost.org/LICENSE_1_0.txt)
  6. import urllib
  7. import tarfile
  8. import socket
  9. import time
  10. import getopt
  11. import glob
  12. import shutil
  13. import stat
  14. import os.path
  15. import os
  16. import platform
  17. import traceback
  18. import string
  19. import sys
  20. regression_root = os.path.abspath( os.path.dirname( sys.argv[0] ) )
  21. regression_results = os.path.join( regression_root, 'results' )
  22. regression_log = os.path.join( regression_results, 'bjam.log' )
  23. install_log = os.path.join( regression_results, 'bjam_install.log' )
  24. boost_root = os.path.join( regression_root, 'boost' )
  25. xsl_reports_dir = os.path.join( boost_root, 'tools', 'regression', 'xsl_reports' )
  26. timestamp_path = os.path.join( regression_root, 'timestamp' )
  27. cvs_command_line = 'cvs -z9 %(command)s'
  28. cvs_ext_command_line = 'cvs -d:ext:%(user)s@cvs.sourceforge.net:/cvsroot/boost -z9 %(command)s'
  29. cvs_pserver_command_line = 'cvs -d:pserver:%(user)s@cvs.sourceforge.net:/cvsroot/boost -z9 %(command)s'
  30. bjam = {}
  31. process_jam_log = {}
  32. if sys.platform == 'win32':
  33. bjam[ 'name' ] = 'bjam.exe'
  34. bjam[ 'build_cmd' ] = lambda toolset: 'build.bat %s' % toolset
  35. bjam[ 'is_supported_toolset' ] = lambda x: x in [ 'borland', 'como', 'gcc', 'gcc-nocygwin' \
  36. , 'intel-win32', 'metrowerks', 'mingw' \
  37. , 'msvc', 'vc7' \
  38. ]
  39. process_jam_log[ 'name' ] = 'process_jam_log.exe'
  40. process_jam_log[ 'default_toolset' ] = 'vc-7_1'
  41. patch_boost_name = 'patch_boost.bat'
  42. else:
  43. bjam[ 'name' ] = 'bjam'
  44. bjam[ 'build_cmd' ] = lambda toolset:'./build.sh %s' % toolset
  45. bjam[ 'is_supported_toolset' ] = lambda x: x in [ 'acc', 'como', 'darwin', 'gcc' \
  46. , 'intel-linux', 'kcc', 'kylix' \
  47. , 'mipspro', 'sunpro', 'tru64cxx' \
  48. , 'vacpp'\
  49. ]
  50. process_jam_log[ 'name' ] = 'process_jam_log'
  51. process_jam_log[ 'default_toolset' ] = 'gcc'
  52. patch_boost_name = './patch_boost'
  53. bjam[ 'default_toolset' ] = ''
  54. bjam[ 'path' ] = os.path.join( regression_root, bjam[ 'name' ] )
  55. bjam[ 'source_dir' ] = os.path.join( boost_root, 'tools', 'build', 'jam_src' )
  56. bjam[ 'build_path_root' ] = bjam[ 'source_dir' ]
  57. process_jam_log[ 'path' ] = os.path.join( regression_root, process_jam_log[ 'name' ] )
  58. process_jam_log[ 'source_dir' ] = os.path.join( boost_root, 'tools', 'regression', 'build' )
  59. process_jam_log[ 'build_path_root' ] = os.path.join(
  60. boost_root, 'bin', 'boost', 'tools', 'regression', 'build'
  61. , process_jam_log[ 'name' ]
  62. )
  63. process_jam_log[ 'build_cmd' ] = lambda toolset: bjam_command( toolset )
  64. process_jam_log[ 'is_supported_toolset' ] = lambda x : True
  65. build_monitor_url = 'http://www.meta-comm.com/engineering/resources/build_monitor.zip'
  66. pskill_url = 'http://www.sysinternals.com/files/pskill.zip'
  67. utils = None
  68. def log( message ):
  69. sys.stderr.write( '# %s\n' % message )
  70. sys.stderr.flush()
  71. def rmtree( path ):
  72. if os.path.exists( path ):
  73. if sys.platform == 'win32':
  74. os.system( 'del /f /s /q "%s" >nul 2>&1' % path )
  75. shutil.rmtree( path )
  76. else:
  77. os.system( 'rm -f -r "%s"' % path )
  78. def retry( f, args, max_attempts=2, sleep_secs=10 ):
  79. for attempts in range( max_attempts, -1, -1 ):
  80. try:
  81. return f( *args )
  82. except Exception, msg:
  83. log( '%s failed with message "%s"' % ( f.__name__, msg ) )
  84. if attempts == 0:
  85. log( 'Giving up.' )
  86. raise
  87. log( 'Retrying (%d more attempts).' % attempts )
  88. time.sleep( sleep_secs )
  89. def cleanup( args, **unused ):
  90. if args == []: args = [ 'source', 'bin' ]
  91. if 'source' in args:
  92. log( 'Cleaning up "%s" directory ...' % boost_root )
  93. rmtree( boost_root )
  94. if 'bin' in args:
  95. log( 'Cleaning up "%s" directory ...' % regression_results )
  96. rmtree( regression_results )
  97. def http_get( source_url, destination, proxy ):
  98. if proxy is None: proxies = None
  99. else: proxies = { 'http' : proxy }
  100. src = urllib.urlopen( source_url, proxies = proxies )
  101. f = open( destination, 'wb' )
  102. while True:
  103. data = src.read( 16*1024 )
  104. if len( data ) == 0: break
  105. f.write( data )
  106. f.close()
  107. src.close()
  108. def download_boost_tarball( destination, tag, proxy ):
  109. tarball_name = 'boost-%s.tar.bz2' % tag
  110. tarball_path = os.path.join( destination, tarball_name )
  111. tarball_url = 'http://www.meta-comm.com/engineering/boost/snapshot/%s' % tarball_name
  112. log( 'Downloading "%s" to "%s"...' % ( tarball_url, os.path.dirname( tarball_path ) ) )
  113. if os.path.exists( tarball_path ):
  114. os.unlink( tarball_path )
  115. http_get(
  116. tarball_url
  117. , tarball_path
  118. , proxy
  119. )
  120. return tarball_path
  121. def find_boost_dirs( path ):
  122. return [ x for x in glob.glob( os.path.join( path, 'boost[-_]*' ) )
  123. if os.path.isdir( x ) ]
  124. def unpack_tarball( tarball_path, destination ):
  125. log( 'Looking for old unpacked archives...' )
  126. old_boost_dirs = find_boost_dirs( destination )
  127. for old_boost_dir in old_boost_dirs:
  128. if old_boost_dir != tarball_path:
  129. log( 'Deleting old directory %s.' % old_boost_dir )
  130. rmtree( old_boost_dir )
  131. log( 'Unpacking boost tarball ("%s")...' % tarball_path )
  132. b = os.path.basename( tarball_path )
  133. name = b[ 0: b.find( '.' ) ]
  134. extension =b[ b.find( '.' ) : ]
  135. if extension in ( ".tar.gz", ".tar.bz2" ):
  136. mode = os.path.splitext( extension )[1][1:]
  137. tar = tarfile.open( tarball_path, 'r:%s' % mode )
  138. for tarinfo in tar:
  139. tar.extract( tarinfo, destination )
  140. if sys.platform == 'win32' and not tarinfo.isdir():
  141. # workaround what appears to be a Win32-specific bug in 'tarfile'
  142. # (modification times for extracted files are not set properly)
  143. f = os.path.join( destination, tarinfo.name )
  144. os.chmod( f, stat.S_IWRITE )
  145. os.utime( f, ( tarinfo.mtime, tarinfo.mtime ) )
  146. tar.close()
  147. elif extension in ( ".zip" ):
  148. import zipfile
  149. z = zipfile.ZipFile( tarball_path, 'r', zipfile.ZIP_DEFLATED )
  150. for f in z.infolist():
  151. destination_file_path = os.path.join( destination, f.filename )
  152. print f.filename
  153. if destination_file_path[-1] == "/": # directory
  154. if not os.path.exists( destination_file_path ):
  155. os.makedirs( destination_file_path )
  156. else: # file
  157. result = open( destination_file_path, 'wb' )
  158. result.write( z.read( f.filename ) )
  159. result.close()
  160. z.close()
  161. else:
  162. raise "Do not know how to unpack archives with extension \"%s\"" % extension
  163. boost_dir = find_boost_dirs( destination )[0]
  164. log( ' Unpacked into directory "%s"' % boost_dir )
  165. if os.path.exists( boost_root ):
  166. log( 'Deleting "%s" directory...' % boost_root )
  167. rmtree( boost_root )
  168. log( 'Renaming "%s" into "%s"' % ( boost_dir, boost_root ) )
  169. os.rename( boost_dir, boost_root )
  170. def cvs_command( user, command ):
  171. if user is None:
  172. cmd = cvs_command_line % { 'command': command }
  173. elif user == 'anonymous':
  174. cmd = cvs_pserver_command_line % { 'user': user, 'command': command }
  175. else:
  176. cmd = cvs_ext_command_line % { 'user': user, 'command': command }
  177. log( 'Executing CVS command "%s"' % cmd )
  178. rc = os.system( cmd )
  179. if rc != 0:
  180. raise Exception( 'CVS command "%s" failed with code %d' % ( cmd, rc ) )
  181. def cvs_checkout( user, tag, args ):
  182. if tag != 'CVS-HEAD':
  183. command = 'checkout -r %s boost' % tag
  184. else:
  185. command = 'checkout boost'
  186. os.chdir( regression_root )
  187. retry(
  188. cvs_command
  189. , ( user, command )
  190. , max_attempts=5
  191. )
  192. def cvs_update( user, tag, args ):
  193. if tag != 'CVS-HEAD':
  194. command = 'update -dPA -r %s' % tag
  195. else:
  196. command = 'update -dPA'
  197. os.chdir( os.path.join( regression_root, 'boost' ) )
  198. retry(
  199. cvs_command
  200. , ( user, command )
  201. , max_attempts=5
  202. )
  203. def format_time( t ):
  204. return time.strftime(
  205. '%a, %d %b %Y %H:%M:%S +0000'
  206. , t
  207. )
  208. def refresh_timestamp():
  209. if os.path.exists( timestamp_path ):
  210. os. unlink( timestamp_path )
  211. open( timestamp_path, 'w' ).close()
  212. def timestamp():
  213. return format_time(
  214. time.gmtime( os.stat( timestamp_path ).st_mtime )
  215. )
  216. def get_source( user, tag, proxy, args, **unused ):
  217. refresh_timestamp()
  218. log( 'Getting sources (%s)...' % timestamp() )
  219. if user is not None:
  220. cvs_checkout( user, tag, args )
  221. else:
  222. tarball_path = download_boost_tarball( regression_root, tag, proxy )
  223. unpack_tarball( tarball_path, regression_root )
  224. def update_source( user, tag, proxy, args, **unused ):
  225. if user is not None or os.path.exists( os.path.join( boost_root, 'CVS' ) ):
  226. open( timestamp_path, 'w' ).close()
  227. log( 'Updating sources from CVS (%s)...' % timestamp() )
  228. cvs_update( user, tag, args )
  229. else:
  230. get_source( user, tag, proxy, args )
  231. def tool_path( name_or_spec ):
  232. if isinstance( name_or_spec, basestring ):
  233. return os.path.join( regression_root, name_or_spec )
  234. if os.path.exists( name_or_spec[ 'path' ] ):
  235. return name_or_spec[ 'path' ]
  236. if name_or_spec.has_key( 'build_path' ):
  237. return name_or_spec[ 'build_path' ]
  238. build_path_root = name_or_spec[ 'build_path_root' ]
  239. log( 'Searching for "%s" in "%s"...' % ( name_or_spec[ 'name' ], build_path_root ) )
  240. for root, dirs, files in os.walk( build_path_root ):
  241. if name_or_spec[ 'name' ] in files:
  242. return os.path.join( root, name_or_spec[ 'name' ] )
  243. raise Exception( 'Cannot find "%s" in any of the following locations:\n%s' % (
  244. name_or_spec[ 'name' ]
  245. , '\n'.join( [ name_or_spec[ 'path' ], build_path_root ] )
  246. ) )
  247. def build_if_needed( tool, toolset, toolsets ):
  248. if os.path.exists( tool[ 'path' ] ):
  249. log( 'Found preinstalled "%s"; will use it.' % tool[ 'path' ] )
  250. return
  251. log( 'Preinstalled "%s" is not found; building one...' % tool[ 'path' ] )
  252. if toolset is None:
  253. if toolsets is not None:
  254. toolset = string.split( toolsets, ',' )[0]
  255. if not tool[ 'is_supported_toolset' ]( toolset ):
  256. log( 'Warning: Specified toolset (%s) cannot be used to bootstrap "%s".'\
  257. % ( toolset, tool[ 'name' ] ) )
  258. toolset = tool[ 'default_toolset' ]
  259. log( ' Using default toolset for the platform (%s).' % toolset )
  260. else:
  261. toolset = tool[ 'default_toolset' ]
  262. log( 'Warning: No bootstrap toolset for "%s" was specified.' % tool[ 'name' ] )
  263. log( ' Using default toolset for the platform (%s).' % toolset )
  264. if os.path.exists( tool[ 'source_dir' ] ):
  265. log( 'Found "%s" source directory "%s"' % ( tool[ 'name' ], tool[ 'source_dir' ] ) )
  266. build_cmd = tool[ 'build_cmd' ]( toolset )
  267. log( 'Building "%s" (%s)...' % ( tool[ 'name'], build_cmd ) )
  268. utils.system( [
  269. 'cd %s' % tool[ 'source_dir' ]
  270. , build_cmd
  271. ] )
  272. else:
  273. raise 'Could not find "%s" source directory "%s"' % ( tool[ 'name' ], tool[ 'source_dir' ] )
  274. if not tool.has_key( 'build_path' ):
  275. tool[ 'build_path' ] = tool_path( tool )
  276. if not os.path.exists( tool[ 'build_path' ] ):
  277. raise 'Failed to find "%s" after build.' % tool[ 'build_path' ]
  278. log( '%s succesfully built in "%s" location' % ( tool[ 'name' ], tool[ 'build_path' ] ) )
  279. def import_utils():
  280. global utils
  281. if utils is None:
  282. sys.path.append( xsl_reports_dir )
  283. import utils as utils_module
  284. utils = utils_module
  285. def download_if_needed( tool_name, tool_url, proxy ):
  286. path = tool_path( tool_name )
  287. if not os.path.exists( path ):
  288. log( 'Preinstalled "%s" is not found.' % path )
  289. log( ' Downloading from %s...' % tool_url )
  290. zip_path = '%s.zip' % os.path.splitext( path )[0]
  291. http_get( tool_url, zip_path, proxy )
  292. log( ' Unzipping %s...' % path )
  293. utils.unzip( zip_path, os.path.dirname( path ) )
  294. log( ' Removing %s...' % zip_path )
  295. os.unlink( zip_path )
  296. log( 'Done.' )
  297. def setup(
  298. comment
  299. , toolsets
  300. , bjam_toolset
  301. , pjl_toolset
  302. , monitored
  303. , proxy
  304. , args
  305. , **unused
  306. ):
  307. import_utils()
  308. if os.path.exists( patch_boost_name ):
  309. log( 'Found patch file "%s". Executing it.' % patch_boost_name )
  310. utils.system( [ patch_boost_name ] )
  311. build_if_needed( bjam, bjam_toolset, toolsets )
  312. build_if_needed( process_jam_log, pjl_toolset, toolsets )
  313. if monitored:
  314. if sys.platform == 'win32':
  315. download_if_needed( 'build_monitor.exe', build_monitor_url, proxy )
  316. download_if_needed( 'pskill.exe', pskill_url, proxy )
  317. else:
  318. log( 'Warning: Test monitoring is not supported on this platform (yet).' )
  319. log( ' Please consider contributing this piece!' )
  320. def bjam_command( toolsets ):
  321. result = '%s "-sBOOST_BUILD_PATH=%s:%s" "-sBOOST_ROOT=%s"'\
  322. % (
  323. tool_path( bjam )
  324. , regression_root
  325. , os.path.join( boost_root, 'tools/build/v1' )
  326. , boost_root
  327. )
  328. if not toolsets is None:
  329. result += ' "-sTOOLS=%s"' % string.join( string.split( toolsets, ',' ), ' ' )
  330. return result
  331. def install( toolsets, **unused ):
  332. import_utils()
  333. os.chdir( os.path.join( boost_root ) )
  334. log( 'Making "%s" directory...' % regression_results )
  335. utils.makedirs( regression_results )
  336. install_cmd = '%s -d2 install >>%s 2>&1' % ( bjam_command( toolsets ), install_log )
  337. log( 'Installing libraries (%s)...' % install_cmd )
  338. utils.system( [ install_cmd ] )
  339. def start_build_monitor( timeout ):
  340. if sys.platform == 'win32':
  341. build_monitor_path = tool_path( 'build_monitor.exe' )
  342. if os.path.exists( build_monitor_path ):
  343. utils.system( [ 'start /belownormal %s bjam.exe %d' % ( build_monitor_path, timeout*60 ) ] )
  344. else:
  345. log( 'Warning: Build monitor is not found at "%s"' % build_monitor_path )
  346. def stop_build_monitor():
  347. if sys.platform == 'win32':
  348. build_monitor_path = tool_path( 'build_monitor.exe' )
  349. if os.path.exists( build_monitor_path ):
  350. utils.system( [ '%s build_monitor' % tool_path( 'pskill.exe' ) ] )
  351. def run_process_jam_log():
  352. log( 'Getting test case results out of "%s"...' % regression_log )
  353. utils.checked_system( [
  354. '%s %s <%s' % (
  355. tool_path( process_jam_log )
  356. , regression_results
  357. , regression_log
  358. )
  359. ] )
  360. def test(
  361. toolsets
  362. , bjam_options
  363. , monitored
  364. , timeout
  365. , args
  366. , **unused
  367. ):
  368. if args == []:
  369. args = [ "test", "process" ]
  370. import_utils()
  371. try:
  372. if monitored:
  373. start_build_monitor( timeout )
  374. cd = os.getcwd()
  375. os.chdir( os.path.join( boost_root, 'status' ) )
  376. log( 'Making "%s" directory...' % regression_results )
  377. utils.makedirs( regression_results )
  378. results_libs = os.path.join( regression_results, 'libs' )
  379. results_status = os.path.join( regression_results, 'status' )
  380. if "clean" in args:
  381. rmtree( results_libs )
  382. rmtree( results_status )
  383. if "test" in args:
  384. test_cmd = '%s -d2 --dump-tests %s "-sALL_LOCATE_TARGET=%s" >>%s 2>&1' % (
  385. bjam_command( toolsets )
  386. , bjam_options
  387. , regression_results
  388. , regression_log
  389. )
  390. log( 'Starting tests (%s)...' % test_cmd )
  391. utils.system( [ test_cmd ] )
  392. if "process" in args:
  393. run_process_jam_log()
  394. os.chdir( cd )
  395. finally:
  396. if monitored:
  397. stop_build_monitor()
  398. def collect_logs(
  399. tag
  400. , runner
  401. , platform
  402. , user
  403. , comment
  404. , incremental
  405. , args
  406. , **unused
  407. ):
  408. import_utils()
  409. if comment is None:
  410. comment = 'comment.html'
  411. comment_path = os.path.join( regression_root, comment )
  412. if not os.path.exists( comment_path ):
  413. log( 'Comment file "%s" not found; creating default comment.' % comment_path )
  414. f = open( comment_path, 'w' )
  415. f.write( '<p>Tests are run on %s platform.</p>' % string.capitalize( sys.platform ) )
  416. f.close()
  417. run_type = ''
  418. if incremental: run_type = 'incremental'
  419. else: run_type = 'full'
  420. source = 'tarball'
  421. cvs_root_file = os.path.join( boost_root, 'CVS', 'root' )
  422. if os.path.exists( cvs_root_file ):
  423. if string.split( open( cvs_root_file ).readline(), '@' )[0] == ':pserver:anonymous':
  424. source = 'anonymous CVS'
  425. else:
  426. source = 'CVS'
  427. from runner import collect_logs
  428. collect_logs(
  429. regression_results
  430. , runner
  431. , tag
  432. , platform
  433. , comment_path
  434. , timestamp_path
  435. , user
  436. , source
  437. , run_type
  438. )
  439. def upload_logs(
  440. tag
  441. , runner
  442. , user
  443. , ftp_proxy
  444. , debug_level
  445. , **unused
  446. ):
  447. import_utils()
  448. from runner import upload_logs
  449. upload_logs( regression_results, runner, tag, user, ftp_proxy, debug_level )
  450. def update_itself( **unused ):
  451. source = os.path.join( xsl_reports_dir, 'runner', os.path.basename( sys.argv[0] ) )
  452. self = os.path.join( regression_root, os.path.basename( sys.argv[0] ) )
  453. log( 'Updating %s from %s...' % ( self, source ) )
  454. log( ' Checking modification dates...' )
  455. if os.stat( self ).st_mtime > os.stat( source ).st_mtime:
  456. log( 'Warning: The current version of script appears to be newer than the source.' )
  457. log( ' Update skipped.' )
  458. else:
  459. log( ' Saving a backup copy of the current script...' )
  460. os.chmod( self, stat.S_IWRITE ) # Win32 workaround
  461. shutil.move( self, '%s~' % self )
  462. log( ' Replacing %s with a newer version...' % self )
  463. shutil.copy2( source, self )
  464. def send_mail( smtp_login, mail, subject, msg = '', debug_level = 0 ):
  465. import smtplib
  466. if not smtp_login:
  467. server_name = 'mail.%s' % mail.split( '@' )[-1]
  468. user_name = None
  469. password = None
  470. else:
  471. server_name = smtp_login.split( '@' )[-1]
  472. ( user_name, password ) = string.split( smtp_login.split( '@' )[0], ':' )
  473. log( ' Sending mail through "%s"...' % server_name )
  474. smtp_server = smtplib.SMTP( server_name )
  475. smtp_server.set_debuglevel( debug_level )
  476. if user_name:
  477. smtp_server.login( user_name, password )
  478. smtp_server.sendmail(
  479. mail
  480. , [ mail ]
  481. , 'Subject: %s\nTo: %s\n\n%s' % ( subject, mail, msg )
  482. )
  483. def regression(
  484. tag
  485. , local
  486. , runner
  487. , platform
  488. , user
  489. , comment
  490. , toolsets
  491. , bjam_options
  492. , bjam_toolset
  493. , pjl_toolset
  494. , incremental
  495. , monitored
  496. , timeout
  497. , mail = None
  498. , smtp_login = None
  499. , proxy = None
  500. , ftp_proxy = None
  501. , debug_level = 0
  502. , args = []
  503. ):
  504. try:
  505. mail_subject = 'Boost regression for %s on %s' % ( tag, string.split(socket.gethostname(), '.')[0] )
  506. start_time = time.localtime()
  507. if mail:
  508. log( 'Sending start notification to "%s"' % mail )
  509. send_mail(
  510. smtp_login
  511. , mail
  512. , '%s started at %s.' % ( mail_subject, format_time( start_time ) )
  513. , debug_level = debug_level
  514. )
  515. if local is not None:
  516. log( 'Using local file "%s"' % local )
  517. b = os.path.basename( local )
  518. tag = b[ 0: b.find( '.' ) ]
  519. log( 'Tag: "%s"' % tag )
  520. unpack_tarball( local, regression_root )
  521. else:
  522. if incremental:
  523. update_source( user, tag, proxy, [] )
  524. else:
  525. cleanup( [] )
  526. get_source( user, tag, proxy, [] )
  527. setup( comment, toolsets, bjam_toolset, pjl_toolset, monitored, proxy, [] )
  528. test( toolsets, bjam_options, monitored, timeout, [] )
  529. collect_logs( tag, runner, platform, user, comment, incremental, [] )
  530. upload_logs( tag, runner, user, ftp_proxy, debug_level )
  531. update_itself()
  532. if mail:
  533. log( 'Sending report to "%s"' % mail )
  534. end_time = time.localtime()
  535. send_mail(
  536. smtp_login
  537. , mail
  538. , '%s completed successfully at %s.' % ( mail_subject, format_time( end_time ) )
  539. , debug_level = debug_level
  540. )
  541. except:
  542. if mail:
  543. log( 'Sending report to "%s"' % mail )
  544. traceback_ = '\n'.join( apply( traceback.format_exception, sys.exc_info() ) )
  545. end_time = time.localtime()
  546. send_mail(
  547. smtp_login
  548. , mail
  549. , '%s failed at %s.' % ( mail_subject, format_time( end_time ) )
  550. , traceback_
  551. , debug_level
  552. )
  553. raise
  554. def show_revision( **unused ):
  555. modified = '$Date$'
  556. revision = '$Revision$'
  557. import re
  558. re_keyword_value = re.compile( r'^\$\w+:\s+(.*)\s+\$$' )
  559. print '\n\tResivion: %s' % re_keyword_value.match( revision ).group( 1 )
  560. print '\tLast modified on: %s\n' % re_keyword_value.match( modified ).group( 1 )
  561. def accept_args( args ):
  562. args_spec = [
  563. 'tag='
  564. , 'local='
  565. , 'runner='
  566. , 'platform='
  567. , 'user='
  568. , 'comment='
  569. , 'toolsets='
  570. , 'bjam-options='
  571. , 'bjam-toolset='
  572. , 'pjl-toolset='
  573. , 'timeout='
  574. , 'mail='
  575. , 'smtp-login='
  576. , 'proxy='
  577. , 'ftp-proxy='
  578. , 'debug-level='
  579. , 'incremental'
  580. , 'monitored'
  581. , 'help'
  582. ]
  583. options = {
  584. '--tag' : 'CVS-HEAD'
  585. , '--local' : None
  586. , '--platform' : platform.system()
  587. , '--user' : None
  588. , '--comment' : None
  589. , '--toolsets' : None
  590. , '--bjam-options' : ''
  591. , '--bjam-toolset' : None
  592. , '--pjl-toolset' : None
  593. , '--timeout' : 5
  594. , '--mail' : None
  595. , '--smtp-login' : None
  596. , '--proxy' : None
  597. , '--debug-level' : 0
  598. , '--ftp-proxy' : None
  599. }
  600. ( option_pairs, other_args ) = getopt.getopt( args, '', args_spec )
  601. map( lambda x: options.__setitem__( x[0], x[1] ), option_pairs )
  602. if not options.has_key( '--runner' ) or options.has_key( '--help' ):
  603. usage()
  604. sys.exit( 1 )
  605. return {
  606. 'tag' : options[ '--tag' ]
  607. , 'local' : options[ '--local' ]
  608. , 'runner' : options[ '--runner' ]
  609. , 'platform' : options[ '--platform']
  610. , 'user' : options[ '--user' ]
  611. , 'comment' : options[ '--comment' ]
  612. , 'toolsets' : options[ '--toolsets' ]
  613. , 'bjam_options' : options[ '--bjam-options' ]
  614. , 'bjam_toolset' : options[ '--bjam-toolset' ]
  615. , 'pjl_toolset' : options[ '--pjl-toolset' ]
  616. , 'incremental' : options.has_key( '--incremental' )
  617. , 'monitored' : options.has_key( '--monitored' )
  618. , 'timeout' : options[ '--timeout' ]
  619. , 'mail' : options[ '--mail' ]
  620. , 'smtp_login' : options[ '--smtp-login' ]
  621. , 'proxy' : options[ '--proxy' ]
  622. , 'ftp_proxy' : options[ '--ftp-proxy' ]
  623. , 'debug_level' : int(options[ '--debug-level' ])
  624. , 'args' : other_args
  625. }
  626. commands = {
  627. 'cleanup' : cleanup
  628. , 'get-source' : get_source
  629. , 'update-source' : update_source
  630. , 'setup' : setup
  631. , 'install' : install
  632. , 'test' : test
  633. , 'collect-logs' : collect_logs
  634. , 'upload-logs' : upload_logs
  635. , 'update-itself' : update_itself
  636. , 'regression' : regression
  637. , 'show-revision' : show_revision
  638. }
  639. def usage():
  640. print 'Usage:\n\t%s [command] options' % os.path.basename( sys.argv[0] )
  641. print '''
  642. Commands:
  643. \t%s
  644. Options:
  645. \t--runner runner ID (e.g. 'Metacomm')
  646. \t--tag the tag for the results ('CVS-HEAD' by default)
  647. \t--local the name of the boost tarball
  648. \t--comment an HTML comment file to be inserted in the reports
  649. \t ('comment.html' by default)
  650. \t--incremental do incremental run (do not remove previous binaries)
  651. \t--monitored do a monitored run
  652. \t--timeout specifies the timeout, in minutes, for a single test
  653. \t run/compilation (enforced only in monitored runs, 5 by
  654. \t default)
  655. \t--user SourceForge user name for a shell/CVS account (optional)
  656. \t--toolsets comma-separated list of toolsets to test with (optional)
  657. \t--bjam-options options to pass to the regression test (optional)
  658. \t--bjam-toolset bootstrap toolset for 'bjam' executable (optional)
  659. \t--pjl-toolset bootstrap toolset for 'process_jam_log' executable
  660. \t (optional)
  661. \t--mail email address to send run notification to (optional)
  662. \t--smtp-login STMP server address/login information, in the following
  663. \t form: <user>:<password>@<host>[:<port>] (optional).
  664. \t--proxy HTTP proxy server address and port (e.g.
  665. \t 'http://www.someproxy.com:3128', optional)
  666. \t--ftp-proxy FTP proxy server (e.g. 'ftpproxy', optional)
  667. \t--debug-level debugging level; controls the amount of debugging
  668. \t output printed; 0 by default (no debug output)
  669. ''' % '\n\t'.join( commands.keys() )
  670. print 'Example:\n\t%s --runner=Metacomm\n' % os.path.basename( sys.argv[0] )
  671. print 'For more documentation, see http://tinyurl.com/4f2zp\n'
  672. if len(sys.argv) > 1 and sys.argv[1] in commands:
  673. command = sys.argv[1]
  674. args = sys.argv[ 2: ]
  675. if command not in [ 'collect-logs', 'upload-logs' ]:
  676. args.insert( 0, '--runner=' )
  677. else:
  678. command = 'regression'
  679. args = sys.argv[ 1: ]
  680. commands[ command ]( **accept_args( args ) )
粤ICP备19079148号