[Xfce4-commits] <thunar-vcs-plugin:master> * thunar-vcs-plugin/tvp-git-action.c tvp-git-helper/main.c tvp-git-helper/tgh-common.[ch] tvp-git-helper/tgh-blame{, -dialog}.[ch]: Added blame action.

Peter de Ridder noreply at xfce.org
Sun Oct 25 13:40:01 CET 2009


Updating branch refs/heads/master
         to ef4219bf85cd30b554dab08ba8e3d6730b51304b (commit)
       from 76ce9ffac4c45b6990b605bde754a36c73ef73aa (commit)

commit ef4219bf85cd30b554dab08ba8e3d6730b51304b
Author: Peter de Ridder <peter at xfce.org>
Date:   Sun Oct 25 14:38:00 2009 +0100

    * thunar-vcs-plugin/tvp-git-action.c tvp-git-helper/main.c
      tvp-git-helper/tgh-common.[ch]
      tvp-git-helper/tgh-blame{,-dialog}.[ch]: Added blame action.

 ChangeLog                                          |    3 +
 README                                             |    2 +-
 thunar-vcs-plugin/tvp-git-action.c                 |   20 ++++
 tvp-git-helper/Makefile.am                         |    4 +
 tvp-git-helper/main.c                              |   17 +++
 .../{tgh-notify-dialog.c => tgh-blame-dialog.c}    |  103 ++++++++++++--------
 tvp-git-helper/tgh-blame-dialog.h                  |   53 ++++++++++
 tvp-git-helper/tgh-blame.c                         |   95 ++++++++++++++++++
 tvp-git-helper/{tgh-log.h => tgh-blame.h}          |    8 +-
 tvp-git-helper/tgh-common.c                        |   63 ++++++++++++
 tvp-git-helper/tgh-common.h                        |    2 +
 11 files changed, 323 insertions(+), 47 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8de9565..31a0089 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2009-10-25	Peter de Ridder <peter at xfce.org>
 
+	* thunar-vcs-plugin/tvp-git-action.c tvp-git-helper/main.c
+	  tvp-git-helper/tgh-common.[ch]
+	  tvp-git-helper/tgh-blame{,-dialog}.[ch]: Added blame action.
 	* tvp-git-helper/tgh-clone.c: Fixed a memory leak.
 	* tvp-git-helper/tgh-log-dialog.c: Removed expander column.
 	* tvp-svn-helper/tsh-log-dialog.c: Changed "File" to "Path".
diff --git a/README b/README
index 3404d57..5ec7ec6 100644
--- a/README
+++ b/README
@@ -9,7 +9,7 @@ The current features are:
   export, import, lock, log, move, properties, relocate, resolved, revert,
   status, switch, unlock, update.
 - Subversion info in file properties dialog.
-- Limmited git support: add, branch, clone, log, reset, stash, status.
+- Limmited git support: add, blame, branch, clone, log, reset, stash, status.
 
 
 Usage
diff --git a/thunar-vcs-plugin/tvp-git-action.c b/thunar-vcs-plugin/tvp-git-action.c
index c0d6022..ce1edba 100644
--- a/thunar-vcs-plugin/tvp-git-action.c
+++ b/thunar-vcs-plugin/tvp-git-action.c
@@ -55,6 +55,8 @@ struct _TvpGitAction
 
     struct {
         unsigned is_parent : 1;
+        unsigned is_directory : 1;
+        unsigned is_file : 1;
     } property;
 
     GList *files;
@@ -65,6 +67,8 @@ struct _TvpGitAction
 
 enum {
     PROPERTY_IS_PARENT = 1,
+    PROPERTY_IS_DIRECTORY,
+    PROPERTY_IS_FILE
 };
 
 
