[anjuta/libgit2-glib] git: Port the status command to libgit2-glib



commit dd400b5717893623e59f7beb1148b2ea80a7be4a
Author: James Liggett <jrliggett cox net>
Date:   Mon Jul 22 15:37:31 2013 -0700

    git: Port the status command to libgit2-glib

 plugins/git/git-status-command.c |  299 +++++++-------------------------------
 plugins/git/git-status-command.h |   19 +--
 plugins/git/git-status-pane.c    |  135 ++++++++---------
 plugins/git/git-status.c         |   42 +++++-
 plugins/git/git-status.h         |    5 +-
 plugins/git/git-vcs-interface.c  |   45 ++++---
 plugins/git/plugin.c             |   38 +----
 plugins/git/plugin.h             |    3 +-
 8 files changed, 199 insertions(+), 387 deletions(-)
---
diff --git a/plugins/git/git-status-command.c b/plugins/git/git-status-command.c
index 7679985..eef39e8 100644
--- a/plugins/git/git-status-command.c
+++ b/plugins/git/git-status-command.c
@@ -24,310 +24,111 @@
 
 #include "git-status-command.h"
 
-#define STATUS_REGEX "((M|A|D|U|\\?|\\s){2}) (.*)"
-
 struct _GitStatusCommandPriv
 {
-       GQueue *status_queue;
+       GAsyncQueue *status_queue;
        GitStatusSections sections;
-       GHashTable *status_codes;
-       GHashTable *conflict_codes;
-       GRegex *status_regex;
-       GFileMonitor *head_monitor;
-       GFileMonitor *index_monitor;
+       gchar *path;
 };
 
-G_DEFINE_TYPE (GitStatusCommand, git_status_command, GIT_TYPE_PROCESS_COMMAND);
+G_DEFINE_TYPE (GitStatusCommand, git_status_command, GIT_TYPE_COMMAND);
 
-static guint
-git_status_command_run (AnjutaCommand *command)
+static void
+git_status_command_init (GitStatusCommand *self)
 {
-       git_process_command_add_arg (GIT_PROCESS_COMMAND (command), "status");
-       git_process_command_add_arg (GIT_PROCESS_COMMAND (command), "--porcelain");
-       
-       return 0;
+       self->priv = g_new0 (GitStatusCommandPriv, 1);
+       self->priv->status_queue = g_async_queue_new_full (g_object_unref);
 }
 
 static void
