Commit 7b9075ea authored by Christian Hergert's avatar Christian Hergert Committed by Matthew Leeds

pipeline: add IdeBuildPipeline

The new IdeBuildPipeline provides a pluggable pipeline with phases. Stages
are attached within a given stage. When the pipeline is executed, it tries
to avoid performing unnecessary work so that we can speed up the rate at
which some user-actions can be performed (such as running).

You can invalidate phases for which those stages will need to be
re-executed next time the pipeline advances to that phase.

Stages can override some of this behavior by attaching to the ::query
signal to determine their "completed" status. If work needs to be
performed asynchronously, it can put a "hold" on the stage and release
the hold after the asynchronous work is completed. The pipeline will
pause to wait for thie operation to complete.

You likely want to use some of the pre-created build stage subclasses
such as for creating directories, launching subprocesses, or performing
transfers.
parent 77a6958e
......@@ -34,6 +34,12 @@ libide_1_0_la_public_headers = \
buildsystem/ide-build-command.h \
buildsystem/ide-build-command-queue.h \
buildsystem/ide-build-manager.h \
buildsystem/ide-build-pipeline.h \
buildsystem/ide-build-pipeline-addin.h \
buildsystem/ide-build-stage.h \
buildsystem/ide-build-stage-launcher.h \
buildsystem/ide-build-stage-mkdirs.h \
buildsystem/ide-build-stage-transfer.h \
buildsystem/ide-build-result-addin.h \
buildsystem/ide-build-result.h \
buildsystem/ide-build-system.h \
......@@ -203,6 +209,12 @@ libide_1_0_la_public_sources = \
buildsystem/ide-build-command.c \
buildsystem/ide-build-command-queue.c \
buildsystem/ide-build-manager.c \
buildsystem/ide-build-pipeline.c \
buildsystem/ide-build-pipeline-addin.c \
buildsystem/ide-build-stage.c \
buildsystem/ide-build-stage-launcher.c \
buildsystem/ide-build-stage-mkdirs.c \
buildsystem/ide-build-stage-transfer.c \
buildsystem/ide-build-result-addin.c \
buildsystem/ide-build-result.c \
buildsystem/ide-build-system.c \
......@@ -375,6 +387,7 @@ libide_1_0_la_SOURCES = \
application/ide-application-tests.h \
buildsystem/ide-build-log.c \
buildsystem/ide-build-log-private.h \
buildsystem/ide-build-stage-private.h \
editor/ide-editor-frame-actions.c \
editor/ide-editor-frame-actions.h \
editor/ide-editor-frame-private.h \
......
/* ide-build-pipeline-addin.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "ide-build-pipeline-addin"
#include "ide-context.h"
#include "buildsystem/ide-build-pipeline-addin.h"
G_DEFINE_INTERFACE (IdeBuildPipelineAddin, ide_build_pipeline_addin, G_TYPE_OBJECT)
static void
ide_build_pipeline_addin_default_init (IdeBuildPipelineAddinInterface *iface)
{
g_object_interface_install_property (iface,
g_param_spec_object ("context",
NULL,
NULL,
IDE_TYPE_CONTEXT,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)));
}
void
ide_build_pipeline_addin_load (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline)
{
g_return_if_fail (IDE_IS_BUILD_PIPELINE_ADDIN (self));
g_return_if_fail (IDE_IS_BUILD_PIPELINE (pipeline));
if (IDE_BUILD_PIPELINE_ADDIN_GET_IFACE (self)->load)
IDE_BUILD_PIPELINE_ADDIN_GET_IFACE (self)->load (self, pipeline);
}
void
ide_build_pipeline_addin_unload (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline)
{
GArray *ar;
g_return_if_fail (IDE_IS_BUILD_PIPELINE_ADDIN (self));
g_return_if_fail (IDE_IS_BUILD_PIPELINE (pipeline));
if (IDE_BUILD_PIPELINE_ADDIN_GET_IFACE (self)->unload)
IDE_BUILD_PIPELINE_ADDIN_GET_IFACE (self)->unload (self, pipeline);
/* Unload any stages that are tracked by the addin */
ar = g_object_get_data (G_OBJECT (self), "IDE_BUILD_PIPELINE_ADDIN_STAGES");
if G_LIKELY (ar != NULL)
{
for (guint i = 0; i < ar->len; i++)
{
guint stage_id = g_array_index (ar, guint, i);
ide_build_pipeline_disconnect (pipeline, stage_id);
}
}
}
/**
* ide_build_pipeline_addin_track:
* @self: An #IdeBuildPipelineAddin
* @stage_id: a stage id returned from ide_build_pipeline_connect()
*
* This function will track the stage_id that was returned from
* ide_build_pipeline_connect() or similar functions. Doing so results in
* the stage being automatically disconnected when the addin is unloaded.
*
* This means that many #IdeBuildPipelineAddin implementations do not need
* an unload vfunc if they track all registered stages.
*
* You should not mix this function with manual pipeline disconnections.
* While it should work, that is not yet guaranteed.
*/
void
ide_build_pipeline_addin_track (IdeBuildPipelineAddin *self,
guint stage_id)
{
GArray *ar;
g_return_if_fail (IDE_IS_BUILD_PIPELINE_ADDIN (self));
g_return_if_fail (stage_id > 0);
ar = g_object_get_data (G_OBJECT (self), "IDE_BUILD_PIPELINE_ADDIN_STAGES");
if (ar == NULL)
{
ar = g_array_new (FALSE, FALSE, sizeof (guint));
g_object_set_data_full (G_OBJECT (self), "IDE_BUILD_PIPELINE_ADDIN_STAGES",
ar, (GDestroyNotify)g_array_unref);
}
g_array_append_val (ar, stage_id);
}
/* ide-build-pipeline-addin.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_BUILD_PIPELINE_ADDIN_H
#define IDE_BUILD_PIPELINE_ADDIN_H
#include <gio/gio.h>
#include "ide-build-pipeline.h"
G_BEGIN_DECLS
#define IDE_TYPE_BUILD_PIPELINE_ADDIN (ide_build_pipeline_addin_get_type())
G_DECLARE_INTERFACE (IdeBuildPipelineAddin, ide_build_pipeline_addin, IDE, BUILD_PIPELINE_ADDIN, GObject)
struct _IdeBuildPipelineAddinInterface
{
GTypeInterface type_interface;
void (*load) (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline);
void (*unload) (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline);
};
void ide_build_pipeline_addin_load (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline);
void ide_build_pipeline_addin_unload (IdeBuildPipelineAddin *self,
IdeBuildPipeline *pipeline);
void ide_build_pipeline_addin_track (IdeBuildPipelineAddin *self,
guint stage_id);
G_END_DECLS
#endif /* IDE_BUILD_PIPELINE_ADDIN_H */
This diff is collapsed.
/* ide-build-pipeline.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_BUILD_PIPELINE_H
#define IDE_BUILD_PIPELINE_H
#include <gio/gio.h>
#include "ide-types.h"
#include "buildsystem/ide-build-log.h"
#include "buildsystem/ide-build-stage.h"
#include "buildsystem/ide-configuration.h"
#include "subprocess/ide-subprocess-launcher.h"
G_BEGIN_DECLS
#define IDE_TYPE_BUILD_PIPELINE (ide_build_pipeline_get_type())
#define IDE_BUILD_PHASE_MASK (0xFFFFFF)
#define IDE_BUILD_PHASE_WHENCE_MASK (IDE_BUILD_PHASE_BEFORE | IDE_BUILD_PHASE_AFTER)
typedef enum
{
IDE_BUILD_PHASE_NONE = 0,
IDE_BUILD_PHASE_PREPARE = 1 << 0,
IDE_BUILD_PHASE_DOWNLOADS = 1 << 1,
IDE_BUILD_PHASE_DEPENDENCIES = 1 << 2,
IDE_BUILD_PHASE_AUTOGEN = 1 << 3,
IDE_BUILD_PHASE_CONFIGURE = 1 << 4,
IDE_BUILD_PHASE_BUILD = 1 << 6,
IDE_BUILD_PHASE_INSTALL = 1 << 7,
IDE_BUILD_PHASE_EXPORT = 1 << 8,
IDE_BUILD_PHASE_FINAL = 1 << 9,
IDE_BUILD_PHASE_BEFORE = 1 << 28,
IDE_BUILD_PHASE_AFTER = 1 << 29,
IDE_BUILD_PHASE_FINISHED = 1 << 30,
IDE_BUILD_PHASE_FAILED = 1 << 31,
} IdeBuildPhase;
G_DECLARE_FINAL_TYPE (IdeBuildPipeline, ide_build_pipeline, IDE, BUILD_PIPELINE, IdeObject)
gboolean ide_build_pipeline_get_busy (IdeBuildPipeline *self);
IdeConfiguration *ide_build_pipeline_get_configuration (IdeBuildPipeline *self);
const gchar *ide_build_pipeline_get_builddir (IdeBuildPipeline *self);
const gchar *ide_build_pipeline_get_srcdir (IdeBuildPipeline *self);
gchar *ide_build_pipeline_get_message (IdeBuildPipeline *self);
IdeSubprocessLauncher *ide_build_pipeline_create_launcher (IdeBuildPipeline *self,
GError **error);
gchar *ide_build_pipeline_build_srcdir_path (IdeBuildPipeline *self,
const gchar *first_part,
...) G_GNUC_NULL_TERMINATED;
gchar *ide_build_pipeline_build_builddir_path (IdeBuildPipeline *self,
const gchar *first_part,
...) G_GNUC_NULL_TERMINATED;
void ide_build_pipeline_invalidate_phase (IdeBuildPipeline *self,
IdeBuildPhase phases);
gboolean ide_build_pipeline_request_phase (IdeBuildPipeline *self,
IdeBuildPhase phase);
guint ide_build_pipeline_connect (IdeBuildPipeline *self,
IdeBuildPhase phase,
gint priority,
IdeBuildStage *stage);
guint ide_build_pipeline_connect_launcher (IdeBuildPipeline *self,
IdeBuildPhase phase,
gint priority,
IdeSubprocessLauncher *launcher);
void ide_build_pipeline_disconnect (IdeBuildPipeline *self,
guint stage_id);
IdeBuildStage *ide_build_pipeline_get_stage_by_id (IdeBuildPipeline *self,
guint stage_id);
guint ide_build_pipeline_add_log_observer (IdeBuildPipeline *self,
IdeBuildLogObserver observer,
gpointer observer_data,
GDestroyNotify observer_data_destroy);
gboolean ide_build_pipeline_remove_log_observer (IdeBuildPipeline *self,
guint observer_id);
void ide_build_pipeline_emit_diagnostic (IdeBuildPipeline *self,
IdeDiagnostic *diagnostic);
guint ide_build_pipeline_add_error_format (IdeBuildPipeline *self,
const gchar *regex,
GRegexCompileFlags flags);
gboolean ide_build_pipeline_remove_error_format (IdeBuildPipeline *self,
guint error_format_id);
void ide_build_pipeline_execute_async (IdeBuildPipeline *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_build_pipeline_execute_finish (IdeBuildPipeline *self,
GAsyncResult *result,
GError **error);
void ide_build_pipeline_foreach_stage (IdeBuildPipeline *self,
GFunc stage_callback,
gpointer user_data);
void ide_build_pipeline_clean_async (IdeBuildPipeline *self,
IdeBuildPhase phase,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_build_pipeline_clean_finish (IdeBuildPipeline *self,
GAsyncResult *result,
GError **error);
void ide_build_pipeline_rebuild_async (IdeBuildPipeline *self,
IdeBuildPhase phase,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_build_pipeline_rebuild_finish (IdeBuildPipeline *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
#endif /* IDE_BUILD_PIPELINE_H */
/* ide-build-stage-launcher.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "ide-build-stage-launcher"
#include "ide-debug.h"
#include "buildsystem/ide-build-log.h"
#include "buildsystem/ide-build-pipeline.h"
#include "buildsystem/ide-build-stage-launcher.h"
#include "subprocess/ide-subprocess.h"
typedef struct
{
IdeSubprocessLauncher *launcher;
IdeSubprocessLauncher *clean_launcher;
guint ignore_exit_status : 1;
} IdeBuildStageLauncherPrivate;
enum {
PROP_0,
PROP_CLEAN_LAUNCHER,
PROP_IGNORE_EXIT_STATUS,
PROP_LAUNCHER,
N_PROPS
};
G_DEFINE_TYPE_WITH_PRIVATE (IdeBuildStageLauncher, ide_build_stage_launcher, IDE_TYPE_BUILD_STAGE)
static GParamSpec *properties [N_PROPS];
static void
ide_build_stage_launcher_wait_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdeSubprocess *subprocess = (IdeSubprocess *)object;
IdeBuildStageLauncher *self = NULL;
IdeBuildStageLauncherPrivate *priv;
g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
gint exit_status;
IDE_ENTRY;
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (G_IS_TASK (task));
self = g_task_get_source_object (task);
g_assert (IDE_IS_BUILD_STAGE_LAUNCHER (self));
priv = ide_build_stage_launcher_get_instance_private (self);
IDE_TRACE_MSG (" %s.ignore_exit_status=%u",
G_OBJECT_TYPE_NAME (self),
priv->ignore_exit_status);
if (!ide_subprocess_wait_finish (subprocess, result, &error))
{
g_task_return_error (task, g_steal_pointer (&error));
IDE_EXIT;
}
if (ide_subprocess_get_if_signaled (subprocess))
{
g_task_return_new_error (task,
G_SPAWN_ERROR,
G_SPAWN_ERROR_FAILED,
"The process was terminated by signal %d",
ide_subprocess_get_term_sig (subprocess));
IDE_EXIT;
}
exit_status = ide_subprocess_get_exit_status (subprocess);
if (priv->ignore_exit_status)
IDE_GOTO (ignore_exit_failures);
if (!g_spawn_check_exit_status (exit_status, &error))
{
g_task_return_error (task, g_steal_pointer (&error));
IDE_EXIT;
}
ignore_exit_failures:
g_task_return_boolean (task, TRUE);
IDE_EXIT;
}
static void
ide_build_stage_launcher_run (IdeBuildStage *stage,
IdeSubprocessLauncher *launcher,
IdeBuildPipeline *pipeline,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)stage;
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
g_autoptr(GTask) task = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(IdeSubprocess) subprocess = NULL;
GSubprocessFlags flags;
IDE_ENTRY;
g_assert (IDE_IS_BUILD_STAGE_LAUNCHER (self));
g_assert (IDE_IS_BUILD_PIPELINE (pipeline));
g_assert (!launcher || IDE_IS_SUBPROCESS_LAUNCHER (launcher));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_build_stage_launcher_run);
if (launcher == NULL)
{
g_task_return_boolean (task, TRUE);
IDE_EXIT;
}
flags = ide_subprocess_launcher_get_flags (launcher);
/* Disable flags we do not want set for build pipeline stuff */
if (flags & G_SUBPROCESS_FLAGS_STDERR_SILENCE)
flags &= ~G_SUBPROCESS_FLAGS_STDERR_SILENCE;
if (flags & G_SUBPROCESS_FLAGS_STDERR_MERGE)
flags &= ~G_SUBPROCESS_FLAGS_STDERR_MERGE;
if (flags & G_SUBPROCESS_FLAGS_STDIN_INHERIT)
flags &= ~G_SUBPROCESS_FLAGS_STDIN_INHERIT;
/* Ensure we have access to stdin/stdout streams */
flags |= G_SUBPROCESS_FLAGS_STDOUT_PIPE;
flags |= G_SUBPROCESS_FLAGS_STDERR_PIPE;
ide_subprocess_launcher_set_flags (launcher, flags);
/* Now launch the process */
subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, &error);
if (subprocess == NULL)
{
g_task_return_error (task, g_steal_pointer (&error));
IDE_EXIT;
}
ide_build_stage_log_subprocess (IDE_BUILD_STAGE (self), subprocess);
IDE_TRACE_MSG ("Waiting for process %s to complete, %s exit status",
ide_subprocess_get_identifier (subprocess),
priv->ignore_exit_status ? "ignoring" : "checking");
ide_subprocess_wait_async (subprocess,
cancellable,
ide_build_stage_launcher_wait_cb,
g_steal_pointer (&task));
IDE_EXIT;
}
static void
ide_build_stage_launcher_execute_async (IdeBuildStage *stage,
IdeBuildPipeline *pipeline,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)stage;
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
g_return_if_fail (IDE_IS_BUILD_STAGE_LAUNCHER (self));
ide_build_stage_launcher_run (stage, priv->launcher, pipeline, cancellable, callback, user_data);
}
static gboolean
ide_build_stage_launcher_execute_finish (IdeBuildStage *stage,
GAsyncResult *result,
GError **error)
{
gboolean ret;
IDE_ENTRY;
g_assert (IDE_IS_BUILD_STAGE_LAUNCHER (stage));
g_assert (G_IS_TASK (result));
ret = g_task_propagate_boolean (G_TASK (result), error);
IDE_RETURN (ret);
}
static void
ide_build_stage_launcher_clean_async (IdeBuildStage *stage,
IdeBuildPipeline *pipeline,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)stage;
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
g_return_if_fail (IDE_IS_BUILD_STAGE_LAUNCHER (self));
ide_build_stage_launcher_run (stage, priv->clean_launcher, pipeline, cancellable, callback, user_data);
}
static gboolean
ide_build_stage_launcher_clean_finish (IdeBuildStage *stage,
GAsyncResult *result,
GError **error)
{
gboolean ret;
IDE_ENTRY;
g_assert (IDE_IS_BUILD_STAGE_LAUNCHER (stage));
g_assert (G_IS_TASK (result));
ret = g_task_propagate_boolean (G_TASK (result), error);
IDE_RETURN (ret);
}
static void
ide_build_stage_launcher_finalize (GObject *object)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)object;
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
g_clear_object (&priv->launcher);
g_clear_object (&priv->clean_launcher);
G_OBJECT_CLASS (ide_build_stage_launcher_parent_class)->finalize (object);
}
static void
ide_build_stage_launcher_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)object;
switch (prop_id)
{
case PROP_CLEAN_LAUNCHER:
g_value_set_object (value, ide_build_stage_launcher_get_clean_launcher (self));
break;
case PROP_IGNORE_EXIT_STATUS:
g_value_set_boolean (value, ide_build_stage_launcher_get_ignore_exit_status (self));
break;
case PROP_LAUNCHER:
g_value_set_object (value, ide_build_stage_launcher_get_launcher (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_build_stage_launcher_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
IdeBuildStageLauncher *self = (IdeBuildStageLauncher *)object;
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
switch (prop_id)
{
case PROP_CLEAN_LAUNCHER:
ide_build_stage_launcher_set_clean_launcher (self, g_value_get_object (value));
break;
case PROP_IGNORE_EXIT_STATUS:
ide_build_stage_launcher_set_ignore_exit_status (self, g_value_get_boolean (value));
break;
case PROP_LAUNCHER:
priv->launcher = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ide_build_stage_launcher_class_init (IdeBuildStageLauncherClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
IdeBuildStageClass *build_stage_class = IDE_BUILD_STAGE_CLASS (klass);
object_class->finalize = ide_build_stage_launcher_finalize;
object_class->get_property = ide_build_stage_launcher_get_property;
object_class->set_property = ide_build_stage_launcher_set_property;
build_stage_class->execute_async = ide_build_stage_launcher_execute_async;
build_stage_class->execute_finish = ide_build_stage_launcher_execute_finish;
build_stage_class->clean_async = ide_build_stage_launcher_clean_async;
build_stage_class->clean_finish = ide_build_stage_launcher_clean_finish;
properties [PROP_CLEAN_LAUNCHER] =
g_param_spec_object ("clean-launcher",
"Clean Launcher",
"The subprocess launcher for cleaning",
IDE_TYPE_SUBPROCESS_LAUNCHER,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties [PROP_IGNORE_EXIT_STATUS] =
g_param_spec_boolean ("ignore-exit-status",
"Ignore Exit Status",
"If the exit status of the subprocess should be ignored",
FALSE,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties [PROP_LAUNCHER] =
g_param_spec_object ("launcher",
"Launcher",
"The subprocess launcher to execute",
IDE_TYPE_SUBPROCESS_LAUNCHER,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
ide_build_stage_launcher_init (IdeBuildStageLauncher *self)
{
}
/**
* ide_build_stage_launcher_get_launcher:
*
* Returns: (transfer none): An #IdeSubprocessLauncher
*/
IdeSubprocessLauncher *
ide_build_stage_launcher_get_launcher (IdeBuildStageLauncher *self)
{
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);
g_return_val_if_fail (IDE_IS_BUILD_STAGE_LAUNCHER (self), NULL);
return priv->launcher;
}
IdeBuildStage *
ide_build_stage_launcher_new (IdeContext *context,
IdeSubprocessLauncher *launcher)
{
return g_object_new (IDE_TYPE_BUILD_STAGE_LAUNCHER,
"context", context,
"launcher", launcher,
NULL);
}
/**
* ide_build_stage_launcher_get_ignore_exit_status:
*
* Gets the "ignore-exit-status" property.
*
* If set to %TRUE, a non-zero exit status from the subprocess will not cause
* the build stage to fail.
*/
gboolean
ide_build_stage_launcher_get_ignore_exit_status (IdeBuildStageLauncher *self)
{
IdeBuildStageLauncherPrivate *priv = ide_build_stage_launcher_get_instance_private (self);