# [PATCH 2/2] gitk: Allow checking out a remote branch

9 messages from 2016-01-15 to 2016-12-12. Participants: Rogier Goossens, Paul Mackerras.
Thread: https://gitlist.dev/t/41204

## Rogier Goossens, 2016-01-15 21:31

Subject: [PATCH 0/2] gitk: Two improvements to the branch context menu
Message-ID: <51900395.pKIx87RN0F@wiske>
URL: https://gitlist.dev/e/51900395.pKIx87RN0F%40wiske

```
Hi,

I made two improvements to the gitk branch context menu:
1) gitk: Add a 'rename' option to the branch context menu
2) gitk: Allow checking out a remote branch
	(i.e. create and check out a local branch that tracks
	the specified remote branch)

They are related by the facts that they both affect the
branch context menu, and that the second depends on changes
introduced by the first.

```

## Rogier Goossens, 2016-01-15 21:38

Subject: [PATCH 1/2] gitk: Add a 'rename' option to the branch context menu
Message-ID: <1859807.50qitjY8Ul@wiske>
URL: https://gitlist.dev/e/1859807.50qitjY8Ul%40wiske
In-Reply-To: <51900395.pKIx87RN0F@wiske>

```

Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>
---
 gitk | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 84 insertions(+), 5 deletions(-)

diff --git a/gitk b/gitk
index 5f1255c..e9465fb 100755
--- a/gitk
+++ b/gitk
@@ -2665,6 +2665,7 @@ proc makewindow {} {
     makemenu $headctxmenu {
 	{mc "Check out this branch" command cobranch}
 	{mc "Remove this branch" command rmbranch}
+	{mc "Rename this branch" command mvbranch}
 	{mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
     }
     $headctxmenu configure -tearoff 0
@@ -9526,6 +9527,80 @@ proc mkbrgo {top} {
     }
 }
 
+proc mvbranch {} {
+    global mvbrtop NS
+    global headmenuid headmenuhead
+
+    set prevname $headmenuhead
+    set id $headmenuid
+
+    set top .renamebranch
+    catch {destroy $top}
+    ttk_toplevel $top
+    make_transient $top .
+    ${NS}::label $top.title -text [mc "Rename branch %s" $prevname]
+    grid $top.title - -pady 10
+    ${NS}::label $top.id -text [mc "ID:"]
+    ${NS}::entry $top.sha1 -width 40
+    $top.sha1 insert 0 $id
+    $top.sha1 conf -state readonly
+    grid $top.id $top.sha1 -sticky w
+    ${NS}::label $top.nlab -text [mc "Name:"]
+    ${NS}::entry $top.name -width 40
+    $top.name insert 0 $prevname
+    grid $top.nlab $top.name -sticky w
+    ${NS}::frame $top.buts
+    ${NS}::button $top.buts.go -text [mc "Rename"] -command [list mvbrgo $top $prevname]
+    ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
+    bind $top <Key-Return> [list mvbrgo $top $prevname]
+    bind $top <Key-Escape> "catch {destroy $top}"
+    grid $top.buts.go $top.buts.can
+    grid columnconfigure $top.buts 0 -weight 1 -uniform a
+    grid columnconfigure $top.buts 1 -weight 1 -uniform a
+    grid $top.buts - -pady 10 -sticky ew
+    focus $top.name
+}
+
+proc mvbrgo {top prevname} {
+    global headids idheads mainhead mainheadid
+
+    set name [$top.name get]
+    set id [$top.sha1 get]
+    set cmdargs {}
+    if {$name eq $prevname} {
+	catch {destroy $top}
+	return
+    }
+    if {$name eq {}} {
+	error_popup [mc "Please specify a new name for the branch"] $top
+	return
+    }
+    catch {destroy $top}
+    lappend cmdargs -m $prevname $name
+    nowbusy renamebranch
+    update
+    if {[catch {
+	eval exec git branch $cmdargs
+    } err]} {
+	notbusy renamebranch
+	error_popup $err
+    } else {
+	notbusy renamebranch
+	removehead $id $prevname
+	removedhead $id $prevname
+	set headids($name) $id
+	lappend idheads($id) $name
+	addedhead $id $name
+	if {$prevname eq $mainhead} {
+	    set mainhead $name
+	    set mainheadid $id
+	}
+	redrawtags $id
+	dispneartags 0
+	run refill_reflist
+    }
+}
+
 proc exec_citool {tool_args {baseid {}}} {
     global commitinfo env
 
@@ -9756,15 +9831,19 @@ proc headmenu {x y id head} {
     stopfinding
     set headmenuid $id
     set headmenuhead $head
-    set state normal
+    array set state {0 normal 1 normal 2 normal 3 normal}
     if {[string match "remotes/*" $head]} {
-	set state disabled
+	set state(0) disabled
+	set state(1) disabled
+	set state(2) disabled
     }
     if {$head eq $mainhead} {
-	set state disabled
+	set state(0) disabled
+	set state(1) disabled
+    }
+    foreach i {0 1 2 3} {
+	$headctxmenu entryconfigure $i -state $state($i)
     }
-    $headctxmenu entryconfigure 0 -state $state
-    $headctxmenu entryconfigure 1 -state $state
     tk_popup $headctxmenu $x $y
 }
 
-- 
2.1.4

```

