[gitg] Implemented stash actions (remove, apply)



commit 72bc8371afa34a28e4c59c7bbce98ebd9406e1bf
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun Jul 5 16:53:43 2009 +0200

    Implemented stash actions (remove, apply)

 gitg/gitg-branch-actions.c |  186 ++++++++++++++++++++++++++-
 gitg/gitg-branch-actions.h |    1 +
 gitg/gitg-dnd.c            |   12 +-
 gitg/gitg-label-renderer.c |    5 +
 gitg/gitg-menus.xml        |    8 +
 gitg/gitg-ref.c            |   13 ++-
 gitg/gitg-ref.h            |    3 +-
 gitg/gitg-repository.c     |   73 ++++++-----
 gitg/gitg-window.c         |  304 +++++++++++++++++++++++++++++---------------
 9 files changed, 458 insertions(+), 147 deletions(-)
---
diff --git a/gitg/gitg-branch-actions.c b/gitg/gitg-branch-actions.c
index 0a13e94..cbf0ae9 100644
--- a/gitg/gitg-branch-actions.c
+++ b/gitg/gitg-branch-actions.c
@@ -342,6 +342,109 @@ remove_remote_branch (GitgWindow *window,
 	return ret;
 }
 
+static gchar *
+get_stash_refspec (GitgRepository *repository, GitgRef *stash)
+{
+	gchar **out;
+	
+	out = gitg_repository_command_with_outputv (repository, 
+	                                            NULL,
+	                                            "log",
+	                                            "--no-color",
+	                                            "--pretty=oneline",
+	                                            "-g",
+	                                            "refs/stash",
+	                                            NULL);
+
+	gchar **ptr = out;
+	gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (stash));
+	gchar *ret = NULL;
+	
+	while (ptr && *ptr)
+	{
+		if (g_str_has_prefix (*ptr, sha1))
+		{
+			gchar *start = *ptr + HASH_SHA_SIZE + 1;
+			gchar *end = strchr (start, ':');
+			
+			if (end)
+			{
+				ret = g_strndup (start, end - start);
+			}
+			break;
+		}
+	}
+	
+	g_strfreev (out);
+	g_free (sha1);
+	
+	return ret;
+}
+
+static GitgRunner *
+remove_stash (GitgWindow *window, GitgRef *ref)
+{
+	gint r = message_dialog (window,
+	                         GTK_MESSAGE_QUESTION,
+	                         _("Are you sure you want to remove this stash item?"),
+	                         _("This permanently removes the stash item"),
+	                         _("Remove stash"));
+	
+	if (r != GTK_RESPONSE_ACCEPT)
+	{
+		return NULL;
+	}
+	
+	GitgRepository *repository = gitg_window_get_repository (window);
+	gchar *spec = get_stash_refspec (repository, ref);
+	
+	if (!spec)
+	{
+		return NULL;
+	}
+
+	if (!gitg_repository_commandv (repository,
+	                               NULL,
+	                               "reflog",
+	                               "delete",
+	                               "--updateref",
+	                               "--rewrite",
+	                               spec,
+	                               NULL))
+	{
+		message_dialog (window,
+		                GTK_MESSAGE_ERROR,
+		                _("Failed to remove stash"),
+		                _("The stash item could not be successfully removed"),
+		                NULL);
+	}
+	else
+	{
+		if (!gitg_repository_commandv (repository,
+		                               NULL,
+		                               "rev-parse",
+		                               "--verify",
+		                               "refs/stash {0}",
+		                               NULL))
+		{
+			gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (ref));
+			gitg_repository_commandv (repository,
+			                          NULL,
+			                          "update-ref",
+			                          "-d",
+			                          "refs/stash",
+			                          sha1,
+			                          NULL);
+			g_free (sha1);
+		}
+
+		gitg_repository_reload (repository);
+	}
+
+	g_free (spec);
+	return NULL;
+}
+
 GitgRunner * 
 gitg_branch_actions_remove (GitgWindow *window,
                             GitgRef    *ref)
@@ -360,6 +463,8 @@ gitg_branch_actions_remove (GitgWindow *window,
 		case GITG_REF_TYPE_REMOTE:
 			ret = remove_remote_branch (window, cp);
 		break;
+		case GITG_REF_TYPE_STASH:
+			ret = remove_stash (window, cp);
 		default:
 		break;
 	}