-git_status_command_handle_output (GitProcessCommand *git_process_command, const gchar *output)
+git_status_command_finalize (GObject *object)
 {
        GitStatusCommand *self;
-       GMatchInfo *match_info;
-       GitStatus *status_object;
-       gchar *status;
-       gchar *path;
        
-       self = GIT_STATUS_COMMAND (git_process_command);
-       status_object = NULL;
-
-       if (g_regex_match (self->priv->status_regex, output, 0, &match_info))
-       {
-               /* Determine which section this entry goes in */
-               status = g_match_info_fetch (match_info, 1);
-               path = g_match_info_fetch (match_info, 3);
-
-               if (status[0] == ' ')
-               {
-                       /* Changed but not updated */
-                       if (self->priv->sections & GIT_STATUS_SECTION_NOT_UPDATED)
-                       {
-                               status_object = git_status_new(path, 
-                                                              GPOINTER_TO_INT (g_hash_table_lookup 
(self->priv->status_codes, 
-                                                                                                             
           GINT_TO_POINTER (status[1]))));
-                       }
-               }
-               else if (status[1] == ' ')
-               {
-                       /* Added to commit */
-                       if (self->priv->sections & GIT_STATUS_SECTION_COMMIT)
-                       {
-                               status_object = git_status_new(path, 
-                                                              GPOINTER_TO_INT (g_hash_table_lookup 
(self->priv->status_codes, 
-                                                                                                             
   GINT_TO_POINTER (status[0]))));
-                       }
-               }
-               else
-               {
-                       /* File may have been added to the index and then changed again in
-                        * the working tree, or it could be a conflict */
-
-                       /* Unversioned files */
-                       if (status[0] == '?')
-                       {
-                               if (self->priv->sections & GIT_STATUS_SECTION_UNTRACKED)
-                               {
-                                       status_object = git_status_new(path, 
-                                                                          ANJUTA_VCS_STATUS_UNVERSIONED);
-                               }
-                       }
-                       else if (g_hash_table_lookup_extended (self->priv->conflict_codes, status,
-                                                              NULL, NULL))
-                       {
-                               /* Conflicts are put in the changed but not updated section */
-                               if (self->priv->sections & GIT_STATUS_SECTION_NOT_UPDATED)
-                               {
-                                       status_object = git_status_new (path, 
-                                                                       ANJUTA_VCS_STATUS_CONFLICTED);
-                               }
-                       }
-                       else
-                       {
-                               status_object = git_status_new(path, 
-                                                              GPOINTER_TO_INT(g_hash_table_lookup 
(self->priv->status_codes, 
-                                                                                                   
GINT_TO_POINTER (status[0]))));
-                       }
-                           
-               }
-
-               
-
-               g_free (status);
-               g_free (path);
-
-               if (status_object)
-               {
-                       g_queue_push_tail (self->priv->status_queue, status_object);
-                       anjuta_command_notify_data_arrived (ANJUTA_COMMAND (self));
-               }
-               
-       }
-
-       g_match_info_free (match_info);
+       self = GIT_STATUS_COMMAND (object);
        
-}
-
-static void
-git_status_command_init (GitStatusCommand *self)
-{
-       self->priv = g_new0 (GitStatusCommandPriv, 1);
-       self->priv->status_queue = g_queue_new ();
+       g_async_queue_unref (self->priv->status_queue);
+       g_free (self->priv->path);
        
-       self->priv->status_regex = g_regex_new (STATUS_REGEX, 0, 0, NULL);
-       self->priv->status_codes = g_hash_table_new (g_direct_hash, g_direct_equal);
-       self->priv->conflict_codes = g_hash_table_new (g_str_hash, g_str_equal);
-
-       /* Initialize status code hash tables */
-       g_hash_table_insert (self->priv->status_codes, 
-                            GINT_TO_POINTER ('M'),
-                            GINT_TO_POINTER (ANJUTA_VCS_STATUS_MODIFIED));
-
-       g_hash_table_insert (self->priv->status_codes, 
-                            GINT_TO_POINTER ('A'),
-                            GINT_TO_POINTER (ANJUTA_VCS_STATUS_ADDED));
-
-       g_hash_table_insert (self->priv->status_codes, 
-                            GINT_TO_POINTER ('D'),
-                            GINT_TO_POINTER (ANJUTA_VCS_STATUS_MODIFIED));
-
-       /* TODO: Handle each conflict case individually so that we can eventually
-        * give the user more information about the conflict */
-       g_hash_table_insert (self->priv->conflict_codes, "DD", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "AU", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "UD", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "UA", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "DU", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "AA", NULL);
-       g_hash_table_insert (self->priv->conflict_codes, "UU", NULL);
-}
+       g_free (self->priv);
 
-static void
-on_file_monitor_changed (GFileMonitor *monitor, GFile *file, GFile *other_file,
-                         GFileMonitorEvent event, AnjutaCommand *command)
-{
-       /* Handle created and modified events just to cover all possible cases. 
-        * Sometimes git does some odd things... */
-       if (event == G_FILE_MONITOR_EVENT_CHANGED ||
-           event == G_FILE_MONITOR_EVENT_CREATED)
-       {
-               anjuta_command_start (command);
-       }
+       G_OBJECT_CLASS (git_status_command_parent_class)->finalize (object);
 }
 
-static gboolean
-git_status_command_start_automatic_monitor (AnjutaCommand *command)
+static gint
+git_status_command_status_callback (const gchar *file, GgitStatusFlags flags, 
+                                                       GitStatusCommand *self)
 {
-       GitStatusCommand *self;
-       gchar *working_directory;
-       gchar *git_head_path;
-       gchar *git_index_path;
-       GFile *git_head_file;
-       GFile *git_index_file;
-
-       self = GIT_STATUS_COMMAND (command);
-
-       g_object_get (self, "working-directory", &working_directory, NULL);
-
-       /* Watch for changes to the HEAD file and the index file, so that we can
-        * at least detect commits and index changes. */
-       git_head_path = g_strjoin (G_DIR_SEPARATOR_S,
-                                  working_directory,
-                                  ".git",
-                                  "HEAD",
-                                  NULL);
-       git_index_path = g_strjoin (G_DIR_SEPARATOR_S,
-                                   working_directory,
-                                   ".git",
-                                   "index",
-                                   NULL);
-       git_head_file = g_file_new_for_path (git_head_path);
-       git_index_file = g_file_new_for_path (git_index_path);
-       self->priv->head_monitor = g_file_monitor_file (git_head_file, 0, NULL, 
-                                                       NULL);
-       self->priv->index_monitor = g_file_monitor_file (git_index_file, 0, NULL,
-                                                        NULL);
+       GitStatus *status;
 
-       g_signal_connect (G_OBJECT (self->priv->head_monitor), "changed",
-                         G_CALLBACK (on_file_monitor_changed),
-                         command);
+       status = git_status_new (file, flags);
 
-       g_signal_connect (G_OBJECT (self->priv->index_monitor), "changed",
-                         G_CALLBACK (on_file_monitor_changed),
-                         command);
+       g_async_queue_push (self->priv->status_queue, status);
+       anjuta_task_notify_data_arrived (ANJUTA_TASK (self));
 
-       g_free (git_head_path);
-       g_free (git_index_path);
-       g_object_unref (git_head_file);
-       g_object_unref (git_index_file);
-
-       return TRUE;
+       return 0;
 }
 
 static void
