[Xfce4-commits] <thunar-vcs-plugin:master> Initial implementation of svn diff command.

Stefan Sperling noreply at xfce.org
Mon Sep 3 16:26:04 CEST 2012


Updating branch refs/heads/master
         to e72751addf1a8c0d6253e88ac1f9b5c52c5362b2 (commit)
       from 7d4a5f0c9f4e5bd8494afd882aa8a6964e3122d5 (commit)

commit e72751addf1a8c0d6253e88ac1f9b5c52c5362b2
Author: Stefan Sperling <stsp at stsp.name>
Date:   Mon Aug 20 14:47:04 2012 +0200

    Initial implementation of svn diff command.
    
    Add a diff command to the Subversion context menu which shows
    local changes in the working copy. Diffing to the repository is
    not supported and all svn diff options are hard-coded for now.

 thunar-vcs-plugin/tvp-svn-action.c                 |    6 +-
 tvp-svn-helper/Makefile.am                         |    4 +
 tvp-svn-helper/main.c                              |   19 ++-
 .../tsh-diff-dialog.c                              |  167 ++++++++-------
 tvp-svn-helper/tsh-diff-dialog.h                   |   50 +++++
 tvp-svn-helper/tsh-diff.c                          |  224 ++++++++++++++++++++
 .../tgh-branch.h => tvp-svn-helper/tsh-diff.h      |    9 +-
 7 files changed, 392 insertions(+), 87 deletions(-)

diff --git a/thunar-vcs-plugin/tvp-svn-action.c b/thunar-vcs-plugin/tvp-svn-action.c
index b42840f..a8619e6 100644
--- a/thunar-vcs-plugin/tvp-svn-action.c
+++ b/thunar-vcs-plugin/tvp-svn-action.c
@@ -341,10 +341,10 @@ tvp_svn_action_create_menu_item (GtkAction *action)
   {
     add_subaction (action, GTK_MENU_SHELL (menu), "tvp::delete", Q_("Menu|Delete"), _("Delete"), GTK_STOCK_DELETE, "--delete");
   }
-  /* Version control (file) */
-  if (tvp_action->property.file_version_control) 
+  /* Version control (all) */
+  if ((tvp_action->property.is_parent && tvp_action->property.parent_version_control) || tvp_action->property.directory_version_control || tvp_action->property.file_version_control)
   {
-    add_subaction_u (GTK_MENU_SHELL (menu), "tvp::diff", Q_("Menu|Diff"), _("Diff"), GTK_STOCK_FIND_AND_REPLACE, _("Diff"));
+    add_subaction (action, GTK_MENU_SHELL (menu), "tvp::diff", Q_("Menu|Diff"), _("Diff"), GTK_STOCK_CONVERT, "--diff");
   }
   /* Version control and No version control (parent) */
   if (tvp_action->property.is_parent || tvp_action->property.directory_version_control || tvp_action->property.file_version_control)
diff --git a/tvp-svn-helper/Makefile.am b/tvp-svn-helper/Makefile.am
index 899309f..634bf0b 100644
--- a/tvp-svn-helper/Makefile.am
+++ b/tvp-svn-helper/Makefile.am
@@ -46,6 +46,8 @@ tvp_svn_helper_SOURCES =						\
 	tsh-copy.c							\
 	tsh-delete.h							\
 	tsh-delete.c							\
+	tsh-diff.h							\
+	tsh-diff.c							\
 	tsh-export.h							\
 	tsh-export.c							\
 	tsh-import.h							\
@@ -78,6 +80,8 @@ tvp_svn_helper_SOURCES =						\
 	tsh-dialog-common.c						\
 	tsh-blame-dialog.h						\
 	tsh-blame-dialog.c						\
+	tsh-diff-dialog.h						\
+	tsh-diff-dialog.c						\
 	tsh-file-dialog.h						\
 	tsh-file-dialog.c						\
 	tsh-file-selection-dialog.h					\
diff --git a/tvp-svn-helper/main.c b/tvp-svn-helper/main.c
index 79ad89f..f64d708 100644
--- a/tvp-svn-helper/main.c
+++ b/tvp-svn-helper/main.c
@@ -42,6 +42,7 @@
 #include "tsh-commit.h"
 #include "tsh-copy.h"
 #include "tsh-delete.h"
+#include "tsh-diff.h"
 #include "tsh-export.h"
 #include "tsh-import.h"
 #include "tsh-lock.h"
