[gitg] Allow redirection of stderr to stdout in shell/runner/io



commit 92328760b3e341007c3c941416897e429f03725c
Author: Jesse van den Kieboom <jesse vandenkieboom epfl ch>
Date:   Fri Aug 19 22:49:48 2011 +0200

    Allow redirection of stderr to stdout in shell/runner/io

 libgitg/gitg-io.c         |   42 +++++++++++++++++++++++++++++++++++++++-
 libgitg/gitg-io.h         |   47 +++++++++++++++++++++++++++-----------------
 libgitg/gitg-repository.c |   34 ++++++++++++++++++++++++++++---
 libgitg/gitg-runner.c     |   25 ++++++++++++++++++++++-
 libgitg/gitg-shell.c      |    5 ++++
 5 files changed, 128 insertions(+), 25 deletions(-)
---
diff --git a/libgitg/gitg-io.c b/libgitg/gitg-io.c
index c6fbcb7..955020a 100644
--- a/libgitg/gitg-io.c
+++ b/libgitg/gitg-io.c
@@ -34,6 +34,7 @@ struct _GitgIOPrivate
 	guint cancelled : 1;
 	guint running : 1;
 	guint auto_utf8 : 1;
+	guint stderr_to_stdout : 1;
 };
 
 enum
@@ -45,7 +46,8 @@ enum
 	PROP_CANCELLED,
 	PROP_EXIT_STATUS,
 	PROP_RUNNING,
-	PROP_AUTO_UTF8
+	PROP_AUTO_UTF8,
+	PROP_STDERR_TO_STDOUT
 };
 
 enum
@@ -105,6 +107,9 @@ gitg_io_set_property (GObject      *object,
 		case PROP_AUTO_UTF8:
 			gitg_io_set_auto_utf8 (self, g_value_get_boolean (value));
 			break;
+		case PROP_STDERR_TO_STDOUT:
+			gitg_io_set_stderr_to_stdout (self, g_value_get_boolean (value));
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -139,6 +144,9 @@ gitg_io_get_property (GObject    *object,
 		case PROP_AUTO_UTF8:
 			g_value_set_boolean (value, self->priv->auto_utf8);
 			break;
+		case PROP_STDERR_TO_STDOUT:
+			g_value_set_boolean (value, self->priv->stderr_to_stdout);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -221,6 +229,14 @@ gitg_io_class_init (GitgIOClass *klass)
 	                                                       FALSE,
 	                                                       G_PARAM_READWRITE));
 
+	g_object_class_install_property (object_class,
+	                                 PROP_STDERR_TO_STDOUT,
+	                                 g_param_spec_boolean ("stderr-to-stdout",
+	                                                       "stderr to stdout",
+	                                                       "Redirect stderr to stdout",
+	                                                       FALSE,
+	                                                       G_PARAM_READWRITE));
+
 	signals[BEGIN] =
 		g_signal_new ("begin",
 		              G_TYPE_FROM_CLASS (klass),
@@ -465,3 +481,27 @@ gitg_io_get_auto_utf8 (GitgIO *io)
 
 	return io->priv->auto_utf8;
 }
+
+void
+gitg_io_set_stderr_to_stdout (GitgIO   *io,
+                              gboolean  redirect)
+{
+	g_return_if_fail (GITG_IS_IO (io));
+
+	if (io->priv->stderr_to_stdout == redirect)
+	{
+		return;
+	}
+
+	io->priv->stderr_to_stdout = redirect;
+
+	g_object_notify (G_OBJECT (io), "stderr-to-stdout");
+}
+
+gboolean
+gitg_io_get_stderr_to_stdout (GitgIO *io)
+{
+	g_return_val_if_fail (GITG_IS_IO (io), FALSE);
+
+	return io->priv->stderr_to_stdout;
+}
diff --git a/libgitg/gitg-io.h b/libgitg/gitg-io.h
index 620b43c..153ae87 100644
--- a/libgitg/gitg-io.h
+++ b/libgitg/gitg-io.h
@@ -63,32 +63,43 @@ struct _GitgIOClass
 	void (*end) (GitgIO *io, GError *error);
 };
 