@@ -588,7 +693,11 @@ stash_changes (GitgWindow *window, gchar **ref, gboolean storeref)
 {
 	if (no_changes (gitg_window_get_repository (window)))
 	{
-		*ref = NULL;
+		if (ref)
+		{
+			*ref = NULL;
+		}
+
 		return TRUE;
 	}
 
@@ -1126,11 +1235,80 @@ gitg_branch_actions_push_remote (GitgWindow  *window,
 
 gboolean
 gitg_branch_actions_apply_stash (GitgWindow *window,
-                                 GitgRef    *stash)
+                                 GitgRef    *stash,
+                                 GitgRef    *branch)
 {
 	g_return_val_if_fail (GITG_IS_WINDOW (window), FALSE);
-	g_return_val_if_fail (stash != NULL, FALSE);	
+	g_return_val_if_fail (gitg_ref_get_ref_type (stash) == GITG_REF_TYPE_STASH, FALSE);
+	g_return_val_if_fail (gitg_ref_get_ref_type (branch) == GITG_REF_TYPE_BRANCH, FALSE);
+	
+	gchar *message = g_strdup_printf (_("Are you sure you want to apply the stash item to local branch <%s>?"),
+	                                  gitg_ref_get_shortname (branch));
+	
+	if (message_dialog (window,
+	                    GTK_MESSAGE_QUESTION,
+	                    _("Apply stash"),
+	                    message,
+	                    _("Apply stash")) != GTK_RESPONSE_ACCEPT)
+	{
+		g_free (message);
+		return FALSE;
+	}
+	
+	GitgRepository *repository = gitg_window_get_repository (window);
+	GitgRef *current = gitg_repository_get_current_working_ref (repository);
+	
+	if (!gitg_ref_equal (branch, current))
+	{
+		if (!stash_changes (window, NULL, TRUE))
+		{
+			return FALSE;
+		}
 	
-	return FALSE;
+		if (!checkout_local_branch_real (window, branch))
+		{
+			message_dialog (window,
+				            GTK_MESSAGE_ERROR,
+				            _("Failed to checkout local branch <%s>"),
+				            NULL,
+				            NULL,
+				            gitg_ref_get_shortname (branch));
+			return FALSE;
+		}
+	}
+	
+	gchar *sha1 = gitg_utils_hash_to_sha1_new (gitg_ref_get_hash (stash));
+	gboolean ret;
+	
+	if (!gitg_repository_commandv (repository,
+	                               NULL,
+	                               "stash",
+	                               "apply",
+	                               "--index",
+	                               sha1,
+	                               NULL))
+	{
+		message = g_strdup_printf (_("The stash could not be applied to local branch <%s>"),
+		                           gitg_ref_get_shortname (branch));
+		message_dialog (window,
+		                GTK_MESSAGE_ERROR,
+		                _("Failed to apply stash"),
+		                message,
+		                NULL);
+		g_free (message);
+		ret = FALSE;
+		
+		if (!gitg_ref_equal (current, branch)  && no_changes (repository))
+		{
+			checkout_local_branch_real (window, current);
+		}
+	}
+	else
+	{
+		ret = TRUE;
+		gitg_repository_reload (repository);
+	}
+	
+	return ret;
 }
 
diff --git a/gitg/gitg-branch-actions.h b/gitg/gitg-branch-actions.h
index 4cc8cdb..1cb9d64 100644
--- a/gitg/gitg-branch-actions.h
+++ b/gitg/gitg-branch-actions.h
@@ -37,6 +37,7 @@ GitgRunner *gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, Git
 GitgRunner *gitg_branch_actions_push (GitgWindow *window, GitgRef *source, GitgRef *dest);
 GitgRunner *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote);
 
+gboolean gitg_branch_actions_apply_stash (GitgWindow *window, GitgRef *stash, GitgRef *branch);
 G_END_DECLS
 
 #endif /* __GITG_BRANCH_ACTIONS_H__ */
