From a494a69d6aee61660eed4131fc4f1083b82fc82e Mon Sep 17 00:00:00 2001 From: James Liggett Date: Sat, 31 May 2008 16:55:25 -0700 Subject: [PATCH] Add progress handling to GitCommand Also include a stock signal handler that should handle the progress bar for any command. --- plugins/git/git-command.c | 65 +++++++++++++++++++++++++++++++++++++++++++--- plugins/git/git-command.h | 1 + plugins/git/git-ui-utils.c | 55 +++++++++++++++++++++++++++++++++++++++ plugins/git/git-ui-utils.h | 11 ++++++++ 4 files changed, 129 insertions(+), 3 deletions(-) diff --git a/plugins/git/git-command.c b/plugins/git/git-command.c index 7ead1c62..442293ea 100644 --- a/plugins/git/git-command.c +++ b/plugins/git/git-command.c @@ -24,6 +24,10 @@ #include "git-command.h" +#define ERROR_REGEX "^(?:warning|fatal|error): (.*)" +#define PROGRESS_REGEX "(\\d{1,3}(?=%))" +#define STATUS_REGEX "(.*):" + enum { PROP_0, @@ -39,6 +43,8 @@ struct _GitCommandPriv size_t num_args; gchar *working_directory; GRegex *error_regex; + GRegex *progress_regex; + GRegex *status_regex; GString *error_string; GQueue *info_queue; gboolean single_line_output; @@ -213,6 +219,11 @@ git_command_error_handler (GitCommand *self, const gchar *output) { GMatchInfo *match_info; gchar *error; + gchar *progress; + gfloat progress_fraction; + gchar *delimiter; /* Some delimiter that git puts in its output */ + gchar *clean_output; /* Ouput without this delimiter */ + gchar *status; if (g_regex_match (self->priv->error_regex, output, 0, &match_info)) { @@ -222,8 +233,53 @@ git_command_error_handler (GitCommand *self, const gchar *output) g_string_append (self->priv->error_string, error); g_free (error); } + else if (g_regex_match (self->priv->progress_regex, output, 0, &match_info)) + { + progress_fraction = 0.0; + + /* Make sure not to report 100% progress twice */ + while (g_match_info_matches (match_info) && + progress_fraction < 1.0) + { + progress = g_match_info_fetch (match_info, 1); + progress_fraction = (g_ascii_strtod (progress, NULL) / 100); + g_free (progress); + + anjuta_command_notify_progress (ANJUTA_COMMAND (self), + progress_fraction); + + g_match_info_next (match_info, NULL); + } + + g_match_info_free (match_info); + + /* Some git versions put the status on a different line; newer ones + * in the 1.5 series use the same line, so check for it here. */ + if (g_regex_match (self->priv->status_regex, output, 0, &match_info)) + { + status = g_match_info_fetch (match_info, 1); + git_command_push_info (self, status); + + g_free (status); + g_match_info_free (match_info); + } + } else - git_command_send_output_to_info (self, output); + { + /* With some commands, like fetch, git will put some kind of + * delimiter in its output, character 0x1b. If it exists, filter it + * out. */ + delimiter = strchr (output, 0x1b); + + if (delimiter) + { + clean_output = g_strndup (output, (delimiter - output)); + git_command_send_output_to_info (self, clean_output); + g_free (clean_output); + } + else + git_command_send_output_to_info (self, output); + } } static void @@ -251,8 +307,9 @@ git_command_init (GitCommand *self) G_CALLBACK (git_command_child_exited), self); - self->priv->error_regex = g_regex_new ("^(?:warning|fatal|error): (.*)", 0, - 0, NULL); + self->priv->error_regex = g_regex_new (ERROR_REGEX, 0, 0, NULL); + self->priv->progress_regex = g_regex_new (PROGRESS_REGEX, 0, 0, NULL); + self->priv->status_regex = g_regex_new (STATUS_REGEX, 0, 0, NULL); self->priv->error_string = g_string_new (""); self->priv->info_queue = g_queue_new (); } @@ -284,6 +341,8 @@ git_command_finalize (GObject *object) g_object_unref (self->priv->launcher); g_regex_unref (self->priv->error_regex); + g_regex_unref (self->priv->progress_regex); + g_regex_unref (self->priv->status_regex); g_string_free (self->priv->error_string, TRUE); g_queue_free (self->priv->info_queue); g_free (self->priv->working_directory); diff --git a/plugins/git/git-command.h b/plugins/git/git-command.h index e78038f2..97ddc4b3 100644 --- a/plugins/git/git-command.h +++ b/plugins/git/git-command.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/plugins/git/git-ui-utils.c b/plugins/git/git-ui-utils.c index a5197e53..e9951bd8 100644 --- a/plugins/git/git-ui-utils.c +++ b/plugins/git/git-ui-utils.c @@ -48,6 +48,34 @@ git_ui_data_free (GitUIData* data) g_free (data); } +GitProgressData * +git_progress_data_new (Git *plugin, const gchar *text) +{ + GitProgressData *data; + AnjutaStatus *status; + + data = g_new0 (GitProgressData, 1); + data->plugin = plugin; + data->text = g_strdup (text); + + status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell, NULL); + anjuta_status_progress_add_ticks (status, 100); + + return data; +} + +void +git_progress_data_free (GitProgressData *data) +{ + AnjutaStatus *status; + + status = anjuta_shell_get_status (ANJUTA_PLUGIN (data->plugin)->shell, + NULL); + + g_free (data->text); + g_free (data); +} + static void on_message_view_destroy (Git* plugin, gpointer destroyed_view) { @@ -289,6 +317,33 @@ on_command_info_arrived (AnjutaCommand *command, Git *plugin) } void +on_command_progress (AnjutaCommand *command, gfloat progress, + GitProgressData *data) +{ + AnjutaStatus *status; + gint ticks; + + status = anjuta_shell_get_status (ANJUTA_PLUGIN (data->plugin)->shell, + NULL); + + /* There are cases where there are multiple stages to a task, and each + * has their own progress indicator. If one stage has completed and another + * is beginning, add another 100 ticks to reflect the progress of this new + * stage. */ + if (data->last_progress == 100) + { + anjuta_status_progress_add_ticks (status, 100); + data->last_progress = 0; + } + + ticks = progress * 100; + anjuta_status_progress_increment_ticks (status, + (ticks - data->last_progress), + data->text); + data->last_progress = ticks; +} + +void on_list_branch_command_data_arrived (AnjutaCommand *command, GitBranchComboData *data) { diff --git a/plugins/git/git-ui-utils.h b/plugins/git/git-ui-utils.h index 64bd4e5e..67ad8511 100644 --- a/plugins/git/git-ui-utils.h +++ b/plugins/git/git-ui-utils.h @@ -41,8 +41,17 @@ typedef struct Git* plugin; } GitUIData; +typedef struct +{ + Git *plugin; + gint last_progress; + gchar *text; +} GitProgressData; + GitUIData* git_ui_data_new (Git* plugin, GladeXML* gxml); void git_ui_data_free (GitUIData* data); +GitProgressData *git_progress_data_new (Git *plugin, const gchar *text); +void git_progress_data_free (GitProgressData *data); void create_message_view (Git* plugin); gboolean check_input (GtkWidget *parent, GtkWidget *widget, const gchar *input, const gchar *error_message); @@ -61,6 +70,8 @@ void on_command_finished (AnjutaCommand *command, guint return_code, void on_status_command_data_arrived (AnjutaCommand *command, AnjutaVcsStatusTreeView *tree_view); void on_command_info_arrived (AnjutaCommand *command, Git *plugin); +void on_command_progress (AnjutaCommand *command, gfloat progress, + GitProgressData *data); void on_list_branch_command_data_arrived (AnjutaCommand *command, GitBranchComboData *data); void on_list_branch_command_finished (AnjutaCommand *command, guint return_code, -- 2.11.4.GIT