feat: run external tools in background tasks
This commit is contained in:
parent
dc45abaf0d
commit
2ffbdec888
7 changed files with 4837 additions and 2 deletions
15
Makefile
15
Makefile
|
|
@ -44,6 +44,7 @@ TEST_BACKGROUND_TASK := tests/test_background_task
|
||||||
TEST_TASK_MANAGER := tests/test_task_manager
|
TEST_TASK_MANAGER := tests/test_task_manager
|
||||||
TEST_TOOL_REGISTRY := tests/test_tool_registry
|
TEST_TOOL_REGISTRY := tests/test_tool_registry
|
||||||
TEST_TOOL_PROCESS := tests/test_tool_process
|
TEST_TOOL_PROCESS := tests/test_tool_process
|
||||||
|
TEST_TOOL_TASK := tests/test_tool_task
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
|
|
@ -162,6 +163,13 @@ $(TEST_TOOL_PROCESS): \
|
||||||
src/core/tool_process.c
|
src/core/tool_process.c
|
||||||
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_TOOL_TASK): \
|
||||||
|
tests/test_tool_task.c \
|
||||||
|
src/core/tool_task.c \
|
||||||
|
src/core/tool_registry.c \
|
||||||
|
src/core/tool_process.c \
|
||||||
|
src/core/background_task.c
|
||||||
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS)
|
||||||
|
|
||||||
test: \
|
test: \
|
||||||
$(TEST_NODE) \
|
$(TEST_NODE) \
|
||||||
|
|
@ -178,7 +186,8 @@ test: \
|
||||||
$(TEST_BACKGROUND_TASK) \
|
$(TEST_BACKGROUND_TASK) \
|
||||||
$(TEST_TASK_MANAGER) \
|
$(TEST_TASK_MANAGER) \
|
||||||
$(TEST_TOOL_REGISTRY) \
|
$(TEST_TOOL_REGISTRY) \
|
||||||
$(TEST_TOOL_PROCESS)
|
$(TEST_TOOL_PROCESS) \
|
||||||
|
$(TEST_TOOL_TASK)
|
||||||
@echo "Exécution des tests..."
|
@echo "Exécution des tests..."
|
||||||
@./$(TEST_NODE)
|
@./$(TEST_NODE)
|
||||||
@./$(TEST_TREE_MODEL)
|
@./$(TEST_TREE_MODEL)
|
||||||
|
|
@ -195,6 +204,7 @@ test: \
|
||||||
@$(TEST_TASK_MANAGER)
|
@$(TEST_TASK_MANAGER)
|
||||||
@$(TEST_TOOL_REGISTRY)
|
@$(TEST_TOOL_REGISTRY)
|
||||||
@$(TEST_TOOL_PROCESS)
|
@$(TEST_TOOL_PROCESS)
|
||||||
|
@$(TEST_TOOL_TASK)
|
||||||
@echo "Tous les tests sont valides."
|
@echo "Tous les tests sont valides."
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
|
|
@ -219,6 +229,7 @@ clean:
|
||||||
$(TEST_BACKGROUND_TASK) \
|
$(TEST_BACKGROUND_TASK) \
|
||||||
$(TEST_TASK_MANAGER) \
|
$(TEST_TASK_MANAGER) \
|
||||||
$(TEST_TOOL_REGISTRY) \
|
$(TEST_TOOL_REGISTRY) \
|
||||||
$(TEST_TOOL_PROCESS)
|
$(TEST_TOOL_PROCESS) \
|
||||||
|
$(TEST_TOOL_TASK)
|
||||||
|
|
||||||
.PHONY: clean run test
|
.PHONY: clean run test
|
||||||
|
|
|
||||||
1083
docs/tickets/open/TICKET-038.md
Normal file
1083
docs/tickets/open/TICKET-038.md
Normal file
File diff suppressed because it is too large
Load diff
299
include/core/tool_task.h
Normal file
299
include/core/tool_task.h
Normal file
|
|
@ -0,0 +1,299 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file tool_task.h
|
||||||
|
* @brief Exécution d'un outil externe dans une tâche d'arrière-plan.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_TOOL_TASK_H
|
||||||
|
#define LABFY_INVESTIGATION_TOOL_TASK_H
|
||||||
|
|
||||||
|
#include "core/background_task.h"
|
||||||
|
#include "core/tool_process.h"
|
||||||
|
#include "core/tool_registry.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erreurs produites par ToolTask.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Un argument transmis au module est invalide.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_INVALID_ARGUMENT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L'identifiant demandé n'existe pas dans le registre.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_TOOL_NOT_FOUND,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* La disponibilité de l'outil n'a pas encore été vérifiée.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_TOOL_NOT_CHECKED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L'outil a été vérifié mais son exécutable est absent.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_TOOL_MISSING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L'outil est disponible, mais son chemin résolu est invalide.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_INVALID_TOOL_STATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* La BackgroundTask n'a pas pu être créée.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_TASK_CREATION,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* La BackgroundTask n'a pas pu être démarrée.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_TASK_START,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* L'exécution externe a échoué.
|
||||||
|
*/
|
||||||
|
TOOL_TASK_ERROR_PROCESS
|
||||||
|
} ToolTaskError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Domaine d'erreur de ToolTask.
|
||||||
|
*/
|
||||||
|
#define TOOL_TASK_ERROR \
|
||||||
|
tool_task_error_quark()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exécution préparée d'un outil externe.
|
||||||
|
*
|
||||||
|
* Cette structure possède :
|
||||||
|
*
|
||||||
|
* - la BackgroundTask avant son transfert éventuel à d'autres modules ;
|
||||||
|
* - les données du worker avant le démarrage ;
|
||||||
|
* - les copies de l'identifiant, du chemin et des arguments.
|
||||||
|
*/
|
||||||
|
typedef struct ToolTask ToolTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Résultat opaque produit par une ToolTask.
|
||||||
|
*/
|
||||||
|
typedef struct ToolTaskResult ToolTaskResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le domaine d'erreur de ToolTask.
|
||||||
|
*
|
||||||
|
* @return Quark GLib du domaine d'erreur.
|
||||||
|
*/
|
||||||
|
GQuark tool_task_error_quark(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prépare une tâche exécutant un outil enregistré.
|
||||||
|
*
|
||||||
|
* Cette fonction ne démarre pas la tâche.
|
||||||
|
*
|
||||||
|
* Toutes les informations nécessaires à l'exécution sont copiées. Le
|
||||||
|
* ToolTask créé ne dépend donc plus de la durée de vie du registre ni des
|
||||||
|
* chaînes fournies.
|
||||||
|
*
|
||||||
|
* L'outil doit avoir été vérifié avec tool_registry_refresh() et être dans
|
||||||
|
* l'état TOOL_AVAILABILITY_AVAILABLE.
|
||||||
|
*
|
||||||
|
* @param tool_registry Registre contenant l'outil.
|
||||||
|
* @param tool_identifier Identifiant interne de l'outil.
|
||||||
|
* @param task_title Titre affiché pour la BackgroundTask.
|
||||||
|
* @param arguments Tableau d'arguments terminé par NULL, ou NULL.
|
||||||
|
* @param working_directory Dossier de travail facultatif, ou NULL.
|
||||||
|
* @param error Emplacement facultatif pour l'erreur.
|
||||||
|
*
|
||||||
|
* @return Nouveau ToolTask, ou NULL en cas d'échec.
|
||||||
|
*/
|
||||||
|
ToolTask *tool_task_new(
|
||||||
|
const ToolRegistry *tool_registry,
|
||||||
|
const char *tool_identifier,
|
||||||
|
const char *task_title,
|
||||||
|
const char *const arguments[],
|
||||||
|
const char *working_directory,
|
||||||
|
GError **error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère une ToolTask.
|
||||||
|
*
|
||||||
|
* Avant le démarrage, cette fonction libère également les données préparées
|
||||||
|
* pour le worker.
|
||||||
|
*
|
||||||
|
* Après un démarrage réussi, les données du worker appartiennent à la
|
||||||
|
* BackgroundTask.
|
||||||
|
*
|
||||||
|
* La fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param tool_task Tâche à libérer.
|
||||||
|
*/
|
||||||
|
void tool_task_free(
|
||||||
|
ToolTask *tool_task
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne la BackgroundTask associée.
|
||||||
|
*
|
||||||
|
* Le pointeur retourné est emprunté. Il reste valide tant que ToolTask
|
||||||
|
* conserve sa propre référence ou qu'un autre propriétaire, par exemple
|
||||||
|
* TaskManager, conserve une référence.
|
||||||
|
*
|
||||||
|
* Cette fonction permet notamment d'ajouter la tâche au TaskManager avant
|
||||||
|
* son démarrage.
|
||||||
|
*
|
||||||
|
* @param tool_task ToolTask consultée.
|
||||||
|
*
|
||||||
|
* @return BackgroundTask associée, ou NULL.
|
||||||
|
*/
|
||||||
|
BackgroundTask *tool_task_get_background_task(
|
||||||
|
const ToolTask *tool_task
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Démarre l'exécution asynchrone de l'outil.
|
||||||
|
*
|
||||||
|
* Si le démarrage réussit :
|
||||||
|
*
|
||||||
|
* - la BackgroundTask devient propriétaire des données du worker ;
|
||||||
|
* - ToolTask ne doit plus les libérer ;
|
||||||
|
* - ToolTask peut être libérée dès qu'un autre propriétaire conserve une
|
||||||
|
* référence sur la BackgroundTask.
|
||||||
|
*
|
||||||
|
* Si le démarrage échoue, ToolTask conserve la propriété de ses données.
|
||||||
|
*
|
||||||
|
* @param tool_task ToolTask à démarrer.
|
||||||
|
* @param completion_callback Callback final facultatif.
|
||||||
|
* @param completion_data Données facultatives du callback.
|
||||||
|
* @param completion_data_destroy Destructeur facultatif des données.
|
||||||
|
* @param error Emplacement facultatif pour l'erreur.
|
||||||
|
*
|
||||||
|
* @return TRUE si la tâche a été démarrée, sinon FALSE.
|
||||||
|
*/
|
||||||
|
gboolean tool_task_start(
|
||||||
|
ToolTask *tool_task,
|
||||||
|
BackgroundTaskCompletionCallback completion_callback,
|
||||||
|
gpointer completion_data,
|
||||||
|
GDestroyNotify completion_data_destroy,
|
||||||
|
GError **error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le résultat d'une BackgroundTask créée par ToolTask.
|
||||||
|
*
|
||||||
|
* Cette fonction doit uniquement être appelée avec une BackgroundTask
|
||||||
|
* obtenue par tool_task_get_background_task().
|
||||||
|
*
|
||||||
|
* Le pointeur retourné est emprunté et appartient à la BackgroundTask.
|
||||||
|
* Il n'est disponible qu'après l'état BACKGROUND_TASK_STATE_COMPLETED.
|
||||||
|
*
|
||||||
|
* @param background_task Tâche créée par ToolTask.
|
||||||
|
*
|
||||||
|
* @return Résultat ToolTask emprunté, ou NULL.
|
||||||
|
*/
|
||||||
|
const ToolTaskResult *tool_task_result_from_background_task(
|
||||||
|
const BackgroundTask *background_task
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère un résultat ToolTask.
|
||||||
|
*
|
||||||
|
* Cette fonction est normalement transmise comme destructeur du résultat à
|
||||||
|
* background_task_start().
|
||||||
|
*
|
||||||
|
* La fonction accepte NULL.
|
||||||
|
*
|
||||||
|
* @param result Résultat à libérer.
|
||||||
|
*/
|
||||||
|
void tool_task_result_free(
|
||||||
|
ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne l'identifiant de l'outil exécuté.
|
||||||
|
*
|
||||||
|
* La chaîne retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
*
|
||||||
|
* @return Identifiant de l'outil, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *tool_task_result_get_tool_identifier(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le chemin de l'exécutable utilisé.
|
||||||
|
*
|
||||||
|
* La chaîne retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
*
|
||||||
|
* @return Chemin de l'exécutable, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *tool_task_result_get_executable_path(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le nombre d'arguments transmis à l'outil.
|
||||||
|
*
|
||||||
|
* Le chemin de l'exécutable, utilisé comme argv[0], n'est pas compté.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
*
|
||||||
|
* @return Nombre d'arguments.
|
||||||
|
*/
|
||||||
|
gsize tool_task_result_get_argument_count(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne un argument transmis à l'outil.
|
||||||
|
*
|
||||||
|
* La chaîne retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
* @param index Index de l'argument.
|
||||||
|
*
|
||||||
|
* @return Argument correspondant, ou NULL si l'index est invalide.
|
||||||
|
*/
|
||||||
|
const char *tool_task_result_get_argument(
|
||||||
|
const ToolTaskResult *result,
|
||||||
|
gsize index
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le dossier de travail utilisé.
|
||||||
|
*
|
||||||
|
* La chaîne retournée est empruntée.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
*
|
||||||
|
* @return Dossier de travail, ou NULL.
|
||||||
|
*/
|
||||||
|
const char *tool_task_result_get_working_directory(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retourne le résultat brut du processus externe.
|
||||||
|
*
|
||||||
|
* Le pointeur retourné est emprunté et ne doit pas être libéré.
|
||||||
|
*
|
||||||
|
* @param result Résultat consulté.
|
||||||
|
*
|
||||||
|
* @return Résultat ToolProcess, ou NULL.
|
||||||
|
*/
|
||||||
|
const ToolProcessResult *tool_task_result_get_process_result(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
Binary file not shown.
981
src/core/tool_task.c
Normal file
981
src/core/tool_task.c
Normal file
|
|
@ -0,0 +1,981 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file tool_task.c
|
||||||
|
* @brief Exécution d'un outil externe dans une tâche d'arrière-plan.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "core/tool_task.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct ToolTaskWorkerData
|
||||||
|
* @brief Données privées transmises au worker.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *tool_identifier;
|
||||||
|
char *tool_display_name;
|
||||||
|
char *executable_path;
|
||||||
|
|
||||||
|
char **arguments;
|
||||||
|
gsize argument_count;
|
||||||
|
|
||||||
|
char *working_directory;
|
||||||
|
} ToolTaskWorkerData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct ToolTask
|
||||||
|
* @brief Exécution externe préparée.
|
||||||
|
*/
|
||||||
|
struct ToolTask
|
||||||
|
{
|
||||||
|
BackgroundTask *background_task;
|
||||||
|
ToolTaskWorkerData *worker_data;
|
||||||
|
|
||||||
|
gboolean started;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct ToolTaskResult
|
||||||
|
* @brief Résultat d'une exécution externe en arrière-plan.
|
||||||
|
*/
|
||||||
|
struct ToolTaskResult
|
||||||
|
{
|
||||||
|
char *tool_identifier;
|
||||||
|
char *executable_path;
|
||||||
|
|
||||||
|
char **arguments;
|
||||||
|
gsize argument_count;
|
||||||
|
|
||||||
|
char *working_directory;
|
||||||
|
|
||||||
|
ToolProcessResult *process_result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vérifie qu'une chaîne est définie et non vide.
|
||||||
|
*
|
||||||
|
* @param text Chaîne à vérifier.
|
||||||
|
*
|
||||||
|
* @return TRUE si la chaîne est valide.
|
||||||
|
*/
|
||||||
|
static gboolean tool_task_string_is_valid(
|
||||||
|
const char *text
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return text != NULL &&
|
||||||
|
text[0] != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Duplique un tableau d'arguments terminé par NULL.
|
||||||
|
*
|
||||||
|
* Un tableau vide terminé par NULL est créé lorsque arguments vaut NULL.
|
||||||
|
*
|
||||||
|
* @param arguments Arguments à copier, ou NULL.
|
||||||
|
* @param out_argument_count Emplacement recevant le nombre d'arguments.
|
||||||
|
*
|
||||||
|
* @return Nouveau tableau terminé par NULL.
|
||||||
|
*/
|
||||||
|
static char **tool_task_duplicate_arguments(
|
||||||
|
const char *const arguments[],
|
||||||
|
gsize *out_argument_count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char **arguments_copy = NULL;
|
||||||
|
|
||||||
|
gsize argument_count = 0;
|
||||||
|
gsize argument_index = 0;
|
||||||
|
|
||||||
|
if (out_argument_count != NULL)
|
||||||
|
{
|
||||||
|
*out_argument_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments != NULL)
|
||||||
|
{
|
||||||
|
while (arguments[argument_count] != NULL)
|
||||||
|
{
|
||||||
|
argument_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments_copy = g_new0(
|
||||||
|
char *,
|
||||||
|
argument_count + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
for (argument_index = 0;
|
||||||
|
argument_index < argument_count;
|
||||||
|
argument_index++)
|
||||||
|
{
|
||||||
|
arguments_copy[argument_index] =
|
||||||
|
g_strdup(
|
||||||
|
arguments[argument_index]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments_copy[argument_count] = NULL;
|
||||||
|
|
||||||
|
if (out_argument_count != NULL)
|
||||||
|
{
|
||||||
|
*out_argument_count =
|
||||||
|
argument_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arguments_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Libère les données privées du worker.
|
||||||
|
*
|
||||||
|
* @param user_data Pointeur vers ToolTaskWorkerData.
|
||||||
|
*/
|
||||||
|
static void tool_task_worker_data_free(
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ToolTaskWorkerData *worker_data =
|
||||||
|
user_data;
|
||||||
|
|
||||||
|
if (worker_data == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&worker_data->tool_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&worker_data->tool_display_name,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&worker_data->executable_path,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&worker_data->arguments,
|
||||||
|
g_strfreev
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&worker_data->working_directory,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
worker_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adapte tool_task_result_free() à GDestroyNotify.
|
||||||
|
*
|
||||||
|
* @param user_data Pointeur vers ToolTaskResult.
|
||||||
|
*/
|
||||||
|
static void tool_task_result_destroy(
|
||||||
|
gpointer user_data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tool_task_result_free(
|
||||||
|
user_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Produit une erreur ToolTask avec une cause facultative.
|
||||||
|
*
|
||||||
|
* @param error Emplacement facultatif pour l'erreur.
|
||||||
|
* @param error_code Code ToolTask.
|
||||||
|
* @param context_message Description de l'échec.
|
||||||
|
* @param cause Erreur d'origine facultative.
|
||||||
|
*/
|
||||||
|
static void tool_task_set_wrapped_error(
|
||||||
|
GError **error,
|
||||||
|
ToolTaskError error_code,
|
||||||
|
const char *context_message,
|
||||||
|
const GError *cause
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const char *cause_message = NULL;
|
||||||
|
|
||||||
|
if (cause == NULL ||
|
||||||
|
cause->message == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
error_code,
|
||||||
|
context_message
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cause_message = cause->message;
|
||||||
|
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
error_code,
|
||||||
|
"%s : %s",
|
||||||
|
context_message,
|
||||||
|
cause_message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Crée le résultat ToolTask à partir des données du worker.
|
||||||
|
*
|
||||||
|
* La fonction devient propriétaire de process_result.
|
||||||
|
*
|
||||||
|
* @param worker_data Données de l'exécution.
|
||||||
|
* @param process_result Résultat brut du processus.
|
||||||
|
*
|
||||||
|
* @return Nouveau résultat.
|
||||||
|
*/
|
||||||
|
static ToolTaskResult *tool_task_result_new(
|
||||||
|
const ToolTaskWorkerData *worker_data,
|
||||||
|
ToolProcessResult *process_result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ToolTaskResult *task_result = NULL;
|
||||||
|
|
||||||
|
if (worker_data == NULL ||
|
||||||
|
process_result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_result = g_new0(
|
||||||
|
ToolTaskResult,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result->tool_identifier =
|
||||||
|
g_strdup(
|
||||||
|
worker_data->tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result->executable_path =
|
||||||
|
g_strdup(
|
||||||
|
worker_data->executable_path
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result->arguments =
|
||||||
|
tool_task_duplicate_arguments(
|
||||||
|
(const char *const *)
|
||||||
|
worker_data->arguments,
|
||||||
|
&task_result->argument_count
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result->working_directory =
|
||||||
|
g_strdup(
|
||||||
|
worker_data->working_directory
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result->process_result =
|
||||||
|
process_result;
|
||||||
|
|
||||||
|
return task_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Exécute l'outil externe dans le thread secondaire.
|
||||||
|
*
|
||||||
|
* @param background_task Tâche en cours.
|
||||||
|
* @param cancellable Objet d'annulation.
|
||||||
|
* @param worker_data_pointer Données privées du worker.
|
||||||
|
* @param result Emplacement recevant ToolTaskResult.
|
||||||
|
* @param error Emplacement recevant une erreur.
|
||||||
|
*
|
||||||
|
* @return TRUE lorsqu'un résultat exploitable a été produit.
|
||||||
|
*/
|
||||||
|
static gboolean tool_task_worker(
|
||||||
|
BackgroundTask *background_task,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
gpointer worker_data_pointer,
|
||||||
|
gpointer *result,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ToolTaskWorkerData *worker_data =
|
||||||
|
worker_data_pointer;
|
||||||
|
|
||||||
|
ToolProcessResult *process_result = NULL;
|
||||||
|
ToolTaskResult *task_result = NULL;
|
||||||
|
|
||||||
|
GError *process_error = NULL;
|
||||||
|
|
||||||
|
char *execution_status = NULL;
|
||||||
|
char *final_status = NULL;
|
||||||
|
|
||||||
|
gboolean process_success = FALSE;
|
||||||
|
|
||||||
|
if (background_task == NULL ||
|
||||||
|
cancellable == NULL ||
|
||||||
|
worker_data == NULL ||
|
||||||
|
result == NULL ||
|
||||||
|
error == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Les arguments du worker ToolTask sont invalides."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
|
|
||||||
|
background_task_report_progress(
|
||||||
|
background_task,
|
||||||
|
0.0,
|
||||||
|
"Préparation de l'exécution"
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Une annulation demandée avant le lancement doit être transmise
|
||||||
|
* sous la forme attendue par BackgroundTask.
|
||||||
|
*/
|
||||||
|
if (g_cancellable_set_error_if_cancelled(
|
||||||
|
cancellable,
|
||||||
|
error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
execution_status = g_strdup_printf(
|
||||||
|
"Exécution de %s",
|
||||||
|
tool_task_string_is_valid(
|
||||||
|
worker_data->tool_display_name
|
||||||
|
)
|
||||||
|
? worker_data->tool_display_name
|
||||||
|
: worker_data->tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
background_task_report_progress(
|
||||||
|
background_task,
|
||||||
|
0.1,
|
||||||
|
execution_status
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
execution_status
|
||||||
|
);
|
||||||
|
|
||||||
|
execution_status = NULL;
|
||||||
|
|
||||||
|
process_success = tool_process_run(
|
||||||
|
worker_data->executable_path,
|
||||||
|
(const char *const *)
|
||||||
|
worker_data->arguments,
|
||||||
|
worker_data->working_directory,
|
||||||
|
cancellable,
|
||||||
|
&process_result,
|
||||||
|
&process_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!process_success)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* BackgroundTask reconnaît une annulation lorsque le domaine
|
||||||
|
* d'erreur est G_IO_ERROR et le code G_IO_ERROR_CANCELLED.
|
||||||
|
*/
|
||||||
|
if (process_error != NULL &&
|
||||||
|
g_error_matches(
|
||||||
|
process_error,
|
||||||
|
TOOL_PROCESS_ERROR,
|
||||||
|
TOOL_PROCESS_ERROR_CANCELLED
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_CANCELLED,
|
||||||
|
"%s",
|
||||||
|
process_error->message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tool_task_set_wrapped_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR_PROCESS,
|
||||||
|
"L'exécution de l'outil externe a échoué",
|
||||||
|
process_error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&process_error
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process_result == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_PROCESS,
|
||||||
|
"ToolProcess n'a produit aucun résultat exploitable."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
background_task_report_progress(
|
||||||
|
background_task,
|
||||||
|
0.9,
|
||||||
|
"Traitement du résultat"
|
||||||
|
);
|
||||||
|
|
||||||
|
task_result = tool_task_result_new(
|
||||||
|
worker_data,
|
||||||
|
process_result
|
||||||
|
);
|
||||||
|
|
||||||
|
if (task_result == NULL)
|
||||||
|
{
|
||||||
|
tool_process_result_free(
|
||||||
|
process_result
|
||||||
|
);
|
||||||
|
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_PROCESS,
|
||||||
|
"Le résultat de l'outil n'a pas pu être construit."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ToolTaskResult possède maintenant ToolProcessResult.
|
||||||
|
*/
|
||||||
|
process_result = NULL;
|
||||||
|
|
||||||
|
if (tool_process_result_is_success(
|
||||||
|
task_result->process_result
|
||||||
|
))
|
||||||
|
{
|
||||||
|
final_status = g_strdup(
|
||||||
|
"Exécution terminée avec succès"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (tool_process_result_exited_normally(
|
||||||
|
task_result->process_result
|
||||||
|
))
|
||||||
|
{
|
||||||
|
final_status = g_strdup_printf(
|
||||||
|
"Exécution terminée avec le code %d",
|
||||||
|
tool_process_result_get_exit_status(
|
||||||
|
task_result->process_result
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (tool_process_result_was_signaled(
|
||||||
|
task_result->process_result
|
||||||
|
))
|
||||||
|
{
|
||||||
|
final_status = g_strdup_printf(
|
||||||
|
"Exécution terminée par le signal %d",
|
||||||
|
tool_process_result_get_termination_signal(
|
||||||
|
task_result->process_result
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final_status = g_strdup(
|
||||||
|
"Exécution terminée"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
background_task_report_progress(
|
||||||
|
background_task,
|
||||||
|
1.0,
|
||||||
|
final_status
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
final_status
|
||||||
|
);
|
||||||
|
|
||||||
|
*result = task_result;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GQuark tool_task_error_quark(void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string(
|
||||||
|
"labfy-investigation-tool-task-error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTask *tool_task_new(
|
||||||
|
const ToolRegistry *tool_registry,
|
||||||
|
const char *tool_identifier,
|
||||||
|
const char *task_title,
|
||||||
|
const char *const arguments[],
|
||||||
|
const char *working_directory,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ToolTask *tool_task = NULL;
|
||||||
|
ToolTaskWorkerData *worker_data = NULL;
|
||||||
|
|
||||||
|
const ToolInfo *tool_info = NULL;
|
||||||
|
|
||||||
|
const char *tool_display_name = NULL;
|
||||||
|
const char *executable_path = NULL;
|
||||||
|
|
||||||
|
ToolAvailability availability;
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
error == NULL || *error == NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tool_registry == NULL ||
|
||||||
|
!tool_task_string_is_valid(
|
||||||
|
tool_identifier
|
||||||
|
) ||
|
||||||
|
!tool_task_string_is_valid(
|
||||||
|
task_title
|
||||||
|
) ||
|
||||||
|
(working_directory != NULL &&
|
||||||
|
working_directory[0] == '\0'))
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Les arguments fournis à ToolTask sont invalides."
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_info = tool_registry_find(
|
||||||
|
tool_registry,
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tool_info == NULL)
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_TOOL_NOT_FOUND,
|
||||||
|
"Aucun outil portant l'identifiant '%s' n'est enregistré.",
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
availability = tool_info_get_availability(
|
||||||
|
tool_info
|
||||||
|
);
|
||||||
|
|
||||||
|
if (availability ==
|
||||||
|
TOOL_AVAILABILITY_UNKNOWN)
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_TOOL_NOT_CHECKED,
|
||||||
|
"La disponibilité de l'outil '%s' n'a pas été vérifiée.",
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (availability ==
|
||||||
|
TOOL_AVAILABILITY_MISSING)
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_TOOL_MISSING,
|
||||||
|
"L'outil '%s' est absent de la machine.",
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
executable_path =
|
||||||
|
tool_info_get_resolved_path(
|
||||||
|
tool_info
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!tool_task_string_is_valid(
|
||||||
|
executable_path
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_set_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_INVALID_TOOL_STATE,
|
||||||
|
"L'outil '%s' est disponible mais ne possède aucun chemin.",
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_display_name =
|
||||||
|
tool_info_get_display_name(
|
||||||
|
tool_info
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data = g_new0(
|
||||||
|
ToolTaskWorkerData,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data->tool_identifier =
|
||||||
|
g_strdup(
|
||||||
|
tool_identifier
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data->tool_display_name =
|
||||||
|
g_strdup(
|
||||||
|
tool_display_name
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data->executable_path =
|
||||||
|
g_strdup(
|
||||||
|
executable_path
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data->arguments =
|
||||||
|
tool_task_duplicate_arguments(
|
||||||
|
arguments,
|
||||||
|
&worker_data->argument_count
|
||||||
|
);
|
||||||
|
|
||||||
|
worker_data->working_directory =
|
||||||
|
g_strdup(
|
||||||
|
working_directory
|
||||||
|
);
|
||||||
|
|
||||||
|
tool_task = g_new0(
|
||||||
|
ToolTask,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
tool_task->background_task =
|
||||||
|
background_task_new(
|
||||||
|
task_title
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tool_task->background_task == NULL)
|
||||||
|
{
|
||||||
|
tool_task_worker_data_free(
|
||||||
|
worker_data
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
tool_task
|
||||||
|
);
|
||||||
|
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_TASK_CREATION,
|
||||||
|
"La tâche d'arrière-plan n'a pas pu être créée."
|
||||||
|
);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_task->worker_data =
|
||||||
|
worker_data;
|
||||||
|
|
||||||
|
tool_task->started =
|
||||||
|
FALSE;
|
||||||
|
|
||||||
|
return tool_task;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tool_task_free(
|
||||||
|
ToolTask *tool_task
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tool_task == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avant le démarrage, ToolTask possède les données du worker.
|
||||||
|
*
|
||||||
|
* Après un démarrage réussi, le pointeur vaut NULL car la propriété
|
||||||
|
* a été transférée à BackgroundTask.
|
||||||
|
*/
|
||||||
|
if (tool_task->worker_data != NULL)
|
||||||
|
{
|
||||||
|
tool_task_worker_data_free(
|
||||||
|
tool_task->worker_data
|
||||||
|
);
|
||||||
|
|
||||||
|
tool_task->worker_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
background_task_unref(
|
||||||
|
tool_task->background_task
|
||||||
|
);
|
||||||
|
|
||||||
|
tool_task->background_task = NULL;
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
tool_task
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BackgroundTask *tool_task_get_background_task(
|
||||||
|
const ToolTask *tool_task
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (tool_task == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tool_task->background_task;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean tool_task_start(
|
||||||
|
ToolTask *tool_task,
|
||||||
|
BackgroundTaskCompletionCallback completion_callback,
|
||||||
|
gpointer completion_data,
|
||||||
|
GDestroyNotify completion_data_destroy,
|
||||||
|
GError **error
|
||||||
|
)
|
||||||
|
{
|
||||||
|
GError *start_error = NULL;
|
||||||
|
gboolean start_success = FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
error == NULL || *error == NULL,
|
||||||
|
FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tool_task == NULL ||
|
||||||
|
tool_task->background_task == NULL ||
|
||||||
|
tool_task->worker_data == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_INVALID_ARGUMENT,
|
||||||
|
"La ToolTask fournie est invalide."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool_task->started ||
|
||||||
|
background_task_get_state(
|
||||||
|
tool_task->background_task
|
||||||
|
) != BACKGROUND_TASK_STATE_PENDING)
|
||||||
|
{
|
||||||
|
g_set_error_literal(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR,
|
||||||
|
TOOL_TASK_ERROR_TASK_START,
|
||||||
|
"La ToolTask a déjà été démarrée."
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_success = background_task_start(
|
||||||
|
tool_task->background_task,
|
||||||
|
tool_task_worker,
|
||||||
|
tool_task->worker_data,
|
||||||
|
tool_task_worker_data_free,
|
||||||
|
tool_task_result_destroy,
|
||||||
|
completion_callback,
|
||||||
|
completion_data,
|
||||||
|
completion_data_destroy,
|
||||||
|
&start_error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!start_success)
|
||||||
|
{
|
||||||
|
tool_task_set_wrapped_error(
|
||||||
|
error,
|
||||||
|
TOOL_TASK_ERROR_TASK_START,
|
||||||
|
"La tâche d'arrière-plan n'a pas pu être démarrée",
|
||||||
|
start_error
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(
|
||||||
|
&start_error
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BackgroundTask n'a pas pris possession des données.
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* La propriété des données du worker appartient désormais à
|
||||||
|
* BackgroundTask.
|
||||||
|
*/
|
||||||
|
tool_task->worker_data = NULL;
|
||||||
|
tool_task->started = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToolTaskResult *tool_task_result_from_background_task(
|
||||||
|
const BackgroundTask *background_task
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (background_task == NULL ||
|
||||||
|
background_task_get_state(
|
||||||
|
background_task
|
||||||
|
) != BACKGROUND_TASK_STATE_COMPLETED)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Précondition publique :
|
||||||
|
* background_task doit provenir de ToolTask.
|
||||||
|
*/
|
||||||
|
return background_task_get_result(
|
||||||
|
background_task
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tool_task_result_free(
|
||||||
|
ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&result->tool_identifier,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&result->executable_path,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&result->arguments,
|
||||||
|
g_strfreev
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&result->working_directory,
|
||||||
|
g_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_pointer(
|
||||||
|
&result->process_result,
|
||||||
|
tool_process_result_free
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(
|
||||||
|
result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tool_task_result_get_tool_identifier(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->tool_identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tool_task_result_get_executable_path(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->executable_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize tool_task_result_get_argument_count(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->argument_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tool_task_result_get_argument(
|
||||||
|
const ToolTaskResult *result,
|
||||||
|
gsize index
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL ||
|
||||||
|
result->arguments == NULL ||
|
||||||
|
index >= result->argument_count)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->arguments[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tool_task_result_get_working_directory(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->working_directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ToolProcessResult *tool_task_result_get_process_result(
|
||||||
|
const ToolTaskResult *result
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result->process_result;
|
||||||
|
}
|
||||||
BIN
tests/test_tool_task
Executable file
BIN
tests/test_tool_task
Executable file
Binary file not shown.
2461
tests/test_tool_task.c
Normal file
2461
tests/test_tool_task.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue