mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
Merge pull request #1012 from pasis/extended_plugin_handling
Extended plugin handling
This commit is contained in:
commit
47dba10975
10
configure.ac
10
configure.ac
@ -159,9 +159,13 @@ CFLAGS="$CFLAGS_RESTORE"
|
||||
AS_IF([test "x$ncurses_cv_wget_wch" != xyes],
|
||||
[AC_MSG_ERROR([ncurses does not support wide characters])])
|
||||
|
||||
### Check for other profanity dependencies
|
||||
### Check for glib libraries
|
||||
PKG_CHECK_MODULES([glib], [glib-2.0 >= 2.40], [],
|
||||
[AC_MSG_ERROR([glib 2.40 or higher is required for profanity])])
|
||||
PKG_CHECK_MODULES([gio], [gio-2.0], [],
|
||||
[AC_MSG_ERROR([libgio-2.0 from glib-2.0 is required for profanity])])
|
||||
|
||||
### Check for other profanity dependencies
|
||||
PKG_CHECK_MODULES([curl], [libcurl], [],
|
||||
[AC_CHECK_LIB([curl], [main], [],
|
||||
[AC_MSG_ERROR([libcurl is required for profanity])])])
|
||||
@ -297,9 +301,9 @@ AS_IF([test "x$PACKAGE_STATUS" = xdevelopment],
|
||||
AS_IF([test "x$PLATFORM" = xosx],
|
||||
[AM_CFLAGS="$AM_CFLAGS -Qunused-arguments"])
|
||||
AM_LDFLAGS="$AM_LDFLAGS -export-dynamic"
|
||||
AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS}"
|
||||
AM_CPPFLAGS="$AM_CPPFLAGS $glib_CFLAGS $gio_CFLAGS $curl_CFLAGS $libnotify_CFLAGS $PYTHON_CPPFLAGS ${GTK_CFLAGS}"
|
||||
AM_CPPFLAGS="$AM_CPPFLAGS -DTHEMES_PATH=\"\\\"$THEMES_PATH\\\"\" -DICONS_PATH=\"\\\"$ICONS_PATH\\\"\""
|
||||
LIBS="$glib_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} -lgio-2.0 $LIBS"
|
||||
LIBS="$glib_LIBS $gio_LIBS $curl_LIBS $libnotify_LIBS $PYTHON_LIBS $PYTHON_LDFLAGS ${GTK_LIBS} $LIBS"
|
||||
|
||||
AC_SUBST(AM_LDFLAGS)
|
||||
AC_SUBST(AM_CFLAGS)
|
||||
|
@ -2084,6 +2084,8 @@ static struct cmd_t command_defs[] =
|
||||
CMD_SUBFUNCS(
|
||||
{ "sourcepath", cmd_plugins_sourcepath },
|
||||
{ "install", cmd_plugins_install },
|
||||
{ "uninstall", cmd_plugins_uninstall },
|
||||
{ "update", cmd_plugins_update },
|
||||
{ "load", cmd_plugins_load },
|
||||
{ "unload", cmd_plugins_unload },
|
||||
{ "reload", cmd_plugins_reload },
|
||||
@ -2095,6 +2097,8 @@ static struct cmd_t command_defs[] =
|
||||
"/plugins sourcepath set <path>",
|
||||
"/plugins sourcepath clear",
|
||||
"/plugins install [<path>]",
|
||||
"/plugins uninstall [<plugin>]",
|
||||
"/plugins update [<path>]",
|
||||
"/plugins unload [<plugin>]",
|
||||
"/plugins load [<plugin>]",
|
||||
"/plugins reload [<plugin>]",
|
||||
@ -2105,6 +2109,8 @@ static struct cmd_t command_defs[] =
|
||||
{ "sourcepath set <path>", "Set the default path to install plugins from, will be used if no arg is passed to /plugins install." },
|
||||
{ "sourcepath clear", "Clear the default plugins source path." },
|
||||
{ "install [<path>]", "Install a plugin, or all plugins found in a directory (recursive). Passing no argument will use the sourcepath if one is set." },
|
||||
{ "uninstall [<plugin>]", "Uninstall a plugin." },
|
||||
{ "update [<path>]", "Updates an installed plugin" },
|
||||
{ "load [<plugin>]", "Load a plugin that already exists in the plugin directory, passing no argument loads all found plugins." },
|
||||
{ "unload [<plugin>]", "Unload a loaded plugin, passing no argument will unload all plugins." },
|
||||
{ "reload [<plugin>]", "Reload a plugin, passing no argument will reload all plugins." },
|
||||
@ -2113,6 +2119,8 @@ static struct cmd_t command_defs[] =
|
||||
"/plugins sourcepath set /home/meee/projects/profanity-plugins",
|
||||
"/plugins install",
|
||||
"/plugins install /home/steveharris/Downloads/metal.py",
|
||||
"/plugins update /home/steveharris/Downloads/metal.py",
|
||||
"/plugins uninstall browser.py",
|
||||
"/plugins load browser.py",
|
||||
"/plugins unload say.py",
|
||||
"/plugins reload wikipedia.py")
|
||||
|
@ -6616,15 +6616,16 @@ cmd_plugins_install(ProfWin *window, const char *const command, gchar **args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GString* error_message = g_string_new(NULL);
|
||||
gchar *plugin_name = g_path_get_basename(path);
|
||||
gboolean result = plugins_install(plugin_name, path);
|
||||
gboolean result = plugins_install(plugin_name, path, error_message);
|
||||
if (result) {
|
||||
cons_show("Plugin installed: %s", plugin_name);
|
||||
} else {
|
||||
cons_show("Failed to install plugin: %s", plugin_name);
|
||||
cons_show("Failed to install plugin: %s. %s", plugin_name, error_message->str);
|
||||
}
|
||||
g_free(plugin_name);
|
||||
|
||||
g_string_free(error_message, TRUE);
|
||||
free(path);
|
||||
return TRUE;
|
||||
}
|
||||
@ -6662,6 +6663,88 @@ cmd_plugins_install(ProfWin *window, const char *const command, gchar **args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cmd_plugins_update(ProfWin *window, const char *const command, gchar **args)
|
||||
{
|
||||
char *path = args[1];
|
||||
if (path == NULL) {
|
||||
char* sourcepath = prefs_get_string(PREF_PLUGINS_SOURCEPATH);
|
||||
if (sourcepath) {
|
||||
path = strdup(sourcepath);
|
||||
prefs_free_string(sourcepath);
|
||||
} else {
|
||||
cons_show("Either a path must be provided or the sourcepath property must be set, see /help plugins");
|
||||
return TRUE;
|
||||
}
|
||||
} else if (path[0] == '~' && path[1] == '/') {
|
||||
if (asprintf(&path, "%s/%s", getenv("HOME"), path+2) == -1) {
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
path = strdup(path);
|
||||
}
|
||||
|
||||
if (access(path, R_OK) != 0) {
|
||||
cons_show("File not found: %s", path);
|
||||
free(path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (is_regular_file(path)) {
|
||||
if (!g_str_has_suffix(path, ".py") && !g_str_has_suffix(path, ".so")) {
|
||||
cons_show("Plugins must have one of the following extensions: '.py' '.so'");
|
||||
free(path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GString* error_message = g_string_new(NULL);
|
||||
gchar *plugin_name = g_path_get_basename(path);
|
||||
if (plugins_unload(plugin_name)) {
|
||||
if (plugins_uninstall(plugin_name)) {
|
||||
if (plugins_install(plugin_name, path, error_message)) {
|
||||
cons_show("Plugin installed: %s", plugin_name);
|
||||
} else {
|
||||
cons_show("Failed to install plugin: %s. %s", plugin_name, error_message->str);
|
||||
}
|
||||
} else {
|
||||
cons_show("Failed to uninstall plugin: %s.", plugin_name);
|
||||
}
|
||||
} else {
|
||||
cons_show("Failed to unload plugin: %s.", plugin_name);
|
||||
}
|
||||
g_free(plugin_name);
|
||||
g_string_free(error_message, TRUE);
|
||||
free(path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (is_dir(path)) {
|
||||
free(path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(path);
|
||||
cons_show("Argument must be a file or directory.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cmd_plugins_uninstall(ProfWin *window, const char *const command, gchar **args)
|
||||
{
|
||||
if (args[1] == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean res = plugins_uninstall(args[1]);
|
||||
if (res) {
|
||||
cons_show("Uninstalled plugin: %s", args[1]);
|
||||
} else {
|
||||
cons_show("Failed to uninstall plugin: %s", args[1]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cmd_plugins_load(ProfWin *window, const char *const command, gchar **args)
|
||||
{
|
||||
|
@ -162,6 +162,8 @@ gboolean cmd_console(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_sourcepath(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_install(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_update(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_uninstall(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_load(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_unload(ProfWin *window, const char *const command, gchar **args);
|
||||
gboolean cmd_plugins_reload(ProfWin *window, const char *const command, gchar **args);
|
||||
|
31
src/common.c
31
src/common.c
@ -46,6 +46,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#ifdef HAVE_NCURSESW_NCURSES_H
|
||||
#include <ncursesw/ncurses.h>
|
||||
@ -105,28 +106,16 @@ mkdir_recursive(const char *dir)
|
||||
}
|
||||
|
||||
gboolean
|
||||
copy_file(const char *const sourcepath, const char *const targetpath)
|
||||
copy_file(const char *const sourcepath, const char *const targetpath, const gboolean overwrite_existing)
|
||||
{
|
||||
int ch;
|
||||
FILE *source = fopen(sourcepath, "rb");
|
||||
if (source == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FILE *target = fopen(targetpath, "wb");
|
||||
if (target == NULL) {
|
||||
fclose(source);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while((ch = fgetc(source)) != EOF) {
|
||||
fputc(ch, target);
|
||||
}
|
||||
|
||||
fclose(source);
|
||||
fclose(target);
|
||||
|
||||
return TRUE;
|
||||
GFile *source = g_file_new_for_path(sourcepath);
|
||||
GFile *dest = g_file_new_for_path(targetpath);
|
||||
GError *error = NULL;
|
||||
GFileCopyFlags flags = overwrite_existing ? G_FILE_COPY_OVERWRITE : G_FILE_COPY_NONE;
|
||||
gboolean success = g_file_copy (source, dest, flags, NULL, NULL, NULL, &error);
|
||||
g_object_unref(source);
|
||||
g_object_unref(dest);
|
||||
return success;
|
||||
}
|
||||
|
||||
char*
|
||||
|
@ -82,7 +82,7 @@ typedef enum {
|
||||
|
||||
gboolean create_dir(char *name);
|
||||
gboolean mkdir_recursive(const char *dir);
|
||||
gboolean copy_file(const char *const src, const char *const target);
|
||||
gboolean copy_file(const char *const src, const char *const target, const gboolean overwrite_existing);
|
||||
char* str_replace(const char *string, const char *substr, const char *replacement);
|
||||
int str_contains(const char str[], int size, char ch);
|
||||
gboolean strtoi_range(char *str, int *saveptr, int min, int max, char **err_msg);
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
@ -149,16 +150,19 @@ plugins_install_all(const char *const path)
|
||||
get_file_paths_recursive(path, &contents);
|
||||
|
||||
GSList *curr = contents;
|
||||
GString *error_message = NULL;
|
||||
while (curr) {
|
||||
error_message = g_string_new(NULL);
|
||||
if (g_str_has_suffix(curr->data, ".py") || g_str_has_suffix(curr->data, ".so")) {
|
||||
gchar *plugin_name = g_path_get_basename(curr->data);
|
||||
if (plugins_install(plugin_name, curr->data)) {
|
||||
if (plugins_install(plugin_name, curr->data, error_message)) {
|
||||
result->installed = g_slist_append(result->installed, strdup(curr->data));
|
||||
} else {
|
||||
result->failed = g_slist_append(result->failed, strdup(curr->data));
|
||||
}
|
||||
}
|
||||
curr = g_slist_next(curr);
|
||||
g_string_free(error_message, TRUE);
|
||||
}
|
||||
|
||||
g_slist_free_full(contents, g_free);
|
||||
@ -167,7 +171,25 @@ plugins_install_all(const char *const path)
|
||||
}
|
||||
|
||||
gboolean
|
||||
plugins_install(const char *const plugin_name, const char *const filename)
|
||||
plugins_uninstall(const char *const plugin_name)
|
||||
{
|
||||
plugins_unload(plugin_name);
|
||||
char *plugins_dir = files_get_data_path(DIR_PLUGINS);
|
||||
GString *target_path = g_string_new(plugins_dir);
|
||||
free(plugins_dir);
|
||||
g_string_append(target_path, "/");
|
||||
g_string_append(target_path, plugin_name);
|
||||
GFile *file = g_file_new_for_path(target_path->str);
|
||||
GError *error = NULL;
|
||||
gboolean result = g_file_delete(file, NULL, &error);
|
||||
g_object_unref(file);
|
||||
g_error_free(error);
|
||||
g_string_free(target_path, TRUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
plugins_install(const char *const plugin_name, const char *const filename, GString *error_message)
|
||||
{
|
||||
char *plugins_dir = files_get_data_path(DIR_PLUGINS);
|
||||
GString *target_path = g_string_new(plugins_dir);
|
||||
@ -175,18 +197,19 @@ plugins_install(const char *const plugin_name, const char *const filename)
|
||||
g_string_append(target_path, "/");
|
||||
g_string_append(target_path, plugin_name);
|
||||
|
||||
ProfPlugin *plugin = g_hash_table_lookup(plugins, plugin_name);
|
||||
if (plugin) {
|
||||
plugins_unload(plugin_name);
|
||||
if (g_file_test (target_path->str, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
log_info("Failed to install plugin: %s, file exists", plugin_name);
|
||||
g_string_assign(error_message, "File exists");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean result = copy_file(filename, target_path->str);
|
||||
gboolean result = copy_file(filename, target_path->str, false);
|
||||
g_string_free(target_path, TRUE);
|
||||
|
||||
if (result) {
|
||||
result = plugins_load(plugin_name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,9 @@ void plugins_shutdown(void);
|
||||
|
||||
void plugins_free_install_result(PluginsInstallResult *result);
|
||||
|
||||
gboolean plugins_install(const char *const plugin_name, const char *const filename);
|
||||
gboolean plugins_install(const char *const plugin_name, const char *const filename, GString * error_message);
|
||||
gboolean plugins_uninstall(const char *const plugin_name);
|
||||
gboolean plugins_update(const char *const plugin_name, const char *const filename, GString * error_message);
|
||||
PluginsInstallResult* plugins_install_all(const char *const path);
|
||||
gboolean plugins_load(const char *const name);
|
||||
GSList* plugins_load_all(void);
|
||||
|
Loading…
Reference in New Issue
Block a user