Bug 2718 - improve the error message when opening a project in a read-only directory.

This commit is contained in:
Dmitry Vedenko 2021-03-29 17:45:12 +03:00 committed by James Crook
parent 0a085daa92
commit f1395ff621
4 changed files with 51 additions and 16 deletions

View File

@ -63,25 +63,37 @@ bool DBConnection::ShouldBypass()
} }
void DBConnection::SetError( void DBConnection::SetError(
const TranslatableString &msg, const TranslatableString &libraryError) const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{ {
wxLogMessage(wxT("Connection msg: %s"), msg.Debug()); wxLogMessage(wxT("Connection msg: %s"), msg.Debug());
if (!libraryError.empty()) if (!libraryError.empty())
wxLogMessage(wxT("Connection error: %s"), libraryError.Debug()); wxLogMessage(wxT("Connection error: %s"), libraryError.Debug());
mpErrors->mLastError = msg; mpErrors->mLastError = msg;
mpErrors->mLibraryError = libraryError; mpErrors->mLibraryError = libraryError;
mpErrors->mErrorCode = errorCode;
} }
void DBConnection::SetDBError( void DBConnection::SetDBError(
const TranslatableString &msg, const TranslatableString &libraryError) const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{ {
mpErrors->mErrorCode = errorCode < 0 ?
sqlite3_errcode(DB()) : errorCode;
mpErrors->mLastError = msg; mpErrors->mLastError = msg;
wxLogMessage(wxT("SQLite error: %s"), mpErrors->mLastError.Debug());
wxLogMessage(
wxT("SQLite error (%d): %s"),
mpErrors->mErrorCode,
mpErrors->mLastError.Debug()
);
printf("SQLite error: %s", mpErrors->mLastError.Debug().mb_str().data()); printf("SQLite error: %s", mpErrors->mLastError.Debug().mb_str().data());
mpErrors->mLibraryError = libraryError.empty() mpErrors->mLibraryError = libraryError.empty()
? Verbatim(sqlite3_errmsg(DB())) : libraryError; ? Verbatim(sqlite3_errmsg(DB())) : libraryError;
wxLogMessage(wxT(" Lib error: %s"), mpErrors->mLibraryError.Debug()); wxLogMessage(wxT(" Lib error: %s"), mpErrors->mLibraryError.Debug());
printf(" Lib error: %s", mpErrors->mLibraryError.Debug().mb_str().data()); printf(" Lib error: %s", mpErrors->mLibraryError.Debug().mb_str().data());
} }

View File

@ -31,6 +31,7 @@ struct DBConnectionErrors
{ {
TranslatableString mLastError; TranslatableString mLastError;
TranslatableString mLibraryError; TranslatableString mLibraryError;
int mErrorCode { 0 };
}; };
class DBConnection class DBConnection
@ -84,12 +85,14 @@ public:
//! Just set stored errors //! Just set stored errors
void SetError( void SetError(
const TranslatableString &msg, const TranslatableString &msg,
const TranslatableString &libraryError = {} ); const TranslatableString &libraryError = {},
int errorCode = {});
//! Set stored errors and write to log; and default libraryError to what database library reports //! Set stored errors and write to log; and default libraryError to what database library reports
void SetDBError( void SetDBError(
const TranslatableString &msg, const TranslatableString &msg,
const TranslatableString &libraryError = {} ); const TranslatableString& libraryError = {},
int errorCode = -1);
private: private:
bool ModeConfig(sqlite3 *db, const char *schema, const char *config); bool ModeConfig(sqlite3 *db, const char *schema, const char *config);

View File

@ -499,7 +499,8 @@ int ProjectFileIO::Exec(const char *query, const ExecCB &callback)
{ {
SetDBError( SetDBError(
XO("Failed to execute a project file command:\n\n%s").Format(query), XO("Failed to execute a project file command:\n\n%s").Format(query),
Verbatim(errmsg) Verbatim(errmsg),
rc
); );
} }
if (errmsg) if (errmsg)
@ -596,6 +597,17 @@ bool ProjectFileIO::CheckVersion()
wxString result; wxString result;
if (!GetValue("SELECT Count(*) FROM sqlite_master WHERE type='table';", result)) if (!GetValue("SELECT Count(*) FROM sqlite_master WHERE type='table';", result))
{ {
// Bug 2718 workaround for a better error message:
// If at this point we get SQLITE_CANTOPEN, then the directory is read-only
if (GetLastErrorCode() == SQLITE_CANTOPEN)
{
SetError(
/* i18n-hint: An error message. */
XO("Project is in a read only directory\n(Unable to create the required temporary files)"),
GetLibraryError()
);
}
return false; return false;
} }
@ -2170,30 +2182,35 @@ wxLongLong ProjectFileIO::GetFreeDiskSpace() const
return -1; return -1;
} }
const TranslatableString &ProjectFileIO::GetLastError() const TranslatableString &ProjectFileIO::GetLastError() const
{ {
return mpErrors->mLastError; return mpErrors->mLastError;
} }
const TranslatableString &ProjectFileIO::GetLibraryError() const TranslatableString &ProjectFileIO::GetLibraryError() const
{ {
return mpErrors->mLibraryError; return mpErrors->mLibraryError;
} }
int ProjectFileIO::GetLastErrorCode() const
{
return mpErrors->mErrorCode;
}
void ProjectFileIO::SetError( void ProjectFileIO::SetError(
const TranslatableString &msg, const TranslatableString &libraryError ) const TranslatableString& msg, const TranslatableString& libraryError, int errorCode)
{ {
auto &currConn = CurrConn(); auto &currConn = CurrConn();
if (currConn) if (currConn)
currConn->SetError(msg, libraryError); currConn->SetError(msg, libraryError, errorCode);
} }
void ProjectFileIO::SetDBError( void ProjectFileIO::SetDBError(
const TranslatableString &msg, const TranslatableString &libraryError) const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{ {
auto &currConn = CurrConn(); auto &currConn = CurrConn();
if (currConn) if (currConn)
currConn->SetDBError(msg, libraryError); currConn->SetDBError(msg, libraryError, errorCode);
} }
void ProjectFileIO::SetBypass() void ProjectFileIO::SetBypass()

View File

@ -114,8 +114,9 @@ public:
// specific database. This is the workhorse for the above 3 methods. // specific database. This is the workhorse for the above 3 methods.
static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid); static int64_t GetDiskUsage(DBConnection &conn, SampleBlockID blockid);
const TranslatableString &GetLastError(); const TranslatableString &GetLastError() const;
const TranslatableString &GetLibraryError(); const TranslatableString &GetLibraryError() const;
int GetLastErrorCode() const;
// Provides a means to bypass "DELETE"s at shutdown if the database // Provides a means to bypass "DELETE"s at shutdown if the database
// is just going to be deleted anyway. This prevents a noticeable // is just going to be deleted anyway. This prevents a noticeable
@ -256,11 +257,13 @@ private:
//! Just set stored errors //! Just set stored errors
void SetError(const TranslatableString & msg, void SetError(const TranslatableString & msg,
const TranslatableString &libraryError = {}); const TranslatableString& libraryError = {},
int errorCode = {});
//! Set stored errors and write to log; and default libraryError to what database library reports //! Set stored errors and write to log; and default libraryError to what database library reports
void SetDBError(const TranslatableString & msg, void SetDBError(const TranslatableString & msg,
const TranslatableString &libraryError = {}); const TranslatableString& libraryError = {},
int errorCode = -1);
bool ShouldCompact(const std::vector<const TrackList *> &tracks); bool ShouldCompact(const std::vector<const TrackList *> &tracks);