@@ -116,6 +120,12 @@ tvp_git_action_class_init (TvpGitActionClass *klass)
     g_object_class_install_property (gobject_class, PROPERTY_IS_PARENT,
             g_param_spec_boolean ("is-parent", "", "", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
 
+    g_object_class_install_property (gobject_class, PROPERTY_IS_DIRECTORY,
+            g_param_spec_boolean ("is-directory", "", "", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+    g_object_class_install_property (gobject_class, PROPERTY_IS_FILE,
+            g_param_spec_boolean ("is-file", "", "", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
     action_signal[SIGNAL_NEW_PROCESS] = g_signal_new("new-process", G_OBJECT_CLASS_TYPE(gobject_class), G_SIGNAL_RUN_FIRST,
             0, NULL, NULL, tsh_cclosure_marshal_VOID__POINTER_STRING, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
 
@@ -153,6 +163,8 @@ tvp_git_action_new (const gchar *name,
             "name", name,
             "label", label,
             "is-parent", is_parent,
+            "is-directory", is_direcotry,
+            "is-file", is_file,
 #if !GTK_CHECK_VERSION(2,9,0)
             "stock-id", "git",
 #else
@@ -188,6 +200,12 @@ tvp_git_action_set_property (GObject *object, guint property_id, const GValue *v
         case PROPERTY_IS_PARENT:
             TVP_GIT_ACTION (object)->property.is_parent = g_value_get_boolean (value)?1:0;
             break;
+        case PROPERTY_IS_DIRECTORY:
+            TVP_GIT_ACTION (object)->property.is_directory = g_value_get_boolean (value)?1:0;
+            break;
+        case PROPERTY_IS_FILE:
+            TVP_GIT_ACTION (object)->property.is_file = g_value_get_boolean (value)?1:0;
+            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
             break;
@@ -245,6 +263,8 @@ tvp_git_action_create_menu_item (GtkAction *action)
 
     add_subaction (action, GTK_MENU_SHELL(menu), "tvp::add", Q_("Menu|Add"), _("Add"), GTK_STOCK_ADD, "--add");
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::bisect", Q_("Menu|Bisect"), _("Bisect"), NULL, _("Bisect"));
+  if (tvp_action->property.is_file)
+    add_subaction (action, GTK_MENU_SHELL (menu), "tvp::blame", Q_("Menu|Blame"), _("Blame"), GTK_STOCK_INDEX, "--blame");
   if(tvp_action->property.is_parent)
     add_subaction (action, GTK_MENU_SHELL(menu), "tvp::branch", Q_("Menu|Branch"), _("Branch"), NULL, "--branch");
     add_subaction_u(GTK_MENU_SHELL(menu), "tvp::checkout", Q_("Menu|Checkout"), _("Checkout"), GTK_STOCK_CONNECT, _("Checkout"));
diff --git a/tvp-git-helper/Makefile.am b/tvp-git-helper/Makefile.am
index ada3794..12a1932 100644
--- a/tvp-git-helper/Makefile.am
+++ b/tvp-git-helper/Makefile.am
@@ -16,6 +16,8 @@ tvp_git_helper_SOURCES =						\
 	main.c								\
 	tgh-add.h							\
 	tgh-add.c							\
+	tgh-blame.h							\
+	tgh-blame.c							\
 	tgh-branch.h							\
 	tgh-branch.c							\
 	tgh-clone.h							\
@@ -32,6 +34,8 @@ tvp_git_helper_SOURCES =						\
 	tgh-status.c							\
 	tgh-dialog-common.h						\
 	tgh-dialog-common.c						\
+	tgh-blame-dialog.h						\
+	tgh-blame-dialog.c						\
 	tgh-branch-dialog.h						\
 	tgh-branch-dialog.c						\
 	tgh-file-selection-dialog.h					\
diff --git a/tvp-git-helper/main.c b/tvp-git-helper/main.c
index 3313699..c1e6458 100644
--- a/tvp-git-helper/main.c
+++ b/tvp-git-helper/main.c
@@ -31,6 +31,7 @@
 #include "tgh-common.h"
 
 #include "tgh-add.h"
+#include "tgh-blame.h"
 #include "tgh-branch.h"
 #include "tgh-clone.h"
 #include "tgh-log.h"
@@ -55,6 +56,7 @@ int main (int argc, char *argv[])
   /* CMD-line options */
   gboolean print_version = FALSE;
   gboolean add = FALSE;
+  gboolean blame = FALSE;
   gboolean branch = FALSE;
   gboolean clone = FALSE;
   gboolean log = FALSE;
@@ -82,6 +84,12 @@ int main (int argc, char *argv[])
 
   GOptionEntry branch_options_table[] =
   {
+    { "blame", '\0', 0, G_OPTION_ARG_NONE, &blame, N_("Execute blame action"), NULL },
+    { NULL, '\0', 0, 0, NULL, NULL, NULL }
+  };
+
+  GOptionEntry blame_options_table[] =
+  {
     { "branch", '\0', 0, G_OPTION_ARG_NONE, &branch, N_("Execute branch action"), NULL },
     { NULL, '\0', 0, 0, NULL, NULL, NULL }
   };
@@ -128,6 +136,10 @@ int main (int argc, char *argv[])
   g_option_group_add_entries(option_group, add_options_table);
   g_option_context_add_group(option_context, option_group);
 
+  option_group = g_option_group_new("blame", N_("Blame Related Options:"), N_("Blame"), NULL, NULL);
+  g_option_group_add_entries(option_group, blame_options_table);
+  g_option_context_add_group(option_context, option_group);
+
   option_group = g_option_group_new("branch", N_("Branch Related Options:"), N_("Branch"), NULL, NULL);
   g_option_group_add_entries(option_group, branch_options_table);
   g_option_context_add_group(option_context, option_group);
@@ -169,6 +181,11 @@ int main (int argc, char *argv[])
     has_child = tgh_add(files, &pid);
   }
 
+  if(blame)
+  {
+    has_child = tgh_blame(files, &pid);
+  }
+
   if(branch)
   {
     has_child = tgh_branch(files, &pid);
diff --git a/tvp-git-helper/tgh-notify-dialog.c b/tvp-git-helper/tgh-blame-dialog.c
similarity index 64%
copy from tvp-git-helper/tgh-notify-dialog.c
copy to tvp-git-helper/tgh-blame-dialog.c
index d964321..24adf64 100644
--- a/tvp-git-helper/tgh-notify-dialog.c
+++ b/tvp-git-helper/tgh-blame-dialog.c
@@ -24,11 +24,12 @@
 #include <thunar-vfs/thunar-vfs.h>
 #include <gtk/gtk.h>
 
-#include "tgh-notify-dialog.h"
+#include "tgh-common.h"
+#include "tgh-blame-dialog.h"
 
 static void cancel_clicked (GtkButton*, gpointer);
 
-struct _TghNotifyDialog
+struct _TghBlameDialog
 {
   GtkDialog dialog;
 
@@ -37,12 +38,12 @@ struct _TghNotifyDialog
   GtkWidget *cancel;
 };
 
-struct _TghNotifyDialogClass
+struct _TghBlameDialogClass
 {
   GtkDialogClass dialog_class;
 };
 
-G_DEFINE_TYPE (TghNotifyDialog, tgh_notify_dialog, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE (TghBlameDialog, tgh_blame_dialog, GTK_TYPE_DIALOG)
 
 enum {
   SIGNAL_CANCEL = 0,
@@ -52,28 +53,31 @@ enum {
 static guint signals[SIGNAL_COUNT];
 
 static void
-tgh_notify_dialog_class_init (TghNotifyDialogClass *klass)
+tgh_blame_dialog_class_init (TghBlameDialogClass *klass)
 {
   signals[SIGNAL_CANCEL] = g_signal_new("cancel-clicked",
-    G_OBJECT_CLASS_TYPE (klass),
-    G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-    0, NULL, NULL,
-    g_cclosure_marshal_VOID__VOID,
-    G_TYPE_NONE, 0);
+      G_OBJECT_CLASS_TYPE (klass),
+      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+      0, NULL, NULL,
+      g_cclosure_marshal_VOID__VOID,
+      G_TYPE_NONE, 0);
 }
 
 enum {
-  COLUMN_ACTION = 0,
-  COLUMN_PATH,
+  COLUMN_LINE_NO = 0,
+  COLUMN_REVISION,
+  COLUMN_AUTHOR,
+  COLUMN_DATE,
+  COLUMN_LINE,
   COLUMN_COUNT
 };
 
 static void
-tgh_notify_dialog_init (TghNotifyDialog *dialog)
+tgh_blame_dialog_init (TghBlameDialog *dialog)
 {
-  GtkWidget *button;
   GtkWidget *tree_view;
   GtkWidget *scroll_window;
+  GtkWidget *button;
   GtkCellRenderer *renderer;
   GtkTreeModel *model;
 
@@ -81,20 +85,38 @@ tgh_notify_dialog_init (TghNotifyDialog *dialog)
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
   dialog->tree_view = tree_view = gtk_tree_view_new ();
-  
+
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                               -1, _("Action"),
-                                               renderer, "text",
-                                               COLUMN_ACTION, NULL);
-  
+      -1, _("Line"), renderer,
+      "text", COLUMN_LINE_NO,
+      NULL);
+
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                               -1, _("Path"),
-                                               renderer, "text",
-                                               COLUMN_PATH, NULL);
+      -1, _("Revision"), renderer,
+      "text", COLUMN_REVISION,
+      NULL);
 
-  model = GTK_TREE_MODEL (gtk_list_store_new (COLUMN_COUNT, G_TYPE_STRING, G_TYPE_STRING));
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Author"), renderer,
+      "text", COLUMN_AUTHOR,
+      NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, _("Date"), renderer,
+      "text", COLUMN_DATE,
+      NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
+      -1, NULL, renderer,
+      "text", COLUMN_LINE,
+      NULL);
+
+  model = GTK_TREE_MODEL (gtk_list_store_new (COLUMN_COUNT, G_TYPE_INT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING));
 
   gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
 
@@ -105,7 +127,7 @@ tgh_notify_dialog_init (TghNotifyDialog *dialog)
   gtk_widget_show (tree_view);
   gtk_widget_show (scroll_window);
 
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Notify"));
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Blame"));
 
   dialog->close = button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
   gtk_widget_hide (button);
@@ -119,9 +141,9 @@ tgh_notify_dialog_init (TghNotifyDialog *dialog)
 }
 
 GtkWidget*
-tgh_notify_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags)
+tgh_blame_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags)
 {
-  TghNotifyDialog *dialog = g_object_new (TGH_TYPE_NOTIFY_DIALOG, NULL);
+  TghBlameDialog *dialog = g_object_new (TGH_TYPE_BLAME_DIALOG, NULL);
 
   if(title)
     gtk_window_set_title (GTK_WINDOW(dialog), title);
@@ -142,32 +164,29 @@ tgh_notify_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags fla
 }
 
 void       
-tgh_notify_dialog_add (TghNotifyDialog *dialog, const gchar *action, const gchar *file)
+tgh_blame_dialog_add (TghBlameDialog *dialog, gint64 line_no, const gchar *revision, const gchar *author, const gchar *date, const gchar *line)
 {
   GtkTreeModel *model;
   GtkTreeIter iter;
-  GtkTreePath *path;
 
-  g_return_if_fail (TGH_IS_NOTIFY_DIALOG (dialog));
+  g_return_if_fail (TGH_IS_BLAME_DIALOG (dialog));
 
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
 
   gtk_list_store_append (GTK_LIST_STORE (model), &iter);
   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                      COLUMN_ACTION, action,
-                      COLUMN_PATH, file,
-                      -1);
-
-  path = gtk_tree_model_get_path (model, &iter);
-  gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->tree_view), path, NULL, FALSE, 0, 0);
-
-  gtk_tree_path_free (path);
+      COLUMN_LINE_NO, line_no,
+      COLUMN_REVISION, revision,
+      COLUMN_AUTHOR, author,
+      COLUMN_DATE, date,
+      COLUMN_LINE, line,
+      -1);
 }
 
 void
