From 95c3c5f9959e7d44e7dc3d50f6731009ad82dc56 Mon Sep 17 00:00:00 2001 From: James Liggett Date: Thu, 24 Apr 2008 20:25:11 -0700 Subject: [PATCH] Implement support for listing and merging branches. --- TODO.tasks | 10 +- plugins/git/Makefile.am | 12 +- plugins/git/anjuta-git.glade | 235 +++++++++++++++++++++++++++++++++- plugins/git/anjuta-git.ui | 2 + plugins/git/git-branch-combo-model.c | 106 +++++++++++++++ plugins/git/git-branch-combo-model.h | 52 ++++++++ plugins/git/git-branch-list-command.c | 174 +++++++++++++++++++++++++ plugins/git/git-branch-list-command.h | 71 ++++++++++ plugins/git/git-branch.c | 87 +++++++++++++ plugins/git/git-branch.h | 62 +++++++++ plugins/git/git-merge-command.c | 113 ++++++++++++++++ plugins/git/git-merge-command.h | 63 +++++++++ plugins/git/git-merge-dialog.c | 181 ++++++++++++++++++++++++++ plugins/git/git-merge-dialog.h | 35 +++++ plugins/git/git-ui-utils.c | 27 ++++ plugins/git/git-ui-utils.h | 6 + plugins/git/plugin.c | 9 ++ 17 files changed, 1238 insertions(+), 7 deletions(-) create mode 100644 plugins/git/git-branch-combo-model.c create mode 100644 plugins/git/git-branch-combo-model.h create mode 100644 plugins/git/git-branch-list-command.c create mode 100644 plugins/git/git-branch-list-command.h create mode 100644 plugins/git/git-branch.c create mode 100644 plugins/git/git-branch.h create mode 100644 plugins/git/git-merge-command.c create mode 100644 plugins/git/git-merge-command.h create mode 100644 plugins/git/git-merge-dialog.c create mode 100644 plugins/git/git-merge-dialog.h diff --git a/TODO.tasks b/TODO.tasks index f1d85900..50977fd1 100644 --- a/TODO.tasks +++ b/TODO.tasks @@ -663,11 +663,6 @@ Fix c++/gobject class generator to allow adding members, methods, signals, prope - - Merging branches - - - Remote branch handling @@ -740,6 +735,11 @@ Fix c++/gobject class generator to allow adding members, methods, signals, prope Resolving conflicts + + + + + Merging branches diff --git a/plugins/git/Makefile.am b/plugins/git/Makefile.am index 8270f4ed..0d47a50e 100644 --- a/plugins/git/Makefile.am +++ b/plugins/git/Makefile.am @@ -69,7 +69,17 @@ libanjuta_git_la_SOURCES = \ git-remove-dialog.c \ git-remove-dialog.h \ git-resolve-dialog.c \ - git-resolve-dialog.h + git-resolve-dialog.h \ + git-branch.h \ + git-branch.c \ + git-branch-list-command.h \ + git-branch-list-command.c \ + git-merge-command.h \ + git-merge-command.c \ + git-branch-combo-model.c \ + git-branch-combo-model.h \ + git-merge-dialog.h \ + git-merge-dialog.c libanjuta_git_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS) diff --git a/plugins/git/anjuta-git.glade b/plugins/git/anjuta-git.glade index 2daa76e6..bbedbc15 100644 --- a/plugins/git/anjuta-git.glade +++ b/plugins/git/anjuta-git.glade @@ -1,6 +1,6 @@ - + @@ -681,4 +681,237 @@ + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Merge + GTK_WIN_POS_CENTER_ON_PARENT + GDK_WINDOW_TYPE_HINT_DIALOG + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Branch:</b> + True + + + label_item + + + + + False + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Do not commit + 0 + True + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Squash + 0 + True + + + False + False + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Options:</b> + True + + + label_item + + + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + GTK_SHADOW_NONE + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Use a custom log message + 0 + True + + + False + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + + + 400 + True + False + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + + + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Log message:</b> + True + + + label_item + + + + + 2 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-cancel + True + -6 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-ok + True + -5 + + + 1 + + + + + False + GTK_PACK_END + + + + + diff --git a/plugins/git/anjuta-git.ui b/plugins/git/anjuta-git.ui index 0858963f..dc5375be 100644 --- a/plugins/git/anjuta-git.ui +++ b/plugins/git/anjuta-git.ui @@ -10,6 +10,8 @@ + + diff --git a/plugins/git/git-branch-combo-model.c b/plugins/git/git-branch-combo-model.c new file mode 100644 index 00000000..83c9953a --- /dev/null +++ b/plugins/git/git-branch-combo-model.c @@ -0,0 +1,106 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta + * Copyright (C) James Liggett 2008 + * + * anjuta is free software. + * + * You may 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. + * + * 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 anjuta. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#include "git-branch-combo-model.h" + +enum +{ + COL_ACTIVE, + COL_NAME, + + NUM_COLS +}; + +GitBranchComboData * +git_branch_combo_data_new (GtkListStore *model, GtkComboBox *combo_box, + GladeXML *gxml, Git *plugin) +{ + GitBranchComboData *data; + + data = g_new0 (GitBranchComboData, 1); + data->model = model; + data->combo_box = combo_box; + data->gxml = gxml; + data->plugin = plugin; + + return data; +} + +void +git_branch_combo_data_free (GitBranchComboData *data) +{ + g_object_unref (data->gxml); + g_free (data); +} + +GtkListStore * +git_branch_combo_model_new (void) +{ + return gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING); +} + +void +git_branch_combo_model_setup_widget (GtkWidget *widget) +{ + GtkCellRenderer *renderer; + + /* Active column */ + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, FALSE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), renderer, + "stock-id", COL_ACTIVE); + + /* Name column */ + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, FALSE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), renderer, + "text", COL_NAME); +} + +void +git_branch_combo_model_append (GtkListStore *model, GitBranch *branch) +{ + gchar *name; + GtkTreeIter iter; + + name = git_branch_get_name (branch); + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, COL_NAME, name, -1); + + if (git_branch_is_active (branch)) + gtk_list_store_set (model, &iter, COL_ACTIVE, GTK_STOCK_YES, -1); + + g_free (name); +} + +gchar * +git_branch_combo_model_get_branch (GtkListStore *model, GtkTreeIter *iter) +{ + gchar *branch; + + gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COL_NAME, &branch, -1); + + return branch; +} diff --git a/plugins/git/git-branch-combo-model.h b/plugins/git/git-branch-combo-model.h new file mode 100644 index 00000000..7b2b9fbb --- /dev/null +++ b/plugins/git/git-branch-combo-model.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta + * Copyright (C) James Liggett 2008 + * + * anjuta is free software. + * + * You may 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. + * + * 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 anjuta. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GIT_BRANCH_COMBO_MODEL_H +#define _GIT_BRANCH_COMBO_MODEL_H + +#include +#include +#include "git-branch.h" +#include "plugin.h" + +typedef struct +{ + GtkListStore *model; + GtkComboBox *combo_box; + GladeXML *gxml; /* Seems redundant, but we don't know what the combo box + * is called in the glade file. */ + Git *plugin; +} GitBranchComboData; + +GitBranchComboData *git_branch_combo_data_new (GtkListStore *model, + GtkComboBox *combo_box, + GladeXML *gxml, Git *plugin); +void git_branch_combo_data_free (GitBranchComboData *data); +GtkListStore *git_branch_combo_model_new (void); +void git_branch_combo_model_setup_widget (GtkWidget *widget); +void git_branch_combo_model_append (GtkListStore *model, GitBranch *branch); +gchar *git_branch_combo_model_get_branch (GtkListStore *model, + GtkTreeIter *iter); + +#endif diff --git a/plugins/git/git-branch-list-command.c b/plugins/git/git-branch-list-command.c new file mode 100644 index 00000000..16aa3b42 --- /dev/null +++ b/plugins/git/git-branch-list-command.c @@ -0,0 +1,174 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#include "git-branch-list-command.h" + +/* Detects the currently active branch in the output */ +#define ACTIVE_BRANCH_REGEX "^\\* (.*)" + +/* Other branches. Just strips off the space and newlines for us :) */ +#define REGULAR_BRANCH_REGEX "^(?:\\s) (.*)" + +struct _GitBranchListCommandPriv +{ + GitBranchType type; + GRegex *active_branch_regex; + GRegex *regular_branch_regex; + GQueue *output; +}; + +G_DEFINE_TYPE (GitBranchListCommand, git_branch_list_command, GIT_TYPE_COMMAND); + +static void +git_branch_list_command_init (GitBranchListCommand *self) +{ + self->priv = g_new0 (GitBranchListCommandPriv, 1); + self->priv->active_branch_regex = g_regex_new (ACTIVE_BRANCH_REGEX, 0, 0, + NULL); + self->priv->regular_branch_regex = g_regex_new (REGULAR_BRANCH_REGEX, 0, 0, + NULL); + self->priv->output = g_queue_new (); +} + +static void +git_branch_list_command_finalize (GObject *object) +{ + GitBranchListCommand *self; + GList *current_branch; + + self = GIT_BRANCH_LIST_COMMAND (object); + current_branch = self->priv->output->head; + + g_regex_unref (self->priv->active_branch_regex); + g_regex_unref (self->priv->regular_branch_regex); + + while (current_branch) + { + g_object_unref (current_branch->data); + current_branch = g_list_next (current_branch); + } + + g_queue_free (self->priv->output); + g_free (self->priv); + + G_OBJECT_CLASS (git_branch_list_command_parent_class)->finalize (object); +} + +static guint +git_branch_list_command_run (AnjutaCommand *command) +{ + GitBranchListCommand *self; + + self = GIT_BRANCH_LIST_COMMAND (command); + + git_command_add_arg (GIT_COMMAND (command), "branch"); + + switch (self->priv->type) + { + case GIT_BRANCH_TYPE_REMOTE: + git_command_add_arg (GIT_COMMAND (command), "-r"); + break; + case GIT_BRANCH_TYPE_ALL: + git_command_add_arg (GIT_COMMAND (command), "-a"); + break; + default: + break; + } + + return 0; +} + +static void +git_branch_list_command_handle_output (GitCommand *git_command, + const gchar *output) +{ + GitBranchListCommand *self; + GMatchInfo *match_info; + gchar *branch_name; + GitBranch *branch; + gboolean active; + + match_info = NULL; + branch_name = NULL; + branch = NULL; + active = FALSE; + + self = GIT_BRANCH_LIST_COMMAND (git_command); + + if (g_regex_match (self->priv->active_branch_regex, output, 0, &match_info)) + { + branch_name = g_match_info_fetch (match_info, 1); + active = TRUE; + } + else if (g_regex_match (self->priv->regular_branch_regex, output, 0, + &match_info)) + { + branch_name = g_match_info_fetch (match_info, 1); + } + + if (branch_name) + branch = git_branch_new (branch_name, active); + + g_free (branch_name); + g_match_info_free (match_info); + + g_queue_push_head (self->priv->output, branch); + anjuta_command_notify_data_arrived (ANJUTA_COMMAND (git_command)); + +} + +static void +git_branch_list_command_class_init (GitBranchListCommandClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + GitCommandClass* parent_class = GIT_COMMAND_CLASS (klass); + AnjutaCommandClass *command_class = ANJUTA_COMMAND_CLASS (klass); + + object_class->finalize = git_branch_list_command_finalize; + parent_class->output_handler = git_branch_list_command_handle_output; + command_class->run = git_branch_list_command_run; +} + + +GitBranchListCommand * +git_branch_list_command_new (const gchar *working_directory, + GitBranchType type) +{ + GitBranchListCommand *self; + + self = g_object_new (GIT_TYPE_BRANCH_LIST_COMMAND, + "working-directory", working_directory, + "single-line-output", TRUE, + NULL); + + self->priv->type = type; + + return self; +} + +GQueue * +git_branch_list_command_get_output (GitBranchListCommand *self) +{ + return self->priv->output; +} diff --git a/plugins/git/git-branch-list-command.h b/plugins/git/git-branch-list-command.h new file mode 100644 index 00000000..bf70ad96 --- /dev/null +++ b/plugins/git/git-branch-list-command.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GIT_BRANCH_LIST_COMMAND_H_ +#define _GIT_BRANCH_LIST_COMMAND_H_ + +#include +#include "git-command.h" +#include "git-branch.h" + +G_BEGIN_DECLS + +#define GIT_TYPE_BRANCH_LIST_COMMAND (git_branch_list_command_get_type ()) +#define GIT_BRANCH_LIST_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIT_TYPE_BRANCH_LIST_COMMAND, GitBranchListCommand)) +#define GIT_BRANCH_LIST_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIT_TYPE_BRANCH_LIST_COMMAND, GitBranchListCommandClass)) +#define GIT_IS_BRANCH_LIST_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIT_TYPE_BRANCH_LIST_COMMAND)) +#define GIT_IS_BRANCH_LIST_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIT_TYPE_BRANCH_LIST_COMMAND)) +#define GIT_BRANCH_LIST_COMMAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIT_TYPE_BRANCH_LIST_COMMAND, GitBranchListCommandClass)) + +typedef struct _GitBranchListCommandClass GitBranchListCommandClass; +typedef struct _GitBranchListCommand GitBranchListCommand; +typedef struct _GitBranchListCommandPriv GitBranchListCommandPriv; + +typedef enum +{ + GIT_BRANCH_TYPE_LOCAL, + GIT_BRANCH_TYPE_REMOTE, + GIT_BRANCH_TYPE_ALL +} GitBranchType; + +struct _GitBranchListCommandClass +{ + GitCommandClass parent_class; +}; + +struct _GitBranchListCommand +{ + GitCommand parent_instance; + + GitBranchListCommandPriv *priv; +}; + +GType git_branch_list_command_get_type (void) G_GNUC_CONST; +GitBranchListCommand *git_branch_list_command_new (const gchar *working_directory, + GitBranchType type); +GQueue *git_branch_list_command_get_output (GitBranchListCommand *self); + +G_END_DECLS + +#endif /* _GIT_BRANCH_LIST_COMMAND_H_ */ diff --git a/plugins/git/git-branch.c b/plugins/git/git-branch.c new file mode 100644 index 00000000..5ab575dd --- /dev/null +++ b/plugins/git/git-branch.c @@ -0,0 +1,87 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#include "git-branch.h" + +struct _GitBranchPriv +{ + gchar *name; + gboolean active; +}; + +G_DEFINE_TYPE (GitBranch, git_branch, G_TYPE_OBJECT); + +static void +git_branch_init (GitBranch *self) +{ + self->priv = g_new0 (GitBranchPriv, 1); +} + +static void +git_branch_finalize (GObject *object) +{ + GitBranch *self; + + self = GIT_BRANCH (object); + + g_free (self->priv->name); + g_free (self->priv); + + G_OBJECT_CLASS (git_branch_parent_class)->finalize (object); +} + +static void +git_branch_class_init (GitBranchClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + GObjectClass* parent_class = G_OBJECT_CLASS (klass); + + object_class->finalize = git_branch_finalize; +} + + +GitBranch * +git_branch_new (const gchar *name, gboolean active) +{ + GitBranch *self; + + self = g_object_new (GIT_TYPE_BRANCH, NULL); + + self->priv->name = g_strdup (name); + self->priv->active = active; + + return self; +} + +gchar * +git_branch_get_name (GitBranch *self) +{ + return g_strdup (self->priv->name); +} + +gboolean +git_branch_is_active (GitBranch *self) +{ + return self->priv->active; +} diff --git a/plugins/git/git-branch.h b/plugins/git/git-branch.h new file mode 100644 index 00000000..0fe29509 --- /dev/null +++ b/plugins/git/git-branch.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GIT_BRANCH_H_ +#define _GIT_BRANCH_H_ + +#include + +G_BEGIN_DECLS + +#define GIT_TYPE_BRANCH (git_branch_get_type ()) +#define GIT_BRANCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIT_TYPE_BRANCH, GitBranch)) +#define GIT_BRANCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIT_TYPE_BRANCH, GitBranchClass)) +#define GIT_IS_BRANCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIT_TYPE_BRANCH)) +#define GIT_IS_BRANCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIT_TYPE_BRANCH)) +#define GIT_BRANCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIT_TYPE_BRANCH, GitBranchClass)) + +typedef struct _GitBranchClass GitBranchClass; +typedef struct _GitBranch GitBranch; +typedef struct _GitBranchPriv GitBranchPriv; + +struct _GitBranchClass +{ + GObjectClass parent_class; +}; + +struct _GitBranch +{ + GObject parent_instance; + + GitBranchPriv *priv; +}; + +GType git_branch_get_type (void) G_GNUC_CONST; +GitBranch *git_branch_new (const gchar *name, gboolean active); +gchar *git_branch_get_name (GitBranch *self); +gboolean git_branch_is_active (GitBranch *self); + +G_END_DECLS + +#endif /* _GIT_BRANCH_H_ */ diff --git a/plugins/git/git-merge-command.c b/plugins/git/git-merge-command.c new file mode 100644 index 00000000..a776a8fa --- /dev/null +++ b/plugins/git/git-merge-command.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#include "git-merge-command.h" + +struct _GitMergeCommandPriv +{ + gchar *branch; + gchar *log; + gboolean no_commit; + gboolean squash; +}; + +G_DEFINE_TYPE (GitMergeCommand, git_merge_command, GIT_TYPE_COMMAND); + +static void +git_merge_command_init (GitMergeCommand *self) +{ + self->priv = g_new0 (GitMergeCommandPriv, 1); +} + +static void +git_merge_command_finalize (GObject *object) +{ + GitMergeCommand *self; + + self = GIT_MERGE_COMMAND (object); + + g_free (self->priv->branch); + g_free (self->priv->log); + g_free (self->priv); + + G_OBJECT_CLASS (git_merge_command_parent_class)->finalize (object); +} + +static guint +git_merge_command_run (AnjutaCommand *command) +{ + GitMergeCommand *self; + + self = GIT_MERGE_COMMAND (command); + + git_command_add_arg (GIT_COMMAND (command), "merge"); + + if (self->priv->no_commit) + git_command_add_arg (GIT_COMMAND (command), "--no-commit"); + + if (self->priv->squash) + git_command_add_arg (GIT_COMMAND (command), "--squash"); + + if (self->priv->log) + { + git_command_add_arg (GIT_COMMAND (command), "-m"); + git_command_add_arg (GIT_COMMAND (command), self->priv->log); + } + + git_command_add_arg (GIT_COMMAND (command), self->priv->branch); + + return 0; +} + +static void +git_merge_command_class_init (GitMergeCommandClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + GitCommandClass* parent_class = GIT_COMMAND_CLASS (klass); + AnjutaCommandClass* command_class = ANJUTA_COMMAND_CLASS (klass); + + object_class->finalize = git_merge_command_finalize; + parent_class->output_handler = git_command_send_output_to_info; + command_class->run = git_merge_command_run; +} + + +GitMergeCommand * +git_merge_command_new (const gchar *working_directory, const gchar *branch, + const gchar *log, gboolean no_commit, gboolean squash) +{ + GitMergeCommand *self; + + self = g_object_new (GIT_TYPE_MERGE_COMMAND, + "working-directory", working_directory, + "single-line-output", TRUE, + NULL); + + self->priv->branch = g_strdup (branch); + self->priv->log = g_strdup (log); + self->priv->no_commit = no_commit; + self->priv->squash = squash; + + return self; +} diff --git a/plugins/git/git-merge-command.h b/plugins/git/git-merge-command.h new file mode 100644 index 00000000..080fc16a --- /dev/null +++ b/plugins/git/git-merge-command.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta-git + * Copyright (C) James Liggett 2008 + * + * anjuta-git is free software. + * + * You may 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. + * + * anjuta-git 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 anjuta-git. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GIT_MERGE_COMMAND_H_ +#define _GIT_MERGE_COMMAND_H_ + +#include +#include "git-command.h" + +G_BEGIN_DECLS + +#define GIT_TYPE_MERGE_COMMAND (git_merge_command_get_type ()) +#define GIT_MERGE_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIT_TYPE_MERGE_COMMAND, GitMergeCommand)) +#define GIT_MERGE_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIT_TYPE_MERGE_COMMAND, GitMergeCommandClass)) +#define GIT_IS_MERGE_COMMAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIT_TYPE_MERGE_COMMAND)) +#define GIT_IS_MERGE_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIT_TYPE_MERGE_COMMAND)) +#define GIT_MERGE_COMMAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIT_TYPE_MERGE_COMMAND, GitMergeCommandClass)) + +typedef struct _GitMergeCommandClass GitMergeCommandClass; +typedef struct _GitMergeCommand GitMergeCommand; +typedef struct _GitMergeCommandPriv GitMergeCommandPriv; + +struct _GitMergeCommandClass +{ + GitCommandClass parent_class; +}; + +struct _GitMergeCommand +{ + GitCommand parent_instance; + + GitMergeCommandPriv *priv; +}; + +GType git_merge_command_get_type (void) G_GNUC_CONST; +GitMergeCommand *git_merge_command_new (const gchar *working_directory, + const gchar *branch, const gchar *log, + gboolean no_commit, gboolean squash); + +G_END_DECLS + +#endif /* _GIT_MERGE_COMMAND_H_ */ diff --git a/plugins/git/git-merge-dialog.c b/plugins/git/git-merge-dialog.c new file mode 100644 index 00000000..3ca967b9 --- /dev/null +++ b/plugins/git/git-merge-dialog.c @@ -0,0 +1,181 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta + * Copyright (C) James Liggett 2008 + * + * anjuta is free software. + * + * You may 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. + * + * 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 anjuta. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#include "git-merge-dialog.h" + +static void +on_merge_command_finished (AnjutaCommand *command, guint return_code, + Git *plugin) +{ + AnjutaStatus *status; + + status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell, + NULL); + + anjuta_status (status, _("Git: Merge complete."), 5); + + report_errors (command, return_code); + + g_object_unref (command); +} + + +static void +on_merge_dialog_response (GtkDialog *dialog, gint response_id, + GitBranchComboData *data) +{ + GtkWidget *branch_combo; + GtkWidget *no_commit_check; + GtkWidget *squash_check; + GtkWidget *use_custom_log_check; + GtkWidget *log_view; + gchar *log; + GtkWidget *log_prompt_dialog; + gint prompt_response; + GtkTreeIter iter; + gchar *branch; + GitMergeCommand *merge_command; + + if (response_id == GTK_RESPONSE_OK) + { + branch_combo = glade_xml_get_widget (data->gxml, "branch_combo"); + no_commit_check = glade_xml_get_widget (data->gxml, "no_commit_check"); + squash_check = glade_xml_get_widget (data->gxml, "squash_check"); + use_custom_log_check = glade_xml_get_widget (data->gxml, + "use_custom_log_check"); + log_view = glade_xml_get_widget (data->gxml, "log_view"); + log = NULL; + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (use_custom_log_check))) + { + log = get_log_from_textview (log_view); + + if (!g_utf8_strlen (log, -1)) + { + log_prompt_dialog = gtk_message_dialog_new (GTK_WINDOW(dialog), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_YES_NO, + _("Are you sure that you want to pass an empty log message?")); + + prompt_response = gtk_dialog_run(GTK_DIALOG (log_prompt_dialog)); + gtk_widget_destroy (log_prompt_dialog); + + if (prompt_response == GTK_RESPONSE_NO) + return; + } + } + + gtk_combo_box_get_active_iter (GTK_COMBO_BOX (branch_combo), &iter); + branch = git_branch_combo_model_get_branch (data->model, &iter); + + merge_command = git_merge_command_new (data->plugin->project_root_directory, + branch, log, + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (no_commit_check)), + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (squash_check))); + + g_free (branch); + + create_message_view (data->plugin); + + g_signal_connect (G_OBJECT (merge_command), "command-finished", + G_CALLBACK (on_merge_command_finished), + data->plugin); + + g_signal_connect (G_OBJECT (merge_command), "data-arrived", + G_CALLBACK (on_command_info_arrived), + data->plugin); + + anjuta_command_start (ANJUTA_COMMAND (merge_command)); + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); + git_branch_combo_data_free (data); +} + +static void +on_use_custom_log_check_toggled (GtkToggleButton *toggle_button, GtkWidget *log_view) +{ + gtk_widget_set_sensitive (log_view, + gtk_toggle_button_get_active (toggle_button)); +} + +static void +merge_dialog (Git *plugin) +{ + GladeXML *gxml; + GtkWidget *dialog; + GtkWidget *branch_combo; + GtkWidget *use_custom_log_check; + GtkWidget *log_view; + GtkListStore *branch_list_store; + GitBranchComboData *data; + GitBranchListCommand *list_command; + + gxml = glade_xml_new (GLADE_FILE, "merge_dialog", NULL); + + dialog = glade_xml_get_widget (gxml, "merge_dialog"); + branch_combo = glade_xml_get_widget (gxml, "branch_combo"); + use_custom_log_check = glade_xml_get_widget (gxml, + "use_custom_log_check"); + log_view = glade_xml_get_widget (gxml, "log_view"); + branch_list_store = git_branch_combo_model_new (); + + gtk_combo_box_set_model (GTK_COMBO_BOX (branch_combo), + GTK_TREE_MODEL (branch_list_store)); + git_branch_combo_model_setup_widget (branch_combo); + + data = git_branch_combo_data_new (branch_list_store, + GTK_COMBO_BOX (branch_combo), gxml, + plugin); + + list_command = git_branch_list_command_new (plugin->project_root_directory, + GIT_BRANCH_TYPE_ALL); + + g_signal_connect (G_OBJECT (list_command), "data-arrived", + G_CALLBACK (on_list_branch_command_data_arrived), + data); + + g_signal_connect (G_OBJECT (list_command), "command-finished", + G_CALLBACK (on_list_branch_command_finished), + data); + + anjuta_command_start (ANJUTA_COMMAND (list_command)); + + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (on_merge_dialog_response), + data); + + g_signal_connect (G_OBJECT (use_custom_log_check), "toggled", + G_CALLBACK (on_use_custom_log_check_toggled), + log_view); + + gtk_widget_show_all (dialog); +} + +void +on_menu_git_merge (GtkAction *action, Git *plugin) +{ + merge_dialog (plugin); +} diff --git a/plugins/git/git-merge-dialog.h b/plugins/git/git-merge-dialog.h new file mode 100644 index 00000000..eec714d9 --- /dev/null +++ b/plugins/git/git-merge-dialog.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * anjuta + * Copyright (C) James Liggett 2008 + * + * anjuta is free software. + * + * You may 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. + * + * 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 anjuta. If not, write to: + * The Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GIT_MERGE_DIALOG_H +#define _GIT_MERGE_DIALOG_H + +#include "git-merge-command.h" +#include "git-ui-utils.h" +#include "git-branch-combo-model.h" +#include "git-branch-list-command.h" + +void on_menu_git_merge (GtkAction *action, Git *plugin); + +#endif diff --git a/plugins/git/git-ui-utils.c b/plugins/git/git-ui-utils.c index 18f9ceb9..3570c796 100644 --- a/plugins/git/git-ui-utils.c +++ b/plugins/git/git-ui-utils.c @@ -285,6 +285,33 @@ on_command_info_arrived (AnjutaCommand *command, Git *plugin) } void +on_list_branch_command_data_arrived (AnjutaCommand *command, + GitBranchComboData *data) +{ + GQueue *output_queue; + GitBranch *branch; + + output_queue = git_branch_list_command_get_output (GIT_BRANCH_LIST_COMMAND (command)); + + while (g_queue_peek_head (output_queue)) + { + branch = g_queue_pop_head (output_queue); + git_branch_combo_model_append (data->model, branch); + g_object_unref (branch); + } +} + +void +on_list_branch_command_finished (AnjutaCommand *command, guint return_code, + GitBranchComboData *data) +{ + gtk_combo_box_set_active (data->combo_box, 0); + + report_errors (command, return_code); + g_object_unref (command); +} + +void select_all_status_items (GtkButton *select_all_button, AnjutaVcsStatusTreeView *tree_view) { diff --git a/plugins/git/git-ui-utils.h b/plugins/git/git-ui-utils.h index 32f74f08..e572412f 100644 --- a/plugins/git/git-ui-utils.h +++ b/plugins/git/git-ui-utils.h @@ -32,6 +32,8 @@ #include "plugin.h" #include "git-status-command.h" #include "git-diff-command.h" +#include "git-branch-list-command.h" +#include "git-branch-combo-model.h" typedef struct { @@ -59,6 +61,10 @@ void on_command_finished (AnjutaCommand *command, guint return_code, void on_status_command_data_arrived (AnjutaCommand *command, AnjutaVcsStatusTreeView *tree_view); void on_command_info_arrived (AnjutaCommand *command, Git *plugin); +void on_list_branch_command_data_arrived (AnjutaCommand *command, + GitBranchComboData *data); +void on_list_branch_command_finished (AnjutaCommand *command, guint return_code, + GitBranchComboData *data); void select_all_status_items (GtkButton *select_all_button, AnjutaVcsStatusTreeView *tree_view); void clear_all_status_selections (GtkButton *clear_button, diff --git a/plugins/git/plugin.c b/plugins/git/plugin.c index 343a2967..aeb3f1ea 100644 --- a/plugins/git/plugin.c +++ b/plugins/git/plugin.c @@ -25,6 +25,7 @@ #include "git-add-dialog.h" #include "git-remove-dialog.h" #include "git-resolve-dialog.h" +#include "git-merge-dialog.h" #define UI_FILE PACKAGE_DATA_DIR"/ui/anjuta-git.ui" @@ -72,6 +73,14 @@ static GtkActionEntry actions_git[] = { G_CALLBACK (on_menu_git_remove) /* action callback */ }, { + "ActionGitMerge", /* Action name */ + GTK_STOCK_CONVERT, /* Stock icon, if any */ + N_("_Merge..."), /* Display label */ + NULL, /* short-cut */ + NULL, /* Tooltip */ + G_CALLBACK (on_menu_git_merge) /* action callback */ + }, + { "ActionGitDiffUncommitted", /* Action name */ GTK_STOCK_ZOOM_100, /* Stock icon, if any */ N_("_Diff uncommitted changes"), /* Display label */ -- 2.11.4.GIT