From f3eeac87a47f0d79ae3e45bff1c5023a0740a4c9 Mon Sep 17 00:00:00 2001 From: William Johnson Date: Sun, 13 Oct 2024 18:46:04 -0700 Subject: [PATCH] Get batch command line working for (linux) Electron version. Not super well tested. Need to move setting various directories from in InterSpecAddOn, to BatchCommandLine, and similarly from batch_main.cpp, just to keep it all in one place. --- target/electron/CMakeLists.txt | 1 + target/electron/InterSpecAddOn.cpp | 63 ++++++++++++++++++++++++++++-- target/electron/README.md | 1 + target/electron/app/main.js | 39 +++++++++++------- target/electron/package.json | 2 +- 5 files changed, 87 insertions(+), 19 deletions(-) diff --git a/target/electron/CMakeLists.txt b/target/electron/CMakeLists.txt index 26ba6fd9..f5d8d952 100644 --- a/target/electron/CMakeLists.txt +++ b/target/electron/CMakeLists.txt @@ -9,6 +9,7 @@ set( BUILD_AS_LOCAL_SERVER OFF CACHE BOOL "N/A" ) set( USE_OSX_NATIVE_MENU OFF CACHE BOOL "N/A" ) set( USE_SPECRUM_FILE_QUERY_WIDGET ON CACHE BOOL "Enable Spectrum File Query Widget" ) set( USE_REMOTE_RID ON CACHE BOOL "Enables using remote RID tool" ) +set( USE_BATCH_TOOLS ON CACHE BOOL "Enables using batch tool" ) IF(WIN32) add_definitions(-DBOOST_ALL_NO_LIB) #Prevent boost auto-linking, which seems to call in vc141 boost libs instead of vc142 diff --git a/target/electron/InterSpecAddOn.cpp b/target/electron/InterSpecAddOn.cpp index 811cca46..c516530c 100644 --- a/target/electron/InterSpecAddOn.cpp +++ b/target/electron/InterSpecAddOn.cpp @@ -39,6 +39,10 @@ #include "target/electron/ElectronUtils.h" #if( USE_BATCH_TOOLS ) +#include "SpecUtils/StringAlgo.h" +#include "SpecUtils/Filesystem.h" + +#include "InterSpec/InterSpec.h" #include "InterSpec/BatchCommandLine.h" #endif @@ -542,16 +546,69 @@ namespace InterSpecAddOn Napi::Value element = jsArray.Get(i); // Check if the element is a string - if (!element.IsString()) { + if( !element.IsString() ) + { Napi::TypeError::New(env, "Array elements must be strings").ThrowAsJavaScriptException(); return Napi::Number(); - } + }//if( !element.IsString() ) str_args[i] = element.ToString(); if( str_args[i].empty() ) str_args[i] = " "; str_args_ptrs[i] = &(str_args[i][0]); - } + + + auto checkarg = [&str_args,i,numargs]( const std::string &teststr ) -> std::string { + + if( !SpecUtils::istarts_with(str_args[i], teststr) ) + return ""; + std::string docroot; + if( (str_args[i].length() > (teststr.size()+1)) && (str_args[i][teststr.size()] == '=') ) + docroot = str_args[i].substr(teststr.size() + 1); + else if( (i+1) < numargs ) + docroot = str_args[i+1]; + else + return ""; + + if( docroot.length() && ((docroot.front()=='\"') || (docroot.front()=='\'')) ) + docroot = docroot.substr(1); + if( docroot.length() && ((docroot.back()=='\"') || (docroot.back()=='\'')) ) + docroot = docroot.substr(0, docroot.size() - 1); + return docroot; + };//checkarg lambda + + // TODO: this setting directories should either be brought out to node.js stuff, or integrated into BatchCommandLine::run_batch_command(...) + const std::string docroot = checkarg( "--docroot" ); + const std::string userdatadir = checkarg( "--userdatadir" ); + + if( !docroot.empty() ) + { + const std::string datadir = SpecUtils::append_path( docroot, "data" ); + + try + { + InterSpec::setStaticDataDirectory( datadir ); + }catch( std::exception &e ) + { + std::cerr << "Failed to set static data directory: " << e.what() << std::endl; + Napi::Number::New( env, -7 ); + } + }//if( !docroot.empty() ) + + if( !userdatadir.empty() ) + { + try + { + InterSpec::setWritableDataDirectory( userdatadir ); + }catch( std::exception &e ) + { + std::cerr << "Warning: Failed to set user data directory: " << e.what() << std::endl + << "Use the '--userdatadir' option to set this to the same one the InterSpec GUI app" + << " uses, if you would like to share detectors, or other files." << std::endl; + //return -8; + } + }//if( !userdatadir.empty() ) + }//for( uint32_t i = 0; i < numargs; i++ ) const int rcode = BatchCommandLine::run_batch_command( static_cast(numargs), &(str_args_ptrs[0]) ); diff --git a/target/electron/README.md b/target/electron/README.md index 22c060cf..09181553 100755 --- a/target/electron/README.md +++ b/target/electron/README.md @@ -161,6 +161,7 @@ npm install uglify-js -g npm install uglifycss -g npm install cmake-js -g npm install --save-dev node-addon-api --arch=x64 +npm install node-api-headers npm install electron --arch=x64 npm install electron-packager diff --git a/target/electron/app/main.js b/target/electron/app/main.js index 0616f6e4..4538c8d0 100755 --- a/target/electron/app/main.js +++ b/target/electron/app/main.js @@ -58,20 +58,6 @@ let interspec_url = null; global.__basedir = __dirname; -// Check if we only want to run -for( let path_string of process.argv ) { - if( path_string.startsWith("--batch") || path_string.startsWith("/batch") ) { - console.log( "Will run batch"); - - //TODO: redirect stderr/stdout to console.log - const rdcode = interspec.runBatchAnalysis( process.argv ); - - console.log( "Batch analysis returned code " + rcode ); - - app.quit(); - return; - } -} // Keep a global reference of the window objects, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. @@ -999,7 +985,30 @@ function browseForDirectory( token, title, msg ){ return (dirs.length<1) ? '' : dirs[0]; };//function browseForDirectory +// Check if we only want to run +for( let path_string of process.argv ) { + if( path_string.startsWith("--batch") || path_string.startsWith("/batch") ) { + console.log( "Will run batch"); + + let has_docroot = false, has_userdata = false; + for( let str of process.argv ) { + has_docroot = (has_docroot || str.startsWith('--docroot')); + has_userdata = (has_userdata || str.startsWith('--userdatadir')); + } + + if( !has_docroot ) + process.argv.push( "--docroot=\'" + path.dirname(require.main.filename) + "'"); + if( !has_userdata ) + process.argv.push( "--userdatadir=\'" + userdata + "'") + + const rcode = interspec.runBatchAnalysis( process.argv ); + + console.log( "Batch analysis returned code " + rcode ); + app.quit(); + return; + } +} // This method will be called when Electron has finished @@ -1008,7 +1017,7 @@ function browseForDirectory( token, title, msg ){ app.on('ready', function(){ const process_name = require.main.filename; //actually process.cwd()==path.dirname(require.main.filename) when running using node from command line - + //It looks like we dont need to change the CWD anymore (I think everywhere in // InterSpec no longer assumes a specific CWD), but lets do it anyway. process.chdir( path.dirname(require.main.filename) ); diff --git a/target/electron/package.json b/target/electron/package.json index 7cb87d5e..cab1d4be 100755 --- a/target/electron/package.json +++ b/target/electron/package.json @@ -24,7 +24,7 @@ "license": "LGPL-2.1-only", "dependencies": { "cmake-js": "^6.1.0", - "node-api-headers": "^1.1.0" + "node-api-headers": "^1.3.0" }, "devDependencies": { "electron": "^21.4.4",