diff --git a/gitg/gitg-dnd.c b/gitg/gitg-dnd.c
index ebd9d81..522cb55 100644
--- a/gitg/gitg-dnd.c
+++ b/gitg/gitg-dnd.c
@@ -128,6 +128,7 @@ can_drag (GitgRef *ref)
 	{
 		case GITG_REF_TYPE_BRANCH:
 		case GITG_REF_TYPE_REMOTE:
+		case GITG_REF_TYPE_STASH:
 			return TRUE;
 		break;
 		default:
@@ -155,6 +156,10 @@ can_drop (GitgRef *source, GitgRef *dest)
 	{
 		return dest_type == GITG_REF_TYPE_BRANCH;
 	}
+	else if (source_type == GITG_REF_TYPE_STASH)
+	{
+		return dest_type == GITG_REF_TYPE_BRANCH;
+	}
 	
 	return FALSE;
 }
@@ -219,11 +224,6 @@ update_highlight (GitgDndData *data, gint x, gint y)
 	                               NULL,
 	                               NULL);
 
-	if (ref && !can_drag (ref))
-	{
-		ref = NULL;
-	}
-
 	if (ref != data->cursor_ref)
 	{
 		if (data->cursor_ref)
@@ -231,7 +231,7 @@ update_highlight (GitgDndData *data, gint x, gint y)
 			gitg_ref_set_state (data->cursor_ref, GITG_REF_STATE_NONE);
 		}
 		
-		if (ref)
+		if (ref && gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_NONE)
 		{
 			gitg_ref_set_state (ref, GITG_REF_STATE_PRELIGHT);
 			
diff --git a/gitg/gitg-label-renderer.c b/gitg/gitg-label-renderer.c
index 9fc86cd..b48ab8a 100644
--- a/gitg/gitg-label-renderer.c
+++ b/gitg/gitg-label-renderer.c
@@ -108,6 +108,11 @@ get_type_color (GitgRefType type, gdouble *r, gdouble *g, gdouble *b)
 			*g = 1;
 			*b = 0;
 		break;
+		case GITG_REF_TYPE_STASH:
+			*r = 1;
+			*g = 0.8;
+			*b = 0.5;
+		break;
 		default:
 			*r = 1;
 			*g = 1;
diff --git a/gitg/gitg-menus.xml b/gitg/gitg-menus.xml
index 675d905..2a15470 100644
--- a/gitg/gitg-menus.xml
+++ b/gitg/gitg-menus.xml
@@ -63,6 +63,11 @@
             <property name="label">Push branch to...</property>
           </object>
         </child>
+        <child>
+          <object class="GtkAction" id="StashAction">
+            <property name="label">Apply stash to...</property>
+          </object>
+        </child>
       </object>
     </child>
     <child>
@@ -101,6 +106,9 @@
         <menu name="Push" action="PushAction">
           <placeholder name="Placeholder"/>
         </menu>
+        <menu name="Stash" action="StashAction">
+          <placeholder name="Placeholder"/>
+        </menu>
       </popup>
       <popup name="dnd_popup">
         <menuitem action="RebaseDndAction"/>
diff --git a/gitg/gitg-ref.c b/gitg/gitg-ref.c
index b620170..c62bf9a 100644
--- a/gitg/gitg-ref.c
+++ b/gitg/gitg-ref.c
@@ -68,7 +68,8 @@ gitg_ref_new(gchar const *hash, gchar const *name)
 	PrefixTypeMap map[] = {
 		{"refs/heads/", GITG_REF_TYPE_BRANCH},
 		{"refs/remotes/", GITG_REF_TYPE_REMOTE},
-		{"refs/tags/", GITG_REF_TYPE_TAG}
+		{"refs/tags/", GITG_REF_TYPE_TAG},
+		{"refs/stash", GITG_REF_TYPE_STASH}
 	};
 
 	inst->prefix = NULL;
@@ -83,7 +84,15 @@ gitg_ref_new(gchar const *hash, gchar const *name)
 			continue;
 		
 		inst->type = map[i].type;
-		inst->shortname = g_strdup(name + strlen(map[i].prefix));
+		
+		if (inst->type == GITG_REF_TYPE_STASH)
+		{
+			inst->shortname = g_strdup("stash");
+		}
+		else
+		{
+			inst->shortname = g_strdup(name + strlen(map[i].prefix));
+		}
 		
 		if (map[i].type == GITG_REF_TYPE_REMOTE && (pos = strchr(inst->shortname, '/')))
 		{
diff --git a/gitg/gitg-ref.h b/gitg/gitg-ref.h
index 8a4da07..a9f19be 100644
--- a/gitg/gitg-ref.h
+++ b/gitg/gitg-ref.h
@@ -37,7 +37,8 @@ typedef enum
 	GITG_REF_TYPE_NONE = 0,
 	GITG_REF_TYPE_BRANCH,
 	GITG_REF_TYPE_REMOTE,
-	GITG_REF_TYPE_TAG
+	GITG_REF_TYPE_TAG,
+	GITG_REF_TYPE_STASH
 } GitgRefType;
 
 typedef enum
diff --git a/gitg/gitg-repository.c b/gitg/gitg-repository.c
index 91a9e7a..7e12acc 100644
--- a/gitg/gitg-repository.c
+++ b/gitg/gitg-repository.c
@@ -550,6 +550,40 @@ on_loader_end_loading(GitgRunner *object, gboolean cancelled, GitgRepository *re
 	}
 }
 