-git_status_command_stop_automatic_monitor (AnjutaCommand *command)
+git_status_command_run (AnjutaTask *task)
 {
        GitStatusCommand *self;
+       GgitRepository *repository;
+       GgitStatusOptions *options;
+       GgitStatusOption option_flags;
+       const gchar *paths[2];
 
-       self = GIT_STATUS_COMMAND (command); 
+       self = GIT_STATUS_COMMAND (task);;
 
-       if (self->priv->head_monitor)
-       {
-               g_file_monitor_cancel (self->priv->head_monitor);
-               g_object_unref (self->priv->head_monitor);
-               self->priv->head_monitor = NULL;
-       }
+       g_object_get (self, "repository", &repository, NULL);
 
-       if (self->priv->index_monitor)
+       if (repository)
        {
-               g_file_monitor_cancel (self->priv->index_monitor);
-               g_object_unref (self->priv->index_monitor);
-               self->priv->index_monitor = NULL;
-       }
-}
+               option_flags = 0;
 
-static void
-git_status_command_clear_output (GitStatusCommand *self)
-{
-       GList *current_output;
+               if (self->priv->sections & GIT_STATUS_SECTION_UNTRACKED)
+                       option_flags |= GGIT_STATUS_OPTION_INCLUDE_UNTRACKED;
 
-       current_output = self->priv->status_queue->head;
+               paths[0] = self->priv->path;
+               paths[1] = NULL;
 
-       while (current_output)
-       {
-               g_object_unref (current_output->data);
-               current_output = g_list_next (current_output);
-       }
+               options = ggit_status_options_new (option_flags, 0, paths);
 
-       g_queue_clear (self->priv->status_queue);
-}
+               ggit_repository_file_status_foreach (repository, options, 
+                                                    (GgitStatusCallback) git_status_command_status_callback,
+                                                    self, NULL);
 
-static void
-git_status_command_data_arrived (AnjutaCommand *command)
-{
-       git_status_command_clear_output (GIT_STATUS_COMMAND (command));
-}
-
-
-static void
-git_status_command_finalize (GObject *object)
-{
-       GitStatusCommand *self;
-       
-       self = GIT_STATUS_COMMAND (object);
-       
-       git_status_command_clear_output (self);
-       git_status_command_stop_automatic_monitor (ANJUTA_COMMAND (self));
-       
-       g_queue_free (self->priv->status_queue);
-       g_regex_unref (self->priv->status_regex);
-       
-       g_free (self->priv);
-
-       G_OBJECT_CLASS (git_status_command_parent_class)->finalize (object);
+               ggit_status_options_free (options);
+       }
 }
 
 static void
 git_status_command_class_init (GitStatusCommandClass *klass)
 {
        GObjectClass* object_class = G_OBJECT_CLASS (klass);
-       GitProcessCommandClass* parent_class = GIT_PROCESS_COMMAND_CLASS (klass);
-       AnjutaCommandClass* command_class = ANJUTA_COMMAND_CLASS (klass);
+       AnjutaTaskClass* task_class = ANJUTA_TASK_CLASS (klass);
 
        object_class->finalize = git_status_command_finalize;
-       parent_class->output_handler = git_status_command_handle_output;
-       command_class->run = git_status_command_run;
-       command_class->data_arrived = git_status_command_data_arrived;
-       command_class->start_automatic_monitor = git_status_command_start_automatic_monitor;
-       command_class->stop_automatic_monitor = git_status_command_stop_automatic_monitor;
+       task_class->run = git_status_command_run;
 }
 
 
-GitStatusCommand *
-git_status_command_new (const gchar *working_directory, 
-                                               GitStatusSections sections)
+GitCommand *
+git_status_command_new (GitStatusSections sections, const gchar *path)
 {
        GitStatusCommand *self;
        
-       self = g_object_new (GIT_TYPE_STATUS_COMMAND, 
-                                                "working-directory", working_directory,
-                                                "single-line-output", TRUE,
-                                                NULL);
+       self = g_object_new (GIT_TYPE_STATUS_COMMAND, NULL);
        
        self->priv->sections = sections;
+       self->priv->path = g_strdup (path);
+
+       g_print ("Given path: %s\n", path);
        
-       return self;
+       return GIT_COMMAND (self);
 }
 