@@ -83,6 +84,7 @@ int main (int argc, char *argv[])
 	gboolean commit = FALSE;
 	gboolean copy = FALSE;
 	gboolean delete = FALSE;
+	gboolean diff = FALSE;
 	gboolean export = FALSE;
 	gboolean import = FALSE;
 	gboolean lock = FALSE;
@@ -157,6 +159,12 @@ int main (int argc, char *argv[])
 		{ NULL, '\0', 0, 0, NULL, NULL, NULL }
 	};
 
+	GOptionEntry diff_options_table[] =
+	{
+		{ "diff", '\0', 0, G_OPTION_ARG_NONE, &diff, N_("Execute diff action"), NULL },
+		{ NULL, '\0', 0, 0, NULL, NULL, NULL }
+	};
+
 	GOptionEntry export_options_table[] =
 	{
 		{ "export", '\0', 0, G_OPTION_ARG_NONE, &export, N_("Execute export action"), NULL },
@@ -280,6 +288,10 @@ int main (int argc, char *argv[])
 	g_option_group_add_entries(option_group, delete_options_table);
 	g_option_context_add_group(option_context, option_group);
 
+	option_group = g_option_group_new("diff", N_("Diff Related Options:"), N_("Diff"), NULL, NULL);
+	g_option_group_add_entries(option_group, diff_options_table);
+	g_option_context_add_group(option_context, option_group);
+
 	option_group = g_option_group_new("export", N_("Export Related Options:"), N_("Export"), NULL, NULL);
 	g_option_group_add_entries(option_group, export_options_table);
 	g_option_context_add_group(option_context, option_group);
@@ -367,7 +379,7 @@ int main (int argc, char *argv[])
 		return EXIT_FAILURE;
 	}
 
