← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3276: allow updating plugins rather than refusing to install

 

------------------------------------------------------------
revno: 3276
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2013-04-25 20:08:15 +0200
message:
  allow updating plugins rather than refusing to install
modified:
  dcpp/PluginManager.cpp
  dcpp/PluginManager.h
  dcpp/forward.h
  win32/PluginInfoDlg.cpp
  win32/PluginInfoDlg.h
  win32/PluginPage.cpp
  win32/PluginPage.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/PluginManager.cpp'
--- dcpp/PluginManager.cpp	2013-04-23 17:41:14 +0000
+++ dcpp/PluginManager.cpp	2013-04-25 18:08:15 +0000
@@ -81,7 +81,7 @@
 	SimpleXML xml;
 	xml.fromXML(File(info_path, File::READ, File::OPEN).read());
 
-	DcextInfo info;
+	DcextInfo info { };
 
 	if(xml.findChild("dcext")) {
 		xml.stepIn();
@@ -114,7 +114,7 @@
 		string version;
 		parse("ApiVersion", version);
 		if(Util::toInt(version) < DCAPI_CORE_VER) {
-			throw str(F_("%1% is too old, contact the plugin author for an update") % Util::getFileName(path));
+			throw Exception(str(F_("%1% is too old, contact the plugin author for an update") % Util::getFileName(path)));
 		}
 
 		parse("UUID", info.uuid);
@@ -154,26 +154,32 @@
 		throw Exception(str(F_("%1% is not compatible with %2%") % Util::getFileName(path) % APPNAME));
 	}
 
-	if(isLoaded(info.uuid)) {
-		throw Exception(str(F_("%1% is already installed") % Util::getFileName(path)));
+	{
+		Lock l(cs);
+
+		auto it = findPlugin(info.uuid);
+		if(it != plugins.end()) {
+			auto& plugin = *it;
+			if(plugin->getInfo().version < info.version) {
+				info.updating = true;
+			} else {
+				throw Exception(str(F_("%1% is already installed") % plugin->getInfo().name));
+			}
+		}
 	}
 
 	return info;
 }
 
