Add Ctrl+Shift+R on debug mode to recover the active document from active backup session

In this way we can test on each moment how the information is being
saved and will be recovered. We can find bugs with missing or invalid
doc::Object::incrementVersion() calls.
This commit is contained in:
David Capello 2016-11-07 17:47:53 -03:00
parent 1b2b98ec38
commit 644b8ff0a4
7 changed files with 57 additions and 7 deletions

View File

@ -59,6 +59,9 @@ because they don't depend on any other component.
# Debugging Tricks # Debugging Tricks
On Windows, you can use F5 to show the amount of used memory. Also * On Windows, you can use F5 to show the amount of used memory.
`Ctrl+Shift+Q` crashes the application in case that you want to test * On debug mode (when `_DEBUG` is defined), `Ctrl+Alt+Shift+Q` crashes
the anticrash feature or your need a memory dump file. the application in case that you want to test the anticrash feature
or your need a memory dump file.
* On debug mode, you can use `Ctrl+Alt+Shift+R` to recover the active
document from the data recovery store.

View File

@ -129,6 +129,7 @@ public:
void deleteDataRecovery() { void deleteDataRecovery() {
#ifdef ENABLE_DATA_RECOVERY #ifdef ENABLE_DATA_RECOVERY
delete m_recovery; delete m_recovery;
m_recovery = nullptr;
#endif #endif
} }
@ -845,6 +846,11 @@ Preferences& App::preferences() const
return m_coreModules->m_preferences; return m_coreModules->m_preferences;
} }
crash::DataRecovery* App::dataRecovery() const
{
return m_modules->recovery();
}
void App::showNotification(INotificationDelegate* del) void App::showNotification(INotificationDelegate* del)
{ {
m_mainWindow->showNotification(del); m_mainWindow->showNotification(del);

View File

@ -42,6 +42,10 @@ namespace app {
class Timeline; class Timeline;
class Workspace; class Workspace;
namespace crash {
class DataRecovery;
}
namespace tools { namespace tools {
class ActiveToolManager; class ActiveToolManager;
class Tool; class Tool;
@ -78,6 +82,7 @@ namespace app {
ContextBar* contextBar() const; ContextBar* contextBar() const;
Timeline* timeline() const; Timeline* timeline() const;
Preferences& preferences() const; Preferences& preferences() const;
crash::DataRecovery* dataRecovery() const;
AppBrushes& brushes() { AppBrushes& brushes() {
ASSERT(m_brushes.get()); ASSERT(m_brushes.get());

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -28,6 +28,8 @@ namespace crash {
DataRecovery(doc::Context* context); DataRecovery(doc::Context* context);
~DataRecovery(); ~DataRecovery();
Session* activeSession() { return m_inProgress.get(); }
// Returns the list of sessions that can be recovered. // Returns the list of sessions that can be recovered.
const Sessions& sessions() { return m_sessions; } const Sessions& sessions() { return m_sessions; }

View File

@ -25,6 +25,7 @@
#include "base/process.h" #include "base/process.h"
#include "base/split_string.h" #include "base/split_string.h"
#include "base/string.h" #include "base/string.h"
#include "base/unique_ptr.h"
namespace app { namespace app {
namespace crash { namespace crash {
@ -173,6 +174,17 @@ void Session::restoreBackup(Backup* backup)
} }
} }
void Session::restoreBackupById(const ObjectId id)
{
std::string docDir = base::join_path(m_path, base::convert_to<std::string>(int(id)));
if (!base::is_directory(docDir))
return;
base::UniquePtr<Backup> backup(new Backup(docDir));
if (backup)
restoreBackup(backup.get());
}
void Session::restoreRawImages(Backup* backup, RawImagesAs as) void Session::restoreRawImages(Backup* backup, RawImagesAs as)
{ {
Console console; Console console;

View File

@ -12,6 +12,7 @@
#include "base/disable_copying.h" #include "base/disable_copying.h"
#include "base/process.h" #include "base/process.h"
#include "base/shared_ptr.h" #include "base/shared_ptr.h"
#include "doc/object_id.h"
#include <fstream> #include <fstream>
#include <string> #include <string>
@ -52,6 +53,7 @@ namespace crash {
void removeDocument(app::Document* doc); void removeDocument(app::Document* doc);
void restoreBackup(Backup* backup); void restoreBackup(Backup* backup);
void restoreBackupById(const doc::ObjectId id);
void restoreRawImages(Backup* backup, RawImagesAs as); void restoreRawImages(Backup* backup, RawImagesAs as);
void deleteBackup(Backup* backup); void deleteBackup(Backup* backup);

View File

@ -15,7 +15,6 @@
#include "app/console.h" #include "app/console.h"
#include "app/document.h" #include "app/document.h"
#include "app/ini_file.h" #include "app/ini_file.h"
#include "app/modules/editors.h"
#include "app/modules/gfx.h" #include "app/modules/gfx.h"
#include "app/modules/gui.h" #include "app/modules/gui.h"
#include "app/modules/palettes.h" #include "app/modules/palettes.h"
@ -47,6 +46,11 @@
#include <list> #include <list>
#include <vector> #include <vector>
#if defined(_DEBUG) && defined(ENABLE_DATA_RECOVERY)
#include "app/crash/data_recovery.h"
#include "app/modules/editors.h"
#endif
namespace app { namespace app {
using namespace gfx; using namespace gfx;
@ -372,14 +376,30 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
case kKeyDownMessage: { case kKeyDownMessage: {
#ifdef _DEBUG #ifdef _DEBUG
// Left Shift+Ctrl+Q generates a crash (useful to test the anticrash feature) // Ctrl+Shift+Q generates a crash (useful to test the anticrash feature)
if (msg->ctrlPressed() && if (msg->ctrlPressed() &&
msg->shiftPressed() && msg->shiftPressed() &&
static_cast<KeyMessage*>(msg)->scancode() == kKeyQ) { static_cast<KeyMessage*>(msg)->scancode() == kKeyQ) {
int* p = nullptr; int* p = nullptr;
*p = 0; *p = 0;
} }
#endif
#ifdef ENABLE_DATA_RECOVERY
// Ctrl+Shift+R recover active sprite from the backup store
if (msg->ctrlPressed() &&
msg->shiftPressed() &&
static_cast<KeyMessage*>(msg)->scancode() == kKeyR &&
App::instance()->dataRecovery() &&
App::instance()->dataRecovery()->activeSession() &&
current_editor &&
current_editor->document()) {
App::instance()
->dataRecovery()
->activeSession()
->restoreBackupById(current_editor->document()->id());
}
#endif // ENABLE_DATA_RECOVERY
#endif // _DEBUG
// Call base impl to check if there is a foreground window as // Call base impl to check if there is a foreground window as
// top level that needs keys. (In this way we just do not // top level that needs keys. (In this way we just do not