diff --git a/src/LyX.cpp b/src/LyX.cpp index 706950fe9f..0a21b4b224 100644 --- a/src/LyX.cpp +++ b/src/LyX.cpp @@ -60,8 +60,6 @@ #include "support/Messages.h" #include "support/os.h" #include "support/Package.h" -#include "support/PathChanger.h" -#include "support/Systemcall.h" #include "support/bind.h" #include @@ -127,18 +125,6 @@ void showFileError(string const & error) "Please check your installation."), from_utf8(error))); } - -void reconfigureUserLyXDir() -{ - string const configure_command = package().configure_command(); - - lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl; - PathChanger p(package().user_support()); - Systemcall one; - one.startscript(Systemcall::Wait, configure_command); - lyxerr << "LyX: " << to_utf8(_("Done!")) << endl; -} - } // namespace anon /// The main application class private implementation. @@ -724,7 +710,7 @@ namespace { } } } - + void cleanDuplicateEnvVars() { std::set seen; @@ -825,11 +811,11 @@ bool LyX::init() // Check that user LyX directory is ok. { - string const lock_file = package().user_support().absFileName() + ".lyx_configure_lock"; + string const lock_file = package().getConfigureLockName(); int fd = fileLock(lock_file.c_str()); if (queryUserLyXDir(package().explicit_user_support())) { - reconfigureUserLyXDir(); + package().reconfigureUserLyXDir(""); } fileUnlock(fd, lock_file.c_str()); } @@ -956,27 +942,6 @@ void emergencyCleanup() } -// return true if file does not exist or is older than configure.py. -static bool needsUpdate(string const & file) -{ - // We cannot initialize configure_script directly because the package - // is not initialized yet when static objects are constructed. - static FileName configure_script; - static bool firstrun = true; - if (firstrun) { - configure_script = - FileName(addName(package().system_support().absFileName(), - "configure.py")); - firstrun = false; - } - - FileName absfile = - FileName(addName(package().user_support().absFileName(), file)); - return !absfile.exists() - || configure_script.lastModified() > absfile.lastModified(); -} - - bool LyX::queryUserLyXDir(bool explicit_userdir) { // Does user directory exist? @@ -984,10 +949,10 @@ bool LyX::queryUserLyXDir(bool explicit_userdir) if (sup.exists() && sup.isDirectory()) { first_start = false; - return needsUpdate("lyxrc.defaults") - || needsUpdate("lyxmodules.lst") - || needsUpdate("textclass.lst") - || needsUpdate("packages.lst"); + return configFileNeedsUpdate("lyxrc.defaults") + || configFileNeedsUpdate("lyxmodules.lst") + || configFileNeedsUpdate("textclass.lst") + || configFileNeedsUpdate("packages.lst"); } first_start = !explicit_userdir; diff --git a/src/frontends/qt4/GuiApplication.cpp b/src/frontends/qt4/GuiApplication.cpp index 5cf11b7fdb..bcf7d65607 100644 --- a/src/frontends/qt4/GuiApplication.cpp +++ b/src/frontends/qt4/GuiApplication.cpp @@ -72,8 +72,6 @@ #include "support/Messages.h" #include "support/os.h" #include "support/Package.h" -#include "support/PathChanger.h" -#include "support/Systemcall.h" #include "support/TempFile.h" #ifdef Q_OS_MAC @@ -1065,8 +1063,8 @@ double GuiApplication::pixelRatio() const return 1.0; #endif } - - + + void GuiApplication::clearSession() { QSettings settings; @@ -1460,18 +1458,16 @@ void GuiApplication::reconfigure(string const & option) current_view_->message(_("Running configure...")); // Run configure in user lyx directory - PathChanger p(package().user_support()); - string configure_command = package().configure_command(); - configure_command += option; - Systemcall one; - int const ret = one.startscript(Systemcall::Wait, configure_command); - p.pop(); + string const lock_file = package().getConfigureLockName(); + int fd = fileLock(lock_file.c_str()); + int const ret = package().reconfigureUserLyXDir(option); // emit message signal. if (current_view_) current_view_->message(_("Reloading configuration...")); lyxrc.read(libFileSearch(QString(), "lyxrc.defaults"), false); // Re-read packages.lst LaTeXPackages::getAvailable(); + fileUnlock(fd, lock_file.c_str()); if (ret) Alert::information(_("System reconfiguration failed"), @@ -1713,14 +1709,14 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) // If the request comes from the minibuffer, then we can't reset // the GUI, since that would destory the minibuffer itself and - // cause a crash, since we are currently in one of the methods of - // GuiCommandBuffer. See bug #8540. + // cause a crash, since we are currently in one of the methods of + // GuiCommandBuffer. See bug #8540. if (cmd.origin() != FuncRequest::COMMANDBUFFER) resetGui(); // else // FIXME Unfortunately, that leaves a bug here, since we cannot // reset the GUI in this case. If the changes to lyxrc affected the - // UI, then, nothing would happen. This seems fairly unlikely, but + // UI, then, nothing would happen. This seems fairly unlikely, but // it definitely is a bug. break; @@ -1933,9 +1929,9 @@ void GuiApplication::dispatch(FuncRequest const & cmd, DispatchResult & dr) istringstream ss(argument); Lexer lex; lex.setStream(ss); - + // See #9236 - // We need to make sure that, after we recreat the DocumentClass, + // We need to make sure that, after we recreat the DocumentClass, // which we do in readHeader, we apply it to the document itself. DocumentClassConstPtr olddc = defaults.params().documentClassPtr(); int const unknown_tokens = defaults.readHeader(lex); diff --git a/src/support/Package.cpp b/src/support/Package.cpp index b4b0e1493d..66b0e60f0a 100644 --- a/src/support/Package.cpp +++ b/src/support/Package.cpp @@ -21,12 +21,15 @@ #include "support/lassert.h" #include "support/lstrings.h" #include "support/os.h" +#include "support/PathChanger.h" +#include "support/Systemcall.h" #if defined (USE_WINDOWS_PACKAGING) # include "support/os_win32.h" #endif +#include #include #if !defined (USE_WINDOWS_PACKAGING) && \ @@ -151,7 +154,8 @@ Package::Package(string const & command_line_arg0, << "\n"); } -std::string const & Package::configure_command() const + +int Package::reconfigureUserLyXDir(string const & option) const { if (configure_command_.empty()) { FileName const configure_script(addName(system_support().absFileName(), "configure.py")); @@ -160,7 +164,19 @@ std::string const & Package::configure_command() const with_version_suffix() + " --binary-dir=" + quoteName(FileName(binary_dir().absFileName()).toFilesystemEncoding()); } - return configure_command_; + + lyxerr << to_utf8(_("LyX: reconfiguring user directory")) << endl; + PathChanger p(user_support()); + Systemcall one; + int const ret = one.startscript(Systemcall::Wait, configure_command_ + option); + lyxerr << "LyX: " << to_utf8(_("Done!")) << endl; + return ret; +} + + +string Package::getConfigureLockName() const +{ + return user_support().absFileName() + ".lyx_configure_lock"; } diff --git a/src/support/Package.h b/src/support/Package.h index e5cc323260..c7befb369e 100644 --- a/src/support/Package.h +++ b/src/support/Package.h @@ -134,11 +134,11 @@ public: */ static FileName const & get_home_dir(); - /** Command to run the configure script. - * Caution: This is "ready-to-run", i.e. in the locale encoding, not - * utf8. - */ - std::string const & configure_command() const; + /// Run configure.py + int reconfigureUserLyXDir(std::string const & option) const; + + /// + std::string getConfigureLockName() const; private: FileName binary_dir_; @@ -151,6 +151,10 @@ private: mutable FileName document_dir_; mutable FileName temp_dir_; FileName system_temp_dir_; + /** Command to run the configure script. + * Caution: This is "ready-to-run", i.e. in the locale encoding, not + * utf8. + */ mutable std::string configure_command_; bool explicit_user_support_dir_; bool in_build_dir_; diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp index 040272aade..7691fe3b32 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -745,7 +745,7 @@ string const replaceCurdirPath(string const & path, string const & pathlist) } if (i != string::npos) { newpathlist += sep; - // Stop here if the last element is empty + // Stop here if the last element is empty if (++i == oldpathlist.length()) break; } @@ -1172,6 +1172,27 @@ bool prefs2prefs(FileName const & filename, FileName const & tempfile, bool lfun return true; } + +bool configFileNeedsUpdate(string const & file) +{ + // We cannot initialize configure_script directly because the package + // is not initialized yet when static objects are constructed. + static FileName configure_script; + static bool firstrun = true; + if (firstrun) { + configure_script = + FileName(addName(package().system_support().absFileName(), + "configure.py")); + firstrun = false; + } + + FileName absfile = + FileName(addName(package().user_support().absFileName(), file)); + return !absfile.exists() + || configure_script.lastModified() > absfile.lastModified(); +} + + int fileLock(const char * lock_file) { int fd = -1; diff --git a/src/support/filetools.h b/src/support/filetools.h index cfbec430ec..b041b366a2 100644 --- a/src/support/filetools.h +++ b/src/support/filetools.h @@ -300,6 +300,9 @@ int compare_timestamps(FileName const & file1, FileName const & file2); bool prefs2prefs(FileName const & filename, FileName const & tempfile, bool lfuns); +/// Does file \p file need to be updated by configure.py? +bool configFileNeedsUpdate(std::string const & file); + typedef std::pair cmd_ret; cmd_ret const runCommand(std::string const & cmd); diff --git a/src/tex2lyx/tex2lyx.cpp b/src/tex2lyx/tex2lyx.cpp index e4c26603b1..8f9d6ae788 100644 --- a/src/tex2lyx/tex2lyx.cpp +++ b/src/tex2lyx/tex2lyx.cpp @@ -996,6 +996,20 @@ int main(int argc, char * argv[]) return EXIT_FAILURE; } + // Check that user LyX directory is ok. + FileName const sup = package().user_support(); + if (sup.exists() && sup.isDirectory()) { + string const lock_file = package().getConfigureLockName(); + int fd = fileLock(lock_file.c_str()); + if (configFileNeedsUpdate("lyxrc.defaults") || + configFileNeedsUpdate("lyxmodules.lst") || + configFileNeedsUpdate("textclass.lst") || + configFileNeedsUpdate("packages.lst")) + package().reconfigureUserLyXDir(""); + fileUnlock(fd, lock_file.c_str()); + } else + error_message("User directory does not exist."); + // Now every known option is parsed. Look for input and output // file name (the latter is optional). string infilename = internal_path(os::utf8_argv(1));