-GType gitg_io_get_type (void) G_GNUC_CONST;
-GitgIO *gitg_io_new (void);
+GType          gitg_io_get_type             (void) G_GNUC_CONST;
+GitgIO        *gitg_io_new                  (void);
 
-void gitg_io_begin (GitgIO *io);
-void gitg_io_end (GitgIO *io, GError *error);
+void           gitg_io_begin                (GitgIO        *io);
+void           gitg_io_end                  (GitgIO        *io,
+                                             GError        *error);
 
-void gitg_io_set_input (GitgIO *io, GInputStream *stream);
-void gitg_io_set_output (GitgIO *io, GOutputStream *stream);
+void           gitg_io_set_input            (GitgIO        *io,
+                                             GInputStream  *stream);
+void           gitg_io_set_output           (GitgIO        *io,
+                                             GOutputStream *stream);
 
-GInputStream *gitg_io_get_input (GitgIO *io);
-GOutputStream *gitg_io_get_output (GitgIO *io);
+GInputStream  *gitg_io_get_input            (GitgIO        *io);
+GOutputStream *gitg_io_get_output           (GitgIO        *io);
 
-void gitg_io_close (GitgIO *io);
-void gitg_io_cancel (GitgIO *io);
+void           gitg_io_close                (GitgIO        *io);
+void           gitg_io_cancel               (GitgIO        *io);
 
-gboolean gitg_io_get_cancelled (GitgIO *io);
-void gitg_io_set_cancelled (GitgIO *io, gboolean cancelled);
+gboolean       gitg_io_get_cancelled        (GitgIO        *io);
+void           gitg_io_set_cancelled        (GitgIO        *io,
+                                             gboolean       cancelled);
 
-gint gitg_io_get_exit_status (GitgIO *io);
-void gitg_io_set_exit_status (GitgIO *io, gint status);
+gint           gitg_io_get_exit_status      (GitgIO        *io);
+void           gitg_io_set_exit_status      (GitgIO        *io,
+                                             gint           status);
 
-gboolean gitg_io_get_running (GitgIO *io);
-void gitg_io_set_running (GitgIO *io, gboolean running);
+gboolean       gitg_io_get_running          (GitgIO        *io);
+void           gitg_io_set_running          (GitgIO        *io,
+                                             gboolean       running);
 
-void gitg_io_set_auto_utf8 (GitgIO *io, gboolean auto_utf8);
-gboolean gitg_io_get_auto_utf8 (GitgIO *io);
+void           gitg_io_set_auto_utf8        (GitgIO        *io,
+                                             gboolean       auto_utf8);
+gboolean       gitg_io_get_auto_utf8        (GitgIO        *io);
+
+gboolean       gitg_io_get_stderr_to_stdout (GitgIO        *io);
+void           gitg_io_set_stderr_to_stdout (GitgIO        *io,
+                                             gboolean       redirect);
 
 G_END_DECLS
 
diff --git a/libgitg/gitg-repository.c b/libgitg/gitg-repository.c
index f0c4f92..0bf8fa6 100644
--- a/libgitg/gitg-repository.c
+++ b/libgitg/gitg-repository.c
@@ -1926,6 +1926,17 @@ gitg_repository_exists (GitgRepository *repository)
 	       g_file_query_exists (repository->priv->work_tree, NULL);
 }
 