-GQueue *
+GAsyncQueue *
 git_status_command_get_status_queue (GitStatusCommand *self)
 {
        return self->priv->status_queue;
diff --git a/plugins/git/git-status-command.h b/plugins/git/git-status-command.h
index 551990b..778c71f 100644
--- a/plugins/git/git-status-command.h
+++ b/plugins/git/git-status-command.h
@@ -26,7 +26,8 @@
 #define _GIT_STATUS_COMMAND_H_
 
 #include <glib-object.h>
-#include "git-process-command.h"
+#include <libgit2-glib/ggit-status-options.h>
+#include "git-command.h"
 #include "git-status.h"
 
 G_BEGIN_DECLS
@@ -44,29 +45,25 @@ typedef struct _GitStatusCommandPriv GitStatusCommandPriv;
 
 typedef enum
 {
-       GIT_STATUS_SECTION_COMMIT = 1 << 0,
-       GIT_STATUS_SECTION_NOT_UPDATED = 1 << 1,
-       GIT_STATUS_SECTION_UNTRACKED = 1 << 2,
-       GIT_STATUS_SECTION_MODIFIED = (GIT_STATUS_SECTION_COMMIT | 
-                                                                  GIT_STATUS_SECTION_NOT_UPDATED)
+       GIT_STATUS_SECTION_UNTRACKED = 1 << 0,
 } GitStatusSections;
 
 struct _GitStatusCommandClass
 {
-       GitProcessCommandClass parent_class;
+       GitCommandClass parent_class;
 };
 
 struct _GitStatusCommand
 {
-       GitProcessCommand parent_instance;
+       GitCommand parent_instance;
        
        GitStatusCommandPriv *priv;
 };
 
 GType git_status_command_get_type (void) G_GNUC_CONST;
-GitStatusCommand *git_status_command_new (const gchar *working_directory,
-                                                                                 GitStatusSections sections);
-GQueue *git_status_command_get_status_queue (GitStatusCommand *self);
+GitCommand *git_status_command_new (GitStatusSections sections, 
+                                    const gchar *path);
+GAsyncQueue *git_status_command_get_status_queue (GitStatusCommand *self);
 
 G_END_DECLS
 
diff --git a/plugins/git/git-status-pane.c b/plugins/git/git-status-pane.c
index 6f74de7..4004045 100644
--- a/plugins/git/git-status-pane.c
+++ b/plugins/git/git-status-pane.c
@@ -302,62 +302,58 @@ on_selected_renderer_toggled (GtkCellRendererToggle *renderer, gchar *tree_path,
 }
 
 static void
-add_status_items (GQueue *output, GtkTreeStore *status_model, 
-                  GtkTreeIter *parent_iter, StatusType type)
+add_status_item (GtkTreeStore *status_model, GtkTreeIter *parent_iter, 
+                 StatusType type, const gchar *path, AnjutaVcsStatus status)
 {
-       GitStatus *status_object;
-       AnjutaVcsStatus status;
-       gchar *path;
        GtkTreeIter iter;
 
-       while (g_queue_peek_head (output))
-       {
-               status_object = g_queue_pop_head (output);
-               status = git_status_get_vcs_status (status_object);
-               path = git_status_get_path (status_object);
-
-               gtk_tree_store_append (status_model, &iter, parent_iter);
-               gtk_tree_store_set (status_model, &iter,
-                                   COL_SELECTED, FALSE,
-                                   COL_STATUS, status,
-                                   COL_PATH, path,
-                                   COL_TYPE, type,
-                                   -1);
 
-               g_free (path);
-               g_object_unref (status_object);
-       }
+       gtk_tree_store_append (status_model, &iter, parent_iter);
+       gtk_tree_store_set (status_model, &iter,
+                           COL_SELECTED, FALSE,
+                           COL_STATUS, status,
+                           COL_PATH, path,
+                           COL_TYPE, type,
+                           -1);
 }
 
 static void
-on_commit_status_data_arrived (AnjutaCommand *command, 
-                               GitStatusPane *self)
+on_status_command_data_arrived (AnjutaTask *task, GitStatusPane *self)
 {
        GtkTreeStore *status_model;
-       GQueue *output;
+       GAsyncQueue *status_queue;
+       GitStatus *status;
+       gchar *path;
+       AnjutaVcsStatus index_status;
+       AnjutaVcsStatus working_tree_status;
 
-       status_model = GTK_TREE_STORE (gtk_builder_get_object (self->priv->builder,
-                                                              "status_model"));
-       output = git_status_command_get_status_queue (GIT_STATUS_COMMAND (command));
+       g_print ("Data arrived.\n");
 
-       add_status_items (output, status_model, &(self->priv->commit_iter),
-                         STATUS_TYPE_COMMIT);
+       status_model = GTK_TREE_STORE (gtk_builder_get_object (self->priv->builder,     
+                                                              "status_model"));
+       status_queue = git_status_command_get_status_queue (GIT_STATUS_COMMAND (task));
 
-}
+       while ((status = g_async_queue_try_pop (status_queue)))
+       {
+               path = git_status_get_path (status);
+               index_status = git_status_get_index_status (status);
+               working_tree_status = git_status_get_working_tree_status (status);
 
-static void
-on_not_updated_status_data_arrived (AnjutaCommand *command,
-                                    GitStatusPane *self)
-{
-       GtkTreeStore *status_model;
-       GQueue *output;
+               if (index_status)
+               {
+                       add_status_item (status_model, &(self->priv->commit_iter), 
+                                        STATUS_TYPE_COMMIT, path, index_status);
+               }
 
-       status_model = GTK_TREE_STORE (gtk_builder_get_object (self->priv->builder,
-                                                              "status_model"));
-       output = git_status_command_get_status_queue (GIT_STATUS_COMMAND (command));
+               if (working_tree_status)
+               {
+                       add_status_item (status_model, &(self->priv->not_updated_iter), 
+                                        STATUS_TYPE_NOT_UPDATED, path, working_tree_status);
+               }
 
-       add_status_items (output, status_model, &(self->priv->not_updated_iter),
-                         STATUS_TYPE_NOT_UPDATED);
+               g_free (path);
+               g_object_unref (status);
+       }
 }
 
 static void
@@ -714,11 +710,35 @@ git_status_pane_finalize (GObject *object)
 static void
 git_status_pane_refresh (AnjutaDockPane *pane)
 {
+       GitStatusPane *self;
        Git *plugin;
+       GitCommand *status_command;
+       GtkTreeView *status_view;
 
+       self = GIT_STATUS_PANE (pane);
        plugin = ANJUTA_PLUGIN_GIT (anjuta_dock_pane_get_plugin (pane));
+       status_command = git_status_command_new (0, NULL);
+       status_view = GTK_TREE_VIEW (gtk_builder_get_object (self->priv->builder,
+                                                            "status_view"));
+
+       git_status_pane_clear (self);
+
+       g_signal_connect (G_OBJECT (status_command), "data-arrived",
+                         G_CALLBACK (on_status_command_data_arrived),
+                         pane);
 
-       anjuta_command_start (ANJUTA_COMMAND (plugin->commit_status_command));
+       /* Expand the placeholders so something is visible to the user after 
+        * refreshing */
+       g_signal_connect_swapped (G_OBJECT (status_command),
+                                 "finished",
+                                 G_CALLBACK (gtk_tree_view_expand_all),
+                                 status_view);
+
+       g_signal_connect (G_OBJECT (status_command), "finished",
+                         G_CALLBACK (g_object_unref),
+                         NULL);
+
+       git_thread_pool_push (plugin->thread_pool, status_command);
        
 }
 
@@ -747,36 +767,7 @@ git_status_pane_class_init (GitStatusPaneClass *klass)
 AnjutaDockPane *
 git_status_pane_new (Git *plugin)
 {
-       GitStatusPane *self;
-       GtkTreeView *status_view;
-
-       self = g_object_new (GIT_TYPE_STATUS_PANE, "plugin", plugin, NULL);
-       status_view = GTK_TREE_VIEW (gtk_builder_get_object (self->priv->builder,
-                                                                                                             
   "status_view"));
-
-       g_signal_connect_swapped (G_OBJECT (plugin->commit_status_command), 
-                                 "command-started",
-                                 G_CALLBACK (git_status_pane_clear),
-                                 self);
-
-       /* Expand the placeholders so something is visible to the user after 
-        * refreshing */
-       g_signal_connect_swapped (G_OBJECT (plugin->not_updated_status_command),
-                                 "command-finished",
-                                 G_CALLBACK (gtk_tree_view_expand_all),
-                                 status_view);
-
-       g_signal_connect (G_OBJECT (plugin->commit_status_command),
-                         "data-arrived",
-                         G_CALLBACK (on_commit_status_data_arrived),
-                         self);
-
-       g_signal_connect (G_OBJECT (plugin->not_updated_status_command),
-                         "data-arrived",
-                         G_CALLBACK (on_not_updated_status_data_arrived),
-                         self);
-
-       return ANJUTA_DOCK_PANE (self);
+       return g_object_new (GIT_TYPE_STATUS_PANE, "plugin", plugin, NULL);;
 }
 
 static void
diff --git a/plugins/git/git-status.c b/plugins/git/git-status.c
index 5f2307a..deae6c5 100644
--- a/plugins/git/git-status.c
+++ b/plugins/git/git-status.c
@@ -27,7 +27,8 @@
 struct _GitStatusPriv
 {
        gchar *path;
-       AnjutaVcsStatus status;
+       AnjutaVcsStatus index_status;
+       AnjutaVcsStatus working_tree_status;
 };
 
 G_DEFINE_TYPE (GitStatus, git_status, G_TYPE_OBJECT);
@@ -60,14 +61,27 @@ git_status_class_init (GitStatusClass *klass)
 }
 
 GitStatus *
