[Xfce4-commits] <thunar-vcs-plugin:master> Added support for git branch creation and switching

Peter de Ridder noreply at xfce.org
Sun Feb 27 20:38:12 CET 2011


Updating branch refs/heads/master
         to eed6c8ec0d339083cc24391403ee371e5ed3d906 (commit)
       from f18b89b5bbfa042d121f1e787e7c46532ef81072 (commit)

commit eed6c8ec0d339083cc24391403ee371e5ed3d906
Author: Peter de Ridder <peter at xfce.org>
Date:   Sun Feb 27 15:28:13 2011 +0100

    Added support for git branch creation and switching

 tvp-git-helper/tgh-branch-dialog.c |  151 ++++++++++++++++++++++++++++++-----
 tvp-git-helper/tgh-branch.c        |  119 +++++++++++++++++++++++++++-
 2 files changed, 243 insertions(+), 27 deletions(-)

diff --git a/tvp-git-helper/tgh-branch-dialog.c b/tvp-git-helper/tgh-branch-dialog.c
index c4262a6..8c08f19 100644
--- a/tvp-git-helper/tgh-branch-dialog.c
+++ b/tvp-git-helper/tgh-branch-dialog.c
@@ -25,10 +25,12 @@
 #include <gtk/gtk.h>
 
 #include "tgh-common.h"
+#include "tgh-dialog-common.h"
 #include "tgh-branch-dialog.h"
 
 static void cancel_clicked (GtkButton*, gpointer);
-static void refresh_clicked (GtkButton*, gpointer);
+static void checkout_clicked (GtkButton*, gpointer);
+static void create_clicked (GtkButton*, gpointer);
 
 struct _TghBranchDialog
 {
@@ -37,7 +39,8 @@ struct _TghBranchDialog
   GtkWidget *tree_view;
   GtkWidget *close;
   GtkWidget *cancel;
-  GtkWidget *refresh;
+  GtkWidget *checkout;
+  GtkWidget *create;
 };
 
 struct _TghBranchDialogClass
@@ -49,7 +52,8 @@ G_DEFINE_TYPE (TghBranchDialog, tgh_branch_dialog, GTK_TYPE_DIALOG)
 
 enum {
   SIGNAL_CANCEL = 0,
-  SIGNAL_REFRESH,
+  SIGNAL_CHECKOUT,
+  SIGNAL_CREATE,
   SIGNAL_COUNT
 };
 
@@ -64,12 +68,20 @@ tgh_branch_dialog_class_init (TghBranchDialogClass *klass)
     0, NULL, NULL,
     g_cclosure_marshal_VOID__VOID,
     G_TYPE_NONE, 0);
-  signals[SIGNAL_REFRESH] = g_signal_new("refresh-clicked",
+
+  signals[SIGNAL_CHECKOUT] = g_signal_new("checkout-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_cclosure_marshal_VOID__STRING,
+    G_TYPE_NONE, 1, G_TYPE_STRING);
+
+  signals[SIGNAL_CREATE] = g_signal_new("create-clicked",
+    G_OBJECT_CLASS_TYPE (klass),
+    G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+    0, NULL, NULL,
+    g_cclosure_marshal_VOID__STRING,
+    G_TYPE_NONE, 1, G_TYPE_STRING);
 }
 
 enum {
@@ -86,6 +98,7 @@ tgh_branch_dialog_init (TghBranchDialog *dialog)
   GtkWidget *scroll_window;
   GtkCellRenderer *renderer;
   GtkTreeModel *model;
+  GtkWidget *box;
 
   scroll_window = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
@@ -101,7 +114,7 @@ tgh_branch_dialog_init (TghBranchDialog *dialog)
 
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-                                               -1, _("Path"),
+                                               -1, _("Name"),
                                                renderer, "text",
                                                COLUMN_BRANCH, NULL);
 
@@ -116,23 +129,31 @@ tgh_branch_dialog_init (TghBranchDialog *dialog)
   gtk_widget_show (tree_view);
   gtk_widget_show (scroll_window);
 
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Branch"));
+  tgh_dialog_replace_action_area (GTK_DIALOG (dialog));
+  box = GTK_DIALOG (dialog)->action_area;
 
-  gtk_button_box_set_layout(GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), GTK_BUTTONBOX_EDGE);
+  dialog->checkout = button = gtk_button_new_from_stock(GTK_STOCK_JUMP_TO);
+  gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (checkout_clicked), dialog);
+  gtk_widget_show (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);
-  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cancel_clicked), dialog);
+  dialog->create = button = gtk_button_new_from_stock(GTK_STOCK_NEW);
+  gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (create_clicked), dialog);
   gtk_widget_show (button);
 
-  dialog->refresh = button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, FALSE, TRUE, 0);
-  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (refresh_clicked), dialog);
-  gtk_widget_hide (button);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Branch"));
 
   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_end (GTK_BOX (box), button, FALSE, TRUE, 0);