+static gint
+find_ref_custom (GitgRef *first, GitgRef *second)
+{
+	return gitg_ref_equal (first, second) ? 0 : 1;
+}
+
+static GitgRef *
+add_ref(GitgRepository *self, gchar const *sha1, gchar const *name)
+{
+	GitgRef *ref = gitg_ref_new(sha1, name);
+	GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs, 
+	                                             gitg_ref_get_hash(ref));
+	
+	if (refs == NULL)
+	{
+		g_hash_table_insert(self->priv->refs, 
+		                    (gpointer)gitg_ref_get_hash(ref), 
+		                    g_slist_append(NULL, ref));
+	}
+	else
+	{
+		if (!g_slist_find_custom (refs, ref, (GCompareFunc)find_ref_custom))
+		{
+			refs = g_slist_append(refs, ref);
+		}
+		else
+		{
+			gitg_ref_free (ref);
+		}
+	}
+	
+	return ref;
+}
+
 static void
 loader_update_stash(GitgRepository *repository, gchar **buffer)
 {
@@ -577,6 +611,8 @@ loader_update_stash(GitgRepository *repository, gchar **buffer)
 		gint64 timestamp = g_ascii_strtoll(components[3], NULL, 0);
 		GitgRevision *rv = gitg_revision_new(components[0], components[1], components[2], NULL, timestamp);
 		
+		add_ref (repository, components[0], "refs/stash");
+		
 		gitg_revision_set_sign(rv, 's');
 		append_revision(repository, rv);
 		g_strfreev(components);
@@ -842,27 +878,6 @@ gitg_repository_get_loader(GitgRepository *self)
 	return GITG_RUNNER(g_object_ref(self->priv->loader));
 }
 