-git_status_new (const gchar *path, AnjutaVcsStatus status)
+git_status_new (const gchar *path, GgitStatusFlags status)
 {
        GitStatus *self;
        
        self = g_object_new (GIT_TYPE_STATUS, NULL);
        
        self->priv->path = g_strdup (path);
-       self->priv->status = status;
+
+       /* Map GgitStatusFlags to AnjutaVcsStatus:
+        *   1. Swap bits 1 and 2 to map modified and added in the index
+        *   2. Swap bits 8 and 9 to map modified and added in the working tree
+        *   3. Make sure that bits 3 (removed in index) and 10 (removed in 
+        *      working tree) are preserved because they map to AnjutaVcsStatus 
+        *          without changes.
+        */
+       status = (status & 0x0102) >> 1 | (status & 0x0081) << 1 | (status & 0x0204);
+
+       /* The index values are in the lower three bytes; the working tree values
+        * are in bits 8-10. */
+       self->priv->index_status = (status & 0x0007);
+       self->priv->working_tree_status = (status & 0x0380) >> 7;
        
        return self;
 }
@@ -79,8 +93,28 @@ git_status_get_path (GitStatus *self)
 }
 
 AnjutaVcsStatus
+git_status_get_index_status (GitStatus *self)
+{
+       return self->priv->index_status;
+}
+
+AnjutaVcsStatus
+git_status_get_working_tree_status (GitStatus *self)
+{
+       return self->priv->working_tree_status;
+}
+
+AnjutaVcsStatus
 git_status_get_vcs_status (GitStatus *self)
 {
-       return self->priv->status;
+       /* A "new" status in the working tree section means the file is untracked */
+       if (self->priv->working_tree_status & ANJUTA_VCS_STATUS_ADDED)
+               return ANJUTA_VCS_STATUS_UNVERSIONED;
+       else 
+       {
+               /* Otherwise, favor the index value over the working tree value */
+               return self->priv->index_status == 0 ? self->priv->working_tree_status :
+                          self->priv->index_status;
+       }
 }
 
