[anjuta] git: Properly show changes for files in both the working tree and index, with tests



commit ecf91e0b7ffc394b9f660a49a3892ba1794518a1
Author: James Liggett <jrliggett cox net>
Date:   Tue Oct 1 01:28:27 2013 -0700

    git: Properly show changes for files in both the working tree and index, with tests
    
    We used to always show a file once and only once in the status view, but it is
    valid for git to show modifications for the same file in both the working tree
    and index. Unit tests are included to verify that we are parsing status
    information correctly for these cases.

 configure.ac                     |    1 +
 gtester.mk                       |  117 +++++++++++++++++++++++
 plugins/git/Makefile.am          |    6 +-
 plugins/git/git-status-command.c |  124 ++----------------------
 plugins/git/git-status-command.h |   14 +---
 plugins/git/git-status-factory.c |  148 +++++++++++++++++++++++++++++
 plugins/git/git-status-factory.h |   59 ++++++++++++
 plugins/git/git-status-pane.c    |  193 ++++++++++++++++++++++----------------
 plugins/git/git-status.c         |   25 ++++-
 plugins/git/git-status.h         |    5 +-
 plugins/git/git-vcs-interface.c  |    2 +-
 plugins/git/plugin.c             |   29 ++-----
 plugins/git/plugin.h             |    3 +-
 plugins/git/tests/Makefile.am    |   17 ++++
 plugins/git/tests/testgit.c      |  169 +++++++++++++++++++++++++++++++++
 15 files changed, 670 insertions(+), 242 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 08d77af..ed618bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -840,6 +840,7 @@ plugins/cvs-plugin/Makefile
 plugins/subversion/Makefile
 plugins/git/Makefile
 plugins/git/images/Makefile
+plugins/git/tests/Makefile
 plugins/sourceview/Makefile
 plugins/terminal/Makefile
 plugins/tools/Makefile
