[latexila] Create the build command runner
- From: SÃbastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [latexila] Create the build command runner
- Date: Mon, 9 Jul 2012 18:40:16 +0000 (UTC)
commit 789cf56d7af01a0810b32304463eca021eeda055
Author: SÃbastien Wilmet <swilmet src gnome org>
Date: Mon Jul 9 20:06:54 2012 +0200
Create the build command runner
Initially, the build command runner (it was maybe another name, I don't
recall exactly) was the parent class of the build tool runner. Then the
two classes has been merged. And now instead of using inheritance,
delegation is used.
It is a first step to clean and refactor the build tool runner.
src/build_command_runner.vala | 170 +++++++++++++++++++++++++++++++++++++++++
src/build_tool_runner.vala | 151 ++++---------------------------------
2 files changed, 184 insertions(+), 137 deletions(-)
---
diff --git a/src/build_command_runner.vala b/src/build_command_runner.vala
new file mode 100644
index 0000000..e470a3f
--- /dev/null
+++ b/src/build_command_runner.vala
@@ -0,0 +1,170 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright  2010-2012 SÃbastien Wilmet
+ *
+ * LaTeXila 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.
+ *
+ * LaTeXila 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 LaTeXila. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: SÃbastien Wilmet
+ */
+
+// Run a single command line.
+
+public class BuildCommandRunner : GLib.Object
+{
+ private string[] _command_args;
+ private string? _working_directory;
+
+ private Pid? _child_pid = null;
+ private uint _child_watch_handler = 0;
+ private IOChannel? _out_channel = null;
+
+ public signal void finished (int exit_status);
+
+ public BuildCommandRunner (string[] command_args, string? working_directory)
+ {
+ _command_args = command_args;
+ _working_directory = working_directory;
+ }
+
+ public void execute_with_output () throws Error
+ {
+ int std_out;
+
+ Process.spawn_async_with_pipes (
+ _working_directory,
+ _command_args,
+ null,
+ SpawnFlags.DO_NOT_REAP_CHILD | SpawnFlags.SEARCH_PATH,
+ redirect_stderr_to_stdout,
+ out _child_pid,
+ null,
+ out std_out
+ );
+
+ _child_watch_handler = ChildWatch.add (_child_pid, on_exit);
+
+ _out_channel = new IOChannel.unix_new (std_out);
+ _out_channel.set_encoding (null);
+ }
+
+ public void execute_without_output () throws Error
+ {
+ SpawnFlags flags =
+ SpawnFlags.DO_NOT_REAP_CHILD |
+ SpawnFlags.SEARCH_PATH |
+ SpawnFlags.STDOUT_TO_DEV_NULL |
+ SpawnFlags.STDERR_TO_DEV_NULL;
+
+ Process.spawn_async (_working_directory, _command_args, null, flags, null,
+ out _child_pid);
+
+ _child_watch_handler = ChildWatch.add (_child_pid, on_exit);
+ }
+
+ public void abort ()
+ {
+ if (_child_pid != null)
+ {
+ Posix.kill (_child_pid, Posix.SIGTERM);
+ _child_pid = null;
+ }
+ }
+
+ public string get_output ()
+ {
+ if (_out_channel == null)
+ return "";
+
+ /* Read the output */
+
+ string output = "";
+
+ try
+ {
+ _out_channel.read_to_end (out output, null);
+ }
+ catch (ConvertError e)
+ {
+ warning ("Read output: convert error: %s", e.message);
+ }
+ catch (IOChannelError e)
+ {
+ warning ("Read output: IO channel error: %s", e.message);
+ }
+
+ /* Close the channel */
+
+ try
+ {
+ _out_channel.shutdown (false);
+ }
+ catch (Error e) {}
+
+ _out_channel = null;
+
+ /* Return the result */
+
+ // Check if the output is a valid UTF-8 string
+ if (output.validate ())
+ return output;
+
+ return validate_output (output);
+ }
+
+ private void on_exit (Pid pid, int exit_status)
+ {
+ _child_watch_handler = 0;
+ _child_pid = null;
+
+ finished (exit_status);
+ }
+
+ private void redirect_stderr_to_stdout ()
+ {
+ Posix.dup2 (Posix.STDOUT_FILENO, Posix.STDERR_FILENO);
+ }
+
+ // Convert the output to UTF-8
+ private string validate_output (string output)
+ {
+ // Make the conversion into UTF-8 line by line, because if it is done to the all
+ // string at once, there are some encodings troubles with the "latex" and
+ // "pdflatex" commands (with accents in the filename for instance).
+
+ string new_output = "";
+ string[] lines = output.split ("\n");
+
+ foreach (string line in lines)
+ {
+ string? line_utf8 = line.locale_to_utf8 (-1, null, null);
+
+ if (line_utf8 == null)
+ {
+ try
+ {
+ line_utf8 = convert (line, -1, "UTF-8", "ISO-8859-1");
+ }
+ catch (ConvertError e) {}
+ }
+
+ if (line_utf8 != null && line_utf8.validate ())
+ new_output += line_utf8 + "\n";
+ else
+ warning ("Read output failed: %s", line);
+ }
+
+ return new_output;
+ }
+}
diff --git a/src/build_tool_runner.vala b/src/build_tool_runner.vala
index 3ebf39f..acc4416 100644
--- a/src/build_tool_runner.vala
+++ b/src/build_tool_runner.vala
@@ -21,12 +21,7 @@ using Gtk;
public class BuildToolRunner : GLib.Object
{
- private static const int POLL_INTERVAL = 250;
- private Pid? child_pid = null;
- private uint[] handlers = {};
- private IOChannel out_channel;
- private bool read_output = true;
- private string output = "";
+ private BuildCommandRunner? _command_runner = null;
private BuildView view;
private bool latexmk_show_all;
@@ -124,69 +119,11 @@ public class BuildToolRunner : GLib.Object
return true;
}
- private void execute (string[] command, string? working_directory) throws Error
- {
-// stdout.printf ("command arguments:\n");
-// foreach (string arg in command)
-// stdout.printf ("%s\n", arg);
-// stdout.printf ("\n");
-
- try
- {
- int std_out;
-
- Process.spawn_async_with_pipes (working_directory, command, null,
- SpawnFlags.DO_NOT_REAP_CHILD | SpawnFlags.SEARCH_PATH,
-
- // redirect stderr into stdout
- () => { Posix.dup2 (Posix.STDOUT_FILENO, Posix.STDERR_FILENO); },
-
- out child_pid, null, out std_out);
-
- // we want to know the exit code
- handlers += ChildWatch.add (child_pid, on_exit);
-
- out_channel = new IOChannel.unix_new (std_out);
- out_channel.set_flags (IOFlags.NONBLOCK);
- out_channel.set_encoding (null);
-
- handlers += Timeout.add (POLL_INTERVAL, on_output);
- }
- catch (Error e)
- {
- throw e;
- }
- }
-
- private void execute_without_output (string[] command, string? working_directory)
- throws Error
- {
- read_output = false;
-
- try
- {
- Process.spawn_async (working_directory, command, null,
- SpawnFlags.DO_NOT_REAP_CHILD | SpawnFlags.SEARCH_PATH, null,
- out child_pid);
-
- // we want to know the exit code
- handlers += ChildWatch.add (child_pid, on_exit);
- }
- catch (Error e)
- {
- throw e;
- }
- }
-
/* Abort the running process */
public void abort ()
{
- if (child_pid == null)
- return;
-
- foreach (uint handler in handlers)
- Source.remove (handler);
- Posix.kill (child_pid, Posix.SIGTERM);
+ if (_command_runner != null)
+ _command_runner.abort ();
action_stop_exec.set_sensitive (false);
view.set_partition_state (root_partition, PartitionState.ABORTED);
@@ -194,72 +131,11 @@ public class BuildToolRunner : GLib.Object
view.set_partition_state (job_partitions[i], PartitionState.ABORTED);
}
- private bool on_output ()
+ private void on_command_finished (int exit_status)
{
- return_val_if_fail (read_output, false);
+ return_if_fail (_command_runner != null);
- string? text = null;
- size_t length;
-
- try
- {
- out_channel.read_to_end (out text, out length);
- }
- catch (ConvertError e)
- {
- warning ("Read output: convert error: %s", e.message);
- }
- catch (IOChannelError e)
- {
- warning ("Read output: IO channel error: %s", e.message);
- }
-
- if (length <= 0)
- return true;
-
- // check if the output is a valid UTF-8 string
- if (text.validate ())
- {
- output += text;
- return true;
- }
-
- // make the conversion into UTF-8 line by line, because if it is done to the all
- // string at once, there are some encodings troubles with the "latex" and
- // "pdflatex" commands (with accents in the filename for instance).
- string[] lines = text.split ("\n");
- foreach (string line in lines)
- {
- string? line_utf8 = line.locale_to_utf8 (-1, null, null);
-
- if (line_utf8 == null)
- {
- try
- {
- line_utf8 = convert (line, -1, "UTF-8", "ISO-8859-1");
- }
- catch (ConvertError e) {}
- }
-
- if (line_utf8 != null && line_utf8.validate ())
- output += line_utf8 + "\n";
- else
- warning ("Read output failed: %s", line);
- }
-
- return true;
- }
-
- private void on_exit (Pid pid, int status)
- {
- foreach (uint handler in handlers)
- Source.remove (handler);
-
- // read remaining output
- if (read_output)
- on_output ();
-
- // create post processor
+ // Create post processor
PostProcessor post_processor;
switch (current_job.post_processor)
{
@@ -284,8 +160,8 @@ public class BuildToolRunner : GLib.Object
break;
}
- post_processor.set_status (status);
- post_processor.process (file, output);
+ post_processor.set_status (exit_status);
+ post_processor.process (file, _command_runner.get_output ());
view.append_messages (job_partitions[job_num], post_processor.get_messages ());
@@ -313,9 +189,6 @@ public class BuildToolRunner : GLib.Object
return;
}
- // reset output because it's the same variable for all jobs
- output = "";
-
current_job = jobs[job_num];
string[] command;
@@ -346,12 +219,14 @@ public class BuildToolRunner : GLib.Object
view.append_single_message (job_partitions[job_num], message);
}
+ _command_runner = new BuildCommandRunner (command, directory);
+
try
{
if (current_job.post_processor == PostProcessorType.NO_OUTPUT)
- execute_without_output (command, directory);
+ _command_runner.execute_without_output ();
else
- execute (command, directory);
+ _command_runner.execute_with_output ();
}
catch (Error e)
{
@@ -377,6 +252,8 @@ public class BuildToolRunner : GLib.Object
failed ();
}
+
+ _command_runner.finished.connect (on_command_finished);
}
private string[] get_command_args (string command_line, bool for_printing = false)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]