mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-30 12:05:39 +00:00
Added error handling for corrupt repositories to GuiThemeDownloader
Also added error handling for when directories could not be renamed
This commit is contained in:
parent
b30f8a48d3
commit
2a4c11d9f0
|
@ -375,7 +375,7 @@ bool GuiThemeDownloader::fetchRepository(const std::string& repositoryName, bool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiThemeDownloader::checkLocalChanges(git_repository* repository, bool hasFetched)
|
bool GuiThemeDownloader::checkLocalChanges(git_repository* repository)
|
||||||
{
|
{
|
||||||
git_status_list* status {nullptr};
|
git_status_list* status {nullptr};
|
||||||
size_t statusEntryCount {0};
|
size_t statusEntryCount {0};
|
||||||
|
@ -404,6 +404,34 @@ bool GuiThemeDownloader::checkLocalChanges(git_repository* repository, bool hasF
|
||||||
return (statusEntryCount != 0);
|
return (statusEntryCount != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GuiThemeDownloader::checkCorruptRepository(git_repository* repository)
|
||||||
|
{
|
||||||
|
// For the time being we only check if there are no tracked files in the repository. If there
|
||||||
|
// are none then it would indicate that it has not been properly cloned (for example if the
|
||||||
|
// ES-DE process was killed during the clone operation).
|
||||||
|
git_status_list* status {nullptr};
|
||||||
|
size_t statusEntryCount {0};
|
||||||
|
int errorCode {0};
|
||||||
|
|
||||||
|
#if LIBGIT2_VER_MAJOR >= 1
|
||||||
|
git_status_options statusOptions;
|
||||||
|
git_status_options_init(&statusOptions, GIT_STATUS_OPTIONS_VERSION);
|
||||||
|
#else
|
||||||
|
git_status_options statusOptions = GIT_STATUS_OPTIONS_INIT;
|
||||||
|
#endif
|
||||||
|
statusOptions.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
|
||||||
|
statusOptions.flags = GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
|
||||||
|
GIT_STATUS_OPT_SORT_CASE_SENSITIVELY | GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
|
||||||
|
|
||||||
|
errorCode = git_status_list_new(&status, repository, &statusOptions);
|
||||||
|
if (errorCode == 0)
|
||||||
|
statusEntryCount = git_status_list_entrycount(status);
|
||||||
|
|
||||||
|
git_status_list_free(status);
|
||||||
|
|
||||||
|
return (statusEntryCount == 0);
|
||||||
|
}
|
||||||
|
|
||||||
void GuiThemeDownloader::resetRepository(git_repository* repository)
|
void GuiThemeDownloader::resetRepository(git_repository* repository)
|
||||||
{
|
{
|
||||||
git_object* objectHead {nullptr};
|
git_object* objectHead {nullptr};
|
||||||
|
@ -417,6 +445,7 @@ void GuiThemeDownloader::makeInventory()
|
||||||
for (auto& theme : mThemeSets) {
|
for (auto& theme : mThemeSets) {
|
||||||
const std::string path {mThemeDirectory + theme.reponame};
|
const std::string path {mThemeDirectory + theme.reponame};
|
||||||
theme.invalidRepository = false;
|
theme.invalidRepository = false;
|
||||||
|
theme.corruptRepository = false;
|
||||||
theme.shallowRepository = false;
|
theme.shallowRepository = false;
|
||||||
theme.manuallyDownloaded = false;
|
theme.manuallyDownloaded = false;
|
||||||
theme.hasLocalChanges = false;
|
theme.hasLocalChanges = false;
|
||||||
|
@ -448,6 +477,12 @@ void GuiThemeDownloader::makeInventory()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (checkCorruptRepository(repository)) {
|
||||||
|
theme.corruptRepository = true;
|
||||||
|
git_repository_free(repository);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
theme.isCloned = true;
|
theme.isCloned = true;
|
||||||
|
|
||||||
if (checkLocalChanges(repository))
|
if (checkLocalChanges(repository))
|
||||||
|
@ -460,23 +495,37 @@ void GuiThemeDownloader::makeInventory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiThemeDownloader::renameDirectory(const std::string& path)
|
bool GuiThemeDownloader::renameDirectory(const std::string& path, const std::string& extension)
|
||||||
{
|
{
|
||||||
LOG(LogInfo) << "Renaming directory " << path;
|
LOG(LogInfo) << "Renaming directory " << path;
|
||||||
int index {1};
|
int index {1};
|
||||||
|
bool renameStatus {false};
|
||||||
|
|
||||||
if (!Utils::FileSystem::exists(path + "_DISABLED"))
|
if (!Utils::FileSystem::exists(path + extension)) {
|
||||||
return Utils::FileSystem::renameFile(path, path + "_DISABLED", false);
|
renameStatus = Utils::FileSystem::renameFile(path, path + extension, false);
|
||||||
|
}
|
||||||
// This will hopefully never be needed as it should only occur if a theme has been downloaded
|
else {
|
||||||
// manually multiple times and the theme downloader has been ran multiple times as well.
|
// This will hopefully never be needed as it should only occur if a theme has been
|
||||||
for (; index < 10; ++index) {
|
// downloaded manually multiple times and the theme downloader has been ran multiple times
|
||||||
if (!Utils::FileSystem::exists(path + "_" + std::to_string(index) + "_DISABLED"))
|
// as well.
|
||||||
return Utils::FileSystem::renameFile(
|
for (; index < 10; ++index) {
|
||||||
path, path + "_" + std::to_string(index) + "_DISABLED", false);
|
if (!Utils::FileSystem::exists(path + "_" + std::to_string(index) + extension)) {
|
||||||
|
renameStatus = Utils::FileSystem::renameFile(
|
||||||
|
path, path + "_" + std::to_string(index) + extension, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (renameStatus) {
|
||||||
|
mWindow->pushGui(new GuiMsgBox(
|
||||||
|
getHelpStyle(), "COULDN'T RENAME DIRECTORY \"" + path + "\", PERMISSION PROBLEMS?",
|
||||||
|
"OK", [] { return; }, "", nullptr, "", nullptr, true));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiThemeDownloader::parseThemesList()
|
void GuiThemeDownloader::parseThemesList()
|
||||||
|
@ -600,7 +649,8 @@ void GuiThemeDownloader::populateGUI()
|
||||||
themeName.append(" ").append(ViewController::BRANCH_CHAR);
|
themeName.append(" ").append(ViewController::BRANCH_CHAR);
|
||||||
if (theme.isCloned)
|
if (theme.isCloned)
|
||||||
themeName.append(" ").append(ViewController::TICKMARK_CHAR);
|
themeName.append(" ").append(ViewController::TICKMARK_CHAR);
|
||||||
if (theme.manuallyDownloaded || theme.invalidRepository || theme.shallowRepository)
|
if (theme.manuallyDownloaded || theme.invalidRepository || theme.corruptRepository ||
|
||||||
|
theme.shallowRepository)
|
||||||
themeName.append(" ").append(ViewController::CROSSEDCIRCLE_CHAR);
|
themeName.append(" ").append(ViewController::CROSSEDCIRCLE_CHAR);
|
||||||
if (theme.hasLocalChanges)
|
if (theme.hasLocalChanges)
|
||||||
themeName.append(" ").append(ViewController::EXCLAMATION_CHAR);
|
themeName.append(" ").append(ViewController::EXCLAMATION_CHAR);
|
||||||
|
@ -626,7 +676,39 @@ void GuiThemeDownloader::populateGUI()
|
||||||
theme.reponame + theme.manualExtension + "_DISABLED\"",
|
theme.reponame + theme.manualExtension + "_DISABLED\"",
|
||||||
"PROCEED",
|
"PROCEED",
|
||||||
[this, theme] {
|
[this, theme] {
|
||||||
renameDirectory(mThemeDirectory + theme.reponame + theme.manualExtension);
|
if (renameDirectory(mThemeDirectory + theme.reponame +
|
||||||
|
theme.manualExtension,
|
||||||
|
"_DISABLED")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::promise<bool>().swap(mPromise);
|
||||||
|
mFuture = mPromise.get_future();
|
||||||
|
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
||||||
|
theme.reponame, theme.url);
|
||||||
|
mStatusType = StatusType::STATUS_DOWNLOADING;
|
||||||
|
mStatusText = "DOWNLOADING THEME";
|
||||||
|
},
|
||||||
|
"ABORT", [] { return; }, "", nullptr, true, true,
|
||||||
|
(mRenderer->getIsVerticalOrientation() ?
|
||||||
|
0.75f :
|
||||||
|
0.45f * (1.778f / mRenderer->getScreenAspectRatio()))));
|
||||||
|
}
|
||||||
|
else if (theme.corruptRepository) {
|
||||||
|
mWindow->pushGui(new GuiMsgBox(
|
||||||
|
getHelpStyle(),
|
||||||
|
"IT SEEMS AS IF THIS THEME REPOSITORY IS CORRUPT, WHICH COULD HAVE BEEN CAUSED "
|
||||||
|
"BY AN INTERRUPTION OF A PREVIOUS DOWNLOAD OR UPDATE, FOR EXAMPLE IF THE ES-DE "
|
||||||
|
"PROCESS WAS KILLED. A FRESH DOWNLOAD IS REQUIRED AND THE OLD THEME DIRECTORY "
|
||||||
|
"\"" +
|
||||||
|
theme.reponame + theme.manualExtension + "\" WILL BE RENAMED TO \"" +
|
||||||
|
theme.reponame + theme.manualExtension + "_CORRUPT_DISABLED\"",
|
||||||
|
"PROCEED",
|
||||||
|
[this, theme] {
|
||||||
|
if (renameDirectory(mThemeDirectory + theme.reponame +
|
||||||
|
theme.manualExtension,
|
||||||
|
"_CORRUPT_DISABLED")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::promise<bool>().swap(mPromise);
|
std::promise<bool>().swap(mPromise);
|
||||||
mFuture = mPromise.get_future();
|
mFuture = mPromise.get_future();
|
||||||
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
||||||
|
@ -649,7 +731,11 @@ void GuiThemeDownloader::populateGUI()
|
||||||
theme.reponame + theme.manualExtension + "_DISABLED\"",
|
theme.reponame + theme.manualExtension + "_DISABLED\"",
|
||||||
"PROCEED",
|
"PROCEED",
|
||||||
[this, theme] {
|
[this, theme] {
|
||||||
renameDirectory(mThemeDirectory + theme.reponame + theme.manualExtension);
|
if (renameDirectory(mThemeDirectory + theme.reponame +
|
||||||
|
theme.manualExtension,
|
||||||
|
"_DISABLED")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::promise<bool>().swap(mPromise);
|
std::promise<bool>().swap(mPromise);
|
||||||
mFuture = mPromise.get_future();
|
mFuture = mPromise.get_future();
|
||||||
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
||||||
|
@ -722,7 +808,7 @@ void GuiThemeDownloader::updateGUI()
|
||||||
if (mThemeSets[i].isCloned)
|
if (mThemeSets[i].isCloned)
|
||||||
themeName.append(" ").append(ViewController::TICKMARK_CHAR);
|
themeName.append(" ").append(ViewController::TICKMARK_CHAR);
|
||||||
if (mThemeSets[i].manuallyDownloaded || mThemeSets[i].invalidRepository ||
|
if (mThemeSets[i].manuallyDownloaded || mThemeSets[i].invalidRepository ||
|
||||||
mThemeSets[i].shallowRepository)
|
mThemeSets[i].corruptRepository || mThemeSets[i].shallowRepository)
|
||||||
themeName.append(" ").append(ViewController::CROSSEDCIRCLE_CHAR);
|
themeName.append(" ").append(ViewController::CROSSEDCIRCLE_CHAR);
|
||||||
if (mThemeSets[i].hasLocalChanges)
|
if (mThemeSets[i].hasLocalChanges)
|
||||||
themeName.append(" ").append(ViewController::EXCLAMATION_CHAR);
|
themeName.append(" ").append(ViewController::EXCLAMATION_CHAR);
|
||||||
|
@ -749,6 +835,10 @@ void GuiThemeDownloader::updateInfoPane()
|
||||||
mDownloadStatus->setText(ViewController::CROSSEDCIRCLE_CHAR + " MANUAL DOWNLOAD");
|
mDownloadStatus->setText(ViewController::CROSSEDCIRCLE_CHAR + " MANUAL DOWNLOAD");
|
||||||
mDownloadStatus->setColor(0x992222FF);
|
mDownloadStatus->setColor(0x992222FF);
|
||||||
}
|
}
|
||||||
|
else if (mThemeSets[mList->getCursorId()].corruptRepository) {
|
||||||
|
mDownloadStatus->setText(ViewController::CROSSEDCIRCLE_CHAR + " CORRUPT");
|
||||||
|
mDownloadStatus->setColor(0x992222FF);
|
||||||
|
}
|
||||||
else if (mThemeSets[mList->getCursorId()].shallowRepository) {
|
else if (mThemeSets[mList->getCursorId()].shallowRepository) {
|
||||||
mDownloadStatus->setText(ViewController::CROSSEDCIRCLE_CHAR + " SHALLOW REPO");
|
mDownloadStatus->setText(ViewController::CROSSEDCIRCLE_CHAR + " SHALLOW REPO");
|
||||||
mDownloadStatus->setColor(0x992222FF);
|
mDownloadStatus->setColor(0x992222FF);
|
||||||
|
@ -1051,28 +1141,49 @@ bool GuiThemeDownloader::fetchThemesList()
|
||||||
if (Utils::FileSystem::exists(path)) {
|
if (Utils::FileSystem::exists(path)) {
|
||||||
git_repository* repository {nullptr};
|
git_repository* repository {nullptr};
|
||||||
int errorCode {git_repository_open(&repository, &path[0])};
|
int errorCode {git_repository_open(&repository, &path[0])};
|
||||||
if (errorCode != 0) {
|
|
||||||
if (renameDirectory(path)) {
|
if (errorCode != 0 || checkCorruptRepository(repository)) {
|
||||||
git_repository_free(repository);
|
mWindow->pushGui(new GuiMsgBox(
|
||||||
LOG(LogError) << "Couldn't rename \"" << path << "\", permission problems?";
|
getHelpStyle(),
|
||||||
mWindow->pushGui(new GuiMsgBox(
|
"IT SEEMS AS IF THE THEMES LIST REPOSITORY IS CORRUPT, WHICH COULD HAVE BEEN "
|
||||||
getHelpStyle(), "COULDN'T RENAME DIRECTORY\n" + path + "\nPERMISSION PROBLEMS?",
|
"CAUSED BY AN INTERRUPTION OF A PREVIOUS DOWNLOAD OR UPDATE, FOR EXAMPLE IF THE "
|
||||||
"OK", [] { return; }, "", nullptr, "", nullptr, true));
|
"ES-DE PROCESS WAS KILLED. A FRESH DOWNLOAD IS REQUIRED AND THE OLD DIRECTORY "
|
||||||
return true;
|
"\"themes-list\" WILL BE RENAMED TO \"themes-list_CORRUPT_DISABLED\"",
|
||||||
}
|
"PROCEED",
|
||||||
|
[this, repositoryName, url] {
|
||||||
|
if (renameDirectory(mThemeDirectory + "themes-list", "_CORRUPT_DISABLED")) {
|
||||||
|
mGrid.removeEntry(mCenterGrid);
|
||||||
|
mGrid.setCursorTo(mButtons);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG(LogInfo)
|
||||||
|
<< "GuiThemeDownloader: Creating initial themes list repository clone";
|
||||||
|
mFetchThread = std::thread(&GuiThemeDownloader::cloneRepository, this,
|
||||||
|
repositoryName, url);
|
||||||
|
mStatusType = StatusType::STATUS_DOWNLOADING;
|
||||||
|
mStatusText = "DOWNLOADING THEMES LIST";
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"ABORT",
|
||||||
|
[&] {
|
||||||
|
delete this;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"", nullptr, true, true,
|
||||||
|
(mRenderer->getIsVerticalOrientation() ?
|
||||||
|
0.75f :
|
||||||
|
0.50f * (1.778f / mRenderer->getScreenAspectRatio()))));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// We always hard reset the themes list as it should never contain any local changes.
|
||||||
|
resetRepository(repository);
|
||||||
|
|
||||||
checkLocalChanges(repository);
|
mFetchThread =
|
||||||
|
std::thread(&GuiThemeDownloader::fetchRepository, this, repositoryName, false);
|
||||||
// We always hard reset the themes list as it should never contain any local changes.
|
mStatusType = StatusType::STATUS_UPDATING;
|
||||||
resetRepository(repository);
|
mStatusText = "UPDATING THEMES LIST";
|
||||||
|
}
|
||||||
git_repository_free(repository);
|
git_repository_free(repository);
|
||||||
|
|
||||||
mFetchThread =
|
|
||||||
std::thread(&GuiThemeDownloader::fetchRepository, this, repositoryName, false);
|
|
||||||
mStatusType = StatusType::STATUS_UPDATING;
|
|
||||||
mStatusText = "UPDATING THEMES LIST";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mWindow->pushGui(new GuiMsgBox(
|
mWindow->pushGui(new GuiMsgBox(
|
||||||
|
|
|
@ -68,6 +68,7 @@ private:
|
||||||
std::vector<Screenshot> screenshots;
|
std::vector<Screenshot> screenshots;
|
||||||
bool newEntry;
|
bool newEntry;
|
||||||
bool invalidRepository;
|
bool invalidRepository;
|
||||||
|
bool corruptRepository;
|
||||||
bool shallowRepository;
|
bool shallowRepository;
|
||||||
bool manuallyDownloaded;
|
bool manuallyDownloaded;
|
||||||
bool hasLocalChanges;
|
bool hasLocalChanges;
|
||||||
|
@ -75,6 +76,7 @@ private:
|
||||||
ThemeEntry()
|
ThemeEntry()
|
||||||
: newEntry {false}
|
: newEntry {false}
|
||||||
, invalidRepository {false}
|
, invalidRepository {false}
|
||||||
|
, corruptRepository {false}
|
||||||
, shallowRepository {false}
|
, shallowRepository {false}
|
||||||
, manuallyDownloaded {false}
|
, manuallyDownloaded {false}
|
||||||
, hasLocalChanges {false}
|
, hasLocalChanges {false}
|
||||||
|
@ -87,10 +89,11 @@ private:
|
||||||
bool fetchRepository(const std::string& repositoryName, bool allowReset = false);
|
bool fetchRepository(const std::string& repositoryName, bool allowReset = false);
|
||||||
bool cloneRepository(const std::string& repositoryName, const std::string& url);
|
bool cloneRepository(const std::string& repositoryName, const std::string& url);
|
||||||
|
|
||||||
bool checkLocalChanges(git_repository* repository, bool hasFetched = false);
|
bool checkLocalChanges(git_repository* repository);
|
||||||
|
bool checkCorruptRepository(git_repository* repository);
|
||||||
void resetRepository(git_repository* repository);
|
void resetRepository(git_repository* repository);
|
||||||
void makeInventory();
|
void makeInventory();
|
||||||
bool renameDirectory(const std::string& path);
|
bool renameDirectory(const std::string& path, const std::string& extension);
|
||||||
void parseThemesList();
|
void parseThemesList();
|
||||||
|
|
||||||
void populateGUI();
|
void populateGUI();
|
||||||
|
|
Loading…
Reference in a new issue