[gitg] Use tracked remote and clearify branch in push context menu



commit c43a9684a5cfb49a5aa707047ba4dd895050e50d
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sat Aug 29 11:35:07 2009 +0200

    Use tracked remote and clearify branch in push context menu
    
    The push context menu now uses the tracked remote of the
    branch to show in the context menu. It also clearifies to which
    remote branch it is actually about to push, and whether it is
    an existing branch or a new one. This fixes bug #592098.

 gitg/gitg-branch-actions.c |   21 +++---
 gitg/gitg-branch-actions.h |    2 +-
 gitg/gitg-window.c         |  163 +++++++++++++++++++++++++++++++++++++-------
 3 files changed, 147 insertions(+), 39 deletions(-)
---
diff --git a/gitg/gitg-branch-actions.c b/gitg/gitg-branch-actions.c
index 47db606..8d4cd32 100644
--- a/gitg/gitg-branch-actions.c
+++ b/gitg/gitg-branch-actions.c
@@ -1415,16 +1415,17 @@ gitg_branch_actions_push (GitgWindow *window,
 GitgRunner *
 gitg_branch_actions_push_remote (GitgWindow  *window,
                                  GitgRef     *source,
-                                 gchar const *remote)
+                                 gchar const *remote,
+                                 gchar const *branch)
 {
 	g_return_val_if_fail (GITG_IS_WINDOW (window), NULL);
 	g_return_val_if_fail (remote != NULL, NULL);
 	g_return_val_if_fail (source != NULL, NULL);	
 	g_return_val_if_fail (gitg_ref_get_ref_type (source) == GITG_REF_TYPE_BRANCH, NULL);
 	
-	gchar *message = g_strdup_printf (_("Are you sure you want to push <%s> to remote <%s>?"),
+	gchar *message = g_strdup_printf (_("Are you sure you want to push <%s> to remote <%s/%s>?"),
 	                                  gitg_ref_get_shortname (source),
-	                                  remote);
+	                                  remote, branch);
 	
 	if (message_dialog (window,
 	                    GTK_MESSAGE_QUESTION,
@@ -1439,18 +1440,14 @@ gitg_branch_actions_push_remote (GitgWindow  *window,
 	g_free (message);
 
 	gchar const *name = gitg_ref_get_shortname (source);
-	gchar *rm = g_strconcat (remote, "/", name, NULL);
-	
-	gchar *spec = g_strconcat (name, ":", name, NULL);
-	message = g_strdup_printf (_("Pushing local branch <%s> to remote branch <%s>"),
+	gchar *spec = g_strconcat (name, ":", branch, NULL);
+	message = g_strdup_printf (_("Pushing local branch <%s> to remote branch <%s/%s>"),
 	                           gitg_ref_get_shortname (source),
-	                           rm);
+	                           remote, branch);
 	
-	g_free (rm);
-
 	GitgRunner *ret;
-	gchar *rr = g_strconcat ("refs/remotes/", remote, "/", name, NULL);
-	GitgRef *rmref = gitg_ref_new ("0000000000000000000000000000000000000000", remote);
+	gchar *rr = g_strconcat ("refs/remotes/", remote, "/", branch, NULL);
+	GitgRef *rmref = gitg_ref_new ("0000000000000000000000000000000000000000", rr);
 	g_free (rr);
 
 	RefInfo *info = ref_info_new (source, rmref);
diff --git a/gitg/gitg-branch-actions.h b/gitg/gitg-branch-actions.h
index 991ba28..80ab57d 100644
--- a/gitg/gitg-branch-actions.h
+++ b/gitg/gitg-branch-actions.h
@@ -36,7 +36,7 @@ GitgRunner *gitg_branch_actions_merge (GitgWindow *window, GitgRef *source, Gitg
 GitgRunner *gitg_branch_actions_rebase (GitgWindow *window, GitgRef *source, GitgRef *dest);
 
 GitgRunner *gitg_branch_actions_push (GitgWindow *window, GitgRef *source, GitgRef *dest);
-GitgRunner *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote);
+GitgRunner *gitg_branch_actions_push_remote (GitgWindow *window, GitgRef *source, gchar const *remote, gchar const *branch);
 
 gboolean gitg_branch_actions_apply_stash (GitgWindow *window, GitgRef *stash, GitgRef *branch);
 
diff --git a/gitg/gitg-window.c b/gitg/gitg-window.c
index 383c006..3a0ad1e 100644
--- a/gitg/gitg-window.c
+++ b/gitg/gitg-window.c
@@ -43,8 +43,11 @@
 #include "gitg-dnd.h"
 #include "gitg-branch-actions.h"
 #include "gitg-preferences.h"
+#include "gitg-config.h"
 
 #define DYNAMIC_ACTION_DATA_KEY "GitgDynamicActionDataKey"
+#define DYNAMIC_ACTION_DATA_REMOTE_KEY "GitgDynamicActionDataRemoteKey"
+#define DYNAMIC_ACTION_DATA_BRANCH_KEY "GitgDynamicActionDataBranchKey"
 
 #define GITG_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_WINDOW, GitgWindowPrivate))
 
@@ -1464,10 +1467,13 @@ on_repository_properties(GtkAction *action, GitgWindow *window)
 static void
 on_push_activated (GtkAction *action, GitgWindow *window)
 {
-	gchar const *ptr = g_object_get_data (G_OBJECT (action), 
-	                                      DYNAMIC_ACTION_DATA_KEY);
+	gchar const *remote = g_object_get_data (G_OBJECT (action), 
+	                                         DYNAMIC_ACTION_DATA_REMOTE_KEY);
+	gchar const *branch = g_object_get_data (G_OBJECT (action), 
+	                                         DYNAMIC_ACTION_DATA_BRANCH_KEY);
+
 	add_branch_action (window,
-	                   gitg_branch_actions_push_remote (window, window->priv->popup_refs[0], ptr));
+	                   gitg_branch_actions_push_remote (window, window->priv->popup_refs[0], remote, branch));
 }
 
 static void
@@ -1502,6 +1508,99 @@ on_stash_activated (GtkAction *action, GitgWindow *window)
 }
 
 static void
+get_tracked_ref (GitgWindow *window, GitgRef *branch, gchar **retremote, gchar **retbranch)
+{
+	GitgConfig *config = gitg_config_new (window->priv->repository);
+	gchar *merge;
+	gchar *var;
+	gchar *ret;
+	
+	var = g_strconcat ("branch.", gitg_ref_get_shortname (branch), ".remote", NULL);
+	*retremote = gitg_config_get_value (config, var);
+	g_free (var);
+	
+	if (!*retremote || !**retremote)
+	{
+		g_free (*retremote);
+		*retremote = NULL;
+
+		g_object_unref (config);
+		
+		return;
+	}
+	
+	var = g_strconcat ("branch.", gitg_ref_get_shortname (branch), ".merge", NULL);
+	merge = gitg_config_get_value (config, var);
+	g_free (var);
+	
+	g_object_unref (config);
+	
+	if (merge && g_str_has_prefix (merge, "refs/heads"))
+	{
+		*retbranch = g_strdup (merge + 11);
+	}
+	
+	g_free (merge);
+}
+
+static void
+add_push_action (GitgWindow *window, GtkActionGroup *group, gchar const *name, gchar const *remote, gchar const *branch)
+{
+	gchar *acname = g_strconcat ("Push", remote, branch, "Action", NULL);
+	GtkAction *pushac = gtk_action_new (acname, name, NULL, NULL);
+
+	gtk_action_group_add_action (group, pushac);
+
+	gchar *nm = g_strconcat ("Push", remote, branch, NULL);
+	gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
+			               window->priv->merge_rebase_uid,
+			               "/ui/ref_popup/Push/Placeholder",
+			               nm,
+			               acname,
+			               GTK_UI_MANAGER_MENUITEM,
+			               FALSE);
+
+	g_object_set_data_full (G_OBJECT (pushac),
+		                    DYNAMIC_ACTION_DATA_REMOTE_KEY,
+		                    g_strdup (remote),
+		                    (GDestroyNotify)g_free);
+
+	g_object_set_data_full (G_OBJECT (pushac),
+		                    DYNAMIC_ACTION_DATA_BRANCH_KEY,
+		                    g_strdup (branch),
+		                    (GDestroyNotify)g_free);
+
+	g_signal_connect (pushac, 
+		              "activate", 
+		              G_CALLBACK (on_push_activated), 
+		              window);
+}
+
+static gboolean
+repository_has_ref (GitgWindow *window, gchar const *remote, GitgRef *ref)
+{
+	GSList *refs = gitg_repository_get_refs (window->priv->repository);
+	gchar *combined = g_strconcat (remote, "/", gitg_ref_get_shortname (ref), NULL);
+	
+	while (refs)
+	{
+		GitgRef *r = (GitgRef *)refs->data;
+		
+		if (gitg_ref_get_ref_type (r) == GITG_REF_TYPE_REMOTE &&
+		    strcmp (gitg_ref_get_shortname (r), combined) == 0)
+		{
+			g_free (combined);
+			return TRUE;
+		}
+		
+		refs = g_slist_next (refs);
+	}
+	
+	g_free (combined);
+	return FALSE;
+}
+
+static void
 update_merge_rebase (GitgWindow *window, GitgRef *ref)
 {
 	if (window->priv->merge_rebase_uid != 0)
@@ -1649,38 +1748,50 @@ update_merge_rebase (GitgWindow *window, GitgRef *ref)
 	
 	if (gitg_ref_get_ref_type (ref) == GITG_REF_TYPE_BRANCH)
 	{
+		/* Get the tracked remote of this ref (if any) */
+		gchar *remote = NULL;
+		gchar *branch = NULL;
+		gchar *tracked = NULL;
+		
 		gchar **remotes = gitg_repository_get_remotes (window->priv->repository);
 		gchar **ptr = remotes;
+		
+		get_tracked_ref (window, ref, &remote, &branch);
+		
+		if (remote)
+		{
+			tracked = g_strconcat (remote, "/", branch, NULL);
+			add_push_action (window, ac, tracked, remote, branch);
+		}
 	
 		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);
-		
-			gchar *name = g_strconcat ("Push", *ptr, NULL);
-			gtk_ui_manager_add_ui (window->priv->menus_ui_manager,
-					                   window->priv->merge_rebase_uid,
-					                   "/ui/ref_popup/Push/Placeholder",
-					                   name,
-					                   push,
-					                   GTK_UI_MANAGER_MENUITEM,
-					                   FALSE);
+			if (!tracked || !g_str_has_prefix (tracked, *ptr))
+			{
+				gchar *name;
+				
+				if (repository_has_ref (window, *ptr, ref))
+				{
+					name = g_strconcat (*ptr, "/", gitg_ref_get_shortname (ref), NULL);
+				}
+				else
+				{
+					name = g_strconcat (*ptr, "/", gitg_ref_get_shortname (ref), " (", _("new"), ")", NULL);
+				}
+				
+				add_push_action (window, ac, name, *ptr, gitg_ref_get_shortname (ref));
 
-			g_object_set_data_full (G_OBJECT (pushac),
-				                    DYNAMIC_ACTION_DATA_KEY,
-				                    g_strdup (*ptr),
-				                    (GDestroyNotify)g_free);
+				g_free (name);
+			}
 
-			g_signal_connect (pushac, 
-				              "activate", 
-				              G_CALLBACK (on_push_activated), 
-				              window);
 			++ptr;
 		}
-	
-		g_strfreev (remotes);	
+
+		g_free (tracked);
+		g_strfreev (remotes);
+		
+		g_free (remote);
+		g_free (branch);
 	}
 
 	gtk_ui_manager_ensure_update (window->priv->menus_ui_manager);



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