[anjuta] git: Fix bgo 680401: Git plugin (Status) doesn't work with git version 1.7.10.4
- From: James Liggett <jrliggett src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta] git: Fix bgo 680401: Git plugin (Status) doesn't work with git version 1.7.10.4
- Date: Thu, 23 Aug 2012 02:29:49 +0000 (UTC)
commit 9ae59b43dffe7ff16c29f7430b5dc2907b4bd1be
Author: James Liggett <jrliggett cox net>
Date: Wed Aug 22 19:25:48 2012 -0700
git: Fix bgo 680401: Git plugin (Status) doesn't work with git version 1.7.10.4
Use the --porcelain mode for the status command. The manpage says the format of
porcelain status output should never change, so we should never have this
problem again.
plugins/git/git-status-command.c | 187 +++++++++++++++++++-------------------
plugins/git/git-status.c | 50 +----------
plugins/git/git-status.h | 3 +-
plugins/git/git-vcs-interface.c | 43 ++++-----
4 files changed, 118 insertions(+), 165 deletions(-)
---
diff --git a/plugins/git/git-status-command.c b/plugins/git/git-status-command.c
index 60ca5da..53d6b76 100644
--- a/plugins/git/git-status-command.c
+++ b/plugins/git/git-status-command.c
@@ -24,24 +24,15 @@
#include "git-status-command.h"
-#define STATUS_REGEX "(modified|new file|deleted|unmerged|both modified|both added|both deleted): (.*)"
-#define UNTRACKED_FILES_REGEX "(?:#\\t)(.*)"
-#define SECTION_COMMIT_REGEX "Changes to be committed:"
-#define SECTION_NOT_UPDATED_REGEX "Changed but not updated:|Changes not staged for commit:"
-#define SECTION_UNTRACKED_REGEX "Untracked files:"
+#define STATUS_REGEX "((M|A|D|U|\\?|\\s){2}) (.*)"
struct _GitStatusCommandPriv
{
GQueue *status_queue;
- GHashTable *path_lookup_table;
GitStatusSections sections;
- GitStatusSections current_section;
- GRegex *current_section_regex;
+ GHashTable *status_codes;
+ GHashTable *conflict_codes;
GRegex *status_regex;
- GRegex *untracked_files_regex;
- GRegex *section_commit_regex;
- GRegex *section_not_updated_regex;
- GRegex *section_untracked_regex;
GFileMonitor *head_monitor;
GFileMonitor *index_monitor;
};
@@ -52,6 +43,7 @@ static guint
git_status_command_run (AnjutaCommand *command)
{
git_command_add_arg (GIT_COMMAND (command), "status");
+ git_command_add_arg (GIT_COMMAND (command), "--porcelain");
return 0;
}
@@ -66,66 +58,82 @@ git_status_command_handle_output (GitCommand *git_command, const gchar *output)
gchar *path;
self = GIT_STATUS_COMMAND (git_command);
-
- /* See if the section has changed */
- if (g_regex_match (self->priv->section_commit_regex, output, 0, NULL))
- {
- self->priv->current_section = GIT_STATUS_SECTION_COMMIT;
- self->priv->current_section_regex = self->priv->status_regex;
- return;
- }
- else if (g_regex_match (self->priv->section_not_updated_regex, output, 0,
- NULL))
- {
- self->priv->current_section = GIT_STATUS_SECTION_NOT_UPDATED;
- self->priv->current_section_regex = self->priv->status_regex;
- return;
- }
- else if (g_regex_match (self->priv->section_untracked_regex, output, 0,
- NULL))
- {
- self->priv->current_section = GIT_STATUS_SECTION_UNTRACKED;
- self->priv->current_section_regex = self->priv->untracked_files_regex;
- return;
- }
-
- if (self->priv->sections & self->priv->current_section)
+ status_object = NULL;
+
+ if (g_regex_match (self->priv->status_regex, output, 0, &match_info))
{
- if (g_regex_match (self->priv->current_section_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] == ' ')
{
- if (self->priv->current_section_regex == self->priv->status_regex)
+ /* Changed but not updated */
+ if (self->priv->sections & GIT_STATUS_SECTION_NOT_UPDATED)
{
- status = g_match_info_fetch (match_info, 1);
- path = g_match_info_fetch (match_info, 2);
+ status_object = git_status_new(path,
+ GPOINTER_TO_INT (g_hash_table_lookup (self->priv->status_codes,
+ GINT_TO_POINTER (status[1]))));
}
- else
+ }
+ 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] == '?')
{
- status = g_strdup ("untracked");
- path = g_match_info_fetch (match_info, 1);
+ if (self->priv->sections & GIT_STATUS_SECTION_UNTRACKED)
+ {
+ status_object = git_status_new(path,
+ ANJUTA_VCS_STATUS_UNVERSIONED);
+ }
}
-
- /* Git sometimes mentions paths twice in status output. This can
- * happen, for example, where there is a conflict, in which case a
- * path would show up as both "unmerged" and "modified." */
- g_strchug (path);
-
- if (!g_hash_table_lookup_extended (self->priv->path_lookup_table,
- path, NULL, NULL))
+ else if (g_hash_table_lookup_extended (self->priv->conflict_codes, status,
+ NULL, NULL))
{
- status_object = git_status_new (path, status);
- g_queue_push_tail (self->priv->status_queue, status_object);
- g_hash_table_insert (self->priv->path_lookup_table,
- g_strdup (path), NULL);
- anjuta_command_notify_data_arrived (ANJUTA_COMMAND (git_command));
+ /* 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);
+ }
}
-
- g_free (status);
- g_free (path);
+ else
+ {
+ status_object = git_status_new(path,
+ GPOINTER_TO_INT(g_hash_table_lookup (self->priv->status_codes,
+ GINT_TO_POINTER (status[0]))));
+ }
+
}
- g_match_info_free (match_info);
+
+
+ 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);
+
}
static void
@@ -133,18 +141,33 @@ git_status_command_init (GitStatusCommand *self)
{
self->priv = g_new0 (GitStatusCommandPriv, 1);
self->priv->status_queue = g_queue_new ();
- self->priv->path_lookup_table = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free, NULL);
+
self->priv->status_regex = g_regex_new (STATUS_REGEX, 0, 0, NULL);
- self->priv->untracked_files_regex = g_regex_new (UNTRACKED_FILES_REGEX,
- 0, 0, NULL);
- self->priv->section_commit_regex = g_regex_new (SECTION_COMMIT_REGEX, 0, 0,
- NULL);
- self->priv->section_not_updated_regex = g_regex_new (SECTION_NOT_UPDATED_REGEX,
- 0, 0, NULL);
- self->priv->section_untracked_regex = g_regex_new (SECTION_UNTRACKED_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);
}
static void
@@ -253,38 +276,19 @@ git_status_command_data_arrived (AnjutaCommand *command)
git_status_command_clear_output (GIT_STATUS_COMMAND (command));
}
-static void
-git_status_command_finished (AnjutaCommand *command, guint return_code)
-{
- GitStatusCommand *self;
-
- self = GIT_STATUS_COMMAND (command);
-
- g_hash_table_remove_all (self->priv->path_lookup_table);
-
- ANJUTA_COMMAND_CLASS (git_status_command_parent_class)->command_finished (command,
- return_code);
-}
static void
git_status_command_finalize (GObject *object)
{
GitStatusCommand *self;
- GList *current_status;
self = GIT_STATUS_COMMAND (object);
- current_status = self->priv->status_queue->head;
git_status_command_clear_output (self);
git_status_command_stop_automatic_monitor (ANJUTA_COMMAND (self));
g_queue_free (self->priv->status_queue);
- g_hash_table_destroy (self->priv->path_lookup_table);
g_regex_unref (self->priv->status_regex);
- g_regex_unref (self->priv->untracked_files_regex);
- g_regex_unref (self->priv->section_commit_regex);
- g_regex_unref (self->priv->section_not_updated_regex);
- g_regex_unref (self->priv->section_untracked_regex);
g_free (self->priv);
@@ -302,7 +306,6 @@ git_status_command_class_init (GitStatusCommandClass *klass)
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->command_finished = git_status_command_finished;
command_class->start_automatic_monitor = git_status_command_start_automatic_monitor;
command_class->stop_automatic_monitor = git_status_command_stop_automatic_monitor;
}
diff --git a/plugins/git/git-status.c b/plugins/git/git-status.c
index c6766cb..5f2307a 100644
--- a/plugins/git/git-status.c
+++ b/plugins/git/git-status.c
@@ -27,7 +27,6 @@
struct _GitStatusPriv
{
gchar *path;
- GHashTable *status_lookup_table;
AnjutaVcsStatus status;
};
@@ -37,43 +36,6 @@ static void
git_status_init (GitStatus *self)
{
self->priv = g_new0 (GitStatusPriv, 1);
- self->priv->status_lookup_table = g_hash_table_new (g_str_hash,
- g_str_equal);
-
- /* Set up mappings between git status and VCS status codes */
- g_hash_table_insert (self->priv->status_lookup_table,
- "modified",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_MODIFIED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "new file",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_ADDED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "deleted",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_DELETED));
-
- /* Git 1.7 added a bunch of different conflicted states */
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "unmerged",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_CONFLICTED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "both modified",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_CONFLICTED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "both added",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_CONFLICTED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "both deleted",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_CONFLICTED));
-
- g_hash_table_insert (self->priv->status_lookup_table,
- "untracked",
- GINT_TO_POINTER (ANJUTA_VCS_STATUS_UNVERSIONED));
}
static void
@@ -84,7 +46,6 @@ git_status_finalize (GObject *object)
self = GIT_STATUS (object);
g_free (self->priv->path);
- g_hash_table_destroy (self->priv->status_lookup_table);
g_free (self->priv);
G_OBJECT_CLASS (git_status_parent_class)->finalize (object);
@@ -99,15 +60,14 @@ git_status_class_init (GitStatusClass *klass)
}
GitStatus *
-git_status_new (const gchar *path, const gchar *status)
+git_status_new (const gchar *path, AnjutaVcsStatus status)
{
GitStatus *self;
self = g_object_new (GIT_TYPE_STATUS, NULL);
self->priv->path = g_strdup (path);
- self->priv->status = GPOINTER_TO_INT (g_hash_table_lookup (self->priv->status_lookup_table,
- status));
+ self->priv->status = status;
return self;
}
@@ -124,9 +84,3 @@ git_status_get_vcs_status (GitStatus *self)
return self->priv->status;
}
-gboolean
-git_status_is_working_directory_descendant (GitStatus *self)
-{
- return (!g_str_has_prefix (self->priv->path, "../") &&
- !g_str_has_prefix (self->priv->path, "./"));
-}
diff --git a/plugins/git/git-status.h b/plugins/git/git-status.h
index 88d0b5f..c931bdd 100644
--- a/plugins/git/git-status.h
+++ b/plugins/git/git-status.h
@@ -54,10 +54,9 @@ struct _GitStatus
};
GType git_status_get_type (void) G_GNUC_CONST;
-GitStatus *git_status_new (const gchar *path, const gchar *status);
+GitStatus *git_status_new (const gchar *path, AnjutaVcsStatus status);
gchar *git_status_get_path (GitStatus *self);
AnjutaVcsStatus git_status_get_vcs_status (GitStatus *self);
-gboolean git_status_is_working_directory_descendant (GitStatus *self);
G_END_DECLS
diff --git a/plugins/git/git-vcs-interface.c b/plugins/git/git-vcs-interface.c
index 3620596..5f1eca5 100644
--- a/plugins/git/git-vcs-interface.c
+++ b/plugins/git/git-vcs-interface.c
@@ -192,6 +192,7 @@ on_status_command_data_arrived (AnjutaCommand *command,
{
GQueue *status_queue;
GitStatus *status;
+ const gchar *working_directory;
gchar *path;
gchar *full_path;
GFile *file;
@@ -201,32 +202,29 @@ on_status_command_data_arrived (AnjutaCommand *command,
while (g_queue_peek_head (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);
+ full_path = g_strconcat (working_directory, G_DIR_SEPARATOR_S, path,
+ NULL);
+ file = g_file_new_for_path (full_path);
- if (git_status_is_working_directory_descendant (status))
- {
- path = git_status_get_path (status);
- full_path = g_strconcat (g_object_get_data (G_OBJECT (command), "working-directory"),
- G_DIR_SEPARATOR_S, path, NULL);
- file = g_file_new_for_path (full_path);
-
- DEBUG_PRINT ("Working directory: %s\n", (gchar *) g_object_get_data (G_OBJECT (command), "working-directory"));
- DEBUG_PRINT ("File %s Status %i\n", full_path, git_status_get_vcs_status (status));
-
- if (file)
- {
- callback (file,
- git_status_get_vcs_status (status),
- g_object_get_data (G_OBJECT (command), "user-data"));
+ DEBUG_PRINT ("Working directory: %s\n", working_directory);
+ DEBUG_PRINT ("File %s Status %i\n", full_path, git_status_get_vcs_status (status));
- g_object_unref (file);
- }
+ if (file)
+ {
+ callback (file,
+ git_status_get_vcs_status (status),
+ g_object_get_data (G_OBJECT (command), "user-data"));
- g_free (path);
- g_free (full_path);
+ g_object_unref (file);
}
+
+ g_free (path);
+ g_free (full_path);
g_object_unref (status);
-
}
}
@@ -245,9 +243,8 @@ git_ivcs_query_status (IAnjutaVcs *obj, GFile *file,
g_free (path);
g_object_set_data (G_OBJECT (status_command), "user-data", user_data);
- g_object_set_data_full (G_OBJECT (status_command), "working-directory",
- g_file_get_path (file),
- (GDestroyNotify) g_free);
+ 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),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]