-static GitgRef *
-add_ref(GitgRepository *self, gchar const *sha1, gchar const *name)
-{
-	GitgRef *ref = gitg_ref_new(sha1, name);
-	GSList *refs = (GSList *)g_hash_table_lookup(self->priv->refs, 
-	                                             gitg_ref_get_hash(ref));
-	
-	if (refs == NULL)
-	{
-		g_hash_table_insert(self->priv->refs, 
-		                    (gpointer)gitg_ref_get_hash(ref), 
-		                    g_slist_append(NULL, ref));
-	}
-	else
-	{
-		refs = g_slist_append(refs, ref);
-	}
-	
-	return ref;
-}
-
 static gboolean
 has_left_right(gchar const **av, int argc)
 {
@@ -986,18 +1001,14 @@ load_refs(GitgRepository *self)
 		gchar **components = g_strsplit(buf, " ", 3);
 		guint len = g_strv_length(components);
 		
-		/* Skip refs/stash */
-		if (strcmp(components[0], "refs/stash") != 0)
+		if (len == 2 || len == 3)
 		{
-			if (len == 2 || len == 3)
+			gchar const *obj = len == 3 && *components[2] ? components[2] : components[1];
+			GitgRef *ref = add_ref(self, obj, components[0]);
+		
+			if (current != NULL && strcmp(gitg_ref_get_name(ref), current) == 0)
 			{
-				gchar const *obj = len == 3 && *components[2] ? components[2] : components[1];
-				GitgRef *ref = add_ref(self, obj, components[0]);
-			
-				if (current != NULL && strcmp(gitg_ref_get_name(ref), current) == 0)
-				{
-					self->priv->current_ref = gitg_ref_copy(ref);
-				}
+				self->priv->current_ref = gitg_ref_copy(ref);
 			}
 		}
 		
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 602ee11..8f4d4e5 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -312,12 +312,9 @@ on_renderer_path(GtkTreeViewColumn *column, GitgCellRendererPath *renderer, GtkT
 	
 	GSList *labels;
 	const gchar *lbl = NULL;
+
 	switch (gitg_revision_get_sign(rv))
 	{
-
-		case 's':
-			lbl = "stash";
-		break;
 		case 't':
 			lbl = "staged";
 		break;
@@ -475,21 +472,35 @@ update_dnd_status (GitgWindow *window, GitgRef *source, GitgRef *dest)
 	else
 	{
 		gchar *message = NULL;
+		GitgRefType source_type = gitg_ref_get_ref_type (source);
+		GitgRefType dest_type = gitg_ref_get_ref_type (dest);
 		
-		if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH &&
-		    gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_REMOTE)
+		if (source_type == GITG_REF_TYPE_BRANCH &&
+		    dest_type== GITG_REF_TYPE_REMOTE)
+		{
+			message = g_strdup_printf (_("Push local branch <%s> to remote branch <%s>"), 
+			                           gitg_ref_get_shortname (source),
+			                           gitg_ref_get_shortname (dest));
+		}
+		else if (source_type == GITG_REF_TYPE_BRANCH &&
+		         dest_type == GITG_REF_TYPE_BRANCH)
 		{
-			message = g_strdup_printf (_("Push local branch <%s> to remote branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest));
+			message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on local branch <%s>"), 
+			                           gitg_ref_get_shortname (source), 
+			                           gitg_ref_get_shortname (dest));
 		}
-		else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH &&
-		         gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH)
+		else if (source_type == GITG_REF_TYPE_REMOTE &&
+		         dest_type == GITG_REF_TYPE_BRANCH)
 		{
-			message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on local branch <%s>"), gitg_ref_get_shortname (source), gitg_ref_get_shortname (dest));
+			message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on remote branch <%s>"), 
+			                           gitg_ref_get_shortname (dest), 
+			                           gitg_ref_get_shortname (source));
 		}
-		else if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_REMOTE &&
-		         gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH)
+		else if (source_type == GITG_REF_TYPE_STASH && 
+		         dest_type == GITG_REF_TYPE_BRANCH)
 		{
-			message = g_strdup_printf (_("Merge/rebase local branch <%s> with/on remote branch <%s>"), gitg_ref_get_shortname (dest), gitg_ref_get_shortname (source));
+			message = g_strdup_printf (_("Apply stash to local branch <%s>"),
+			                           gitg_ref_get_shortname (dest));
 		}
 		
 		if (message)
@@ -511,13 +522,22 @@ on_refs_dnd (GitgRef *source, GitgRef *dest, gboolean dropped, GitgWindow *windo
 	}
 
 	gboolean ret = FALSE;
+	GitgRefType source_type = gitg_ref_get_ref_type (source);
+	GitgRefType dest_type = gitg_ref_get_ref_type (dest);
 
-	if (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH &&
-	    gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_REMOTE)
+	if (source_type == GITG_REF_TYPE_BRANCH &&
+	    dest_type == GITG_REF_TYPE_REMOTE)
 	{
 		ret = add_branch_action (window, gitg_branch_actions_push (window, source, dest));
 	}
-	else if (gitg_ref_get_ref_type (dest) == GITG_REF_TYPE_BRANCH)
+	else if (source_type == GITG_REF_TYPE_STASH)
+	{
+		if (dest_type == GITG_REF_TYPE_BRANCH)
+		{
+			ret = gitg_branch_actions_apply_stash (window, source, dest);
+		}
+	}
+	else if (dest_type == GITG_REF_TYPE_BRANCH)
 	{
 		GtkWidget *popup = gtk_ui_manager_get_widget (window->priv->menus_ui_manager,
 	                                                  "/ui/dnd_popup");
@@ -977,12 +997,41 @@ fill_branches_combo(GitgWindow *window)
 }
 
 static void
+update_window_title (GitgWindow *window)
+{
+	if (!window->priv->repository)
+	{
+		gtk_window_set_title (GTK_WINDOW (window), _("gitg"));
+		return;
+	}
+	
+	GitgRef *ref = gitg_repository_get_current_working_ref (window->priv->repository);
+	gchar *refname = NULL;
+	
+	if (ref)
+	{
+		refname = g_strconcat (" (", gitg_ref_get_shortname (ref), ")", NULL);
+	}
+	
+	gchar *basename = g_path_get_basename(gitg_repository_get_path(window->priv->repository));
+	gchar *title = g_strconcat(_("gitg"), " - ", basename, refname, NULL);
+	
+	gtk_window_set_title(GTK_WINDOW(window), title);
+	
+	g_free(basename);
+	g_free(title);
+	g_free (refname);
+}
+
+static void
 on_repository_load(GitgRepository *repository, GitgWindow *window)
 {
 	g_signal_handlers_block_by_func(window->priv->combo_branches, on_branches_combo_changed, window);
 	clear_branches_combo(window);
 	fill_branches_combo(window);
 	g_signal_handlers_unblock_by_func(window->priv->combo_branches, on_branches_combo_changed, window);
+
+	update_window_title (window);
 }
 
 static void
@@ -1062,13 +1111,6 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **
 		gitg_commit_view_set_repository(window->priv->commit_view, window->priv->repository);
 		gitg_revision_view_set_repository(window->priv->revision_view, window->priv->repository);
 		
-		gchar *basename = g_path_get_basename(gitg_repository_get_path(window->priv->repository));
-		gchar *title = g_strdup_printf("%s - %s", _("gitg"), basename);
-		gtk_window_set_title(GTK_WINDOW(window), title);
-		
-		g_free(basename);
-		g_free(title);
-		
 		add_recent_item(window);
 		gtk_widget_set_sensitive(GTK_WIDGET(window->priv->notebook_main), TRUE);
 	}
