From 34f04dda4afea1906a73cc9fa8327aba9bab9d46 Mon Sep 17 00:00:00 2001 From: Angus Leeming Date: Thu, 2 Mar 2006 22:34:10 +0000 Subject: [PATCH] Backport of commit 13284. Fix the way the installer handles the path_prefix stuff. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_3_X@13288 a592a061-630c-0410-9148-cb99ea01b6c8 --- .../Win32/packaging/installer/lyx_configure.C | 323 ++++++++++++------ .../packaging/installer/lyx_installer.nsi | 8 +- 2 files changed, 233 insertions(+), 98 deletions(-) diff --git a/development/Win32/packaging/installer/lyx_configure.C b/development/Win32/packaging/installer/lyx_configure.C index cbc4a56dad..6716b4371b 100644 --- a/development/Win32/packaging/installer/lyx_configure.C +++ b/development/Win32/packaging/installer/lyx_configure.C @@ -10,10 +10,11 @@ * Full author contact details are available in file CREDITS or copy at * http://www.lyx.org/about/credits.php * - * Define four functions that can be called from the NSIS installer: + * Define five functions that can be called from the NSIS installer: * * set_path_prefix [ configure_file, path_prefix ] - * create_bat_files [ bin_dir, lang ] + * create_lyx_bat [ bin_dir, lang ] + * create_relyx_bat [ bin_dir, lang ] * run_configure [ configure_file, path_prefix ] * set_env [ var_name, var_value ] * @@ -28,17 +29,19 @@ * * Compilation requires the exdll.h header file to be installed (here at * C:\Program Files\NSIS\Contrib\ExDLL\exdll.h). The file can be obtained - * from http://cvs.sourceforge.net/viewcvs.py/nsis/NSIS/Contrib/ExDLL/ + * from http://cvs.sourceforge.net/viewcvs.py/nsis/NSIS/Contrib/ExDLL/ * - * Move the resulting lyx_configure.dll to /c/Program\ Files/NSIS/Plugins + * Move the resulting lyx_configure.dll to C:\Program Files\NSIS\Plugins */ #include #include +#include #include #include #include #include +#include #include #include @@ -106,10 +109,19 @@ std::list const tokenize(std::string const & data, while (true) { std::string::size_type const end = data.find(separator, index); if (end == std::string::npos) { - result.push_back(data); + std::string::size_type const count = + data.size() - index; + std::string const elem = data.substr(index, count); + if (elem.size() > 0) { + result.push_back(elem); + } break; } - result.push_back(data.substr(0, end)); + std::string::size_type const count = end - index; + std::string const elem = data.substr(index, count); + if (elem.size() > 0) { + result.push_back(elem); + } index = (end+1 == data.size()) ? std::string::npos : end + 1; } return result; @@ -188,8 +200,10 @@ std::string const sanitize_path_envvar(std::string const & in) // Ensure that each PATH element uses '\' directory separators // and doesn't end in a '\'. string_list::iterator const end = envvar.end(); - for (string_list::iterator it = envvar.begin(); it != end; ++it) - *it = sanitize_win32_path(*it); + for (string_list::iterator it = envvar.begin(); it != end; ++it) { + std::string const new_path = sanitize_win32_path(*it); + *it = new_path; + } remove_duplicates(envvar); return concatenate(envvar, ';'); @@ -260,47 +274,6 @@ bool insert_path_prefix(std::string & data, } -// Inserts code into "configure" to output "path_prefix" to lyxrc.defaults. -// \returns 0 on success, -1 on failure -int set_path_prefix(std::string const & configure_file, - std::string const & path_prefix) -{ - std::ifstream ifs(configure_file.c_str()); - if (!ifs) - return -1; - - std::istreambuf_iterator const begin_ifs(ifs); - std::istreambuf_iterator const end_ifs; - std::string configure_data(begin_ifs, end_ifs); - ifs.close(); - - // Does configure already contain a "path_prefix" entry - // or should we insert one? - std::string::size_type const prefix_pos = - configure_data.find("path_prefix"); - if (prefix_pos != std::string::npos) { - if (!replace_path_prefix(configure_data, prefix_pos, path_prefix)) - return -1; - } else { - std::string::size_type const xfonts_pos = - configure_data.find("X FONTS"); - - if (xfonts_pos == std::string::npos) - return -1; - - if (!insert_path_prefix(configure_data, xfonts_pos, path_prefix)) - return -1; - } - - std::ofstream ofs(configure_file.c_str()); - if (!ofs) - return -1; - - ofs << configure_data; - return 0; -} - - bool write_bat(std::ostream & os, std::string const & quoted_exe) { os << "if \"%~1\" == \"~1\" goto win95\n" @@ -314,35 +287,6 @@ bool write_bat(std::ostream & os, std::string const & quoted_exe) } -// Creates the files lyx.bat and reLyX.bat in the LyX\bin folder. -// \returns 0 on success, -1 on failure -int create_bat_files(std::string const & bin_dir, std::string const & lang) -{ - std::string const lyx_bat_file = bin_dir + "\\lyx.bat"; - std::ofstream lyx_bat(lyx_bat_file.c_str()); - if (!lyx_bat) - return -1; - - lyx_bat << "@echo off\n" - << "if \"%LANG%\"==\"\" SET LANG=" << lang << "\n"; - - std::string const lyx_exe_file = bin_dir + "\\lyx.exe"; - if (!write_bat(lyx_bat, "start \"LyX\" \"" + lyx_exe_file + "\"")) - return -1; - - std::string const relyx_bat_file = bin_dir + "\\reLyX.bat"; - std::ofstream relyx_bat(relyx_bat_file.c_str()); - if (!relyx_bat) - return -1; - - std::string relyx_file = bin_dir + "\\reLyX"; - std::string relyx = "perl.exe \"" + relyx_file + "\""; - if (!write_bat(relyx_bat, "perl.exe \"" + relyx_file + "\"")) - return -1; - return 0; -} - - // A wrapper for GetEnvironmentVariable bool get_environment_variable(std::string const & var, std::string & val) { @@ -375,37 +319,165 @@ bool get_environment_variable(std::string const & var, std::string & val) } +// Inserts code into "configure" to output "path_prefix" to lyxrc.defaults. +// Throws std::runtime_error on failure. +void set_path_prefix(std::string const & configure_file, + std::string const & path_prefix) +{ + std::ifstream ifs(configure_file.c_str()); + if (!ifs) { + std::ostringstream ss; + ss << "Unable to open " << configure_file << " for reading"; + throw std::runtime_error(ss.str()); + } + + std::istreambuf_iterator const begin_ifs(ifs); + std::istreambuf_iterator const end_ifs; + std::string configure_data(begin_ifs, end_ifs); + ifs.close(); + + // Does configure already contain a "path_prefix" entry + // or should we insert one? + std::string::size_type const prefix_pos = + configure_data.find("path_prefix"); + if (prefix_pos != std::string::npos) { + if (!replace_path_prefix(configure_data, prefix_pos, path_prefix)) { + std::ostringstream ss; + ss << "Unable to replace the existing path_prefix in " + << configure_file; + throw std::runtime_error(ss.str()); + } + } else { + std::string::size_type const xfonts_pos = + configure_data.find("if [ \"x$use_cygwin_path_fix"); + + if (xfonts_pos == std::string::npos) { + std::ostringstream ss; + ss << "Unable to find a position to insert the " + "path_prefix entry in " + << configure_file; + throw std::runtime_error(ss.str()); + } + + if (!insert_path_prefix(configure_data, xfonts_pos, path_prefix)) { + std::ostringstream ss; + ss << "Unable to insert a new path_prefix in " + << configure_file; + throw std::runtime_error(ss.str()); + } + } + + std::ofstream ofs(configure_file.c_str()); + if (!ofs) { + std::ostringstream ss; + ss << "Unable to open " << configure_file << " for writing"; + throw std::runtime_error(ss.str()); + } + + ofs << configure_data; + if (!ofs) { + std::ostringstream ss; + ss << "Failed to write " << configure_file; + throw std::runtime_error(ss.str()); + } +} + + +// Creates the lyx.bat file in the LyX\bin folder. +// Throws std::runtime_error on failure. +void create_lyx_bat(std::string const & bin_dir, std::string const & lang) +{ + std::string const lyx_bat_file = bin_dir + "\\lyx.bat"; + std::ofstream ofs(lyx_bat_file.c_str()); + if (!ofs) { + std::ostringstream ss; + ss << "Unable to unable to open " + << lyx_bat_file << " for writing"; + throw std::runtime_error(ss.str()); + } + + ofs << "@echo off\n" + << "if \"%LANG%\"==\"\" SET LANG=" << lang << "\n"; + + std::string const lyx_exe_file = bin_dir + "\\lyx.exe"; + if (!write_bat(ofs, "start \"LyX\" \"" + lyx_exe_file + "\"")) { + std::ostringstream ss; + ss << "Failed to write to " << lyx_bat_file; + throw std::runtime_error(ss.str()); + } +} + + +// Creates the reLyX.bat file in the LyX\bin folder. +// Throws std::runtime_error on failure. +void create_relyx_bat(std::string const & bin_dir, std::string const & lang) +{ + std::string const relyx_bat_file = bin_dir + "\\reLyX.bat"; + std::ofstream ofs(relyx_bat_file.c_str()); + if (!ofs) { + std::ostringstream ss; + ss << "Unable to unable to open " + << relyx_bat_file << " for writing"; + throw std::runtime_error(ss.str()); + } + + std::string relyx_file = bin_dir + "\\reLyX"; + std::string relyx = "perl.exe \"" + relyx_file + "\""; + if (!write_bat(ofs, "perl.exe \"" + relyx_file + "\"")) { + std::ostringstream ss; + ss << "Failed to write to " << relyx_bat_file; + throw std::runtime_error(ss.str()); + } +} + + // Runs "sh configure" to generate things like lyxrc.defaults. -// \returns 0 on success, -1 on failure -int run_configure(std::string const & abs_configure_file_in, - std::string const & path_prefix) +// Throws std::runtime_error on failure. +void run_configure(std::string const & abs_configure_file_in, + std::string const & path_prefix) { std::string const abs_configure_file = sanitize_win32_path(abs_configure_file_in); std::string const configure_dir = dirname(abs_configure_file); std::string const configure_file = basename(abs_configure_file); - if (configure_file.empty() || configure_dir.empty()) - return -1; + if (configure_file.empty() || configure_dir.empty()) { + std::ostringstream ss; + ss << "Invalid path to configure file: " + << abs_configure_file; + throw std::runtime_error(ss.str()); + } - if (SetCurrentDirectory(configure_dir.c_str()) == 0) - return -1; + if (SetCurrentDirectory(configure_dir.c_str()) == 0) { + std::ostringstream ss; + ss << "Unable to cd "<< configure_dir; + throw std::runtime_error(ss.str()); + } std::string path; - if (!get_environment_variable("PATH", path)) - return -1; + if (!get_environment_variable("PATH", path)) { + std::ostringstream ss; + ss << "Unable to grab the PATH environment variable"; + throw std::runtime_error(ss.str()); + } path = sanitize_path_envvar(path_prefix + ';' + path); - if (SetEnvironmentVariable("PATH", path.c_str()) == 0) - return -1; + if (SetEnvironmentVariable("PATH", path.c_str()) == 0) { + std::ostringstream ss; + ss << "Failed to set the PATH environment variable to:\n" + << path << '\n'; + throw std::runtime_error(ss.str()); + } // Even "start /WAIT /B sh.exe configure" returns // before the script is done, so just invoke "sh" directly. // Assumes that configure_file does not need quoting. std::string const command = std::string("sh.exe ") + configure_file; - if (system(command.c_str()) != 0) - return -1; - return 0; + if (system(command.c_str()) != 0) { + std::ostringstream ss; + ss << "Failed to run: " << command; + throw std::runtime_error(ss.str()); + } } } // namespace anon @@ -441,14 +513,53 @@ void __declspec(dllexport) set_path_prefix(HWND const /*hwndParent*/, return; } - int const result = set_path_prefix(configure_file, path_prefix); + int result = 0; + try { + set_path_prefix(configure_file, path_prefix); + } + catch(std::exception const & ex) { + std::cerr << "ERROR: set_path_prefix:\n\t" + << ex.what() << '\n'; + result = -1; + } + push_to_stack(result); } -// Creates the files lyx.bat and reLyX.bat in the LyX\bin folder. +// Creates the lyx.bat file in the LyX\bin folder. extern "C" -void __declspec(dllexport) create_bat_files(HWND const /*hwndParent*/, +void __declspec(dllexport) create_lyx_bat(HWND const /*hwndParent*/, + int const string_size, + char * const variables, + stack_t ** const stacktop) +{ + EXDLL_INIT(); + + std::string const bin_dir = pop_from_stack(); + std::string const lang = pop_from_stack(); + if (bin_dir.empty() || lang.empty()) { + push_to_stack(-1); + return; + } + + int result = 0; + try { + create_lyx_bat(bin_dir, lang); + } + catch(std::exception const & ex) { + std::cerr << "ERROR: create_lyx_bat:\n\t" + << ex.what() << '\n'; + result = -1; + } + + push_to_stack(result); +} + + +// Creates the reLyX.bat file in the LyX\bin folder. +extern "C" +void __declspec(dllexport) create_relyx_bat(HWND const /*hwndParent*/, int const string_size, char * const variables, stack_t ** const stacktop) @@ -462,7 +573,16 @@ void __declspec(dllexport) create_bat_files(HWND const /*hwndParent*/, return; } - int const result = create_bat_files(bin_dir, lang); + int result = 0; + try { + create_relyx_bat(bin_dir, lang); + } + catch(std::exception const & ex) { + std::cerr << "ERROR: create_relyx_bat:\n\t" + << ex.what() << '\n'; + result = -1; + } + push_to_stack(result); } @@ -483,7 +603,16 @@ void __declspec(dllexport) run_configure(HWND const /*hwndParent*/, return; } - int const result = run_configure(configure_file, path_prefix); + int result = 0; + try { + run_configure(configure_file, path_prefix); + } + catch(std::exception const & ex) { + std::cerr << "ERROR: run_configure:\n\t" + << ex.what() << '\n'; + result = -1; + } + push_to_stack(result); } diff --git a/development/Win32/packaging/installer/lyx_installer.nsi b/development/Win32/packaging/installer/lyx_installer.nsi index e434adbdb7..409d0dfa23 100644 --- a/development/Win32/packaging/installer/lyx_installer.nsi +++ b/development/Win32/packaging/installer/lyx_installer.nsi @@ -255,7 +255,13 @@ Section "-Installation actions" SecInstallation ${endif} ${endif} - lyx_configure::create_bat_files "$INSTDIR\bin" "$LangCode" + lyx_configure::create_lyx_bat "$INSTDIR\bin" "$LangCode" + Pop $0 + ${if} $0 != 0 + MessageBox MB_OK "$(CreateCmdFilesFailed)" + ${endif} + + lyx_configure::create_relyx_bat "$INSTDIR\bin" "$LangCode" Pop $0 ${if} $0 != 0 MessageBox MB_OK "$(CreateCmdFilesFailed)"