-void PluginManager::install(const string& uuid, const string& plugin, const StringList& files) {
-	if(uuid.empty() || plugin.empty()) {
-		throw Exception();
-	}
-
+void PluginManager::install(const DcextInfo& info) {
 	const auto source = Util::getTempPath() + "dcext" PATH_SEPARATOR_STR;
-	const auto target = getInstallPath(uuid);
-	const auto lib = target + Util::getFileName(plugin);
+	const auto target = getInstallPath(info.uuid);
+	const auto lib = target + Util::getFileName(info.plugin);
 
 	File::ensureDirectory(lib);
-	File::renameFile(source + plugin, lib);
+	File::renameFile(source + info.plugin, lib);
 
-	for(auto& file: files) {
+	for(auto& file: info.files) {
 		File::ensureDirectory(target + file);
 		File::renameFile(source + file, target + file);
 	}
@@ -215,7 +221,9 @@
 		throw Exception(str(F_("%1% is not a valid plugin") % Util::getFileName(fileName)));
 	}
 
-	checkPlugin(info);
+	if(checkPlugin(info)) {
+		install = true;
+	}
 
 	if(dcMain((install ? ON_INSTALL : ON_LOAD), &dcCore, nullptr) == False) {
 		throw Exception(str(F_("Error loading %1%") % Util::getFileName(fileName)));
@@ -227,15 +235,24 @@
 
 bool PluginManager::isLoaded(const string& guid) {
 	Lock l(cs);
-	auto pluginComp = [&guid](const unique_ptr<PluginInfo>& p) -> bool { return strcmp(p->getInfo().guid, guid.c_str()) == 0; };
-	auto i = std::find_if(plugins.begin(), plugins.end(), pluginComp);
-	return (i != plugins.end());
+	return findPlugin(guid) != plugins.end();
 }
 
-void PluginManager::checkPlugin(const MetaData& info) {
+bool PluginManager::checkPlugin(const MetaData& info) {
+	auto updating = false;
+
 	// Check if user is trying to load a duplicate
-	if(isLoaded(info.guid)) {
-		throw Exception(str(F_("%1% is already installed") % info.name));
+	auto it = findPlugin(info.guid);
+	if(it != plugins.end()) {
+		auto& plugin = *it;
+		if(plugin->getInfo().version < info.version) {
+			LogManager::getInstance()->message(str(F_("Updating the %1% plugin from version %2% to version %3%") %
+				string(plugin->getInfo().name) % plugin->getInfo().version % info.version));
+			plugins.erase(it);
+			updating = true;
+		} else {
+			throw Exception(str(F_("%1% is already installed") % info.name));
+		}
 	}
 
 	// Check API compatibility (this should only block on absolutely wrecking api changes, which generally should not happen)
@@ -251,6 +268,13 @@
 			}
 		}
 	}
+
+	return updating;
+}
+
+vector<unique_ptr<PluginInfo>>::iterator PluginManager::findPlugin(const string& guid) {
+	return std::find_if(plugins.begin(), plugins.end(), [&guid](const unique_ptr<PluginInfo>& p) {
+		return strcmp(p->getInfo().guid, guid.c_str()) == 0; });
 }
 
 void PluginManager::unloadPlugins() {

=== modified file 'dcpp/PluginManager.h'
--- dcpp/PluginManager.h	2013-04-23 17:41:14 +0000
+++ dcpp/PluginManager.h	2013-04-25 18:08:15 +0000
@@ -89,6 +89,7 @@
 
 /** Information about a dcext-packaged plugin that has just been extracted. */
 struct DcextInfo {
+	DcextInfo() : version(0), updating(false) { }
 	string uuid;
 	string name;
 	double version;
@@ -97,6 +98,7 @@
 	string website;
 	string plugin;
 	StringList files;
+	bool updating;
 };
 
 class PluginManager : public Singleton<PluginManager>, private TimerManagerListener,
@@ -108,7 +110,7 @@
 
 	/** Extract a dcext-packaged plugin. Throws on errors. */
 	DcextInfo extract(const string& path);
-	void install(const string& uuid, const string& plugin, const StringList& files);
+	void install(const DcextInfo& info);
 
 	void loadPlugins(function<void (const string&)> f);
 	void loadPlugin(const string& fileName, bool install = false);
@@ -181,8 +183,10 @@
 	void loadSettings() noexcept;
 	void saveSettings() noexcept;
 
-	// Check if the plugin can be loaded; throws if it can't.
-	void checkPlugin(const MetaData& info);
+	/** Check if the plugin can be loaded; throws if it can't.
+	@return Whether the plugin is being updated. */
+	bool checkPlugin(const MetaData& info);
+	vector<unique_ptr<PluginInfo>>::iterator findPlugin(const string& guid);
 
 	// Listeners
 	void on(TimerManagerListener::Second, uint64_t ticks) noexcept { runHook(HOOK_TIMER_SECOND, NULL, &ticks); }

=== modified file 'dcpp/forward.h'
--- dcpp/forward.h	2013-04-13 15:08:45 +0000
+++ dcpp/forward.h	2013-04-25 18:08:15 +0000
@@ -48,6 +48,8 @@
 
 class CRC32Filter;
 
+struct DcextInfo;
+
 class Download;
 typedef Download* DownloadPtr;
 

=== modified file 'win32/PluginInfoDlg.cpp'
--- win32/PluginInfoDlg.cpp	2013-04-23 15:34:45 +0000
+++ win32/PluginInfoDlg.cpp	2013-04-25 18:08:15 +0000
@@ -100,11 +100,12 @@
 		cur->column(0).align = GridInfo::BOTTOM_RIGHT;
 		cur->setSpacing(grid->getSpacing());
 		WinUtil::addDlgButtons(cur,
-			[this, info] { handleOK(info.name, info.uuid, info.plugin, info.files); },
-			[this] { endDialog(IDCANCEL); }).first->setText(T_("Install the plugin"));
+			[this, info] { handleOK(info); },
+			[this] { endDialog(IDCANCEL); })
+			.first->setText(info.updating ? T_("Update the plugin") : T_("Install the plugin"));
 	}
 
-	setText(T_("Adding a plugin"));
+	setText(info.updating ? T_("Updating a plugin") : T_("Adding a plugin"));
 
 	layout();
 	centerWindow();
@@ -112,13 +113,13 @@
 	return false;
 }
 
