git-gui: Consolidate the Fetch and Push menus into a Remote menu

Sometimes the Fetch menu looks really odd, such as if you are in a
repository that has no remotes configured when you start git-gui.
Here we didn't have any items to add to the Fetch menu so it was a
tad confusing for the end-user to see an empty menu on the menu bar.

We now place all of the commands related to fetching and pushing of
changes into a single "Remote" menu.  This way we have a better class
of bucket that we can drop additional remote related items into such
as doing a remote merge or editing the remote configuration specs.

The shortcuts to execute fetch/remote prune/push on existing remote
specifications are now actually submenus listing the remotes by name.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
diff --git a/git-gui.sh b/git-gui.sh
index ca39113..c8307a6 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1792,8 +1792,7 @@
 }
 if {[is_enabled transport]} {
 	.mbar add cascade -label [mc Merge] -menu .mbar.merge
-	.mbar add cascade -label [mc Fetch] -menu .mbar.fetch
-	.mbar add cascade -label [mc Push] -menu .mbar.push
+	.mbar add cascade -label [mc Remote] -menu .mbar.remote
 }
 . configure -menu .mbar
 
@@ -2000,13 +1999,14 @@
 # -- Transport Menu
 #
 if {[is_enabled transport]} {
-	menu .mbar.fetch
+	menu .mbar.remote
 
-	menu .mbar.push
-	.mbar.push add command -label [mc "Push..."] \
+	.mbar.remote add command \
+		-label [mc "Push..."] \
 		-command do_push_anywhere \
 		-accelerator $M1T-P
-	.mbar.push add command -label [mc "Delete..."] \
+	.mbar.remote add command \
+		-label [mc "Delete..."] \
 		-command remote_branch_delete::dialog
 }
 
@@ -2720,8 +2720,14 @@
 if {[is_enabled transport]} {
 	load_all_remotes
 
-	populate_fetch_menu
+	set n [.mbar.remote index end]
 	populate_push_menu
+	populate_fetch_menu
+	set n [expr {[.mbar.remote index end] - $n}]
+	if {$n > 0} {
+		.mbar.remote insert $n separator
+	}
+	unset n
 }
 
 if {[winfo exists $ui_comm]} {
diff --git a/lib/remote.tcl b/lib/remote.tcl
index aba6eb8..0e86dda 100644
--- a/lib/remote.tcl
+++ b/lib/remote.tcl
@@ -135,8 +135,10 @@
 proc populate_fetch_menu {} {
 	global all_remotes repo_config
 
-	set m .mbar.fetch
-	set prune_list [list]
+	set remote_m .mbar.remote
+	set fetch_m $remote_m.fetch
+	set prune_m $remote_m.prune
+
 	foreach r $all_remotes {
 		set enable 0
 		if {![catch {set a $repo_config(remote.$r.url)}]} {
@@ -157,28 +159,34 @@
 		}
 
 		if {$enable} {
-			lappend prune_list $r
-			$m add command \
-				-label [mc "Fetch from %s" $r] \
-				-command [list fetch_from $r]
-		}
-	}
+			if {![winfo exists $fetch_m]} {
+				menu $prune_m
+				$remote_m insert 0 cascade \
+					-label [mc "Prune from"] \
+					-menu $prune_m
 
-	if {$prune_list ne {}} {
-		$m add separator
-	}
-	foreach r $prune_list {
-		$m add command \
-			-label [mc "Prune from %s" $r] \
-			-command [list prune_from $r]
+				menu $fetch_m
+				$remote_m insert 0 cascade \
+					-label [mc "Fetch from"] \
+					-menu $fetch_m
+			}
+
+			$fetch_m add command \
+				-label $r \
+				-command [list fetch_from $r]
+			$prune_m add command \
+				-label $r \
+				-command [list prune_from $r]
+		}
 	}
 }
 
 proc populate_push_menu {} {
 	global all_remotes repo_config
 
-	set m .mbar.push
-	set fast_count 0
+	set remote_m .mbar.remote
+	set push_m $remote_m.push
+
 	foreach r $all_remotes {
 		set enable 0
 		if {![catch {set a $repo_config(remote.$r.url)}]} {
@@ -199,13 +207,16 @@
 		}
 
 		if {$enable} {
-			if {!$fast_count} {
-				$m add separator
+			if {![winfo exists $push_m]} {
+				menu $push_m
+				$remote_m insert 0 cascade \
+					-label [mc "Push to"] \
+					-menu $push_m
 			}
-			$m add command \
-				-label [mc "Push to %s" $r] \
+
+			$push_m add command \
+				-label $r \
 				-command [list push_to $r]
-			incr fast_count
 		}
 	}
 }