@@ -1081,7 +1123,7 @@ load_repository(GitgWindow *window, gchar const *path, gint argc, gchar const **
 		if (path || argc > 1)
 			handle_no_gitdir(window);
 
-		gtk_window_set_title(GTK_WINDOW(window), _("gitg"));
+		update_window_title (window);
 		gtk_widget_set_sensitive(GTK_WIDGET(window->priv->notebook_main), FALSE);
 	}
 }
@@ -1450,6 +1492,15 @@ on_merge_activated (GtkAction *action, GitgWindow *window)
 }
 
 static void
+on_stash_activated (GtkAction *action, GitgWindow *window)
+{
+	GitgRef *dest = g_object_get_data (G_OBJECT (action), 
+	                                   DYNAMIC_ACTION_DATA_KEY);
+
+	gitg_branch_actions_apply_stash (window, window->priv->popup_refs[0], dest);
+}
+
+static void
 update_merge_rebase (GitgWindow *window, GitgRef *ref)
 {
 	if (window->priv->merge_rebase_uid != 0)
@@ -1473,7 +1524,8 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref)
 		g_list_free (actions);
 	}
 	
-	if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH)
+	if (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH &&
+	    gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_STASH)
 	{
 		return;
 	}
@@ -1494,7 +1546,7 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref)
 	
 	GSList *refs = gitg_repository_get_refs (window->priv->repository);
 	GSList *item;