+  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (cancel_clicked), dialog);
   gtk_widget_show (button);
 
+  tgh_make_homogeneous (dialog->checkout, dialog->create, dialog->close, dialog->cancel, NULL);
+
   gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
 }
 
@@ -182,7 +203,7 @@ tgh_branch_dialog_done (TghBranchDialog *dialog)
   g_return_if_fail (TGH_IS_BRANCH_DIALOG (dialog));
 
   gtk_widget_hide (dialog->cancel);
-  gtk_widget_show (dialog->refresh);
+  gtk_widget_show (dialog->close);
 }
 
 static void
@@ -191,23 +212,109 @@ cancel_clicked (GtkButton *button, gpointer user_data)
   TghBranchDialog *dialog = TGH_BRANCH_DIALOG (user_data);
 
   gtk_widget_hide (dialog->cancel);
-  gtk_widget_show (dialog->refresh);
+  gtk_widget_show (dialog->close);
   
   g_signal_emit (dialog, signals[SIGNAL_CANCEL], 0);
 }
 
 static void
-refresh_clicked (GtkButton *button, gpointer user_data)
+checkout_clicked (GtkButton *button, gpointer user_data)
 {
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
   GtkTreeModel *model;
+  gchar *name;
+
   TghBranchDialog *dialog = TGH_BRANCH_DIALOG (user_data);
 
-  gtk_widget_hide (dialog->refresh);
-  gtk_widget_show (dialog->cancel);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+  {
+    gtk_tree_model_get (model, &iter, COLUMN_BRANCH, &name, -1);
+
+    gtk_widget_hide (dialog->close);
+    gtk_widget_show (dialog->cancel);
 
-  g_signal_emit (dialog, signals[SIGNAL_REFRESH], 0);
+    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_CHECKOUT], 0, name);
+
+    g_free (name);
+  }
+}
+
+static void
+create_clicked (GtkButton *button, gpointer user_data)
+{
+  GtkTreeModel *model;
+  GtkWidget *name_dialog;
+  GtkWidget *label, *image, *hbox, *vbox, *name_entry;
+  gchar *name;
+  gint result;
+
+  TghBranchDialog *dialog = TGH_BRANCH_DIALOG (user_data);
+
+  name_dialog = gtk_dialog_new_with_buttons (NULL, GTK_WINDOW (dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_NEW, GTK_RESPONSE_ACCEPT, NULL);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT, GTK_RESPONSE_CANCEL, -1);
+  gtk_window_set_resizable (GTK_WINDOW (name_dialog), FALSE);
+  gtk_window_set_skip_taskbar_hint (GTK_WINDOW (name_dialog), TRUE);
+
+  label = gtk_label_new (_("Branch name:"));
+  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
+  gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+  
+  gtk_misc_set_alignment   (GTK_MISC  (label), 0.0, 0.0);
+
+  name_entry = gtk_entry_new ();
+  
+  hbox = gtk_hbox_new (FALSE, 12);
+  vbox = gtk_vbox_new (FALSE, 12);
+
+  gtk_box_pack_start (GTK_BOX (vbox), label,
+                      FALSE, FALSE, 0);
+
+  gtk_box_pack_start (GTK_BOX (vbox), name_entry,
+                      TRUE, TRUE, 0);
+
+  gtk_box_pack_start (GTK_BOX (hbox), image,
+                      FALSE, FALSE, 0);
+
+  gtk_box_pack_start (GTK_BOX (hbox), vbox,
+                      TRUE, TRUE, 0);
+
+  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (name_dialog))),
+                      hbox,
+                      FALSE, FALSE, 0);
+
+  gtk_container_set_border_width (GTK_CONTAINER (name_dialog), 5);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (name_dialog)->vbox), 14); /* 14 + 2 * 5 = 24 */
+  gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (name_dialog))), 5);
+  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (name_dialog))), 6);
+
+  gtk_widget_show_all (hbox);
+
+  result = gtk_dialog_run (GTK_DIALOG (name_dialog));
+  if (result != GTK_RESPONSE_ACCEPT)
+  {
+    gtk_widget_destroy (name_dialog);
+    return;
+  }
+
+  name = g_strdup (gtk_entry_get_text (GTK_ENTRY (name_entry)));
+
+  gtk_widget_destroy (name_dialog);
+
+  gtk_widget_hide (dialog->close);
+  gtk_widget_show (dialog->cancel);
 
   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_CREATE], 0, name);
+
+  g_free (name);
 }
 
diff --git a/tvp-git-helper/tgh-branch.c b/tvp-git-helper/tgh-branch.c
index 42469af..f646c27 100644
--- a/tvp-git-helper/tgh-branch.c
+++ b/tvp-git-helper/tgh-branch.c
@@ -37,7 +37,27 @@
 
 #include "tgh-branch.h"
 