+static void
+collect_update (GitgShell           *shell,
+                gchar const * const *lines,
+                GPtrArray           *ret)
+{
+	while (lines && *lines)
+	{
+		g_ptr_array_add (ret, g_strdup (*lines++));
+	}
+}
+
 gboolean
 gitg_repository_run_hook (GitgRepository       *repository,
                           gchar const          *name,
@@ -1944,6 +1955,8 @@ gitg_repository_run_hook (GitgRepository       *repository,
 	GFileInfo *info;
 	gboolean canexec;
 	gboolean retval;
+	GitgShell *shell;
+	GPtrArray *ptrar;
 
 	g_return_val_if_fail (GITG_IS_REPOSITORY (repository), FALSE);
 
@@ -2001,10 +2014,23 @@ gitg_repository_run_hook (GitgRepository       *repository,
 
 	g_strfreev (argsv);
 
-	retval = gitg_shell_run_sync_with_output (command,
-	                                          TRUE,
-	                                          &ret,
-	                                          error);
+	shell = gitg_shell_new_synchronized (1000);
+
+	gitg_io_set_stderr_to_stdout (GITG_IO (shell), TRUE);
+	gitg_shell_set_preserve_line_endings (shell, TRUE);
+
+	ptrar = g_ptr_array_sized_new (100);
+
+	g_signal_connect (shell,
+	                  "update",
+	                  G_CALLBACK (collect_update),
+	                  ptrar);
+
+	retval = gitg_shell_run (shell, command, error) &&
+	         gitg_io_get_exit_status (GITG_IO (shell)) == 0;
+
+	g_ptr_array_add (ptrar, NULL);
+	ret = (gchar **)g_ptr_array_free (ptrar, FALSE);
 
 	if (!retval)
 	{
diff --git a/libgitg/gitg-runner.c b/libgitg/gitg-runner.c
index 1b24996..1800415 100644
--- a/libgitg/gitg-runner.c
+++ b/libgitg/gitg-runner.c
@@ -464,6 +464,12 @@ debug_runner_command (GitgRunner *runner)
 	}
 }
 
+static void
+setup_dup_stderr_to_stdout ()
+{
+	dup2 (1, 2);
+}
+
 void
 gitg_runner_run (GitgRunner *runner)
 {
@@ -477,6 +483,9 @@ gitg_runner_run (GitgRunner *runner)
 	GInputStream *output;
 	GitgSmartCharsetConverter *smart;
 	GError *error = NULL;
+	GSpawnFlags flags = 0;
+	gboolean redirect_stderr;
+	GSpawnChildSetupFunc setup_func = NULL;
 
 	g_return_if_fail (GITG_IS_RUNNER (runner));
 
@@ -499,12 +508,24 @@ gitg_runner_run (GitgRunner *runner)
 		debug_runner_command (runner);
 	}
 
+	redirect_stderr = gitg_io_get_stderr_to_stdout (GITG_IO (runner));
+
+	if (!redirect_stderr && !gitg_debug_enabled (GITG_DEBUG_SHELL))
+	{
+		flags = G_SPAWN_STDERR_TO_DEV_NULL;
+	}
+
+	if (redirect_stderr)
+	{
+		setup_func = (GSpawnChildSetupFunc)setup_dup_stderr_to_stdout;
+	}
+
 	ret = g_spawn_async_with_pipes (wd_path,
 	                                (gchar **)gitg_command_get_arguments (runner->priv->command),
 	                                (gchar **)gitg_command_get_environment (runner->priv->command),
 	                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD |
-	                                (gitg_debug_enabled (GITG_DEBUG_SHELL) ? 0 : G_SPAWN_STDERR_TO_DEV_NULL),
-	                                NULL,
+	                                flags,
+	                                setup_func,
 	                                NULL,
 	                                &(runner->priv->pid),
 	                                start_input ? &stdinf : NULL,
diff --git a/libgitg/gitg-shell.c b/libgitg/gitg-shell.c
index 947dc62..56a31e6 100644
--- a/libgitg/gitg-shell.c
+++ b/libgitg/gitg-shell.c
@@ -491,6 +491,11 @@ run_commands (GitgShell    *shell,
 
 		runner = gitg_runner_new (*ptr);
 
+		if (gitg_io_get_stderr_to_stdout (GITG_IO (shell)))
+		{
+			gitg_io_set_stderr_to_stdout (GITG_IO (runner), TRUE);
+		}
+
 		g_signal_connect (runner,
 		                  "end",
 		                  G_CALLBACK (runner_end),



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]