diff --git a/gtester.mk b/gtester.mk
new file mode 100644
index 0000000..6c24bfb
--- /dev/null
+++ b/gtester.mk
@@ -0,0 +1,117 @@
+# GLIB - Library of useful C routines
+
+GTESTER = gtester                      # for non-GLIB packages
+GTESTER_REPORT = gtester-report        # for non-GLIB packages
+NULL =
+
+# initialize variables for unconditional += appending
+BUILT_SOURCES =
+BUILT_EXTRA_DIST =
+CLEANFILES = *.log *.trs
+DISTCLEANFILES =
+MAINTAINERCLEANFILES =
+EXTRA_DIST =
+TEST_PROGS =
+
+noinst_LTLIBRARIES =
+noinst_PROGRAMS =
+noinst_SCRIPTS =
+noinst_DATA =
+
+check_LTLIBRARIES =
+check_PROGRAMS =
+check_SCRIPTS =
+check_DATA =
+
+TESTS =
+
+### testing rules
+
+# test: run all tests in cwd and subdirs
+test: test-nonrecursive
+       @ for subdir in $(SUBDIRS) . ; do \
+           test "$$subdir" = "." -o "$$subdir" = "po" || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+         done
+
+# test-nonrecursive: run tests only in cwd
+test-nonrecursive: ${TEST_PROGS}
+       @test -z "${TEST_PROGS}" || G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" 
G_DEBUG=gc-friendly MALLOC_CHECK_=2 MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) ${GTESTER} --verbose 
${TEST_PROGS}
+
+# test-report: run tests in subdirs and generate report
+# perf-report: run tests in subdirs with -m perf and generate report
+# full-report: like test-report: with -m perf and -m slow
+test-report perf-report full-report:   ${TEST_PROGS}
+       @test -z "${TEST_PROGS}" || { \
+         case $@ in \
+         test-report) test_options="-k";; \
+         perf-report) test_options="-k -m=perf";; \
+         full-report) test_options="-k -m=perf -m=slow";; \
+         esac ; \
+         if test -z "$$GTESTER_LOGDIR" ; then  \
+           G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" ${GTESTER} --verbose 
$$test_options -o test-report.xml ${TEST_PROGS} ; \
+         elif test -n "${TEST_PROGS}" ; then \
+           G_TEST_SRCDIR="$(abs_srcdir)" G_TEST_BUILDDIR="$(abs_builddir)" ${GTESTER} --verbose 
$$test_options -o `mktemp "$$GTESTER_LOGDIR/log-XXXXXX"` ${TEST_PROGS} ; \
+         fi ; \
+       }
+       @ ignore_logdir=true ; \
+         if test -z "$$GTESTER_LOGDIR" ; then \
+           GTESTER_LOGDIR=`mktemp -d "\`pwd\`/.testlogs-XXXXXX"`; export GTESTER_LOGDIR ; \
+           ignore_logdir=false ; \
+         fi ; \
+         if test -d "$(top_srcdir)/.git" ; then \
+           REVISION=`git describe` ; \
+         else \
+           REVISION=$(VERSION) ; \
+         fi ; \
+         for subdir in $(SUBDIRS) . ; do \
+           test "$$subdir" = "." -o "$$subdir" = "po" || \
+           ( cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $@ ) || exit $? ; \
+         done ; \
+         $$ignore_logdir || { \
+           echo '<?xml version="1.0"?>'              > $  xml ; \
+           echo '<report-collection>'               >> $  xml ; \
+           echo '<info>'                            >> $  xml ; \
+           echo '  <package>$(PACKAGE)</package>'   >> $  xml ; \
+           echo '  <version>$(VERSION)</version>'   >> $  xml ; \
+           echo "  <revision>$$REVISION</revision>" >> $  xml ; \
+           echo '</info>'                           >> $  xml ; \
+           for lf in `ls -L "$$GTESTER_LOGDIR"/.` ; do \
+             sed '1,1s/^<?xml\b[^>?]*?>//' <"$$GTESTER_LOGDIR"/"$$lf" >> $  xml ; \
+           done ; \
+           echo >> $  xml ; \
+           echo '</report-collection>' >> $  xml ; \
+           rm -rf "$$GTESTER_LOGDIR"/ ; \
+           ${GTESTER_REPORT} --version 2>/dev/null 1>&2 ; test "$$?" != 0 || ${GTESTER_REPORT} $  xml >$  
html ; \
+         }
+.PHONY: test test-report perf-report full-report test-nonrecursive
+
+.PHONY: lcov genlcov lcov-clean
+# use recursive makes in order to ignore errors during check
+lcov:
+       -$(MAKE) $(AM_MAKEFLAGS) -k check
+       $(MAKE) $(AM_MAKEFLAGS) genlcov
+
+# we have to massage the lcov.info file slightly to hide the effect of libtool
+# placing the objects files in the .libs/ directory separate from the *.c
+# we also have to delete tests/.libs/libmoduletestplugin_*.gcda
+genlcov:
+       rm -f $(top_builddir)/tests/.libs/libmoduletestplugin_*.gcda
+       $(LTP) --directory $(top_builddir) --capture --output-file glib-lcov.info --test-name GLIB_PERF 
--no-checksum --compat-libtool
+       LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory glib-lcov --title "GLib Code 
Coverage" --legend --show-details glib-lcov.info
+       @echo "file://$(abs_top_builddir)/glib-lcov/index.html"
+
+lcov-clean:
+       -$(LTP) --directory $(top_builddir) -z
+       -rm -rf glib-lcov.info glib-lcov
+       -find -name '*.gcda' -print | xargs rm
+
+# run tests in cwd as part of make check
+check-local: test-nonrecursive
+
+
+%.test: %$(EXEEXT) Makefile
+       $(AM_V_GEN) (echo '[Test]' > $  tmp; \
+       echo 'Type=session' >> $  tmp; \
+       echo 'Exec=$(installed_testdir)/$<' >> $  tmp; \
+       mv $  tmp $@)
diff --git a/plugins/git/Makefile.am b/plugins/git/Makefile.am
index ea25f83..21889d0 100644
--- a/plugins/git/Makefile.am
+++ b/plugins/git/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = images
+SUBDIRS = images tests
 
 # Plugin glade file
 git_gladedir = $(anjuta_glade_dir)
@@ -226,7 +226,9 @@ libanjuta_git_la_SOURCES = \
        git-patch-series-pane.c \
        git-patch-series-pane.h \
        git-apply-mailbox-pane.c \
-       git-apply-mailbox-pane.h
+       git-apply-mailbox-pane.h \
+       git-status-factory.c \
+       git-status-factory.h
        
 
 libanjuta_git_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
diff --git a/plugins/git/git-status-command.c b/plugins/git/git-status-command.c
index 2f8833c..cd99596 100644
--- a/plugins/git/git-status-command.c
+++ b/plugins/git/git-status-command.c
@@ -24,15 +24,10 @@
 
 #include "git-status-command.h"
 
-#define STATUS_REGEX "((M|A|D|U|\\?|\\s){2}) (.*)"
-
 struct _GitStatusCommandPriv
 {
        GQueue *status_queue;
-       GitStatusSections sections;
-       GHashTable *status_codes;
-       GHashTable *conflict_codes;
-       GRegex *status_regex;
+       GitStatusFactory *factory;
        GFileMonitor *head_monitor;
        GFileMonitor *index_monitor;
 };