## Rogier Goossens, 2016-01-15 21:43

Subject: [PATCH 2/2] gitk: Allow checking out a remote branch
Message-ID: <1964156.4P5fNkQCS3@wiske>
URL: https://gitlist.dev/e/1964156.4P5fNkQCS3%40wiske
In-Reply-To: <51900395.pKIx87RN0F@wiske>

```

Git allows checking out remote branches, creating a local tracking
branch in the process. Allow gitk to do this as well, provided a
local branch of the same name does not yet exist.

Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>
---
 gitk | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/gitk b/gitk
index e9465fb..7d5fd33 100755
--- a/gitk
+++ b/gitk
@@ -9826,14 +9826,17 @@ proc readresetstat {fd} {
 
 # context menu for a head
 proc headmenu {x y id head} {
-    global headmenuid headmenuhead headctxmenu mainhead
+    global headmenuid headmenuhead headctxmenu mainhead headids
 
     stopfinding
     set headmenuid $id
     set headmenuhead $head
     array set state {0 normal 1 normal 2 normal 3 normal}
     if {[string match "remotes/*" $head]} {
-	set state(0) disabled
+	set localhead [string range $head [expr [string last / $head] + 1] end]
+	if {[info exists headids($localhead)]} {
+	    set state(0) disabled
+	}
 	set state(1) disabled
 	set state(2) disabled
     }
@@ -9852,11 +9855,27 @@ proc cobranch {} {
     global showlocalchanges
 
     # check the tree is clean first??
+    set newhead $headmenuhead
+    set command [list | git checkout]
+    if {[string match "remotes/*" $newhead]} {
+	set remote $newhead
+	set newhead [string range $newhead [expr [string last / $newhead] + 1] end]
+	# The following check is redundant - the menu option should
+	# be disabled to begin with...
+	if {[info exists headids($newhead)]} {
+	    error_popup [mc "A local branch named %s exists already" $newhead]
+	    return
+	}
+	lappend command -b $newhead --track $remote
+    } else {
+	lappend command $newhead
+    }
+    lappend command 2>@1
     nowbusy checkout [mc "Checking out"]
     update
     dohidelocalchanges
     if {[catch {
-	set fd [open [list | git checkout $headmenuhead 2>@1] r]
+	set fd [open $command r]
     } err]} {
 	notbusy checkout
 	error_popup $err
@@ -9864,12 +9883,12 @@ proc cobranch {} {
 	    dodiffindex
 	}
     } else {
-	filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
+	filerun $fd [list readcheckoutstat $fd $newhead $headmenuid]
     }
 }
 
 proc readcheckoutstat {fd newhead newheadid} {
-    global mainhead mainheadid headids showlocalchanges progresscoords
+    global mainhead mainheadid headids idheads showlocalchanges progresscoords
     global viewmainheadid curview
 
     if {[gets $fd line] >= 0} {
@@ -9884,8 +9903,14 @@ proc readcheckoutstat {fd newhead newheadid} {
     notbusy checkout
     if {[catch {close $fd} err]} {
 	error_popup $err
+	return
     }
     set oldmainid $mainheadid
+    if {! [info exists headids($newhead)]} {
+	set headids($newhead) $newheadid
+	lappend idheads($newheadid) $newhead
+	addedhead $newheadid $newhead
+    }
     set mainhead $newhead
     set mainheadid $newheadid
     set viewmainheadid($curview) $newheadid
-- 
2.1.4

```

## Paul Mackerras, 2016-03-19 03:45