-	
+
 	for (item = refs; item; item = g_slist_next (item))
 	{
 		GitgRef *r = GITG_REF (item->data);
@@ -1503,95 +1555,132 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref)
 		{
 			gchar const *rname = gitg_ref_get_shortname (r);
 			
-			gchar *rebase = g_strconcat ("Rebase", rname, "Action", NULL);
-			gchar *merge = g_strconcat ("Merge", rname, "Action", NULL);
+			if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH)
+			{
+				gchar *rebase = g_strconcat ("Rebase", rname, "Action", NULL);
+				gchar *merge = g_strconcat ("Merge", rname, "Action", NULL);
 			
-			GtkAction *rebaseac = gtk_action_new (rebase, rname, NULL, NULL);
-			GtkAction *mergeac = gtk_action_new (merge, rname, NULL, NULL);
-
-			g_object_set_data_full (G_OBJECT (rebaseac),
-			                        DYNAMIC_ACTION_DATA_KEY,
-			                        gitg_ref_copy (r),
-			                        (GDestroyNotify)gitg_ref_free);
-			g_object_set_data_full (G_OBJECT (mergeac),
-			                        DYNAMIC_ACTION_DATA_KEY,
-			                        gitg_ref_copy (r),
-			                        (GDestroyNotify)gitg_ref_free);
-
-			g_signal_connect (rebaseac,
-			                  "activate",
-			                  G_CALLBACK (on_rebase_activated),
-			                  window);
-			g_signal_connect (mergeac,
-			                  "activate",
-			                  G_CALLBACK (on_merge_activated),
-			                  window);
-
-			gtk_action_group_add_action (ac, rebaseac);
-			gtk_action_group_add_action (ac, mergeac);
+				GtkAction *rebaseac = gtk_action_new (rebase, rname, NULL, NULL);
+				GtkAction *mergeac = gtk_action_new (merge, rname, NULL, NULL);
+
+				g_object_set_data_full (G_OBJECT (rebaseac),
+					                    DYNAMIC_ACTION_DATA_KEY,
+					                    gitg_ref_copy (r),
+					                    (GDestroyNotify)gitg_ref_free);
+				g_object_set_data_full (G_OBJECT (mergeac),
+					                    DYNAMIC_ACTION_DATA_KEY,
+					                    gitg_ref_copy (r),
+					                    (GDestroyNotify)gitg_ref_free);
+
+				g_signal_connect (rebaseac,
+					              "activate",
+					              G_CALLBACK (on_rebase_activated),
+					              window);
+				g_signal_connect (mergeac,
+					              "activate",
+					              G_CALLBACK (on_merge_activated),
+					              window);
+
+				gtk_action_group_add_action (ac, rebaseac);
+				gtk_action_group_add_action (ac, mergeac);
 			
-			gchar *name = g_strconcat ("Rebase", rname, NULL);
-
-			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
-			                       window->priv->merge_rebase_uid,
-			                       "/ui/revision_popup/Rebase/Placeholder",
-			                       name,
-			                       rebase,
-			                       GTK_UI_MANAGER_MENUITEM,
-			                       FALSE);
-			g_free (name);
+				gchar *name = g_strconcat ("Rebase", rname, NULL);
+
+				gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+					                   window->priv->merge_rebase_uid,
+					                   "/ui/revision_popup/Rebase/Placeholder",
+					                   name,
+					                   rebase,
+					                   GTK_UI_MANAGER_MENUITEM,
+					                   FALSE);
+				g_free (name);
 			
-			name = g_strconcat ("Merge", rname, NULL);
+				name = g_strconcat ("Merge", rname, NULL);
+
+				gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+					                   window->priv->merge_rebase_uid,
+					                   "/ui/revision_popup/Merge/Placeholder",
+					                   name,
+					                   merge,
+					                   GTK_UI_MANAGER_MENUITEM,
+					                   FALSE);
+				g_free (name);
+
+				g_object_unref (rebaseac);
+				g_object_unref (mergeac);
+			}
+			else
+			{
+				gchar *stash = g_strconcat ("Stash", rname, "Action", NULL);
+			
+				GtkAction *stashac = gtk_action_new (stash, rname, NULL, NULL);
 
-			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
-			                       window->priv->merge_rebase_uid,
-			                       "/ui/revision_popup/Merge/Placeholder",
-			                       name,
-			                       merge,
-			                       GTK_UI_MANAGER_MENUITEM,
-			                       FALSE);
-			g_free (name);
-
-			g_object_unref (rebaseac);
-			g_object_unref (mergeac);
+				g_object_set_data_full (G_OBJECT (stashac),
+					                    DYNAMIC_ACTION_DATA_KEY,
+					                    gitg_ref_copy (r),
+					                    (GDestroyNotify)gitg_ref_free);
+
+				g_signal_connect (stashac,
+					              "activate",
+					              G_CALLBACK (on_stash_activated),
+					              window);
+
+				gtk_action_group_add_action (ac, stashac);
+			
+				gchar *name = g_strconcat ("Stash", rname, NULL);
+
+				gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+					                   window->priv->merge_rebase_uid,
+					                   "/ui/revision_popup/Stash/Placeholder",
+					                   name,
+					                   stash,
+					                   GTK_UI_MANAGER_MENUITEM,
+					                   FALSE);
+				g_free (name);
+
+				g_object_unref (stashac);
+			}
 		}
 	}
 	
 	g_slist_foreach (refs, (GFunc)gitg_ref_free, NULL);
 	g_slist_free (refs);
 	
