TuttleOFX  1
main.cpp
Go to the documentation of this file.
00001 #include <sam/common/utility.hpp>
00002 #include <sam/common/options.hpp>
00003 
00004 #include <tuttle/common/exceptions.hpp>
00005 #include <tuttle/common/utils/applicationPath.hpp>
00006 
00007 #include <tuttle/host/Core.hpp>
00008 
00009 #include <boost/program_options.hpp>
00010 #include <boost/filesystem.hpp>
00011 #include <boost/foreach.hpp>
00012 #include <boost/throw_exception.hpp>
00013 
00014 #include <climits>
00015 
00016 namespace sam {
00017 
00018 namespace bfs = boost::filesystem;
00019 namespace bpo = boost::program_options;
00020 
00021 bfs::path retrieveToolFullPath(const std::string& toolName, const std::vector<bfs::path>& searchPaths)
00022 {
00023         const std::string toolFilename(std::string("sam-") + toolName);
00024         
00025         BOOST_FOREACH( const bfs::path& p, searchPaths )
00026         {
00027                 const bfs::path toolFullPath = p / toolFilename;
00028                 if (bfs::exists(toolFullPath))
00029                 {
00030                         return toolFullPath;
00031                 }
00032         }
00033         
00034         /// @todo exception ?
00035         TUTTLE_LOG_ERROR( "Sam command \"" << toolName << "\" not found." );
00036         // displayAvailableCommands();
00037         exit(255);
00038 }
00039 
00040 std::vector<bfs::path> retrieveSearchPaths(const bfs::path& samDirectory)
00041 {
00042         std::vector<bfs::path> searchPaths;
00043         if( const char* env_ptr = std::getenv( "SAM_PATH" ) )
00044         {
00045                 const std::string env(env_ptr);
00046                 const std::vector<std::string> paths = bpo::split_unix(env, ":;");
00047                 searchPaths.insert(searchPaths.end(), paths.begin(), paths.end());
00048         }
00049         
00050         searchPaths.push_back(samDirectory / "sam");
00051         searchPaths.push_back(samDirectory);
00052         
00053         return searchPaths;
00054 }
00055 
00056 std::vector<bfs::path> retrieveAllSamCommands(const bfs::path& dir)
00057 {
00058         std::vector<bfs::path> res;
00059         if( !bfs::is_directory( dir ) )
00060                 return res;
00061         
00062         bfs::directory_iterator dir_iter(dir), dir_end;
00063         for( ; dir_iter != dir_end; ++dir_iter )
00064         {
00065                 bfs::path cmd = *dir_iter;
00066                 if( boost::starts_with(cmd.filename().string(), "sam-" ) )
00067                 {
00068                         res.push_back( cmd );
00069                 }
00070         }
00071         return res;
00072 }
00073 
00074 std::vector<bfs::path> retrieveAllSamCommands(const std::vector<bfs::path>& dirs)
00075 {
00076         typedef std::map<bfs::path, bfs::path> PathMap;
00077         PathMap allRes;
00078         BOOST_FOREACH( const bfs::path& dir, dirs )
00079         {
00080                 std::vector<bfs::path> dirRes = retrieveAllSamCommands(dir);
00081                 BOOST_FOREACH( const bfs::path& cmd, dirRes )
00082                 {
00083                         if( allRes.find( cmd.filename() ) == allRes.end() )
00084                         {
00085                                 allRes[cmd.filename()] = cmd;
00086                         }
00087                 }
00088         }
00089         std::vector<bfs::path> res;
00090         res.reserve(allRes.size());
00091         BOOST_FOREACH( PathMap::const_reference p, allRes )
00092         {
00093                 res.push_back( p.second );
00094         }
00095         return res;
00096 }
00097 
00098 }
00099 
00100 int main( int argc, char** argv )
00101 {
00102         signal(SIGINT, signal_callback_handler);
00103 
00104         using namespace tuttle::common;
00105         using namespace sam;
00106         
00107         boost::shared_ptr<formatters::Formatter> formatter( formatters::Formatter::get() );
00108         boost::shared_ptr<Color>                 color( Color::get() );
00109         
00110         formatter->init_logging();
00111         
00112         try
00113         {
00114                 std::vector<std::string> cl_options;
00115                 for (int i = 1; i < argc; ++i)
00116                 {
00117                         const std::string s(argv[i]);
00118                         if (!boost::starts_with(s, "-"))
00119                         {
00120                                 break;
00121                         }
00122                         cl_options.push_back(s);
00123                 }
00124                 
00125                 // Declare the supported options.
00126                 bpo::options_description infoOptions;
00127                 infoOptions.add_options()
00128                                 ( kHelpOptionString,     kHelpOptionMessage )
00129                                 ( kVersionOptionString,  kVersionOptionMessage ) // which version?
00130                                 ( kCommandsOptionString, kCommandsOptionMessage )
00131                                 ( kColorOptionString,    kColorOptionMessage );
00132                 
00133                 // describe hidden options
00134                 bpo::options_description hidden;
00135                 hidden.add_options()
00136                                 ( kCommandsListOptionString, kCommandsListOptionMessage )
00137                                 ( kBinariesListOptionString, kBinariesListOptionMessage )
00138                                 ( kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage );
00139                 
00140                 bpo::options_description all_options;
00141                 all_options.add(infoOptions).add(hidden);
00142                 
00143                 bpo::variables_map sam_vm;
00144                 
00145                 //parse the command line, and put the result in vm
00146                 bpo::store(bpo::command_line_parser(cl_options).options(all_options).run(), sam_vm);
00147                 // get environment options and parse them
00148                 if( const char* env_sam_options = std::getenv( "SAM_OPTIONS" ) )
00149                 {
00150                         const std::vector<std::string> envOptions = bpo::split_unix(env_sam_options, " ");
00151                         bpo::store(bpo::command_line_parser(envOptions).options(all_options).run(), sam_vm);
00152                 }
00153                 bpo::notify(sam_vm);
00154                 
00155                 if( sam_vm.count( kColorOptionLongName ) )
00156                 {
00157                         color->enable();
00158                 }
00159                 
00160                 if( sam_vm.count( kEnableColorOptionLongName ) )
00161                 {
00162                         const std::string str = sam_vm[kEnableColorOptionLongName].as<std::string>();
00163                         if( string_to_boolean(str) )
00164                         {
00165                                 color->enable();
00166                         }
00167                         else
00168                         {
00169                                 color->disable();
00170                         }
00171                 }
00172 
00173                 bfs::path fullsam = tuttle::common::applicationFilepath( argv[0] );
00174                 
00175                 bfs::path samDirectory( fullsam.parent_path() );
00176                 const std::vector<bfs::path> searchPaths = retrieveSearchPaths( samDirectory );
00177                 
00178                 if( ( sam_vm.count( kHelpOptionLongName ) || ( argc == 1 ) )
00179                                 || ( ( argc == 2 ) && (strstr( argv[1], kColorOptionLongName ) != NULL ) ) )
00180                 {
00181                         TUTTLE_LOG_INFO( color->_blue << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std );
00182                         TUTTLE_LOG_INFO( "" );
00183                         TUTTLE_LOG_INFO( color->_blue << "NAME" << color->_std );
00184                         TUTTLE_LOG_INFO( color->_green <<"\tsam - A set of command line tools." << color->_std );
00185                         TUTTLE_LOG_INFO( "" );
00186                         TUTTLE_LOG_INFO( color->_blue << "SYNOPSIS" << color->_std );
00187                         TUTTLE_LOG_INFO( color->_green << "\tsam COMMAND [options]..." << color->_std );
00188                         TUTTLE_LOG_INFO( "" );
00189                         TUTTLE_LOG_INFO( color->_blue << "COMMANDS" << color->_std );
00190                         const std::vector<bfs::path> cmds = retrieveAllSamCommands( searchPaths );
00191                         BOOST_FOREACH( const bfs::path& c, cmds )
00192                         {
00193                                 std::cout << std::left << "\t" << std::setw(10) << c.filename().string().substr(4) << std::flush;
00194                                 system((c.string() + " --brief").c_str());
00195                                 std::cout << std::flush;
00196                         }
00197                         TUTTLE_LOG_INFO( "" );
00198                         TUTTLE_LOG_INFO( color->_blue << "DESCRIPTION" << color->_std );
00199                         TUTTLE_LOG_INFO( "Sam is the TuttleOFX command line tool to manage image processing." );
00200                         TUTTLE_LOG_INFO( "" );
00201                         TUTTLE_LOG_INFO( color->_blue << "OPTIONS" << color->_std );
00202                         TUTTLE_LOG_INFO( infoOptions );
00203                         exit( 0 );
00204                 }
00205                 
00206                 if( sam_vm.count( kVersionOptionLongName ) )
00207                 {
00208                         TUTTLE_LOG_INFO( "TuttleOFX Host - version " << TUTTLE_HOST_VERSION_STR);
00209                         exit(0);
00210                 }
00211                 
00212                 if( sam_vm.count(kCommandsOptionLongName ) )
00213                 {
00214                         TUTTLE_LOG_INFO( "" );
00215                         TUTTLE_LOG_INFO( color->_blue << "COMMANDS" << color->_std );
00216                         
00217                         const std::vector<bfs::path> cmds = retrieveAllSamCommands(searchPaths);
00218                         BOOST_FOREACH( const bfs::path& c, cmds )
00219                         {
00220                                 std::cout << std::left << "\t" << std::setw(10) << c.filename().string().substr(4) << std::flush;
00221                                 system((c.string() + " --brief").c_str());
00222                                 std::cout << std::flush;
00223                         }
00224                         TUTTLE_LOG_INFO( "" );
00225                         
00226                         exit(0);
00227                 }
00228                 if( sam_vm.count( kBinariesListOptionLongName ) )
00229                 {
00230                         const std::vector<bfs::path> cmds = retrieveAllSamCommands( searchPaths );
00231                         BOOST_FOREACH( const bfs::path& c, cmds )
00232                         {
00233                                 TUTTLE_LOG_INFO( c.string());
00234                         }
00235                         exit(0);
00236                 }
00237                 if( sam_vm.count( kCommandsListOptionLongName ) )
00238                 {
00239                         const std::vector<bfs::path> cmds = retrieveAllSamCommands( searchPaths );
00240                         BOOST_FOREACH( const bfs::path& c, cmds )
00241                         {
00242                                 TUTTLE_LOG_INFO( c.filename().string().substr(4) );
00243                         }
00244                         exit(0);
00245                 }
00246                 
00247                 const std::string sam_tool(argv[cl_options.size() + 1]);
00248                 std::vector<std::string> sam_cmd;
00249                 for( int i = cl_options.size() + 2; i < argc; ++i )
00250                 {
00251                         static const std::string quote("\"");
00252                         const std::string s(argv[i]);
00253                         sam_cmd.push_back(quote + s + quote);
00254                 }
00255                 
00256                 bfs::path toolFullPath = retrieveToolFullPath(sam_tool, searchPaths);
00257                 
00258                 const std::string fullcmd( toolFullPath.string() + " " + boost::algorithm::join( sam_cmd, " " ) );
00259                 
00260                 // TUTTLE_TLOG_VAR( TUTTLE_INFO, fullcmd );
00261                 int returnCode = system( fullcmd.c_str() );
00262                 // TUTTLE_CLOG_VAR( TUTTLE_INFO, UINT_MAX - returnCode );
00263                 return returnCode>>8;
00264         }
00265         catch( const bpo::error& e )
00266         {
00267                 TUTTLE_LOG_ERROR( "Error in command line: " << e.what() );
00268                 exit(254);
00269         }
00270         catch( ... )
00271         {
00272                 TUTTLE_LOG_ERROR( "Error in command line: " << boost::current_exception_diagnostic_information() );
00273                 exit(254);
00274         }
00275         
00276         return 0;
00277 }
00278