Subject: Re: [PATCH 1/2] gitk: Add a 'rename' option to the branch context menu
Message-ID: <20160319034555.GB27126@fergus.ozlabs.ibm.com>
URL: https://gitlist.dev/e/20160319034555.GB27126%40fergus.ozlabs.ibm.com
In-Reply-To: <1859807.50qitjY8Ul@wiske>

```
On Fri, Jan 15, 2016 at 10:38:49PM +0100, Rogier Goossens wrote:
> 
> Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>

This is a nice idea; I just have some comments about the Tcl here:

> @@ -9756,15 +9831,19 @@ proc headmenu {x y id head} {
>      stopfinding
>      set headmenuid $id
>      set headmenuhead $head
> -    set state normal
> +    array set state {0 normal 1 normal 2 normal 3 normal}
>      if {[string match "remotes/*" $head]} {
> -	set state disabled
> +	set state(0) disabled
> +	set state(1) disabled
> +	set state(2) disabled

Why not "array set state {0 disabled 1 disabled 2 disabled}" instead?

>      }
>      if {$head eq $mainhead} {
> -	set state disabled
> +	set state(0) disabled
> +	set state(1) disabled

Similarly, "array set state {0 disabled 1 disabled}".

> +    }
> +    foreach i {0 1 2 3} {

Why do you go up to 3 when we never disable the 3rd entry?

Paul.

```

## Rogier Goossens, 2016-03-19 18:31

Subject: [PATCH v2 0/2] gitk: Two improvements to the branch context menu
Message-ID: <10662590.KWXHt2RUKZ@wiske>
URL: https://gitlist.dev/e/10662590.KWXHt2RUKZ%40wiske
In-Reply-To: <51900395.pKIx87RN0F@wiske>

```
Hi,

Hereby the revised patches.

Changes since v1:
- Rebased on latest master
- Made the changes you suggested
- Moved 'rename branch' menu option above 'delete branch'
- Cleaned up some code duplication that the previous patches 
introduced.

Rogier.

```

## Rogier Goossens, 2016-03-19 18:32

Subject: [PATCH 1/2] gitk: Add a 'rename' option to the branch context menu
Message-ID: <1733024.6FbHNINAh3@wiske>
URL: https://gitlist.dev/e/1733024.6FbHNINAh3%40wiske
In-Reply-To: <10662590.KWXHt2RUKZ@wiske>