-	gchar **remotes = gitg_repository_get_remotes (window->priv->repository);
-	gchar **ptr = remotes;
-	
-	while (*ptr)
+	if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH)
 	{
-		gchar *push = g_strconcat ("Push", *ptr, "Action", NULL);
-		GtkAction *pushac = gtk_action_new (push, *ptr, NULL, NULL);
+		gchar **remotes = gitg_repository_get_remotes (window->priv->repository);
+		gchar **ptr = remotes;
+	
+		while (*ptr)
+		{
+			gchar *push = g_strconcat ("Push", *ptr, "Action", NULL);
+			GtkAction *pushac = gtk_action_new (push, *ptr, NULL, NULL);
 		
-		gtk_action_group_add_action (ac, pushac);
+			gtk_action_group_add_action (ac, pushac);
 		
-		gchar *name = g_strconcat ("Push", *ptr, NULL);
-		gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
-			                       window->priv->merge_rebase_uid,
-			                       "/ui/revision_popup/Push/Placeholder",
-			                       name,
-			                       push,
-			                       GTK_UI_MANAGER_MENUITEM,
-			                       FALSE);
-
-		g_object_set_data_full (G_OBJECT (pushac),
-		                        DYNAMIC_ACTION_DATA_KEY,
-		                        g_strdup (*ptr),
-		                        (GDestroyNotify)g_free);
-
-		g_signal_connect (pushac, 
-		                  "activate", 
-		                  G_CALLBACK (on_push_activated), 
-		                  window);
-		++ptr;
-	}
+			gchar *name = g_strconcat ("Push", *ptr, NULL);
+			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+					                   window->priv->merge_rebase_uid,
+					                   "/ui/revision_popup/Push/Placeholder",
+					                   name,
+					                   push,
+					                   GTK_UI_MANAGER_MENUITEM,
+					                   FALSE);
+
+			g_object_set_data_full (G_OBJECT (pushac),
+				                    DYNAMIC_ACTION_DATA_KEY,
+				                    g_strdup (*ptr),
+				                    (GDestroyNotify)g_free);
+
+			g_signal_connect (pushac, 
+				              "activate", 
+				              G_CALLBACK (on_push_activated), 
+				              window);
+			++ptr;
+		}
 	
-	g_strfreev (remotes);	
+		g_strfreev (remotes);	
+	}
 
 	gtk_ui_manager_ensure_update (window->priv->menus_ui_manager);
 }
@@ -1663,7 +1752,8 @@ popup_revision (GitgWindow *window, GdkEventButton *event)
 	gtk_tree_path_free (path);
 	
 	if (!ref || (gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_BRANCH && 
-	             gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_REMOTE))
+	             gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_REMOTE &&
+	             gitg_ref_get_ref_type (ref) != GITG_REF_TYPE_STASH))
 	{
 		return FALSE;
 	}
@@ -1703,6 +1793,11 @@ popup_revision (GitgWindow *window, GdkEventButton *event)
 
 		gtk_action_set_visible (checkout, !gitg_ref_equal (working, ref));		
 	}
+	else if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_STASH)
+	{
+		gtk_action_set_label (remove, _("Remove stash"));
+		gtk_action_set_visible (checkout, FALSE);
+	}
 	
 	update_merge_rebase (window, ref);
 	window->priv->popup_refs[0] = ref;
@@ -1726,7 +1821,10 @@ on_tree_view_rv_button_press_event (GtkWidget *widget, GdkEventButton *event, Gi
 void
 on_checkout_branch_action_activate (GtkAction *action, GitgWindow *window)
 {
-	gitg_branch_actions_checkout (window, window->priv->popup_refs[0]);
+	if (gitg_branch_actions_checkout (window, window->priv->popup_refs[0]))
+	{
+		update_window_title (window);
+	}
 }
 
 void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]