-void PluginInfoDlg::handleOK(const string& name, const string& uuid, const string& plugin, const StringList& files) {
+void PluginInfoDlg::handleOK(const DcextInfo& info) {
 	try {
-		PluginManager::getInstance()->install(uuid, plugin, files);
+		PluginManager::getInstance()->install(info);
 		endDialog(IDOK);
 
 	} catch(const Exception& e) {
-		error(Text::toT(e.getError()), Text::toT(name));
+		error(Text::toT(e.getError()), Text::toT(info.name));
 		endDialog(IDCANCEL);
 	}
 }

=== modified file 'win32/PluginInfoDlg.h'
--- win32/PluginInfoDlg.h	2013-04-23 15:34:45 +0000
+++ win32/PluginInfoDlg.h	2013-04-25 18:08:15 +0000
@@ -35,7 +35,7 @@
 
 private:
 	bool handleInitDialog(const string& path);
-	void handleOK(const string& name, const string& uuid, const string& plugin, const StringList& files);
+	void handleOK(const DcextInfo& info);
 
 	void layout();
 

=== modified file 'win32/PluginPage.cpp'
--- win32/PluginPage.cpp	2013-04-23 15:34:45 +0000
+++ win32/PluginPage.cpp	2013-04-25 18:08:15 +0000
@@ -132,9 +132,7 @@
 
 	WinUtil::makeColumns(plugins, columns, 1);
 
-	for(auto& plugin: PluginManager::getInstance()->getPluginList()) {
-		addEntry(plugins->size(), plugin->getInfo());
-	}
+	refreshList();
 
 	handleSelectionChanged();
 
@@ -255,27 +253,25 @@
 		.open(path_t))
 	{
 		auto path = Text::fromT(path_t);
-		auto added = false;
 		if(Util::getFileExt(path) == ".dcext") {
-			added = PluginInfoDlg(this, path).run() == IDOK;
+			PluginInfoDlg(this, path).run();
 		} else {
 			try {
 				PluginManager::getInstance()->loadPlugin(path, true);
-				added = true;
 			} catch(const Exception& e) {
 				dwt::MessageBox(this).show(tstring(T_("Cannot install the plugin:")) + _T("\r\n\r\n") + Text::toT(e.getError()),
 					Text::toT(Util::getFileName(path)), dwt::MessageBox::BOX_OK, dwt::MessageBox::BOX_ICONSTOP);
 			}
 		}
 
-		if(added) {
-			auto pos = plugins->size();
-			addEntry(pos, PluginManager::getInstance()->getPlugin(pos)->getInfo());
-		}
+		refreshList();
 	}
 }
 
 void PluginPage::handleConfigurePlugin() {
+	if(plugins->countSelected() != 1)
+		return;
+
 	auto sel = plugins->getSelected();
 	const PluginInfo *p = PluginManager::getInstance()->getPlugin(sel);
 	if(!p->dcMain(ON_CONFIGURE, PluginManager::getInstance()->getCore(), this->handle())) {
@@ -326,6 +322,13 @@
 	plugins->erase(sel);
 }
 
+void PluginPage::refreshList() {
+	plugins->clear();
+	for(auto& plugin: PluginManager::getInstance()->getPluginList()) {
+		addEntry(plugins->size(), plugin->getInfo());
+	}
+}
+
 void PluginPage::addEntry(size_t idx, const MetaData& info) {
 	TStringList row;
 	row.push_back(Text::toT(info.name));

=== modified file 'win32/PluginPage.h'
--- win32/PluginPage.h	2013-04-22 22:31:37 +0000
+++ win32/PluginPage.h	2013-04-25 18:08:15 +0000
@@ -49,6 +49,7 @@
 	void handleMovePluginDown();	
 	void handleRemovePlugin();
 
+	void refreshList();
 	void addEntry(size_t idx, const MetaData& info);
 };