diff --git a/plugins/git/git-status.h b/plugins/git/git-status.h
index c931bdd..2b0ea31 100644
--- a/plugins/git/git-status.h
+++ b/plugins/git/git-status.h
@@ -27,6 +27,7 @@
 
 #include <glib-object.h>
 #include <libanjuta/anjuta-vcs-status-tree-view.h>
+#include <libgit2-glib/ggit-repository.h>
 
 G_BEGIN_DECLS
 
@@ -54,9 +55,11 @@ struct _GitStatus
 };
 
 GType git_status_get_type (void) G_GNUC_CONST;
-GitStatus *git_status_new (const gchar *path, AnjutaVcsStatus status);
+GitStatus *git_status_new (const gchar *path, GgitStatusFlags status);
 gchar *git_status_get_path (GitStatus *self);
 AnjutaVcsStatus git_status_get_vcs_status (GitStatus *self);
+AnjutaVcsStatus git_status_get_index_status (GitStatus *self);
+AnjutaVcsStatus git_status_get_working_tree_status (GitStatus *self);
 
 G_END_DECLS
 
diff --git a/plugins/git/git-vcs-interface.c b/plugins/git/git-vcs-interface.c
index 5f1eca5..b9748c7 100644
--- a/plugins/git/git-vcs-interface.c
+++ b/plugins/git/git-vcs-interface.c
@@ -190,7 +190,7 @@ static void
 on_status_command_data_arrived (AnjutaCommand *command, 
                                                                IAnjutaVcsStatusCallback callback)
 {
-       GQueue *status_queue;
+       GAsyncQueue *status_queue;
        GitStatus *status;
        const gchar *working_directory;
        gchar *path;
@@ -199,9 +199,8 @@ on_status_command_data_arrived (AnjutaCommand *command,
        
        status_queue = git_status_command_get_status_queue (GIT_STATUS_COMMAND (command));
        
-       while (g_queue_peek_head (status_queue))
+       while ((status = g_async_queue_try_pop (status_queue)))
        {
-               status = g_queue_pop_head (status_queue);
                working_directory = g_object_get_data (G_OBJECT (command), 
                                                       "working-directory");
                path = git_status_get_path (status);
@@ -234,23 +233,39 @@ git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
                                           gpointer user_data, GCancellable *cancel,
                                           AnjutaAsyncNotify *notify, GError **err)
 {
+       Git *plugin;
        gchar *path;
-       GitStatusCommand *status_command;
+       const gchar *project_root_directory;
+       GitCommand *status_command;
+
+       plugin = ANJUTA_PLUGIN_GIT (obj);
+       
+       g_return_if_fail (plugin->thread_pool);
+       
+       path = g_file_get_relative_path (plugin->project_root_file, file);
+       project_root_directory = ANJUTA_PLUGIN_GIT (obj)->project_root_directory;
+       status_command = git_status_command_new (GIT_STATUS_SECTION_UNTRACKED,
+                                                path);
 
-       path = g_file_get_path (file);
-       status_command = git_status_command_new (path, ~0);
+       g_object_set_data (G_OBJECT (status_command), "user-data", user_data);
+       g_object_set_data_full (G_OBJECT (status_command), "working-directory",
+                               g_strdup (project_root_directory), g_free);
 
        g_free (path);
 
-       g_object_set_data (G_OBJECT (status_command), "user-data", user_data);
-       g_object_set_data (G_OBJECT (status_command), "working-directory",
-                          ANJUTA_PLUGIN_GIT (obj)->project_root_directory);
 
        g_signal_connect (G_OBJECT (status_command), "data-arrived",
                          G_CALLBACK (on_status_command_data_arrived),
                          callback);
 
-       g_signal_connect (G_OBJECT (status_command), "command-finished",
+       if (notify)
+       {
+               g_signal_connect_swapped (G_OBJECT (status_command), "finished",
+                                         G_CALLBACK (anjuta_async_notify_notify_finished),
+                                         notify);
+       }
+
+       g_signal_connect (G_OBJECT (status_command), "finished",
                          G_CALLBACK (g_object_unref),
                          NULL);
 
@@ -263,15 +278,7 @@ git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
        }
 #endif
 
-       if (notify)
-       {
-               g_signal_connect_swapped (G_OBJECT (status_command), "command-finished",
-                                         G_CALLBACK (anjuta_async_notify_notify_finished),
-                                         notify);
-       }
-
-       anjuta_command_queue_push (ANJUTA_PLUGIN_GIT (obj)->command_queue,
-                                  ANJUTA_COMMAND (status_command));
+       git_thread_pool_push (plugin->thread_pool, status_command);
 }
 
 void 
diff --git a/plugins/git/plugin.c b/plugins/git/plugin.c
index 4d2daae..503bc43 100644
--- a/plugins/git/plugin.c
+++ b/plugins/git/plugin.c
@@ -641,17 +641,16 @@ on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
 {
        Git *git_plugin;
        gchar *project_root_uri;
-       GFile *file;
        GFile *repository_file;
        
        git_plugin = ANJUTA_PLUGIN_GIT (plugin);
        
        g_free (git_plugin->project_root_directory);
        project_root_uri = g_value_dup_string (value);
-       file = g_file_new_for_uri (project_root_uri);
-       repository_file = g_file_get_child (file, ".git");
+       git_plugin->project_root_file = g_file_new_for_uri (project_root_uri);
+       repository_file = g_file_get_child (git_plugin->project_root_file, ".git");
        
-       git_plugin->project_root_directory = g_file_get_path (file);
+       git_plugin->project_root_directory = g_file_get_path (git_plugin->project_root_file);
        git_plugin->repository = ggit_repository_open (repository_file, NULL);
 
        if (git_plugin->repository)
@@ -661,7 +660,6 @@ on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
                gtk_widget_set_sensitive (git_plugin->command_bar, TRUE);
        }
        
-       g_object_unref (file);
        g_object_unref (repository_file);
        
        g_free (project_root_uri);
@@ -672,12 +670,6 @@ on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
        g_object_set (G_OBJECT (git_plugin->remote_branch_list_command),
                      "working-directory", git_plugin->project_root_directory, 
                      NULL);
-       g_object_set (G_OBJECT (git_plugin->commit_status_command),
-                     "working-directory", git_plugin->project_root_directory,
-                     NULL);
-       g_object_set (G_OBJECT (git_plugin->not_updated_status_command),
-                     "working-directory", git_plugin->project_root_directory,
-                     NULL);
        g_object_set (G_OBJECT (git_plugin->remote_list_command),
                      "working-directory", git_plugin->project_root_directory,
                      NULL);
@@ -692,13 +684,11 @@ on_project_root_added (AnjutaPlugin *plugin, const gchar *name,
                      NULL);
 
        anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->local_branch_list_command));