-static gchar *argv[] = {"git", "--no-pager", "branch", NULL};
+struct exit_args
+{
+  TghOutputParser *parser;
+  TghBranchDialog *dialog;
+};
+
+static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid);
+
+static void child_exit (GPid pid, gint status, gpointer user_data)
+{
+  struct exit_args *args = user_data;
+
+  tgh_child_exit (pid, status, args->parser);
+
+  if (branch_spawn (args->dialog, &pid))
+    tgh_replace_child (TRUE, pid);
+  else
+    tgh_branch_dialog_done (args->dialog);
+
+  g_free (args);
+}
 
 static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid)
 {
@@ -48,7 +68,9 @@ static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid)
   GIOChannel *chan_err;
   TghOutputParser *parser;
 
-  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))
+  static const gchar *argv[] = {"git", "--no-pager", "branch", NULL};
+
+  if(!g_spawn_async_with_pipes(NULL, (gchar**)argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, &fd_out, &fd_err, &error))
   {
     return FALSE;
   }
@@ -65,10 +87,96 @@ static gboolean branch_spawn (TghBranchDialog *dialog, GPid *pid)
   return TRUE;
 }
 
-static void create_branch_child(TghBranchDialog *dialog, gpointer user_data)
+static gboolean branch_checkout_spawn (TghBranchDialog *dialog, const gchar *name, GPid *pid)
+{
+  GError *error = NULL;
+  gint fd_err;
+  GIOChannel *chan_err;
+  TghOutputParser *parser;
+  const gchar **argv;
+  struct exit_args *args;
+
+  argv = g_new (const gchar*, 6);
+
+  argv[0] = "git";
+  argv[1] = "--no-pager";
+  argv[2] = "checkout";
+  argv[3] = "-q";
+  argv[4] = name;
+  argv[5] = NULL;
+
+  if(!g_spawn_async_with_pipes(NULL, (gchar**)argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, NULL, &fd_err, &error))
+  {
+    g_free (argv);
+    return FALSE;
+  }
+  g_free (argv);
+
+  parser = tgh_error_parser_new(GTK_WIDGET(dialog));
+
+  args = g_new (struct exit_args, 1);
+  args->parser = parser;
+  args->dialog = dialog;
+
+  g_child_watch_add(*pid, (GChildWatchFunc)child_exit, args);
+
+  chan_err = g_io_channel_unix_new(fd_err);
+  g_io_add_watch(chan_err, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, parser);
+
+  return TRUE;
+}
+
+static gboolean branch_create_spawn (TghBranchDialog *dialog, const gchar *name, GPid *pid)
+{
+  GError *error = NULL;
+  gint fd_err;
+  GIOChannel *chan_err;
+  TghOutputParser *parser;
+  const gchar **argv;
+  struct exit_args *args;
+
+  argv = g_new (const gchar*, 5);
+
+  argv[0] = "git";
+  argv[1] = "--no-pager";
+  argv[2] = "branch";
+  argv[3] = name;
+  argv[4] = NULL;
+
+  if(!g_spawn_async_with_pipes(NULL, (gchar**)argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, pid, NULL, NULL, &fd_err, &error))
+  {
+    g_free (argv);
+    return FALSE;
+  }
+  g_free (argv);
+
+  parser = tgh_error_parser_new(GTK_WIDGET(dialog));
+
+  args = g_new (struct exit_args, 1);
+  args->parser = parser;
+  args->dialog = dialog;
+
+  g_child_watch_add(*pid, (GChildWatchFunc)child_exit, args);
+
+  chan_err = g_io_channel_unix_new(fd_err);
+  g_io_add_watch(chan_err, G_IO_IN|G_IO_HUP, (GIOFunc)tgh_parse_output_func, parser);
+
+  return TRUE;
+}
+
+static void checkout_branch(TghBranchDialog *dialog, const gchar *name, gpointer user_data)
+{
+  GPid pid;
+  if (branch_checkout_spawn(dialog, name, &pid))
+    tgh_replace_child(TRUE, pid);
+  else
+    tgh_branch_dialog_done(dialog);
+}
+
+static void create_branch(TghBranchDialog *dialog, const gchar *name, gpointer user_data)
 {
   GPid pid;
-  if (branch_spawn(dialog, &pid))
+  if (branch_create_spawn(dialog, name, &pid))
     tgh_replace_child(TRUE, pid);
   else
     tgh_branch_dialog_done(dialog);
@@ -86,7 +194,8 @@ gboolean tgh_branch (gchar **files, GPid *pid)
   g_signal_connect(dialog, "cancel-clicked", tgh_cancel, NULL);
   tgh_dialog_start (GTK_DIALOG (dialog), TRUE);
 
-  g_signal_connect(dialog, "refresh-clicked", G_CALLBACK(create_branch_child), NULL);
+  g_signal_connect(dialog, "checkout-clicked", G_CALLBACK (checkout_branch), NULL);
+  g_signal_connect(dialog, "create-clicked", G_CALLBACK (create_branch), NULL);
 
   return branch_spawn(TGH_BRANCH_DIALOG(dialog), pid);
 }



More information about the Xfce4-commits mailing list