@@ -52,88 +47,16 @@ static void
 git_status_command_handle_output (GitCommand *git_command, const gchar *output)
 {
        GitStatusCommand *self;
-       GMatchInfo *match_info;
        GitStatus *status_object;
-       gchar *status;
-       gchar *path;
        
        self = GIT_STATUS_COMMAND (git_command);
-       status_object = NULL;
-
-       if (g_regex_match (self->priv->status_regex, output, 0, &match_info))
+       status_object = git_status_factory_create_status (self->priv->factory,
+                                                         output);
+       if (status_object)
        {
-               /* 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_queue_push_tail (self->priv->status_queue, status_object);
+               anjuta_command_notify_data_arrived (ANJUTA_COMMAND (self));
        }
-
-       g_match_info_free (match_info);
-       
 }
 
 static void
@@ -141,33 +64,7 @@ git_status_command_init (GitStatusCommand *self)
 {
        self->priv = g_new0 (GitStatusCommandPriv, 1);
        self->priv->status_queue = g_queue_new ();
-       
-       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_DELETED));
-
-       /* 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);
+       self->priv->factory = git_status_factory_new ();
 }
 
 static void
@@ -288,7 +185,7 @@ git_status_command_finalize (GObject *object)
        git_status_command_stop_automatic_monitor (ANJUTA_COMMAND (self));
        
        g_queue_free (self->priv->status_queue);
-       g_regex_unref (self->priv->status_regex);
+       g_object_unref (self->priv->factory);
        
        g_free (self->priv);
 
@@ -312,8 +209,7 @@ git_status_command_class_init (GitStatusCommandClass *klass)
 
 
 GitStatusCommand *
-git_status_command_new (const gchar *working_directory, 
-                                               GitStatusSections sections)
+git_status_command_new (const gchar *working_directory)
 {
        GitStatusCommand *self;
        
@@ -322,8 +218,6 @@ git_status_command_new (const gchar *working_directory,
                                                 "single-line-output", TRUE,
                                                 NULL);
        
-       self->priv->sections = sections;
-       
        return self;
 }
 
diff --git a/plugins/git/git-status-command.h b/plugins/git/git-status-command.h
index cf08d2d..352a825 100644
--- a/plugins/git/git-status-command.h
+++ b/plugins/git/git-status-command.h
@@ -27,7 +27,7 @@
 
 #include <glib-object.h>
 #include "git-command.h"
-#include "git-status.h"
+#include "git-status-factory.h"
 
 G_BEGIN_DECLS
 
@@ -42,15 +42,6 @@ typedef struct _GitStatusCommandClass GitStatusCommandClass;
 typedef struct _GitStatusCommand GitStatusCommand;
 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)
-} GitStatusSections;
-
 struct _GitStatusCommandClass
 {
        GitCommandClass parent_class;
@@ -64,8 +55,7 @@ struct _GitStatusCommand
 };
 
 GType git_status_command_get_type (void) G_GNUC_CONST;
-GitStatusCommand *git_status_command_new (const gchar *working_directory,
-                                                                                 GitStatusSections sections);
+GitStatusCommand *git_status_command_new (const gchar *working_directory);
 GQueue *git_status_command_get_status_queue (GitStatusCommand *self);
 
 G_END_DECLS
diff --git a/plugins/git/git-status-factory.c b/plugins/git/git-status-factory.c
new file mode 100644
index 0000000..af490f5
--- /dev/null
+++ b/plugins/git/git-status-factory.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
+/*
+ * git-status-factory.c
+ * Copyright (C) 2013 James Liggett <jim jim-dekstop>
+ *
+ * anjuta 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.
+ * 
+ * anjuta 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/>.
+ */
+
+#include "git-status-factory.h"
+
+#define STATUS_REGEX "((M|A|D|U|\\?|\\s){2}) (.*)"
+
+struct _GitStatusFactoryPrivate
+{
+       GHashTable *status_codes;
+       GHashTable *conflict_codes;
+       GRegex *status_regex;
+};
+
+
+G_DEFINE_TYPE (GitStatusFactory, git_status_factory, G_TYPE_OBJECT);
+
+static void
+git_status_factory_init (GitStatusFactory *self)
+{
+       self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GIT_TYPE_STATUS_FACTORY, GitStatusFactoryPrivate);
+
+       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_DELETED));
+
+       g_hash_table_insert (self->priv->status_codes,
+                            GINT_TO_POINTER (' '),
+                            GINT_TO_POINTER (ANJUTA_VCS_STATUS_NONE));
+
+       g_hash_table_insert (self->priv->status_codes,
+                            GINT_TO_POINTER ('?'),
+                            GINT_TO_POINTER (ANJUTA_VCS_STATUS_UNVERSIONED));
+
+       /* 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);
+}
+
+static void
+git_status_factory_finalize (GObject *object)
+{
+       GitStatusFactory *self;
+
+       self = GIT_STATUS_FACTORY (object);
+
+       g_regex_unref (self->priv->status_regex);
+       g_hash_table_destroy (self->priv->status_codes);
+       g_hash_table_destroy (self->priv->conflict_codes);
+
+       G_OBJECT_CLASS (git_status_factory_parent_class)->finalize (object);
+}
+
+static void
+git_status_factory_class_init (GitStatusFactoryClass *klass)
+{
+       GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+       g_type_class_add_private (klass, sizeof (GitStatusFactoryPrivate));
+
+       object_class->finalize = git_status_factory_finalize;
+}
+
+
+GitStatusFactory *
+git_status_factory_new (void)
+{
+       return g_object_new (GIT_TYPE_STATUS_FACTORY, NULL);
+}
+
+GitStatus *
+git_status_factory_create_status (GitStatusFactory *self, 
+                                  const gchar *status_line)
+{
+       GMatchInfo *match_info;
+       GitStatus *status_object;
+       gchar *status;
+       gchar *path;
+
+       if (g_regex_match (self->priv->status_regex, status_line, 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 (!g_hash_table_lookup_extended (self->priv->conflict_codes, status, 
+                                                  NULL, NULL))
+               {
+                       status_object = git_status_new (path, 
+                                                       GPOINTER_TO_INT (g_hash_table_lookup 
(self->priv->status_codes, GINT_TO_POINTER (status[0]))),
+                                                       GPOINTER_TO_INT (g_hash_table_lookup 
(self->priv->status_codes, GINT_TO_POINTER (status[1]))));
+               }
+               else
+               {
+                       /* Show conflicts in the working tree only */
+                       status_object = git_status_new (path, ANJUTA_VCS_STATUS_NONE, 
+                                                       ANJUTA_VCS_STATUS_CONFLICTED);
+               }
+
+               g_free (status);
+               g_free (path);
+       }
+       else
+       {
+               status_object = git_status_new ("", ANJUTA_VCS_STATUS_NONE, 
+                                               ANJUTA_VCS_STATUS_NONE);
+       }
+
+       g_match_info_free (match_info);
+
+       return status_object;
+}
+
diff --git a/plugins/git/git-status-factory.h b/plugins/git/git-status-factory.h
new file mode 100644
index 0000000..05ab231
--- /dev/null
+++ b/plugins/git/git-status-factory.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-  */
+/*
+ * git-status-factory.h
+ * Copyright (C) 2013 James Liggett <jim jim-dekstop>
+ *
+ * anjuta 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.
+ * 
+ * anjuta 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 _GIT_STATUS_FACTORY_H_
+#define _GIT_STATUS_FACTORY_H_
+
+#include <glib-object.h>
+#include "git-status.h"
+
+G_BEGIN_DECLS
+
+#define GIT_TYPE_STATUS_FACTORY             (git_status_factory_get_type ())
+#define GIT_STATUS_FACTORY(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIT_TYPE_STATUS_FACTORY, 
GitStatusFactory))
+#define GIT_STATUS_FACTORY_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GIT_TYPE_STATUS_FACTORY, 
GitStatusFactoryClass))
+#define GIT_IS_STATUS_FACTORY(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIT_TYPE_STATUS_FACTORY))
+#define GIT_IS_STATUS_FACTORY_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GIT_TYPE_STATUS_FACTORY))
+#define GIT_STATUS_FACTORY_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GIT_TYPE_STATUS_FACTORY, 
GitStatusFactoryClass))
+
+typedef struct _GitStatusFactoryClass GitStatusFactoryClass;
+typedef struct _GitStatusFactory GitStatusFactory;
+typedef struct _GitStatusFactoryPrivate GitStatusFactoryPrivate;
+
+struct _GitStatusFactoryClass
+{
+       GObjectClass parent_class;
+};
+
+struct _GitStatusFactory
+{
+       GObject parent_instance;
+
+       GitStatusFactoryPrivate *priv;
+};
+
+GType git_status_factory_get_type (void) G_GNUC_CONST;
+GitStatusFactory * git_status_factory_new (void);
+GitStatus *git_status_factory_create_status (GitStatusFactory *self, 
+                                             const gchar *status_line);
+
+G_END_DECLS
+
+#endif /* _GIT_STATUS_FACTORY_H_ */
+
diff --git a/plugins/git/git-status-pane.c b/plugins/git/git-status-pane.c
index 1419d20..62eee97 100644
--- a/plugins/git/git-status-pane.c
+++ b/plugins/git/git-status-pane.c
@@ -61,8 +61,7 @@ struct _GitStatusPanePriv
 
        /* Iters for the two sections: Changes to be committed and Changed but not
         * updated. Status items will be children of these two iters. */