-       anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->commit_status_command));
        anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->remote_list_command));
        anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->tag_list_command));
        anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->stash_list_command));
        anjuta_command_start_automatic_monitor (ANJUTA_COMMAND (git_plugin->ref_command));
        anjuta_command_start (ANJUTA_COMMAND (git_plugin->local_branch_list_command));
-       anjuta_command_start (ANJUTA_COMMAND (git_plugin->commit_status_command));
        anjuta_command_start (ANJUTA_COMMAND (git_plugin->remote_list_command));
        anjuta_command_start (ANJUTA_COMMAND (git_plugin->tag_list_command));
        anjuta_command_start (ANJUTA_COMMAND (git_plugin->stash_list_command));
@@ -731,12 +721,12 @@ on_project_root_removed (AnjutaPlugin *plugin, const gchar *name,
        }
        
        anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->local_branch_list_command));
-       anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->commit_status_command));
        anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->remote_list_command));
        anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->tag_list_command));
        anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->stash_list_command));
        anjuta_command_stop_automatic_monitor (ANJUTA_COMMAND (git_plugin->ref_command));
        
+       g_clear_object (&git_plugin->project_root_file);
        g_free (git_plugin->project_root_directory);
        git_plugin->project_root_directory = NULL;
 
@@ -954,13 +944,6 @@ git_activate_plugin (AnjutaPlugin *plugin)
                          G_CALLBACK (on_branch_list_command_data_arrived),
                          plugin);
 
