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(
const TranslatableString &msg, const TranslatableString &libraryError)
const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{
wxLogMessage(wxT("Connection msg: %s"), msg.Debug());
if (!libraryError.empty())
wxLogMessage(wxT("Connection error: %s"), libraryError.Debug());
mpErrors->mLastError = msg;
mpErrors->mLibraryError = libraryError;
mpErrors->mErrorCode = errorCode;
}
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;
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());
mpErrors->mLibraryError = libraryError.empty()
? Verbatim(sqlite3_errmsg(DB())) : libraryError;
wxLogMessage(wxT(" Lib error: %s"), mpErrors->mLibraryError.Debug());
printf(" Lib error: %s", mpErrors->mLibraryError.Debug().mb_str().data());
}

View File

@ -31,6 +31,7 @@ struct DBConnectionErrors
{
TranslatableString mLastError;
TranslatableString mLibraryError;
int mErrorCode { 0 };
};
class DBConnection
@ -84,12 +85,14 @@ public:
//! Just set stored errors
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
void SetDBError(
const TranslatableString &msg,
const TranslatableString &libraryError = {} );
const TranslatableString& libraryError = {},
int errorCode = -1);
private:
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(
XO("Failed to execute a project file command:\n\n%s").Format(query),
Verbatim(errmsg)
Verbatim(errmsg),
rc
);
}
if (errmsg)
@ -596,6 +597,17 @@ bool ProjectFileIO::CheckVersion()
wxString 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;
}
@ -2170,30 +2182,35 @@ wxLongLong ProjectFileIO::GetFreeDiskSpace() const
return -1;
}
const TranslatableString &ProjectFileIO::GetLastError()
const TranslatableString &ProjectFileIO::GetLastError() const
{
return mpErrors->mLastError;
}
const TranslatableString &ProjectFileIO::GetLibraryError()
const TranslatableString &ProjectFileIO::GetLibraryError() const
{
return mpErrors->mLibraryError;
}
int ProjectFileIO::GetLastErrorCode() const
{
return mpErrors->mErrorCode;
}
void ProjectFileIO::SetError(
const TranslatableString &msg, const TranslatableString &libraryError )
const TranslatableString& msg, const TranslatableString& libraryError, int errorCode)
{
auto &currConn = CurrConn();
if (currConn)
currConn->SetError(msg, libraryError);
currConn->SetError(msg, libraryError, errorCode);
}
void ProjectFileIO::SetDBError(
const TranslatableString &msg, const TranslatableString &libraryError)
const TranslatableString &msg, const TranslatableString &libraryError, int errorCode)
{
auto &currConn = CurrConn();
if (currConn)
currConn->SetDBError(msg, libraryError);
currConn->SetDBError(msg, libraryError, errorCode);
}
void ProjectFileIO::SetBypass()

View File

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