-       GtkTreePath *commit_section;
-       GtkTreePath *not_updated_section;
+       GtkTreePath *parents[3];
 
        /* Hash tables that show which items are selected in each section */
        GHashTable *selected_commit_items;
@@ -319,14 +318,15 @@ git_status_pane_expand_placeholders (GitStatusPane *self)
 {
        GtkTreeView *status_view;
 
-       if (self->priv->commit_section && self->priv->not_updated_section)
+       if (self->priv->parents[STATUS_TYPE_COMMIT] && 
+           self->priv->parents[STATUS_TYPE_NOT_UPDATED])
        {
                status_view = GTK_TREE_VIEW (gtk_builder_get_object (self->priv->builder,
                                                                     "status_view"));
 
-               gtk_tree_view_expand_row (status_view, self->priv->commit_section, 
+               gtk_tree_view_expand_row (status_view, self->priv->parents[STATUS_TYPE_COMMIT], 
                                          self->priv->show_diff);
-               gtk_tree_view_expand_row (status_view, self->priv->not_updated_section, 
+               gtk_tree_view_expand_row (status_view, self->priv->parents[STATUS_TYPE_NOT_UPDATED], 
                                          self->priv->show_diff);
        }
 }
@@ -385,21 +385,75 @@ on_diff_command_finished (AnjutaCommand *command, guint return_code,
        }
 }
 
+static GtkTreePath *
+add_status_item (GtkTreeStore *status_model, const gchar *path,  
+                 AnjutaVcsStatus status, GtkTreePath *parent, StatusType type)
+{
+       GtkTreeIter parent_iter;
+       GtkTreeIter iter;
+
+       g_return_val_if_fail (parent, NULL);
+       g_return_val_if_fail (status != ANJUTA_VCS_STATUS_NONE, NULL);
+
+       gtk_tree_model_get_iter (GTK_TREE_MODEL (status_model), &parent_iter, 
+                                parent);
+       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);
+
+       return gtk_tree_model_get_path (GTK_TREE_MODEL (status_model), &iter);
+}
+
+static void
+setup_diff_command (GitStatusPane *self, const gchar *working_directory,
+                    const gchar *path, AnjutaVcsStatus status, StatusType type,
+                    const GtkTreePath *parent_path)
+{
+       GtkTreeModel *status_model;
+       GitDiffCommand *diff_command;
+
+       g_return_if_fail (type != STATUS_TYPE_NONE);
+
+       status_model = GTK_TREE_MODEL (gtk_builder_get_object (self->priv->builder,
+                                                              "status_model"));
+       if (status != ANJUTA_VCS_STATUS_DELETED)
+       {
+               diff_command = git_diff_command_new (working_directory, path,
+                                                    type == STATUS_TYPE_NOT_UPDATED ? GIT_DIFF_WORKING_TREE 
: GIT_DIFF_INDEX);
+
+               g_signal_connect (G_OBJECT (diff_command), "command-finished",
+                                 G_CALLBACK (on_diff_command_finished),
+                                 self);
+
+               g_signal_connect (G_OBJECT (diff_command), "command-finished",
+                                 G_CALLBACK (g_object_unref),
+                                 NULL);
+
+               g_object_set_data_full (G_OBJECT (diff_command), "parent-path", 
+                                       gtk_tree_path_copy (parent_path),
+                                       (GDestroyNotify) gtk_tree_path_free);
+
+               g_object_set_data (G_OBJECT (diff_command), "model", status_model);
+               g_hash_table_insert (self->priv->diff_commands, diff_command, NULL);
+       }
+}
+
 static void
 git_status_pane_add_status_items (GitStatusPane *self, 
-                                                 StatusType type, 
                                   GitStatusCommand *status_command)
 {
        GtkTreeStore *status_model;
        gchar *working_directory;
        GQueue *output;
-       GtkTreePath *parent;
        GitStatus *status_object;
-       AnjutaVcsStatus status;
+       AnjutaVcsStatus index_status;
+       AnjutaVcsStatus working_tree_status;
        gchar *path;
-       GtkTreeIter parent_iter;
-       GtkTreeIter iter;
-       GitDiffCommand *diff_command;
+       GtkTreePath *tree_path;
 
        status_model = GTK_TREE_STORE (gtk_builder_get_object (self->priv->builder,
                                                               "status_model"));
@@ -408,44 +462,41 @@ git_status_pane_add_status_items (GitStatusPane *self,
                      NULL);
 
        output = git_status_command_get_status_queue (status_command);
-       parent = type == STATUS_TYPE_NOT_UPDATED ? self->priv->not_updated_section : 
self->priv->commit_section;
 
        while (g_queue_peek_head (output))
        {
                status_object = g_queue_pop_head (output);
-               status = git_status_get_vcs_status (status_object);
+               index_status = git_status_get_index_status (status_object);
+               working_tree_status = git_status_get_working_tree_status (status_object);
                path = git_status_get_path (status_object);
 
-               gtk_tree_model_get_iter (GTK_TREE_MODEL (status_model), &parent_iter, 
-                                        parent);
-               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);
-
-               if (status != ANJUTA_VCS_STATUS_DELETED)
+               if (index_status != ANJUTA_VCS_STATUS_NONE)
                {
-                       diff_command = git_diff_command_new (working_directory, path,
-                                                            type == STATUS_TYPE_NOT_UPDATED ? 
GIT_DIFF_WORKING_TREE : GIT_DIFF_INDEX);
+                       if (!(index_status & (ANJUTA_VCS_STATUS_CONFLICTED | ANJUTA_VCS_STATUS_UNVERSIONED)))
+                       {
+                               tree_path = add_status_item (status_model, path, index_status,
+                                                            self->priv->parents[STATUS_TYPE_COMMIT],
+                                                            STATUS_TYPE_COMMIT);
 
-                       g_signal_connect (G_OBJECT (diff_command), "command-finished",
-                                         G_CALLBACK (on_diff_command_finished),
-                                         self);
+                               setup_diff_command (self, working_directory, path, index_status, 
+                                                   STATUS_TYPE_COMMIT, tree_path);
+                               gtk_tree_path_free (tree_path);
+                       }
+               }
 
-                       g_signal_connect (G_OBJECT (diff_command), "command-finished",
-                                         G_CALLBACK (g_object_unref),
-                                         NULL);
 
-                       g_object_set_data_full (G_OBJECT (diff_command), "parent-path", 
-                                               gtk_tree_model_get_path (GTK_TREE_MODEL (status_model), 
-                                                                        &iter),
-                                               (GDestroyNotify) gtk_tree_path_free);
+               if (working_tree_status != ANJUTA_VCS_STATUS_NONE)
+               {
+                       if (!(working_tree_status & (ANJUTA_VCS_STATUS_CONFLICTED | 
ANJUTA_VCS_STATUS_UNVERSIONED)))
+                       {
+                               tree_path = add_status_item (status_model, path, working_tree_status, 
+                                                            self->priv->parents[STATUS_TYPE_NOT_UPDATED],
+                                                            STATUS_TYPE_NOT_UPDATED);
 
-                       g_object_set_data (G_OBJECT (diff_command), "model", status_model);
-                       g_hash_table_insert (self->priv->diff_commands, diff_command, NULL);
+                               setup_diff_command (self, working_directory, path, index_status, 
+                                                   STATUS_TYPE_NOT_UPDATED, tree_path);
+                               gtk_tree_path_free (tree_path);
+                       }
                }
                
                g_free (path);
@@ -456,24 +507,16 @@ git_status_pane_add_status_items (GitStatusPane *self,
 }
 
 static void
-on_commit_status_data_arrived (AnjutaCommand *command, 
-                               GitStatusPane *self)
-{
-       git_status_pane_add_status_items (self, STATUS_TYPE_COMMIT, 
-                                         GIT_STATUS_COMMAND (command));
-}
-
-static void
-on_not_updated_status_data_arrived (AnjutaCommand *command,
-                                    GitStatusPane *self)
+on_status_command_data_arrived (AnjutaCommand *command, 
+                                GitStatusPane *self)
 {
-       git_status_pane_add_status_items (self, STATUS_TYPE_NOT_UPDATED, 
+       git_status_pane_add_status_items (self, 
                                          GIT_STATUS_COMMAND (command));
 }
 
 static void
-on_not_updated_command_finished (AnjutaCommand *command, guint return_code,
-                                 GitStatusPane *self)
+on_status_command_finished (AnjutaCommand *command, guint return_code,
+                            GitStatusPane *self)
 {
        if (g_hash_table_size (self->priv->diff_commands) > 0)
        {
@@ -500,8 +543,8 @@ git_status_pane_clear (GitStatusPane *self)
        gtk_tree_view_set_model (status_view, NULL);
        gtk_tree_store_clear (status_model);
 
-       gtk_tree_path_free (self->priv->commit_section);
-       gtk_tree_path_free (self->priv->not_updated_section);
+       gtk_tree_path_free (self->priv->parents[STATUS_TYPE_COMMIT]);
+       gtk_tree_path_free (self->priv->parents[STATUS_TYPE_NOT_UPDATED]);
        
        gtk_tree_store_append (status_model, &iter, NULL);
        gtk_tree_store_set (status_model, &iter, 
@@ -511,7 +554,7 @@ git_status_pane_clear (GitStatusPane *self)
                            COL_TYPE, STATUS_TYPE_NONE,
                            -1);
        
-       self->priv->commit_section = gtk_tree_model_get_path (GTK_TREE_MODEL (status_model), &iter);
+       self->priv->parents[STATUS_TYPE_COMMIT] = gtk_tree_model_get_path (GTK_TREE_MODEL (status_model), 
&iter);
 
        gtk_tree_store_append (status_model, &iter, NULL);
        gtk_tree_store_set (status_model, &iter, 
@@ -521,7 +564,7 @@ git_status_pane_clear (GitStatusPane *self)
                            COL_TYPE, STATUS_TYPE_NONE,
                            -1);
 
-       self->priv->not_updated_section = gtk_tree_model_get_path (GTK_TREE_MODEL (status_model), &iter);
+       self->priv->parents[STATUS_TYPE_NOT_UPDATED] = gtk_tree_model_get_path (GTK_TREE_MODEL 
(status_model), &iter);
 
        g_hash_table_remove_all (self->priv->selected_commit_items);
        g_hash_table_remove_all (self->priv->selected_not_updated_items);
@@ -533,30 +576,19 @@ git_status_pane_set_selected_column_state (GitStatusPane *self,
                                            gboolean state)
 {
        GtkTreeModel *status_model;
-       GtkTreePath *section;
        GtkTreeIter parent_iter;
        gint i;
        GtkTreeIter iter;
        gchar *path;
        AnjutaVcsStatus status;
 
+       g_return_if_fail (type != STATUS_TYPE_NONE);
+
        status_model = GTK_TREE_MODEL (gtk_builder_get_object (self->priv->builder,
                                                               "status_model"));
 
-       switch (type)
-       {
-               case STATUS_TYPE_COMMIT:
-                       section = self->priv->commit_section;
-                       break;
-               case STATUS_TYPE_NOT_UPDATED:
-                       section = self->priv->not_updated_section;
-                       break;
-               default:
-                       return;
-                       break;
-       }
-
-       gtk_tree_model_get_iter (status_model, &parent_iter, section);
+       gtk_tree_model_get_iter (status_model, &parent_iter, 
+                                self->priv->parents[type]);
        
        i = 0;
 
@@ -908,8 +940,8 @@ git_status_pane_finalize (GObject *object)
        self = GIT_STATUS_PANE (object);
 
        g_object_unref (self->priv->builder);
-       gtk_tree_path_free (self->priv->commit_section);
-       gtk_tree_path_free (self->priv->not_updated_section);
+       gtk_tree_path_free (self->priv->parents[STATUS_TYPE_COMMIT]);
+       gtk_tree_path_free (self->priv->parents[STATUS_TYPE_NOT_UPDATED]);
        g_hash_table_destroy (self->priv->selected_commit_items);
        g_hash_table_destroy (self->priv->selected_not_updated_items);
        g_hash_table_destroy (self->priv->diff_commands);
@@ -929,7 +961,7 @@ git_status_pane_refresh (AnjutaDockPane *pane)
 
        /* Don't refresh again if another refresh is still in progress */
        if (g_hash_table_size (self->priv->diff_commands) == 0)
-               anjuta_command_start (ANJUTA_COMMAND (plugin->commit_status_command));
+               anjuta_command_start (ANJUTA_COMMAND (plugin->status_command));
        
 }
 
@@ -965,24 +997,19 @@ git_status_pane_new (Git *plugin)
        status_diff_button = gtk_builder_get_object (self->priv->builder, 
                                                     "status_diff_button");
 
-       g_signal_connect_swapped (G_OBJECT (plugin->commit_status_command), 
+       g_signal_connect_swapped (G_OBJECT (plugin->status_command), 
                                  "command-started",
                                  G_CALLBACK (git_status_pane_clear),
                                  self);
 
-       g_signal_connect (G_OBJECT (plugin->not_updated_status_command),
+       g_signal_connect (G_OBJECT (plugin->status_command),
                          "command-finished",
-                         G_CALLBACK (on_not_updated_command_finished),
-                         self);
-
-       g_signal_connect (G_OBJECT (plugin->commit_status_command),
-                         "data-arrived",
-                         G_CALLBACK (on_commit_status_data_arrived),
+                         G_CALLBACK (on_status_command_finished),
                          self);
 
-       g_signal_connect (G_OBJECT (plugin->not_updated_status_command),
+       g_signal_connect (G_OBJECT (plugin->status_command),
                          "data-arrived",
-                         G_CALLBACK (on_not_updated_status_data_arrived),
+                         G_CALLBACK (on_status_command_data_arrived),
                          self);
 
        g_settings_bind (plugin->settings, "show-status-diff",
diff --git a/plugins/git/git-status.c b/plugins/git/git-status.c
index 5f2307a..123a5fb 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,16 @@ git_status_class_init (GitStatusClass *klass)
 }
 
 GitStatus *
-git_status_new (const gchar *path, AnjutaVcsStatus status)
+git_status_new (const gchar *path, AnjutaVcsStatus index_status,
+                AnjutaVcsStatus working_tree_status)
 {
        GitStatus *self;
        
        self = g_object_new (GIT_TYPE_STATUS, NULL);
        
        self->priv->path = g_strdup (path);
-       self->priv->status = status;
+       self->priv->index_status = index_status;
+       self->priv->working_tree_status = working_tree_status;
        
        return self;
 }
@@ -79,8 +82,22 @@ 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;
+       /* Favor the index status over the working tree */
+       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..699355a 100644
--- a/plugins/git/git-status.h
+++ b/plugins/git/git-status.h
@@ -54,9 +54,12 @@ 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, AnjutaVcsStatus index_status,
+                           AnjutaVcsStatus working_tree_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 d1d7cb4..3836cd2 100644
--- a/plugins/git/git-vcs-interface.c
+++ b/plugins/git/git-vcs-interface.c
@@ -238,7 +238,7 @@ git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
        GitStatusCommand *status_command;
 
        path = g_file_get_path (file);
-       status_command = git_status_command_new (path, ~0);
+       status_command = git_status_command_new (path);
 
        g_free (path);
 
diff --git a/plugins/git/plugin.c b/plugins/git/plugin.c
index 6598bb8..3a00448 100644
--- a/plugins/git/plugin.c
+++ b/plugins/git/plugin.c
@@ -634,10 +634,7 @@ 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),
+       g_object_set (G_OBJECT (git_plugin->status_command),
                      "working-directory", git_plugin->project_root_directory,
                      NULL);
        g_object_set (G_OBJECT (git_plugin->remote_list_command),
@@ -654,13 +651,13 @@ 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->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->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));
@@ -681,7 +678,7 @@ on_project_root_removed (AnjutaPlugin *plugin, const gchar *name,
        status = anjuta_shell_get_status (plugin->shell, NULL);
        
        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->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));
@@ -910,13 +907,8 @@ 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);
+       /* Status list commands */
+       git_plugin->status_command = git_status_command_new (NULL);
 
        /* Remote list command */
        git_plugin->remote_list_command = git_remote_list_command_new (NULL);
@@ -924,12 +916,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);
 
@@ -1029,8 +1015,7 @@ 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->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);
diff --git a/plugins/git/plugin.h b/plugins/git/plugin.h
index 41325cf..fc639d8 100644
--- a/plugins/git/plugin.h
+++ b/plugins/git/plugin.h
@@ -90,8 +90,7 @@ 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;
+       GitStatusCommand *status_command;
        GitRemoteListCommand *remote_list_command;
        GitTagListCommand *tag_list_command;
        GitStashListCommand *stash_list_command;
diff --git a/plugins/git/tests/Makefile.am b/plugins/git/tests/Makefile.am
new file mode 100644
index 0000000..a936c52
--- /dev/null
+++ b/plugins/git/tests/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/gtester.mk
+
+AM_CPPFLAGS = $(LIBANJUTA_CFLAGS)
+
+noinst_PROGRAMS += $(TEST_PROGS)
+
+TEST_PROGS += \
+       testgit
+
+testgit_SOURCES = \
+       testgit.c   \
+       ../git-status-factory.c \
+       ../git-status-factory.h \
+       ../git-status.c \
+       ../git-status.h 
+
+testgit_LDADD = $(LIBANJUTA_LIBS) $(ANJUTA_LIBS) 
\ No newline at end of file
diff --git a/plugins/git/tests/testgit.c b/plugins/git/tests/testgit.c
new file mode 100644
index 0000000..5c01047
--- /dev/null
+++ b/plugins/git/tests/testgit.c
@@ -0,0 +1,169 @@
+#include <glib.h>
+#include "../git-status-factory.h"
+
+static void 
+check_status (AnjutaVcsStatus index, AnjutaVcsStatus working_tree, 
+              AnjutaVcsStatus expected_index, 
+              AnjutaVcsStatus expected_working_tree,
+              gchar *test_type)
+              
+{
+       if (g_test_verbose ())
+               g_print ("Testing %s\n", test_type);
+
+       g_assert_cmpint (expected_index, ==, index);
+       g_assert_cmpint (expected_working_tree, ==, working_tree);
+}
+
+static void
+test_status (void)
+{
+       GitStatusFactory *factory;
+       GitStatus *status;
+       AnjutaVcsStatus working_tree, index;
+
+       factory = git_status_factory_new ();
+       status = git_status_factory_create_status (factory, 
+                                                                                          " M 
plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_MODIFIED, 
+                     "modified in working tree");
+
+       status = git_status_factory_create_status (factory, 
+                                                                                          "A  
plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_ADDED, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     "added to index");
+
+       status = git_status_factory_create_status (factory,
+                                                  "D  plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_DELETED, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     "removed from index");
+
+       status = git_status_factory_create_status (factory,
+                                                  "MM plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_MODIFIED, 
+                     ANJUTA_VCS_STATUS_MODIFIED, 
+                     "modified in index and working tree");
+
+       status = git_status_factory_create_status (factory,
+                                                  "?? plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_UNVERSIONED, 
+                     ANJUTA_VCS_STATUS_UNVERSIONED, 
+                     "untracked");
+
+       status = git_status_factory_create_status (factory,
+                                                  "DD plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: both deleted");
+
+       status = git_status_factory_create_status (factory,
+                                                  "AU plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: added by us");
+
+       status = git_status_factory_create_status (factory,
+                                                  "UD plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: deleted by them");
+
+       status = git_status_factory_create_status (factory,
+                                                  "UA plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: added by them");
+
+       status = git_status_factory_create_status (factory,
+                                                  "DU plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: deleted by us");
+
+       status = git_status_factory_create_status (factory,
+                                                  "AA plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: both added");
+
+       status = git_status_factory_create_status (factory,
+                                                  "UU plugins/git/plugin.c");
+       index = git_status_get_index_status (status);
+       working_tree = git_status_get_working_tree_status (status);
+
+       g_object_unref (status);
+       check_status (index, working_tree, 
+                     ANJUTA_VCS_STATUS_NONE, 
+                     ANJUTA_VCS_STATUS_CONFLICTED, 
+                     "conflict: both modified");
+       
+       g_object_unref (factory);
+}
+
+int
+main (int argc, char *argv[])
+{
+       g_test_init (&argc, &argv, NULL);
+
+       g_test_add_func ("/Git/Status", test_status);
+
+       return g_test_run ();
+}
\ No newline at end of file


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