-  if(add || blame || delete || revert || resolved || changelist)
+  if(add || blame || delete || diff || revert || resolved || changelist)
   {
     if(!g_strv_length(files))
     {
@@ -417,6 +429,11 @@ int main (int argc, char *argv[])
 		thread = tsh_delete(files, svn_ctx, pool);
 	}
 
+	if(diff)
+	{
+		thread = tsh_diff(files, svn_ctx, pool);
+	}
+
 	if(export)
 	{
 		thread = tsh_export(files, svn_ctx, pool);
diff --git a/tvp-git-helper/tgh-status-dialog.c b/tvp-svn-helper/tsh-diff-dialog.c
similarity index 50%
copy from tvp-git-helper/tgh-status-dialog.c
copy to tvp-svn-helper/tsh-diff-dialog.c
index db06e1a..f18eea4 100644
--- a/tvp-git-helper/tgh-status-dialog.c
+++ b/tvp-svn-helper/tsh-diff-dialog.c
@@ -1,5 +1,6 @@
 /*-
  * Copyright (C) 2007-2011  Peter de Ridder <peter at xfce.org>
+ * Copyright (C) 2012 Stefan Sperling <stsp at stsp.name>
  *
  * 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
@@ -23,28 +24,35 @@
 #include <libxfce4util/libxfce4util.h>
 #include <gtk/gtk.h>
 
-#include "tgh-common.h"
-#include "tgh-status-dialog.h"
+#include <subversion-1/svn_client.h>
+#include <subversion-1/svn_pools.h>
+
+#include "tsh-common.h"
+#include "tsh-diff-dialog.h"
 
 static void cancel_clicked (GtkButton*, gpointer);
 static void refresh_clicked (GtkButton*, gpointer);
 
-struct _TghStatusDialog
+struct _TshDiffDialog
 {
   GtkDialog dialog;
 
-  GtkWidget *tree_view;
+  GtkWidget *text_view;
+  GtkTextTag *tag_red;
+  GtkTextTag *tag_green;
+  GtkTextTag *tag_bold;
   GtkWidget *close;
   GtkWidget *cancel;
   GtkWidget *refresh;
+  gint current_line;
 };
 
-struct _TghStatusDialogClass
+struct _TshDiffDialogClass
 {
   GtkDialogClass dialog_class;
 };
 
-G_DEFINE_TYPE (TghStatusDialog, tgh_status_dialog, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE (TshDiffDialog, tsh_diff_dialog, GTK_TYPE_DIALOG)
 
 enum {
   SIGNAL_CANCEL = 0,
@@ -55,7 +63,7 @@ enum {
 static guint signals[SIGNAL_COUNT];
 
 static void
-tgh_status_dialog_class_init (TghStatusDialogClass *klass)
+tsh_diff_dialog_class_init (TshDiffDialogClass *klass)
 {
   signals[SIGNAL_CANCEL] = g_signal_new("cancel-clicked",
     G_OBJECT_CLASS_TYPE (klass),
@@ -71,62 +79,51 @@ tgh_status_dialog_class_init (TghStatusDialogClass *klass)
     G_TYPE_NONE, 0);
 }
 
-enum {
-  COLUMN_PATH = 0,
-  COLUMN_STAT,
-  COLUMN_ADDED,
-  COLUMN_COUNT
-};
-
 static void
-tgh_status_dialog_init (TghStatusDialog *dialog)
+tsh_diff_dialog_init (TshDiffDialog *dialog)
 {
-  GtkWidget *button;
-  GtkWidget *tree_view;
+  GtkWidget *text_view;
+  GtkTextBuffer *text_buffer;
   GtkWidget *scroll_window;
-  GtkCellRenderer *renderer;
-  GtkTreeModel *model;
+  GtkWidget *button;
+  PangoFontDescription *font_desc;
 
   scroll_window = gtk_scrolled_window_new (NULL, NULL);
   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_toggle_new ();
-  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                               -1, ("Commit"),
-                                               renderer, "active",
-                                               COLUMN_ADDED, 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);
-  
-  renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                               -1, ("State"),
-                                               renderer, "text",
-                                               COLUMN_STAT, NULL);
-
-  model = GTK_TREE_MODEL (gtk_list_store_new (COLUMN_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN));
-
-  gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), model);
-
-  g_object_unref (model);
-
-  gtk_container_add (GTK_CONTAINER (scroll_window), tree_view);
+  dialog->text_view = text_view = gtk_text_view_new ();
+  gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view), FALSE);
+  gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(text_view), FALSE);
+  text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(dialog->text_view));
+  dialog->tag_red = gtk_text_buffer_create_tag(text_buffer, NULL,
+                                               "foreground", "red", NULL);
+  dialog->tag_green = gtk_text_buffer_create_tag(text_buffer, NULL,
+                                                 "foreground",
+                                                 "forestgreen", NULL);
+  dialog->tag_bold = gtk_text_buffer_create_tag(text_buffer, NULL,
+                                                "weight",
+                                                PANGO_WEIGHT_BOLD, NULL);
+  dialog->current_line = 0;
+
+  font_desc = pango_font_description_from_string("Monospace");
+  if (font_desc)
+  {
+    gtk_widget_modify_font(text_view, font_desc);
+    pango_font_description_free(font_desc);
+  }
+
+  gtk_container_add (GTK_CONTAINER (scroll_window), text_view);
   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), scroll_window, TRUE, TRUE, 0);
-  gtk_widget_show (tree_view);
+  gtk_widget_show (text_view);
   gtk_widget_show (scroll_window);
 
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Status"));
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Diff"));
 
-  gtk_button_box_set_layout(GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), GTK_BUTTONBOX_EDGE);
+  dialog->close = button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+  gtk_widget_hide (button);
 
   dialog->cancel = button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 0);
+  gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 0);
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cancel_clicked), dialog);
   gtk_widget_show (button);
 
@@ -135,16 +132,13 @@ tgh_status_dialog_init (TghStatusDialog *dialog)
   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (refresh_clicked), dialog);
   gtk_widget_hide (button);
 
-  dialog->close = button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
-  gtk_widget_show (button);
-
   gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
 }
 
 GtkWidget*
-tgh_status_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags)
+tsh_diff_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags)
 {
-  TghStatusDialog *dialog = g_object_new (TGH_TYPE_STATUS_DIALOG, NULL);
+  TshDiffDialog *dialog = g_object_new (TSH_TYPE_DIFF_DIALOG, NULL);
 
   if(title)
     gtk_window_set_title (GTK_WINDOW(dialog), title);
@@ -165,55 +159,70 @@ tgh_status_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags fla
 }
 
 void       
-tgh_status_dialog_add (TghStatusDialog *dialog, const gchar *file, const gchar *state, gboolean commit)
+tsh_diff_dialog_add (TshDiffDialog *dialog, const char *line, gint len)
 {
-  GtkTreeModel *model;
-  GtkTreeIter iter;
+  GtkTextBuffer *text_buffer;
+  GtkTextIter line_start;
+  GtkTextTag *tag = NULL;
 
-  g_return_if_fail (TGH_IS_STATUS_DIALOG (dialog));
+  g_return_if_fail (TSH_IS_DIFF_DIALOG (dialog));
 
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
+  if (line[0] == '-')
+    tag = dialog->tag_red;
+  else if (line[0] == '+')
+    tag = dialog->tag_green;
+  else if (strncmp(line, "Index", 5) == 0)
+    tag = dialog->tag_bold;
 
-  gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-  gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                      COLUMN_PATH, file,
-                      COLUMN_STAT, state,
-                      COLUMN_ADDED, commit,
-                      -1);
+  gdk_threads_enter();
+
+  text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(dialog->text_view));
+  gtk_text_buffer_get_iter_at_line(text_buffer, &line_start,
+                                   dialog->current_line);
+  if (tag)
+    gtk_text_buffer_insert_with_tags(text_buffer, &line_start, line, len,
+                                     tag, NULL);
+  else
+    gtk_text_buffer_insert(text_buffer, &line_start, line, len);
+
+  gdk_threads_leave();
+
+  dialog->current_line++;
 }
 
 void
-tgh_status_dialog_done (TghStatusDialog *dialog)
+tsh_diff_dialog_done (TshDiffDialog *dialog)
 {
-  g_return_if_fail (TGH_IS_STATUS_DIALOG (dialog));
+  g_return_if_fail (TSH_IS_DIFF_DIALOG (dialog));
 
   gtk_widget_hide (dialog->cancel);
+  gtk_widget_show (dialog->close);
   gtk_widget_show (dialog->refresh);
 }
 
 static void
 cancel_clicked (GtkButton *button, gpointer user_data)
 {
-  TghStatusDialog *dialog = TGH_STATUS_DIALOG (user_data);
-
+  TshDiffDialog *dialog = TSH_DIFF_DIALOG (user_data);
+  
   gtk_widget_hide (dialog->cancel);
+  gtk_widget_show (dialog->close);
   gtk_widget_show (dialog->refresh);
   
   g_signal_emit (dialog, signals[SIGNAL_CANCEL], 0);
 }
 
 static void
-refresh_clicked (GtkButton *button, gpointer user_data)
+refresh_clicked(GtkButton *button, gpointer user_data)
 {
-  GtkTreeModel *model;
-  TghStatusDialog *dialog = TGH_STATUS_DIALOG (user_data);
+  TshDiffDialog *dialog = TSH_DIFF_DIALOG(user_data);
+  GtkTextBuffer *text_buffer;
 
-  gtk_widget_hide (dialog->refresh);
-  gtk_widget_show (dialog->cancel);
+  gtk_widget_hide(dialog->refresh);
+  gtk_widget_show(dialog->cancel);
 
-  g_signal_emit (dialog, signals[SIGNAL_REFRESH], 0);
+  text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(dialog->text_view));
+  gtk_text_buffer_set_text(text_buffer, "", -1);
 
-  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
-  gtk_list_store_clear (GTK_LIST_STORE (model));
+  g_signal_emit(dialog, signals[SIGNAL_REFRESH], 0);
 }
-
diff --git a/tvp-svn-helper/tsh-diff-dialog.h b/tvp-svn-helper/tsh-diff-dialog.h
new file mode 100644
index 0000000..5e68fde
--- /dev/null
+++ b/tvp-svn-helper/tsh-diff-dialog.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (C) 2007-2011  Peter de Ridder <peter at xfce.org>
+ * Copyright (C) 2012 Stefan Sperling <stsp at stsp.name>
+ *
+ * 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
+ */
+
+#ifndef __TSH_DIFF_DIALOG_H__
+#define __TSH_DIFF_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _TshDiffDialogClass TshDiffDialogClass;
+typedef struct _TshDiffDialog      TshDiffDialog;
+
+#define TSH_TYPE_DIFF_DIALOG            (tsh_diff_dialog_get_type ())
+#define TSH_DIFF_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TSH_TYPE_DIFF_DIALOG, TshDiffDialog))
+#define TSH_DIFF_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TSH_TYPE_DIFF_DIALOG, TshDiffDialogClass))
+#define TSH_IS_DIFF_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TSH_TYPE_DIFF_DIALOG))
+#define TSH_IS_DIFF_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TSH_TYPE_DIFF_DIALOG))
+#define TSH_DIFF_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TSH_TYPE_DIFF_DIALOG, TshDiffDialogClass))
+
+GType      tsh_diff_dialog_get_type  (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GtkWidget* tsh_diff_dialog_new       (const gchar *title,
+                                       GtkWindow *parent,
+                                       GtkDialogFlags flags) G_GNUC_MALLOC G_GNUC_INTERNAL;
+
+void       tsh_diff_dialog_add       (TshDiffDialog *dialog,
+                                       const char *line,
+                                       gint len);
+void       tsh_diff_dialog_done      (TshDiffDialog *dialog);
+
+G_END_DECLS;
+
+#endif /* !__TSH_DIFF_DIALOG_H__ */
diff --git a/tvp-svn-helper/tsh-diff.c b/tvp-svn-helper/tsh-diff.c
new file mode 100644
index 0000000..d11aaea
--- /dev/null
+++ b/tvp-svn-helper/tsh-diff.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (C) 2007-2011  Peter de Ridder <peter at xfce.org>
+ * Copyright (C) 2012 Stefan Sperling <stsp at stsp.name>
+ *
+ * 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 <libxfce4util/libxfce4util.h>
+
+#include <apr.h>
+#include <apr_xlate.h>
+#include <subversion-1/svn_version.h>
+#include <subversion-1/svn_client.h>
+#include <subversion-1/svn_pools.h>
+
+#include "tsh-common.h"
+#include "tsh-dialog-common.h"
+#include "tsh-file-selection-dialog.h"
+#include "tsh-diff-dialog.h"
+#include "tsh-log-message-dialog.h"
+
+#include "tsh-diff.h"
+
+struct thread_args {
+  svn_client_ctx_t *ctx;
+  apr_pool_t *pool;
+  TshDiffDialog *dialog;
+  gchar **files;
+};
+
+static gpointer diff_thread (gpointer user_data)
+{
+  struct thread_args *args = user_data;
+  svn_error_t *err;
+  apr_array_header_t *paths;
+  svn_client_ctx_t *ctx = args->ctx;
+  apr_pool_t *subpool, *pool = args->pool;
+  TshDiffDialog *dialog = args->dialog;
+  gchar **files = args->files;
+  gint size, i;
+  GtkWidget *error;
+  apr_file_t *outfile;
+  apr_file_t *errfile;
+
+  size = files?g_strv_length(files):0;
+
+  subpool = svn_pool_create (pool);
+
+  if(size)
+  {
+    paths = apr_array_make (pool, size, sizeof (const char *));
+
+    for (i = 0; i < size; i++)
+    {
+      APR_ARRAY_PUSH (paths, const char *) = files[i];
+    }
+  }
+  else
+  {
+    paths = apr_array_make (pool, 1, sizeof (const char *));
+
+    APR_ARRAY_PUSH (paths, const char *) = ""; // current directory
+  }
+
+  err = svn_io_open_unique_file3(&outfile, NULL, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 pool, subpool);
+  if (err)
+    goto on_error;
+
+  err = svn_io_open_unique_file3(&errfile, NULL, NULL,
+                                 svn_io_file_del_on_pool_cleanup,
+                                 pool, subpool);
+  if (err)
+    goto on_error;
+
+  for (i = 0; i < paths->nelts; i++)
+  {
+    const char *path = APR_ARRAY_IDX(paths, i, const char *);
+    svn_opt_revision_t revision1;
+    svn_opt_revision_t revision2;
+    apr_pool_t *iterpool;
+    apr_off_t pos;
+    svn_stream_t *stream;
+
+    svn_pool_clear(subpool);
+
+    /* Diff local changes. */
+    revision1.kind = svn_opt_revision_base;
+    revision2.kind = svn_opt_revision_working;
+
+#if CHECK_SVN_VERSION_S(1,6)
+    if ((err = svn_client_diff4(NULL, path, &revision1, path, &revision2,
+                                NULL, svn_depth_infinity, FALSE,
+                                FALSE, FALSE, APR_LOCALE_CHARSET,
+                                outfile, errfile, NULL, ctx, subpool))) 
+#else /* CHECK_SVN_VERSION(1,7) */
+    if ((err = svn_client_diff5(NULL, path, &revision1, path, &revision2,
+                                NULL, svn_depth_infinity, FALSE, FALSE,
+                                FALSE, FALSE, FALSE, APR_LOCALE_CHARSET,
+                                outfile, errfile, NULL, ctx, subpool))) 
+#endif
+    {
+      goto on_error;
+    }
+
+    /* XXX Slurps the entire diff into memory. Is there a way to
+     * make GTK display a file directly? */
+    err = svn_io_file_flush_to_disk(outfile, subpool);
+    if (err)
+      goto on_error;
+    pos = 0;
+    err = svn_io_file_seek(outfile, APR_SET, &pos, subpool);
+    if (err)
+      goto on_error;
+
+    stream = svn_stream_from_aprfile2(outfile, FALSE, subpool);
+    iterpool = svn_pool_create(subpool);
+    for (;;)
+    {
+      svn_stringbuf_t *buf;
+      svn_boolean_t eof;
+
+      svn_pool_clear(iterpool);
+
+      err = svn_stream_readline(stream, &buf, APR_EOL_STR, &eof, iterpool);
+      if (err)
+        goto on_error;
+
+      if (eof)
+        break;
+
+      svn_stringbuf_appendcstr(buf, APR_EOL_STR);
+      tsh_diff_dialog_add(dialog, buf->data, buf->len);
+    }
+    svn_pool_destroy(iterpool);
+    err = svn_stream_close(stream);
+    if (err)
+      goto on_error;
+  }
+  svn_pool_destroy (subpool);
+
+  gdk_threads_enter();
+  tsh_diff_dialog_done (dialog);
+  gdk_threads_leave();
+
+  tsh_reset_cancel();
+  return GINT_TO_POINTER (TRUE);
+
+on_error:
+  svn_pool_destroy (subpool);
+  
+  if (err->apr_err != SVN_ERR_CANCELLED)
+  {
+    gchar *error_str;
+
+    error_str = tsh_strerror(err);
+    gdk_threads_enter();
+    error = gtk_message_dialog_new(GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Diff failed"));
+    gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(error), "%s", error_str);
+    tsh_dialog_start(GTK_DIALOG(error), FALSE);
+    tsh_diff_dialog_done (dialog);
+    gdk_threads_leave();
+    g_free(error_str);
+  }
+  
+  svn_error_clear(err);
+  tsh_reset_cancel();
+  return GINT_TO_POINTER (FALSE);
+}
+
+static void create_diff_thread(TshDiffDialog *dialog, struct thread_args *args)
+{
+	GThread *thread = g_thread_create(diff_thread, args, TRUE, NULL);
+  if (thread)
+    tsh_replace_thread(thread);
+  else
+    tsh_diff_dialog_done(dialog);
+}
+
+
+GThread *tsh_diff (gchar **files, svn_client_ctx_t *ctx, apr_pool_t *pool)
+{
+  GtkWidget *dialog;
+  struct thread_args *args;
+
+  dialog = tsh_diff_dialog_new (_("Diff"), NULL, 0);
+  g_signal_connect(dialog, "cancel-clicked", tsh_cancel, NULL);
+  tsh_dialog_start (GTK_DIALOG (dialog), TRUE);
+
+  args = g_malloc (sizeof (struct thread_args));
+  args->ctx = ctx;
+  args->pool = pool;
+  args->dialog = TSH_DIFF_DIALOG (dialog);
+  args->files = files;
+
+  g_signal_connect(dialog, "refresh-clicked", G_CALLBACK(create_diff_thread), args);
+
+  return g_thread_create (diff_thread, args, TRUE, NULL);
+}
+
diff --git a/tvp-git-helper/tgh-branch.h b/tvp-svn-helper/tsh-diff.h
similarity index 81%
copy from tvp-git-helper/tgh-branch.h
copy to tvp-svn-helper/tsh-diff.h
index 3a5eba0..aa5f2af 100644
--- a/tvp-git-helper/tgh-branch.h
+++ b/tvp-svn-helper/tsh-diff.h
@@ -1,5 +1,6 @@
 /*-
  * Copyright (C) 2007-2011  Peter de Ridder <peter at xfce.org>
+ * Copyright (C) 2012 Stefan Sperling <stsp at stsp.name>
  *
  * 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
@@ -16,14 +17,14 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef __TGH_BRANCH_H__
-#define __TGH_BRANCH_H__
+#ifndef __TSH_DIFF_H__
+#define __TSH_DIFF_H__
 
 G_BEGIN_DECLS
 
-gboolean tgh_branch (gchar**, GPid*);
+GThread *tsh_diff (gchar**, svn_client_ctx_t*, apr_pool_t*);
 
 G_END_DECLS
 
-#endif /*__TGH_BRANCH_H__*/
+#endif /*__TSH_DIFF_H__*/
 


More information about the Xfce4-commits mailing list