Ticket #7596: process_jam_log.diff
File process_jam_log.diff, 14.0 KB (added by , 10 years ago) |
---|
-
process_jam_log.cpp
24 24 #include <ctime> 25 25 #include <cctype> // for tolower 26 26 #include <cstdlib> // for exit 27 #include <algorithm> // find 27 28 28 29 using std::string; 29 30 namespace xml = boost::tiny_xml; … … 46 47 typedef std::map< string, test_info > test2info_map; // key is test-name 47 48 test2info_map test2info; 48 49 49 fs::path boost_root; 50 fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) 50 // get_boost_root --------------------------------------------------------// 51 51 52 // set_boost_root --------------------------------------------------------// 53 54 void set_boost_root() 52 fs::path get_boost_root() 55 53 { 56 57 boost_root= fs::initial_path();54 // figure out where Boost Root is. 55 fs::path ipath = fs::initial_path(); 58 56 59 for(;;) 60 { 61 if ( fs::exists( boost_root / "libs" ) ) 62 { 63 fs::current_path( fs::initial_path() ); // restore initial path 64 return; 65 } 66 fs::current_path( ".." ); 67 if ( boost_root == fs::current_path() ) 68 { 69 fs::current_path( fs::initial_path() ); // restore initial path 70 std::cout << 71 "Abort: process_jam_log must be run from within a boost directory tree\n"; 72 std::exit(1); 73 } 74 boost_root = fs::current_path(); 57 // case I - running from within boost root directory 58 if(fs::exists(ipath / "libs")) 59 return ipath; 60 61 // cast II - we're running from within a lower level boost directory 62 // just return the the part from the root up to the "libs" 63 while(ipath.end() != ipath.begin()){ 64 bool end = ipath.filename() == "libs"; 65 ipath.remove_filename(); 66 if(end) 67 break; 75 68 } 69 70 return ipath; 76 71 } 77 72 78 73 // append_html -------------------------------------------------------------// … … 127 122 : "" 128 123 ; 129 124 } 130 131 125 132 126 // split --------------------------------------------------------------------// 133 127 … … 143 137 return result; 144 138 } 145 139 146 147 140 // extract a target directory path from a jam target string ----------------// 148 141 // s may be relative to the initial_path: 149 142 // ..\..\..\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj … … 155 148 string target_directory( const string & s ) 156 149 { 157 150 string temp( s ); 151 // convert all '\' to '/' 158 152 convert_path_separators( temp ); 153 // remove the last '/' and everything that follows 159 154 temp.erase( temp.find_last_of( "/" ) ); // remove leaf 155 156 // remove command to leave directory 160 157 temp = split( trim_left( temp ) ).back(); 161 if ( temp[0] == '.' ) temp.erase( 0, temp.find_first_not_of( "./" ) );162 else temp.erase( 0, locate_root.string().size()+1 );163 158 if ( echo ) 164 159 std::cout << "\ttarget_directory( \"" << s << "\") -> \"" << temp << "\"" << std::endl; 165 160 return temp; … … 197 192 198 193 // Take a path to a target directory of test, and 199 194 // returns library name corresponding to that path. 200 string test_path_to_library_name( stringconst& path )195 string test_path_to_library_name( fs::path const& path ) 201 196 { 202 std::string result; 203 string::size_type start_pos( path.find( "libs/" ) ); 204 if ( start_pos == string::npos ) { 205 start_pos = path.find( "tools/" ); 197 fs::path::iterator const & end = path.end(); 198 fs::path::iterator const & begin = path.begin(); 199 200 // The path format is ...libs/functional/hash/test/something.test/.... 201 // So, the part between "libs" and "test/something.test" can be considered 202 // as library name. 203 fs::path::iterator library_name_begin = std::find(begin, end, "libs"); 204 if(end == library_name_begin) 205 library_name_begin = std::find(begin, end, "tools"); 206 207 // path doesn't include any markers for library name 208 if(library_name_begin == end) 209 return ""; 210 211 ++library_name_begin; 212 fs::path::iterator library_name_end = std::find(library_name_begin, end, "test"); 213 if(end == library_name_end){ 214 // look for and element with .test in it 215 struct contains_dot_test { 216 const std::string m_arg; 217 contains_dot_test() : 218 m_arg(".test") 219 {} 220 bool operator()(fs::path const & fname) const{ 221 // if file name includes .test return true 222 std::string s = fname.string(); 223 return s.end() != std::search( 224 s.begin(), 225 s.end(), 226 m_arg.begin(), 227 m_arg.end() 228 ); 229 } 230 }; 231 library_name_end = std::find_if(library_name_begin, end, contains_dot_test()); 206 232 } 233 if(end == library_name_end) 234 return ""; 207 235 208 if ( start_pos != string::npos ) 209 { 210 // The path format is ...libs/functional/hash/test/something.test/.... 211 // So, the part between "libs" and "test/something.test" can be considered 212 // as library name. But, for some libraries tests are located too deep, 213 // say numeric/ublas/test/test1 directory, and some libraries have tests 214 // in several subdirectories (regex/example and regex/test). So, nested 215 // directory may belong to several libraries. 236 //But, for some libraries tests are located too deep, 237 // say numeric/ublas/test/test1 directory, and some libraries have tests 238 // in several subdirectories (regex/example and regex/test). So, nested 239 // directory may belong to several libraries. 216 240 217 218 219 220 241 // To disambituate, it's possible to place a 'sublibs' file in 242 // a directory. It means that child directories are separate libraries. 243 // It's still possible to have tests in the directory that has 'sublibs' 244 // file. 221 245 222 std::string interesting; 223 start_pos = path.find( '/', start_pos ) + 1; 224 string::size_type end_pos( path.find( ".test/", start_pos ) ); 225 end_pos = path.rfind('/', end_pos); 226 if (path.substr(end_pos - 5, 5) == "/test") 227 interesting = path.substr( start_pos, end_pos - 5 - start_pos ); 228 else 229 interesting = path.substr( start_pos, end_pos - start_pos ); 246 fs::path result; 230 247 231 // Take slash separate elements until we have corresponding 'sublibs'. 232 end_pos = 0; 233 for(;;) 234 { 248 /* 249 // I can't implement the code below for the case where the 250 // source code is outside the boost root tree. So comment it out here. 251 // Take slash separate elements until we have corresponding 'sublibs'. 252 end_pos = 0; 253 for(;;) 254 { 235 255 end_pos = interesting.find('/', end_pos); 236 256 if (end_pos == string::npos) { 237 result = interesting;238 break;257 result = interesting; 258 break; 239 259 } 240 260 result = interesting.substr(0, end_pos); 241 261 242 262 if ( fs::exists( ( boost_root / "libs" ) / result / "sublibs" ) ) 243 263 { 244 end_pos = end_pos + 1;264 end_pos = end_pos + 1; 245 265 } 246 266 else 247 break; 248 } 267 break; 249 268 } 269 */ 270 return result.string(); 271 } 250 272 251 return result; 252 } 273 // Tries to find target name in the string 'msg', starting from 274 // position start. 275 // If found, extract the directory name from the target name and 276 // stores it in 'dir', and return the position after the target name. 277 // Otherwise, returns string::npos. 278 string::size_type parse_skipped_msg_aux(const string& msg, 279 string::size_type start, 280 string& dir) 281 { 253 282 254 // Tries to find target name in the string 'msg', starting from 255 // position start. 256 // If found, extract the directory name from the target name and 257 // stores it in 'dir', and return the position after the target name. 258 // Otherwise, returns string::npos. 259 string::size_type parse_skipped_msg_aux(const string& msg, 260 string::size_type start, 261 string& dir) 262 { 283 fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) 284 263 285 dir.clear(); 264 286 string::size_type start_pos = msg.find( '<', start ); 265 287 if ( start_pos == string::npos ) return string::npos; … … 327 349 class test_log 328 350 : boost::noncopyable 329 351 { 330 const string &m_target_directory;352 const fs::path m_target_directory; 331 353 xml::element_ptr m_root; 332 354 public: 333 test_log( const string& target_directory,355 test_log( const fs::path & target_directory, 334 356 const string & test_name, 335 357 const string & toolset, 336 358 bool force_new_file ) … … 338 360 { 339 361 if ( !force_new_file ) 340 362 { 341 fs::path pth( locate_root / target_directory / "test_log.xml" ); 363 //fs::path pth( locate_root / target_directory / "test_log.xml" ); 364 fs::path pth( target_directory / "test_log.xml" ); 342 365 fs::ifstream file( pth ); 343 366 if ( file ) // existing file 344 367 { … … 366 389 367 390 if ( info.type.empty() ) 368 391 { 369 if ( target_directory.find( ".lib/" ) != string::npos 370 || target_directory.find( ".dll/" ) != string::npos 371 || target_directory.find( ".so/" ) != string::npos 372 || target_directory.find( ".dylib/" ) != string::npos 373 || target_directory.find( "/build/" ) != string::npos 374 ) 375 { 376 info.type = "lib"; 392 struct contains_substring { 393 const std::string m_arg; 394 const std::string::const_iterator m_begin, m_end; 395 contains_substring(const std::string & arg) : 396 m_arg(arg), 397 m_begin(m_arg.begin()), 398 m_end(m_arg.end()) 399 {} 400 bool operator()(fs::path const & fname) const{ 401 // if file name includes .test return true 402 std::string s = fname.string(); 403 return s.end() != std::search( 404 s.begin(), 405 s.end(), 406 m_begin, 407 m_end 408 ); 409 } 410 }; 411 fs::path::iterator const begin = target_directory.begin(); 412 fs::path::iterator const end = target_directory.end(); 413 414 if( end != std::find_if(begin, end, contains_substring(".lib")) 415 || end != std::find_if(begin, end, contains_substring(".dll")) 416 || end != std::find_if(begin, end, contains_substring(".so")) 417 || end != std::find_if(begin, end, contains_substring(".dylib")) 418 || end != std::find_if(begin, end, contains_substring("build")) 419 ){ 420 info.type = "lib"; 377 421 } 378 else if ( target_directory.find( ".pyd/" ) != string::npos ) 379 info.type = "pyd"; 422 else 423 if( end != std::find_if(begin, end, contains_substring(".pyd")) ){ 424 info.type = "pyd"; 425 } 380 426 } 381 427 382 428 m_root.reset( new xml::element( "test-log" ) ); … … 389 435 m_root->attributes.push_back( 390 436 xml::attribute( "test-program", info.file_path ) ); 391 437 m_root->attributes.push_back( 392 xml::attribute( "target-directory", target_directory ) );438 xml::attribute( "target-directory", target_directory.string() ) ); 393 439 m_root->attributes.push_back( 394 440 xml::attribute( "toolset", toolset ) ); 395 441 m_root->attributes.push_back( … … 399 445 400 446 ~test_log() 401 447 { 402 fs::path pth( locate_root / m_target_directory / "test_log.xml" ); 448 //fs::path pth( locate_root / m_target_directory / "test_log.xml" ); 449 fs::path pth( m_target_directory / "test_log.xml" ); 403 450 if ( create_dirs && !fs::exists( pth.branch_path() ) ) 404 451 fs::create_directories( pth.branch_path() ); 405 452 fs::ofstream file( pth ); … … 411 458 else xml::write( *m_root, file ); 412 459 } 413 460 414 const string& target_directory() const { return m_target_directory; }461 const fs::path & target_directory() const { return m_target_directory; } 415 462 416 463 void remove_action( const string & action_name ) 417 464 // no effect if action_name not found … … 562 609 // streams are implemented using standard C files. 563 610 std::ios::sync_with_stdio(false); 564 611 612 fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) 613 565 614 fs::initial_path(); 566 615 std::istream* input = 0; 567 616 … … 615 664 std::cout << "Abort: option --boost-root requires a directory argument\n"; 616 665 std::exit(1); 617 666 } 667 /* 618 668 boost_root = fs::path( argv[1] ); 619 669 if ( !boost_root.is_complete() ) 620 670 boost_root = ( fs::initial_path() / boost_root ).normalize(); 621 671 */ 622 672 --argc; ++argv; 673 623 674 } 624 675 else if ( std::strcmp( argv[1], "--locate-root" ) == 0 ) 625 676 { … … 655 706 } 656 707 } 657 708 709 /* 658 710 if ( boost_root.empty() ) 659 711 { 660 set_boost_root(); 712 boost_root = get_boost_root(); 713 if(boost_root.empty()){ 714 std::cout << 715 "Abort: Failed to discover boost root\n"; 716 std::exit(1); 717 } 661 718 boost_root.normalize(); 662 719 } 720 */ 663 721 664 722 /* 665 723 if ( locate_root.empty() ) 666 724 { 667 725 locate_root = boost_root; 668 726 } 669 727 else if ( !locate_root.is_complete() ) 670 728 { 671 locate_root = ( fs::initial_path() / locate_root ).normalize(); 672 } 729 //locate_root = ( fs::initial_path() / locate_root ).normalize(); 730 locate_root = locate_root.normalize(); 731 } 673 732 733 if(locate_root.empty()) 734 if(! fs::exists("bin")) 735 locate_root = find_boost_root(fs::initial_path()); 736 */ 737 674 738 if ( input == 0 ) 675 {676 739 input = &std::cin; 677 }678 740 679 std::cout << "boost_root: " << boost_root.string() << '\n' 680 << "locate_root: " << locate_root.string() << '\n'; 741 std::cout << "locate_root: " << locate_root.string() << '\n'; 681 742 682 743 message_manager mgr; 683 744