Subject: [PATCH] git-gui: Modify push dialog to support Gerrit review

From: Joergen Edelbo <[email-masked]>
Date: Thu, 12 Sep 2013 11:21:40 +0200

Problem: It is not possible to push for Gerrit review as you will
always try to push to "refs/heads/..." on the remote.

Changes done:

Add an option in the Push dialog to select "Gerrit review" and a
corresponding entry for a branch name. If this option is selected,
push the changes to "refs/for/<gerrit-branch>/<local branch>". In
this way the local branch names will be used as topic branches on
Gerrit.

If you are on a detached HEAD, then add a "HEAD" entry in the branch
selection list. If this is selected, push HEAD:HEAD in the normal
case and HEAD:refs/for/<gerrit_branch> in the Gerrit case.

The Gerrit branch to push to is controlled by gerrit.reviewbranch
configuration option.
---
Hi again,

Seems like this discussion has died out. Is there no perspective in
changing git-gui to support Gerrit better?

Anyway here is what I consider my final shot at a solution. Compared
to the last one, this commit can handle the case when you work on a 
detached HEAD, and the Gerrit branch to push to is handled by a
configuration option.

BR JÃ¸rgen Edelbo

 git-gui.sh        |    1 +
 lib/option.tcl    |    1 +
 lib/transport.tcl |   48 +++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/git-gui.sh b/git-gui.sh
index b62ae4a..3228654 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -901,6 +901,7 @@ set default_config(gui.diffcontext) 5
 set default_config(gui.diffopts) {}
 set default_config(gui.commitmsgwidth) 75
 set default_config(gui.newbranchtemplate) {}
+set default_config(gerrit.reviewbranch) {}
 set default_config(gui.spellingdictionary) {}
 set default_config(gui.fontui) [font configure font_ui]
 set default_config(gui.fontdiff) [font configure font_diff]
diff --git a/lib/option.tcl b/lib/option.tcl
index 23c9ae7..ffa4226 100644
--- a/lib/option.tcl
+++ b/lib/option.tcl
@@ -157,6 +157,7 @@ proc do_options {} {
 		{t gui.diffopts {mc "Additional Diff Parameters"}}
 		{i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}}
 		{t gui.newbranchtemplate {mc "New Branch Name Template"}}
+		{t gerrit.reviewbranch {mc "Gerrit Review Branch"}}
 		{c gui.encoding {mc "Default File Contents Encoding"}}
 		{b gui.warndetachedcommit {mc "Warn before committing to a detached head"}}
 		{s gui.stageuntracked {mc "Staging of untracked files"} {list "yes" "no" "ask"}}
diff --git a/lib/transport.tcl b/lib/transport.tcl
index e5d211e..9b1cfc5 100644
--- a/lib/transport.tcl
+++ b/lib/transport.tcl
@@ -61,6 +61,7 @@ proc push_to {remote} {
 
 proc start_push_anywhere_action {w} {
 	global push_urltype push_remote push_url push_thin push_tags
+	global gerrit_review gerrit_branch
 	global push_force
 	global repo_config
 
@@ -95,7 +96,19 @@ proc start_push_anywhere_action {w} {
 		set cnt 0
 		foreach i [$w.source.l curselection] {
 			set b [$w.source.l get $i]
-			lappend cmd "refs/heads/$b:refs/heads/$b"
+			if {$gerrit_review && $gerrit_branch ne {}} {
+				switch $b {
+				$gerrit_branch	{ lappend cmd "refs/heads/$b:refs/for/$gerrit_branch" }
+				HEAD		{ lappend cmd "HEAD:refs/for/$gerrit_branch" }
+				default		{ lappend cmd "refs/heads/$b:refs/for/$gerrit_branch/$b" }
+				}
+			} else {
+				if {$b eq HEAD} {
+					lappend cmd "HEAD:HEAD"
+				} else {
+					lappend cmd "refs/heads/$b:refs/heads/$b"
+				}
+			}
 			incr cnt
 		}
 		if {$cnt == 0} {
@@ -118,9 +131,10 @@ trace add variable push_remote write \
 	[list radio_selector push_urltype remote]
 
 proc do_push_anywhere {} {
-	global all_remotes current_branch
+	global all_remotes current_branch is_detached
 	global push_urltype push_remote push_url push_thin push_tags
-	global push_force use_ttk NS
+	global gerrit_review gerrit_branch
+	global push_force use_ttk NS repo_config
 
 	set w .push_setup
 	toplevel $w
@@ -149,6 +163,11 @@ proc do_push_anywhere {} {
 		-height 10 \
 		-width 70 \
 		-selectmode extended
+	if {$is_detached} {
+		$w.source.l insert end HEAD
+		$w.source.l select set end
+		$w.source.l yview end
+	}
 	foreach h [load_all_heads] {
 		$w.source.l insert end $h
 		if {$h eq $current_branch} {
@@ -215,13 +234,36 @@ proc do_push_anywhere {} {
 		-text [mc "Include tags"] \
 		-variable push_tags
 	grid $w.options.tags -columnspan 2 -sticky w
+	${NS}::checkbutton $w.options.gerrit \
+		-text [mc "Gerrit review.  Branch: "] \
+		-variable gerrit_review
+	${NS}::entry $w.options.gerrit_br \
+		-width 50 \
+		-textvariable gerrit_branch \
+		-validate key \
+		-validatecommand {
+			if {%d == 1 && [regexp {\s} %S]} {return 0}
+			if {%d == 1 && [string length %S] > 0} {
+				set gerrit_review 1
+			}
+			if {[string length %P] == 0} {
+				set gerrit_review 0
+			}
+			return 1
+		}
+	grid $w.options.gerrit $w.options.gerrit_br -sticky we -padx {0 5}
 	grid columnconfigure $w.options 1 -weight 1
 	pack $w.options -anchor nw -fill x -pady 5 -padx 5
 
+	if ![info exists gerrit_branch] { 
+		set gerrit_branch {}
+		catch {set gerrit_branch $repo_config(gerrit.reviewbranch)}
+	}
 	set push_url {}
 	set push_force 0
 	set push_thin 0
 	set push_tags 0
+	set gerrit_review [expr {$gerrit_branch ne {}}]
 
 	bind $w <Visibility> "grab $w; focus $w.buttons.create"
 	bind $w <Key-Escape> "destroy $w"
-- 
1.7.9.5