-tgh_notify_dialog_done (TghNotifyDialog *dialog)
+tgh_blame_dialog_done (TghBlameDialog *dialog)
 {
-  g_return_if_fail (TGH_IS_NOTIFY_DIALOG (dialog));
+  g_return_if_fail (TGH_IS_BLAME_DIALOG (dialog));
 
   gtk_widget_hide (dialog->cancel);
   gtk_widget_show (dialog->close);
@@ -176,11 +195,11 @@ tgh_notify_dialog_done (TghNotifyDialog *dialog)
 static void
 cancel_clicked (GtkButton *button, gpointer user_data)
 {
-  TghNotifyDialog *dialog = TGH_NOTIFY_DIALOG (user_data);
-  
+  TghBlameDialog *dialog = TGH_BLAME_DIALOG (user_data);
+
   gtk_widget_hide (dialog->cancel);
   gtk_widget_show (dialog->close);
-  
+
   g_signal_emit (dialog, signals[SIGNAL_CANCEL], 0);
 }
 
diff --git a/tvp-git-helper/tgh-blame-dialog.h b/tvp-git-helper/tgh-blame-dialog.h
new file mode 100644
index 0000000..b7d50cd
--- /dev/null
+++ b/tvp-git-helper/tgh-blame-dialog.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2006 Peter de Ridder <peter at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TGH_BLAME_DIALOG_H__
+#define __TGH_BLAME_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _TghBlameDialogClass TghBlameDialogClass;
+typedef struct _TghBlameDialog      TghBlameDialog;
+
+#define TGH_TYPE_BLAME_DIALOG            (tgh_blame_dialog_get_type ())
+#define TGH_BLAME_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TGH_TYPE_BLAME_DIALOG, TghBlameDialog))
+#define TGH_BLAME_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TGH_TYPE_BLAME_DIALOG, TghBlameDialogClass))
+#define TGH_IS_BLAME_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TGH_TYPE_BLAME_DIALOG))
+#define TGH_IS_BLAME_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TGH_TYPE_BLAME_DIALOG))
+#define TGH_BLAME_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TGH_TYPE_BLAME_DIALOG, TghBlameDialogClass))
+
+GType      tgh_blame_dialog_get_type  (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GtkWidget* tgh_blame_dialog_new       (const gchar *title,
+                                       GtkWindow *parent,
+                                       GtkDialogFlags flags) G_GNUC_MALLOC G_GNUC_INTERNAL;
+
+void       tgh_blame_dialog_add       (TghBlameDialog *dialog,
+                                       gint64 line_no,
+                                       const gchar *revision,
+                                       const gchar *author,
+                                       const gchar *date,
+                                       const gchar *line);
+void       tgh_blame_dialog_done      (TghBlameDialog *dialog);
+
+G_END_DECLS;
+
+#endif /* !__TGH_BLAME_DIALOG_H__ */
diff --git a/tvp-git-helper/tgh-blame.c b/tvp-git-helper/tgh-blame.c
new file mode 100644
index 0000000..af4c6dd
--- /dev/null
+++ b/tvp-git-helper/tgh-blame.c
@@ -0,0 +1,95 @@
+/*-
+ * This program 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 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <thunar-vfs/thunar-vfs.h>
+
+#include "tgh-common.h"
+#include "tgh-dialog-common.h"
+#include "tgh-blame-dialog.h"
+
+#include "tgh-blame.h"
+
+static gboolean blame_spawn (GtkWidget *dialog, gchar *file, GPid *pid)
+{
+  GError *error = NULL;
+  gint fd_out, fd_err;
+  GIOChannel *chan_out, *chan_err;
+  TghOutputParser *parser;
+  gchar **argv;
+
+  argv = g_new (gchar*, 5);
+
+  argv[0] = "git";
+  argv[1] = "blame";
+  argv[2] = "--";
+  argv[3] = file;
+  argv[4] = NULL;
+
+  if (!g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, &fd_out, &fd_err, &error))
+  {
+    g_free (argv);
+    return FALSE;
+  }
+  g_free (argv);
+
+  parser = tgh_error_parser_new (dialog);
+
+  g_child_watch_add (*pid, (GChildWatchFunc)tgh_child_exit, parser);
+
+  chan_out = g_io_channel_unix_new (fd_out);
+  chan_err = g_io_channel_unix_new (fd_err);
+  g_io_add_watch (chan_out, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, tgh_blame_parser_new (dialog));
+  g_io_add_watch (chan_err, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, parser);
+
+  return TRUE;
+}
+
+gboolean tgh_blame (gchar **files, GPid *pid)
+{
+  GtkWidget *dialog;
+
+  if (!files)
+    return FALSE;
+
+  if (chdir(files[0]))
+  {
+    gchar *dirname = g_dirname (files[0]);
+    if (chdir(dirname))
+    {
+      g_free (dirname);
+      return FALSE;
+    }
+    g_free (dirname);
+  }
+
+  dialog = tgh_blame_dialog_new (NULL, NULL, 0);
+  g_signal_connect (dialog, "cancel-clicked", tgh_cancel, NULL);
+  tgh_dialog_start (GTK_DIALOG(dialog), TRUE);
+
+  return blame_spawn (dialog, files[0], pid);
+}
+
diff --git a/tvp-git-helper/tgh-log.h b/tvp-git-helper/tgh-blame.h
similarity index 86%
copy from tvp-git-helper/tgh-log.h
copy to tvp-git-helper/tgh-blame.h
index 4dc7265..a152116 100644
--- a/tvp-git-helper/tgh-log.h
+++ b/tvp-git-helper/tgh-blame.h
@@ -14,14 +14,14 @@
  * Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __TGH_LOG_H__
-#define __TGH_LOG_H__
+#ifndef __TGH_BLAME_H__
+#define __TGH_BLAME_H__
 
 G_BEGIN_DECLS
 
-gboolean tgh_log (gchar**, GPid*);
+gboolean tgh_blame (gchar **, GPid *);
 
 G_END_DECLS
 
-#endif /*__TGH_LOG_H__*/
+#endif /*__TGH_BLAME_H__*/
 
diff --git a/tvp-git-helper/tgh-common.c b/tvp-git-helper/tgh-common.c
index a7b7d1d..26150ca 100644
--- a/tvp-git-helper/tgh-common.c
+++ b/tvp-git-helper/tgh-common.c
@@ -41,6 +41,7 @@
 #include "tgh-log-dialog.h"
 #include "tgh-branch-dialog.h"
 #include "tgh-stash-dialog.h"
+#include "tgh-blame-dialog.h"
 
 #include "tgh-common.h"
 
@@ -430,6 +431,68 @@ tgh_stash_show_parser_new (GtkWidget *dialog)
   return TGH_OUTPUT_PARSER (parser);
 }
 
+typedef struct {
+  TghOutputParser parent;
+  GtkWidget *dialog;
+} TghBlameParser;
+
+static void
+blame_parser_func (TghBlameParser *parser, gchar *line)
+{
+  TghBlameDialog *dialog = TGH_BLAME_DIALOG (parser->dialog);
+  if (line)
+  {
+    gchar *revision, *name, *date, *text, *ptr;
+    guint64 line_no;
+
+    name = strchr (line, '(');
+    *name++ = '\0';
+
+    revision = g_strstrip (line);
+
+    text = strchr (name, ')');
+    *text = '\0';
+    text += 2;
+    text[strlen (text)-1] = '\0';
+
+    ptr = strrchr (name, ' ');
+    line_no = g_ascii_strtoull (ptr, NULL, 10);
+
+    while (*--ptr == ' ');
+    ptr[1] = '\0';
+
+    date = strrchr (name, ' ');
+    *date = '\0';
+    ptr = strrchr (name, ' ');
+    *date = ' ';
+    *ptr = '\0';
+    date = strrchr (name, ' ');
+    *ptr = ' ';
+    *date++ = '\0';
+
+    name = g_strstrip (name);
+
+    tgh_blame_dialog_add (dialog, line_no, revision, name, date, text);
+  }
+  else
+  {
+    tgh_blame_dialog_done (dialog);
+    g_free (parser);
+  }
+}
+
+TghOutputParser*
+tgh_blame_parser_new (GtkWidget *dialog)
+{
+  TghBlameParser *parser = g_new (TghBlameParser,1);
+
+  TGH_OUTPUT_PARSER (parser)->parse = TGH_OUTPUT_PARSER_FUNC (blame_parser_func);
+
+  parser->dialog = dialog;
+
+  return TGH_OUTPUT_PARSER (parser);
+}
+
 gboolean
 tgh_parse_output_func(GIOChannel *source, GIOCondition condition, gpointer data)
 {
diff --git a/tvp-git-helper/tgh-common.h b/tvp-git-helper/tgh-common.h
index ecdd6b2..d324aee 100644
--- a/tvp-git-helper/tgh-common.h
+++ b/tvp-git-helper/tgh-common.h
@@ -47,6 +47,8 @@ TghOutputParser* tgh_branch_parser_new     (GtkWidget *);
 TghOutputParser* tgh_stash_list_parser_new (GtkWidget *);
 TghOutputParser* tgh_stash_show_parser_new (GtkWidget *);
 
+TghOutputParser* tgh_blame_parser_new      (GtkWidget *);
+
 gboolean tgh_parse_output_func  (GIOChannel *, GIOCondition, gpointer);
 
 G_END_DECLS



More information about the Xfce4-commits mailing list