```

Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>
---
 gitk | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 85 insertions(+), 11 deletions(-)

diff --git a/gitk b/gitk
index 805a1c7..84b49bc 100755
--- a/gitk
+++ b/gitk
@@ -2664,6 +2664,7 @@ proc makewindow {} {
     set headctxmenu .headctxmenu
     makemenu $headctxmenu {
 	{mc "Check out this branch" command cobranch}
+	{mc "Rename this branch" command mvbranch}
 	{mc "Remove this branch" command rmbranch}
 	{mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
     }
@@ -9452,26 +9453,58 @@ proc wrcomcan {} {
 }
 
 proc mkbranch {} {
-    global rowmenuid mkbrtop NS
+    global NS rowmenuid
+
+    set top .branchdialog
+
+    set val(name) ""
+    set val(id) $rowmenuid
+    set val(command) [list mkbrgo $top]
+
+    set ui(title) [mc "Create branch"]
+    set ui(accept) [mc "Create"]
+
+    branchdia $top val ui
+}
+
+proc mvbranch {} {
+    global NS
+    global headmenuid headmenuhead
+
+    set top .branchdialog
+
+    set val(name) $headmenuhead
+    set val(id) $headmenuid
+    set val(command) [list mvbrgo $top $headmenuhead]
+
+    set ui(title) [mc "Rename branch %s" $headmenuhead]
+    set ui(accept) [mc "Rename"]
+
+    branchdia $top val ui
+}
+
+proc branchdia {top valvar uivar} {
+    global NS
+    upvar $valvar val $uivar ui
 
-    set top .makebranch
     catch {destroy $top}
     ttk_toplevel $top
     make_transient $top .
-    ${NS}::label $top.title -text [mc "Create new branch"]
+    ${NS}::label $top.title -text $ui(title)
     grid $top.title - -pady 10
     ${NS}::label $top.id -text [mc "ID:"]
     ${NS}::entry $top.sha1 -width 40
-    $top.sha1 insert 0 $rowmenuid
+    $top.sha1 insert 0 $val(id)
     $top.sha1 conf -state readonly
     grid $top.id $top.sha1 -sticky w
     ${NS}::label $top.nlab -text [mc "Name:"]
     ${NS}::entry $top.name -width 40
+    $top.name insert 0 $val(name)
     grid $top.nlab $top.name -sticky w
     ${NS}::frame $top.buts
-    ${NS}::button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
+    ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)
     ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
-    bind $top <Key-Return> [list mkbrgo $top]
+    bind $top <Key-Return> $val(command)
     bind $top <Key-Escape> "catch {destroy $top}"
     grid $top.buts.go $top.buts.can
     grid columnconfigure $top.buts 0 -weight 1 -uniform a
@@ -9526,6 +9559,46 @@ proc mkbrgo {top} {
     }
 }
 
+proc mvbrgo {top prevname} {
+    global headids idheads mainhead mainheadid
+
+    set name [$top.name get]
+    set id [$top.sha1 get]
+    set cmdargs {}
+    if {$name eq $prevname} {
+	catch {destroy $top}
+	return
+    }
+    if {$name eq {}} {
+	error_popup [mc "Please specify a new name for the branch"] $top
+	return
+    }
+    catch {destroy $top}
+    lappend cmdargs -m $prevname $name
+    nowbusy renamebranch
+    update
+    if {[catch {
+	eval exec git branch $cmdargs
+    } err]} {
+	notbusy renamebranch
+	error_popup $err
+    } else {
+	notbusy renamebranch
+	removehead $id $prevname
+	removedhead $id $prevname
+	set headids($name) $id
+	lappend idheads($id) $name
+	addedhead $id $name
+	if {$prevname eq $mainhead} {
+	    set mainhead $name
+	    set mainheadid $id
+	}
+	redrawtags $id
+	dispneartags 0
+	run refill_reflist
+    }
+}
+
 proc exec_citool {tool_args {baseid {}}} {
     global commitinfo env
 
@@ -9756,15 +9829,16 @@ proc headmenu {x y id head} {
     stopfinding
     set headmenuid $id
     set headmenuhead $head
-    set state normal
+    array set state {0 normal 1 normal 2 normal}
     if {[string match "remotes/*" $head]} {
-	set state disabled
+	array set state {0 disabled 1 disabled 2 disabled}
     }
     if {$head eq $mainhead} {
-	set state disabled
+	array set state {0 disabled 2 disabled}
+    }
+    foreach i {0 1 2} {
+	$headctxmenu entryconfigure $i -state $state($i)
     }
-    $headctxmenu entryconfigure 0 -state $state
-    $headctxmenu entryconfigure 1 -state $state
     tk_popup $headctxmenu $x $y
 }
 
-- 
2.1.4

```

## Rogier Goossens, 2016-03-19 18:33

Subject: [PATCH 2/2] gitk: Allow checking out a remote branch
Message-ID: <4410053.4PRisWLqAX@wiske>
URL: https://gitlist.dev/e/4410053.4PRisWLqAX%40wiske
In-Reply-To: <10662590.KWXHt2RUKZ@wiske>

