Index: process_jam_log.cpp =================================================================== --- process_jam_log.cpp (revision 81077) +++ process_jam_log.cpp (working copy) @@ -24,6 +24,7 @@ #include #include // for tolower #include // for exit +#include // find using std::string; namespace xml = boost::tiny_xml; @@ -46,33 +47,27 @@ typedef std::map< string, test_info > test2info_map; // key is test-name test2info_map test2info; - fs::path boost_root; - fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) + // get_boost_root --------------------------------------------------------// - // set_boost_root --------------------------------------------------------// - - void set_boost_root() + fs::path get_boost_root() { - - boost_root = fs::initial_path(); + // figure out where Boost Root is. + fs::path ipath = fs::initial_path(); - for(;;) - { - if ( fs::exists( boost_root / "libs" ) ) - { - fs::current_path( fs::initial_path() ); // restore initial path - return; - } - fs::current_path( ".." ); - if ( boost_root == fs::current_path() ) - { - fs::current_path( fs::initial_path() ); // restore initial path - std::cout << - "Abort: process_jam_log must be run from within a boost directory tree\n"; - std::exit(1); - } - boost_root = fs::current_path(); + // case I - running from within boost root directory + if(fs::exists(ipath / "libs")) + return ipath; + + // cast II - we're running from within a lower level boost directory + // just return the the part from the root up to the "libs" + while(ipath.end() != ipath.begin()){ + bool end = ipath.filename() == "libs"; + ipath.remove_filename(); + if(end) + break; } + + return ipath; } // append_html -------------------------------------------------------------// @@ -127,7 +122,6 @@ : "" ; } - // split --------------------------------------------------------------------// @@ -143,7 +137,6 @@ return result; } - // extract a target directory path from a jam target string ----------------// // s may be relative to the initial_path: // ..\..\..\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj @@ -155,11 +148,13 @@ string target_directory( const string & s ) { string temp( s ); + // convert all '\' to '/' convert_path_separators( temp ); + // remove the last '/' and everything that follows temp.erase( temp.find_last_of( "/" ) ); // remove leaf + + // remove command to leave directory temp = split( trim_left( temp ) ).back(); - if ( temp[0] == '.' ) temp.erase( 0, temp.find_first_not_of( "./" ) ); - else temp.erase( 0, locate_root.string().size()+1 ); if ( echo ) std::cout << "\ttarget_directory( \"" << s << "\") -> \"" << temp << "\"" << std::endl; return temp; @@ -197,69 +192,96 @@ // Take a path to a target directory of test, and // returns library name corresponding to that path. - string test_path_to_library_name( string const& path ) + string test_path_to_library_name( fs::path const& path ) { - std::string result; - string::size_type start_pos( path.find( "libs/" ) ); - if ( start_pos == string::npos ) { - start_pos = path.find( "tools/" ); + fs::path::iterator const & end = path.end(); + fs::path::iterator const & begin = path.begin(); + + // The path format is ...libs/functional/hash/test/something.test/.... + // So, the part between "libs" and "test/something.test" can be considered + // as library name. + fs::path::iterator library_name_begin = std::find(begin, end, "libs"); + if(end == library_name_begin) + library_name_begin = std::find(begin, end, "tools"); + + // path doesn't include any markers for library name + if(library_name_begin == end) + return ""; + + ++library_name_begin; + fs::path::iterator library_name_end = std::find(library_name_begin, end, "test"); + if(end == library_name_end){ + // look for and element with .test in it + struct contains_dot_test { + const std::string m_arg; + contains_dot_test() : + m_arg(".test") + {} + bool operator()(fs::path const & fname) const{ + // if file name includes .test return true + std::string s = fname.string(); + return s.end() != std::search( + s.begin(), + s.end(), + m_arg.begin(), + m_arg.end() + ); + } + }; + library_name_end = std::find_if(library_name_begin, end, contains_dot_test()); } + if(end == library_name_end) + return ""; - if ( start_pos != string::npos ) - { - // The path format is ...libs/functional/hash/test/something.test/.... - // So, the part between "libs" and "test/something.test" can be considered - // as library name. But, for some libraries tests are located too deep, - // say numeric/ublas/test/test1 directory, and some libraries have tests - // in several subdirectories (regex/example and regex/test). So, nested - // directory may belong to several libraries. + //But, for some libraries tests are located too deep, + // say numeric/ublas/test/test1 directory, and some libraries have tests + // in several subdirectories (regex/example and regex/test). So, nested + // directory may belong to several libraries. - // To disambituate, it's possible to place a 'sublibs' file in - // a directory. It means that child directories are separate libraries. - // It's still possible to have tests in the directory that has 'sublibs' - // file. + // To disambituate, it's possible to place a 'sublibs' file in + // a directory. It means that child directories are separate libraries. + // It's still possible to have tests in the directory that has 'sublibs' + // file. - std::string interesting; - start_pos = path.find( '/', start_pos ) + 1; - string::size_type end_pos( path.find( ".test/", start_pos ) ); - end_pos = path.rfind('/', end_pos); - if (path.substr(end_pos - 5, 5) == "/test") - interesting = path.substr( start_pos, end_pos - 5 - start_pos ); - else - interesting = path.substr( start_pos, end_pos - start_pos ); + fs::path result; - // Take slash separate elements until we have corresponding 'sublibs'. - end_pos = 0; - for(;;) - { + /* + // I can't implement the code below for the case where the + // source code is outside the boost root tree. So comment it out here. + // Take slash separate elements until we have corresponding 'sublibs'. + end_pos = 0; + for(;;) + { end_pos = interesting.find('/', end_pos); if (end_pos == string::npos) { - result = interesting; - break; + result = interesting; + break; } result = interesting.substr(0, end_pos); if ( fs::exists( ( boost_root / "libs" ) / result / "sublibs" ) ) { - end_pos = end_pos + 1; + end_pos = end_pos + 1; } else - break; - } + break; } + */ + return result.string(); +} - return result; - } +// Tries to find target name in the string 'msg', starting from +// position start. +// If found, extract the directory name from the target name and +// stores it in 'dir', and return the position after the target name. +// Otherwise, returns string::npos. +string::size_type parse_skipped_msg_aux(const string& msg, + string::size_type start, + string& dir) + { - // Tries to find target name in the string 'msg', starting from - // position start. - // If found, extract the directory name from the target name and - // stores it in 'dir', and return the position after the target name. - // Otherwise, returns string::npos. - string::size_type parse_skipped_msg_aux(const string& msg, - string::size_type start, - string& dir) - { +fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) + dir.clear(); string::size_type start_pos = msg.find( '<', start ); if ( start_pos == string::npos ) return string::npos; @@ -327,10 +349,10 @@ class test_log : boost::noncopyable { - const string & m_target_directory; + const fs::path m_target_directory; xml::element_ptr m_root; public: - test_log( const string & target_directory, + test_log( const fs::path & target_directory, const string & test_name, const string & toolset, bool force_new_file ) @@ -338,7 +360,8 @@ { if ( !force_new_file ) { - fs::path pth( locate_root / target_directory / "test_log.xml" ); + //fs::path pth( locate_root / target_directory / "test_log.xml" ); + fs::path pth( target_directory / "test_log.xml" ); fs::ifstream file( pth ); if ( file ) // existing file { @@ -366,17 +389,40 @@ if ( info.type.empty() ) { - if ( target_directory.find( ".lib/" ) != string::npos - || target_directory.find( ".dll/" ) != string::npos - || target_directory.find( ".so/" ) != string::npos - || target_directory.find( ".dylib/" ) != string::npos - || target_directory.find( "/build/" ) != string::npos - ) - { - info.type = "lib"; + struct contains_substring { + const std::string m_arg; + const std::string::const_iterator m_begin, m_end; + contains_substring(const std::string & arg) : + m_arg(arg), + m_begin(m_arg.begin()), + m_end(m_arg.end()) + {} + bool operator()(fs::path const & fname) const{ + // if file name includes .test return true + std::string s = fname.string(); + return s.end() != std::search( + s.begin(), + s.end(), + m_begin, + m_end + ); + } + }; + fs::path::iterator const begin = target_directory.begin(); + fs::path::iterator const end = target_directory.end(); + + if( end != std::find_if(begin, end, contains_substring(".lib")) + || end != std::find_if(begin, end, contains_substring(".dll")) + || end != std::find_if(begin, end, contains_substring(".so")) + || end != std::find_if(begin, end, contains_substring(".dylib")) + || end != std::find_if(begin, end, contains_substring("build")) + ){ + info.type = "lib"; } - else if ( target_directory.find( ".pyd/" ) != string::npos ) - info.type = "pyd"; + else + if( end != std::find_if(begin, end, contains_substring(".pyd")) ){ + info.type = "pyd"; + } } m_root.reset( new xml::element( "test-log" ) ); @@ -389,7 +435,7 @@ m_root->attributes.push_back( xml::attribute( "test-program", info.file_path ) ); m_root->attributes.push_back( - xml::attribute( "target-directory", target_directory ) ); + xml::attribute( "target-directory", target_directory.string() ) ); m_root->attributes.push_back( xml::attribute( "toolset", toolset ) ); m_root->attributes.push_back( @@ -399,7 +445,8 @@ ~test_log() { - fs::path pth( locate_root / m_target_directory / "test_log.xml" ); + //fs::path pth( locate_root / m_target_directory / "test_log.xml" ); + fs::path pth( m_target_directory / "test_log.xml" ); if ( create_dirs && !fs::exists( pth.branch_path() ) ) fs::create_directories( pth.branch_path() ); fs::ofstream file( pth ); @@ -411,7 +458,7 @@ else xml::write( *m_root, file ); } - const string & target_directory() const { return m_target_directory; } + const fs::path & target_directory() const { return m_target_directory; } void remove_action( const string & action_name ) // no effect if action_name not found @@ -562,6 +609,8 @@ // streams are implemented using standard C files. std::ios::sync_with_stdio(false); + fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none) + fs::initial_path(); std::istream* input = 0; @@ -615,11 +664,13 @@ std::cout << "Abort: option --boost-root requires a directory argument\n"; std::exit(1); } + /* boost_root = fs::path( argv[1] ); if ( !boost_root.is_complete() ) boost_root = ( fs::initial_path() / boost_root ).normalize(); - + */ --argc; ++argv; + } else if ( std::strcmp( argv[1], "--locate-root" ) == 0 ) { @@ -655,29 +706,39 @@ } } + /* if ( boost_root.empty() ) { - set_boost_root(); + boost_root = get_boost_root(); + if(boost_root.empty()){ + std::cout << + "Abort: Failed to discover boost root\n"; + std::exit(1); + } boost_root.normalize(); } + */ - + /* if ( locate_root.empty() ) { locate_root = boost_root; } else if ( !locate_root.is_complete() ) { - locate_root = ( fs::initial_path() / locate_root ).normalize(); - } + //locate_root = ( fs::initial_path() / locate_root ).normalize(); + locate_root = locate_root.normalize(); + } + if(locate_root.empty()) + if(! fs::exists("bin")) + locate_root = find_boost_root(fs::initial_path()); + */ + if ( input == 0 ) - { input = &std::cin; - } - std::cout << "boost_root: " << boost_root.string() << '\n' - << "locate_root: " << locate_root.string() << '\n'; + std::cout << "locate_root: " << locate_root.string() << '\n'; message_manager mgr;