Show alert when we upgrade an existent extension

This commit is contained in:
David Capello 2017-06-23 07:53:31 -03:00
parent 19f6dcfc58
commit 4ccecdeda2
3 changed files with 126 additions and 43 deletions

View File

@ -24,6 +24,8 @@
#include "base/bind.h"
#include "base/convert_to.h"
#include "base/fs.h"
#include "base/string.h"
#include "base/version.h"
#include "doc/image.h"
#include "render/render.h"
#include "she/display.h"
@ -76,6 +78,8 @@ class OptionsWindow : public app::gen::Options {
setEnabled(extension->isEnabled());
}
Extension* extension() { return m_extension; }
bool isEnabled() const {
ASSERT(m_extension);
return m_extension->isEnabled();
@ -725,12 +729,51 @@ private:
ASSERT(!filename.empty());
Extensions& exts = App::instance()->extensions();
ExtensionInfo info = exts.getCompressedExtensionInfo(filename.front());
// Check if the extension already exist
for (auto ext : exts) {
if (base::string_to_lower(ext->name()) !=
base::string_to_lower(info.name))
continue;
bool isDowngrade =
base::Version(info.version.c_str()) <
base::Version(ext->version().c_str());
// Uninstall?
if (ui::Alert::show(
"Update Extension"
"<<The extension '%s' already exists."
"<<Do you want to %s from v%s to v%s?"
"||&Yes||&No",
ext->name().c_str(),
(isDowngrade ? "downgrade": "upgrade"),
ext->version().c_str(),
info.version.c_str()) != 1)
return;
// Uninstall old version
if (ext->canBeUninstalled()) {
exts.uninstallExtension(ext);
ExtensionItem* item = getItemByExtension(ext);
if (item)
deleteExtensionItem(item);
}
break;
}
try {
Extension* extension =
App::instance()->extensions().installCompressedExtension(filename.front());
Extension* ext =
exts.installCompressedExtension(filename.front(), info);
// Enable extension
exts.enableExtension(ext, true);
// Add the new extension in the listbox
ExtensionItem* item = new ExtensionItem(extension);
ExtensionItem* item = new ExtensionItem(ext);
extensionsList()->addChild(item);
extensionsList()->selectChild(item);
extensionsList()->layout();
@ -762,18 +805,29 @@ private:
try {
item->uninstall();
// Remove the item from the list
extensionsList()->removeChild(item);
extensionsList()->layout();
item->deferDelete();
deleteExtensionItem(item);
}
catch (std::exception& ex) {
Console::showException(ex);
}
}
void deleteExtensionItem(ExtensionItem* item) {
// Remove the item from the list
extensionsList()->removeChild(item);
extensionsList()->layout();
item->deferDelete();
}
ExtensionItem* getItemByExtension(Extension* ext) {
for (auto child : extensionsList()->children()) {
ExtensionItem* item = dynamic_cast<ExtensionItem*>(child);
if (item && item->extension() == ext)
return item;
}
return nullptr;
}
void onOpenExtensionFolder() {
ExtensionItem* item = dynamic_cast<ExtensionItem*>(extensionsList()->getSelectedChild());
if (item)

View File

@ -175,11 +175,13 @@ void Extension::DitheringMatrixInfo::destroyMatrix()
Extension::Extension(const std::string& path,
const std::string& name,
const std::string& version,
const std::string& displayName,
const bool isEnabled,
const bool isBuiltinExtension)
: m_path(path)
, m_name(name)
, m_version(version)
, m_displayName(displayName)
, m_isEnabled(isEnabled)
, m_isInstalled(true)
@ -418,45 +420,58 @@ void Extensions::uninstallExtension(Extension* extension)
{
extension->uninstall();
generateExtensionSignals(extension);
auto it = std::find(m_extensions.begin(),
m_extensions.end(), extension);
ASSERT(it != m_extensions.end());
if (it != m_extensions.end())
m_extensions.erase(it);
delete extension;
}
Extension* Extensions::installCompressedExtension(const std::string& zipFn)
ExtensionInfo Extensions::getCompressedExtensionInfo(const std::string& zipFn)
{
std::string dstExtensionPath =
ExtensionInfo info;
info.dstPath =
base::join_path(m_userExtensionsPath,
base::get_file_title(zipFn));
// First of all we read the package.json file inside the .zip to
// know 1) the extension name, 2) that the .json file can be parsed
// correctly, 3) the final destination directory.
std::string commonPath;
{
ReadArchive in(zipFn);
archive_entry* entry;
while ((entry = in.readEntry()) != nullptr) {
const std::string entryFn = archive_entry_pathname(entry);
if (base::get_file_name(entryFn) != kPackageJson)
continue;
ReadArchive in(zipFn);
archive_entry* entry;
while ((entry = in.readEntry()) != nullptr) {
const std::string entryFn = archive_entry_pathname(entry);
if (base::get_file_name(entryFn) != kPackageJson)
continue;
commonPath = base::get_file_path(entryFn);
if (!commonPath.empty() &&
entryFn.size() > commonPath.size())
commonPath.push_back(entryFn[commonPath.size()]);
std::stringstream out;
in.copyDataTo(out);
std::string err;
auto json = json11::Json::parse(out.str(), err);
if (err.empty()) {
auto name = json["name"].string_value();
dstExtensionPath = base::join_path(m_userExtensionsPath, name);
}
break;
info.commonPath = base::get_file_path(entryFn);
if (!info.commonPath.empty() &&
entryFn.size() > info.commonPath.size()) {
info.commonPath.push_back(entryFn[info.commonPath.size()]);
}
}
// Uncompress zipFn in dstExtensionPath
std::stringstream out;
in.copyDataTo(out);
std::string err;
auto json = json11::Json::parse(out.str(), err);
if (err.empty()) {
info.name = json["name"].string_value();
info.version = json["version"].string_value();
info.dstPath = base::join_path(m_userExtensionsPath, info.name);
}
break;
}
return info;
}
Extension* Extensions::installCompressedExtension(const std::string& zipFn,
const ExtensionInfo& info)
{
// Uncompress zipFn in info.dstPath
{
ReadArchive in(zipFn);
WriteArchive out;
@ -468,17 +483,17 @@ Extension* Extensions::installCompressedExtension(const std::string& zipFn)
LOG("EXT: Original filename in zip <%s>...\n", fn.c_str());
if (!commonPath.empty()) {
if (!info.commonPath.empty()) {
// Check mismatch with package.json common path
if (fn.compare(0, commonPath.size(), commonPath) != 0)
if (fn.compare(0, info.commonPath.size(), info.commonPath) != 0)
continue;
fn.erase(0, commonPath.size());
fn.erase(0, info.commonPath.size());
if (fn.empty())
continue;
}
const std::string fullFn = base::join_path(dstExtensionPath, fn);
const std::string fullFn = base::join_path(info.dstPath, fn);
archive_entry_set_pathname(entry, fullFn.c_str());
LOG("EXT: Uncompressing file <%s> to <%s>\n",
@ -489,8 +504,8 @@ Extension* Extensions::installCompressedExtension(const std::string& zipFn)
}
Extension* extension = loadExtension(
dstExtensionPath,
base::join_path(dstExtensionPath, kPackageJson),
info.dstPath,
base::join_path(info.dstPath, kPackageJson),
false);
if (!extension)
throw base::Exception("Error adding the new extension");
@ -522,6 +537,7 @@ Extension* Extensions::loadExtension(const std::string& path,
err.c_str());
}
auto name = json["name"].string_value();
auto version = json["version"].string_value();
auto displayName = json["displayName"].string_value();
LOG("EXT: Extension '%s' loaded\n", name.c_str());
@ -529,6 +545,7 @@ Extension* Extensions::loadExtension(const std::string& path,
base::UniquePtr<Extension> extension(
new Extension(path,
name,
version,
displayName,
// Extensions are enabled by default
get_config_bool("extensions", name.c_str(), true),

View File

@ -27,6 +27,13 @@ namespace app {
class Extensions;
struct ExtensionInfo {
std::string name;
std::string version;
std::string dstPath;
std::string commonPath;
};
class Extension {
friend class Extensions;
public:
@ -49,6 +56,7 @@ namespace app {
Extension(const std::string& path,
const std::string& name,
const std::string& version,
const std::string& displayName,
const bool isEnabled,
const bool isBuiltinExtension);
@ -56,6 +64,7 @@ namespace app {
const std::string& path() const { return m_path; }
const std::string& name() const { return m_name; }
const std::string& version() const { return m_version; }
const std::string& displayName() const { return m_displayName; }
const ExtensionItems& themes() const { return m_themes; }
@ -88,6 +97,7 @@ namespace app {
std::map<std::string, DitheringMatrixInfo> m_ditheringMatrices;
std::string m_path;
std::string m_name;
std::string m_version;
std::string m_displayName;
bool m_isEnabled;
bool m_isInstalled;
@ -107,7 +117,9 @@ namespace app {
void enableExtension(Extension* extension, const bool state);
void uninstallExtension(Extension* extension);
Extension* installCompressedExtension(const std::string& zipFn);
ExtensionInfo getCompressedExtensionInfo(const std::string& zipFn);
Extension* installCompressedExtension(const std::string& zipFn,
const ExtensionInfo& info);
std::string themePath(const std::string& themeId);
std::string palettePath(const std::string& palId);