-       /* Create the status list commands. The different commands correspond to 
-        * the two different sections in status output: Changes to be committed 
-        * (staged) and Changed but not updated (unstaged.) */
-       git_plugin->commit_status_command = git_status_command_new (NULL,
-                                                                   GIT_STATUS_SECTION_COMMIT);
-       git_plugin->not_updated_status_command = git_status_command_new (NULL,
-                                                                        GIT_STATUS_SECTION_NOT_UPDATED);
 
        /* Remote list command */
        git_plugin->remote_list_command = git_remote_list_command_new (NULL);
@@ -968,12 +951,6 @@ git_activate_plugin (AnjutaPlugin *plugin)
        /* Ref list command. used to keep the log up to date */
        git_plugin->ref_command = git_ref_command_new (NULL);
 
-       /* Always run the not updated commmand after the commmit command. */
-       g_signal_connect (G_OBJECT (git_plugin->commit_status_command), 
-                         "command-finished",
-                         G_CALLBACK (run_next_command),
-                         git_plugin->not_updated_status_command);
-
        /* Tag list command */
        git_plugin->tag_list_command = git_tag_list_command_new (NULL);
 
@@ -1077,13 +1054,12 @@ git_deactivate_plugin (AnjutaPlugin *plugin)
 
        g_object_unref (git_plugin->local_branch_list_command);
        g_object_unref (git_plugin->remote_branch_list_command);
-       g_object_unref (git_plugin->commit_status_command);
-       g_object_unref (git_plugin->not_updated_status_command);
        g_object_unref (git_plugin->remote_list_command);
        g_object_unref (git_plugin->tag_list_command);
        g_object_unref (git_plugin->stash_list_command);
        g_object_unref (git_plugin->ref_command);
        
+       g_clear_object (&git_plugin->project_root_file);
        g_free (git_plugin->project_root_directory);
        g_free (git_plugin->current_editor_filename);
        
@@ -1098,6 +1074,8 @@ git_finalize (GObject *obj)
        git_plugin = ANJUTA_PLUGIN_GIT (obj);
 
        g_object_unref (git_plugin->command_queue);
+
+       git_threads_shutdown ();
        
        G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
@@ -1123,6 +1101,8 @@ git_instance_init (GObject *obj)
 {
        Git *plugin = ANJUTA_PLUGIN_GIT (obj);
 
+       git_threads_init ();
+
        plugin->command_queue = anjuta_command_queue_new (ANJUTA_COMMAND_QUEUE_EXECUTE_AUTOMATIC);
        plugin->settings = g_settings_new (SETTINGS_SCHEMA);
 
diff --git a/plugins/git/plugin.h b/plugins/git/plugin.h
index cbf0a1d..8368d4a 100644
--- a/plugins/git/plugin.h
+++ b/plugins/git/plugin.h
@@ -61,6 +61,7 @@ struct _Git
 {
        AnjutaPlugin parent;
        
+       GFile *project_root_file;
        gchar *project_root_directory;
        gchar *current_editor_filename;
 
@@ -95,8 +96,6 @@ struct _Git
         * way of handling project (working directory) changes */
        GitBranchListCommand *local_branch_list_command;
        GitBranchListCommand *remote_branch_list_command;
-       GitStatusCommand *commit_status_command;
-       GitStatusCommand *not_updated_status_command;
        GitRemoteListCommand *remote_list_command;
        GitTagListCommand *tag_list_command;
        GitStashListCommand *stash_list_command;


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