mirror of
https://github.com/profanity-im/profanity.git
synced 2024-09-01 19:24:15 -04:00
Allow installing plugins from directory
This commit is contained in:
parent
c405367dfe
commit
286fecf38d
@ -6214,49 +6214,77 @@ cmd_xa(ProfWin *window, const char *const command, gchar **args)
|
|||||||
gboolean
|
gboolean
|
||||||
cmd_plugins_install(ProfWin *window, const char *const command, gchar **args)
|
cmd_plugins_install(ProfWin *window, const char *const command, gchar **args)
|
||||||
{
|
{
|
||||||
char *filename = args[1];
|
char *path = args[1];
|
||||||
if (filename == NULL) {
|
if (path == NULL) {
|
||||||
cons_bad_cmd_usage(command);
|
cons_bad_cmd_usage(command);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand ~ to $HOME
|
// expand ~ to $HOME
|
||||||
if (filename[0] == '~' && filename[1] == '/') {
|
if (path[0] == '~' && path[1] == '/') {
|
||||||
if (asprintf(&filename, "%s/%s", getenv("HOME"), filename+2) == -1) {
|
if (asprintf(&path, "%s/%s", getenv("HOME"), path+2) == -1) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
filename = strdup(filename);
|
path = strdup(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (access(filename, R_OK) != 0) {
|
if (access(path, R_OK) != 0) {
|
||||||
cons_show("File not found: %s", filename);
|
cons_show("File not found: %s", path);
|
||||||
free(filename);
|
free(path);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_regular_file(filename)) {
|
if (is_regular_file(path)) {
|
||||||
cons_show("Not a file: %s", filename);
|
if (!g_str_has_suffix(path, ".py") && !g_str_has_suffix(path, ".so")) {
|
||||||
free(filename);
|
cons_show("Plugins must have one of the following extensions: '.py' '.so'");
|
||||||
|
free(path);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *plugin_name = g_path_get_basename(path);
|
||||||
|
gboolean result = plugins_install(plugin_name, path);
|
||||||
|
if (result) {
|
||||||
|
cons_show("Plugin installed: %s", plugin_name);
|
||||||
|
} else {
|
||||||
|
cons_show("Failed to install plugin: %s", plugin_name);
|
||||||
|
}
|
||||||
|
g_free(plugin_name);
|
||||||
|
|
||||||
|
free(path);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_str_has_suffix(filename, ".py") && !g_str_has_suffix(filename, ".so")) {
|
if (is_dir(path)) {
|
||||||
cons_show("Plugins must have one of the following extensions: '.py' '.so'");
|
PluginsInstallResult* result = plugins_install_all(path);
|
||||||
free(filename);
|
if (result->installed || result->failed) {
|
||||||
|
if (result->installed) {
|
||||||
|
cons_show("");
|
||||||
|
cons_show("Installed plugins:");
|
||||||
|
GSList *curr = result->installed;
|
||||||
|
while (curr) {
|
||||||
|
cons_show(" %s", curr->data);
|
||||||
|
curr = g_slist_next(curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result->failed) {
|
||||||
|
cons_show("");
|
||||||
|
cons_show("Failed installs:");
|
||||||
|
GSList *curr = result->failed;
|
||||||
|
while (curr) {
|
||||||
|
cons_show(" %s", curr->data);
|
||||||
|
curr = g_slist_next(curr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cons_show("No plugins found in: %s", path);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
plugins_free_install_result(result);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *plugin_name = g_path_get_basename(filename);
|
cons_show("Argument must be a file or directory.");
|
||||||
gboolean result = plugins_install(plugin_name, filename);
|
|
||||||
if (result) {
|
|
||||||
cons_show("Plugin installed: %s", plugin_name);
|
|
||||||
} else {
|
|
||||||
cons_show("Failed to install plugin: %s", plugin_name);
|
|
||||||
}
|
|
||||||
g_free(plugin_name);
|
|
||||||
|
|
||||||
free(filename);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
src/common.c
42
src/common.c
@ -536,3 +536,45 @@ prof_occurrences(const char *const needle, const char *const haystack, int offse
|
|||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
is_regular_file(const char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
stat(path, &st);
|
||||||
|
return S_ISREG(st.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
is_dir(const char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
stat(path, &st);
|
||||||
|
return S_ISDIR(st.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_file_paths_recursive(const char *path, GSList **contents)
|
||||||
|
{
|
||||||
|
if (!is_dir(path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDir* directory = g_dir_open(path, 0, NULL);
|
||||||
|
const gchar *entry = g_dir_read_name(directory);
|
||||||
|
while (entry) {
|
||||||
|
GString *full = g_string_new(path);
|
||||||
|
if (!g_str_has_suffix(full->str, "/")) {
|
||||||
|
g_string_append(full, "/");
|
||||||
|
}
|
||||||
|
g_string_append(full, entry);
|
||||||
|
|
||||||
|
if (is_dir(full->str)) {
|
||||||
|
get_file_paths_recursive(full->str, contents);
|
||||||
|
} else if (is_regular_file(full->str)) {
|
||||||
|
*contents = g_slist_append(*contents, full->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_free(full, FALSE);
|
||||||
|
entry = g_dir_read_name(directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -123,4 +123,8 @@ gboolean is_notify_enabled(void);
|
|||||||
GSList* prof_occurrences(const char *const needle, const char *const haystack, int offset, gboolean whole_word,
|
GSList* prof_occurrences(const char *const needle, const char *const haystack, int offset, gboolean whole_word,
|
||||||
GSList **result);
|
GSList **result);
|
||||||
|
|
||||||
|
int is_regular_file(const char *path);
|
||||||
|
int is_dir(const char *path);
|
||||||
|
void get_file_paths_recursive(const char *directory, GSList **contents);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,6 +129,43 @@ plugins_init(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
plugins_free_install_result(PluginsInstallResult *result)
|
||||||
|
{
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_slist_free_full(result->installed, free);
|
||||||
|
g_slist_free_full(result->failed, free);
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginsInstallResult*
|
||||||
|
plugins_install_all(const char *const path)
|
||||||
|
{
|
||||||
|
PluginsInstallResult *result = malloc(sizeof(PluginsInstallResult));
|
||||||
|
result->installed = NULL;
|
||||||
|
result->failed = NULL;
|
||||||
|
GSList *contents = NULL;
|
||||||
|
get_file_paths_recursive(path, &contents);
|
||||||
|
|
||||||
|
GSList *curr = contents;
|
||||||
|
while (curr) {
|
||||||
|
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)) {
|
||||||
|
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_slist_free_full(contents, g_free);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
plugins_install(const char *const plugin_name, const char *const filename)
|
plugins_install(const char *const plugin_name, const char *const filename)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,11 @@ typedef enum {
|
|||||||
LANG_C
|
LANG_C
|
||||||
} lang_t;
|
} lang_t;
|
||||||
|
|
||||||
|
typedef struct prof_plugins_install_t {
|
||||||
|
GSList *installed;
|
||||||
|
GSList *failed;
|
||||||
|
} PluginsInstallResult;
|
||||||
|
|
||||||
typedef struct prof_plugin_t {
|
typedef struct prof_plugin_t {
|
||||||
char *name;
|
char *name;
|
||||||
lang_t lang;
|
lang_t lang;
|
||||||
@ -107,7 +112,10 @@ char* plugins_autocomplete(const char *const input);
|
|||||||
void plugins_reset_autocomplete(void);
|
void plugins_reset_autocomplete(void);
|
||||||
void plugins_shutdown(void);
|
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);
|
||||||
|
PluginsInstallResult* plugins_install_all(const char *const path);
|
||||||
gboolean plugins_load(const char *const name);
|
gboolean plugins_load(const char *const name);
|
||||||
GSList* plugins_load_all(void);
|
GSList* plugins_load_all(void);
|
||||||
gboolean plugins_unload(const char *const name);
|
gboolean plugins_unload(const char *const name);
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#include "config/preferences.h"
|
#include "config/preferences.h"
|
||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
#include "ui/window.h"
|
#include "ui/window.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
#define FALLBACK_MIMETYPE "application/octet-stream"
|
#define FALLBACK_MIMETYPE "application/octet-stream"
|
||||||
#define FALLBACK_CONTENTTYPE_HEADER "Content-Type: application/octet-stream"
|
#define FALLBACK_CONTENTTYPE_HEADER "Content-Type: application/octet-stream"
|
||||||
@ -330,10 +331,3 @@ off_t file_size(const char* const filename)
|
|||||||
stat(filename, &st);
|
stat(filename, &st);
|
||||||
return st.st_size;
|
return st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_regular_file(const char *filename)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
stat(filename, &st);
|
|
||||||
return S_ISREG(st.st_mode);
|
|
||||||
}
|
|
||||||
|
@ -62,6 +62,5 @@ void* http_file_put(void *userdata);
|
|||||||
|
|
||||||
char* file_mime_type(const char* const file_name);
|
char* file_mime_type(const char* const file_name);
|
||||||
off_t file_size(const char* const file_name);
|
off_t file_size(const char* const file_name);
|
||||||
int is_regular_file(const char *filename);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,5 @@ void* http_file_put(void *userdata) {}
|
|||||||
|
|
||||||
char* file_mime_type(const char* const file_name) {}
|
char* file_mime_type(const char* const file_name) {}
|
||||||
off_t file_size(const char* const file_name) {}
|
off_t file_size(const char* const file_name) {}
|
||||||
int is_regular_file(const char *filename) {}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user