```

Git allows checking out remote branches, creating a local tracking
branch in the process. Allow gitk to do this as well, provided a
local branch of the same name does not yet exist.

Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>
---
 gitk | 36 +++++++++++++++++++++++++++++++-----
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/gitk b/gitk
index 84b49bc..dc75c97 100755
--- a/gitk
+++ b/gitk
@@ -9824,14 +9824,18 @@ proc readresetstat {fd} {
 
 # context menu for a head
 proc headmenu {x y id head} {
-    global headmenuid headmenuhead headctxmenu mainhead
+    global headmenuid headmenuhead headctxmenu mainhead headids
 
     stopfinding
     set headmenuid $id
     set headmenuhead $head
     array set state {0 normal 1 normal 2 normal}
     if {[string match "remotes/*" $head]} {
-	array set state {0 disabled 1 disabled 2 disabled}
+	set localhead [string range $head [expr [string last / $head] + 1] end]
+	if {[info exists headids($localhead)]} {
+	    set state(0) disabled
+	}
+	array set state {1 disabled 2 disabled}
     }
     if {$head eq $mainhead} {
 	array set state {0 disabled 2 disabled}
@@ -9847,11 +9851,27 @@ proc cobranch {} {
     global showlocalchanges
 
     # check the tree is clean first??
+    set newhead $headmenuhead
+    set command [list | git checkout]
+    if {[string match "remotes/*" $newhead]} {
+	set remote $newhead
+	set newhead [string range $newhead [expr [string last / $newhead] + 1] end]
+	# The following check is redundant - the menu option should
+	# be disabled to begin with...
+	if {[info exists headids($newhead)]} {
+	    error_popup [mc "A local branch named %s exists already" $newhead]
+	    return
+	}
+	lappend command -b $newhead --track $remote
+    } else {
+	lappend command $newhead
+    }
+    lappend command 2>@1
     nowbusy checkout [mc "Checking out"]
     update
     dohidelocalchanges
     if {[catch {
-	set fd [open [list | git checkout $headmenuhead 2>@1] r]
+	set fd [open $command r]
     } err]} {
 	notbusy checkout
 	error_popup $err
@@ -9859,12 +9879,12 @@ proc cobranch {} {
 	    dodiffindex
 	}
     } else {
-	filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
+	filerun $fd [list readcheckoutstat $fd $newhead $headmenuid]
     }
 }
 
 proc readcheckoutstat {fd newhead newheadid} {
-    global mainhead mainheadid headids showlocalchanges progresscoords
+    global mainhead mainheadid headids idheads showlocalchanges progresscoords
     global viewmainheadid curview
 
     if {[gets $fd line] >= 0} {
@@ -9879,8 +9899,14 @@ proc readcheckoutstat {fd newhead newheadid} {
     notbusy checkout
     if {[catch {close $fd} err]} {
 	error_popup $err
+	return
     }
     set oldmainid $mainheadid
+    if {! [info exists headids($newhead)]} {
+	set headids($newhead) $newheadid
+	lappend idheads($newheadid) $newhead
+	addedhead $newheadid $newhead
+    }
     set mainhead $newhead
     set mainheadid $newheadid
     set viewmainheadid($curview) $newheadid
-- 
2.1.4

```

## Rogier Goossens, 2016-03-27 07:21

Subject: [PATCH v2a 3/3] gitk: Include commit title in branch dialog
Message-ID: <9310641.nkQBije1VN@wiske>
URL: https://gitlist.dev/e/9310641.nkQBije1VN%40wiske
In-Reply-To: <10662590.KWXHt2RUKZ@wiske>

```
Hi,

I made another branch dialog related change, included in this message.
It applies on top of my other two patches.

Rogier.

------- 8< ------------------- 8< --------------

Only the SHA1 was included. It's convenient to have the title
mentioned as well.

Signed-off-by: Rogier Goossens <goossens.rogier@gmail.com>
---
 gitk | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gitk b/gitk
index dc75c97..413711e 100755
--- a/gitk
+++ b/gitk
@@ -9484,7 +9484,7 @@ proc mvbranch {} {
 }
 
 proc branchdia {top valvar uivar} {
-    global NS
+    global NS commitinfo
     upvar $valvar val $uivar ui
 
     catch {destroy $top}
@@ -9497,6 +9497,11 @@ proc branchdia {top valvar uivar} {
     $top.sha1 insert 0 $val(id)
     $top.sha1 conf -state readonly
     grid $top.id $top.sha1 -sticky w
+    ${NS}::entry $top.head -width 60
+    $top.head insert 0 [lindex $commitinfo($val(id)) 0]
+    $top.head conf -state readonly
+    grid x $top.head -sticky ew
+    grid columnconfigure $top 1 -weight 1
     ${NS}::label $top.nlab -text [mc "Name:"]
     ${NS}::entry $top.name -width 40
     $top.name insert 0 $val(name)
-- 
2.1.4

```

## Paul Mackerras, 2016-12-12 00:02

Subject: Re: [PATCH v2 0/2] gitk: Two improvements to the branch context menu
Message-ID: <20161212000219.GC18316@fergus.ozlabs.ibm.com>
URL: https://gitlist.dev/e/20161212000219.GC18316%40fergus.ozlabs.ibm.com
In-Reply-To: <10662590.KWXHt2RUKZ@wiske>

```
On Sat, Mar 19, 2016 at 07:31:32PM +0100, Rogier Goossens wrote:
> Hi,
> 
> Hereby the revised patches.
> 
> Changes since v1:
> - Rebased on latest master
> - Made the changes you suggested
> - Moved 'rename branch' menu option above 'delete branch'
> - Cleaned up some code duplication that the previous patches 
> introduced.

Thanks, series applied.

Paul.

```
