diff --git a/lib/merge.tcl b/lib/merge.tcl
index 21cd83d9c8eb1ae623dad5e65e794bde7b6cfab8..6caf25f2bea19efbad2190587ea5c414604871f0 100644 (file)
--- a/lib/merge.tcl
+++ b/lib/merge.tcl
# git-gui branch merge support
# Copyright (C) 2006, 2007 Shawn Pearce
-namespace eval merge {
+class merge {
+
+field w ; # top level window
+field w_list ; # widget of available branches
+field list ; # list of available branches
-proc _can_merge {} {
+method _can_merge {} {
global HEAD commit_type file_states
if {[string match amend* $commit_type]} {
The rescan will be automatically started now.
}
unlock_index
- rescan {set ui_status_value {Ready.}}
+ rescan ui_ready
return 0
}
return 1
}
-proc _visualize {w} {
- set revs {}
- foreach i [$w.source.l curselection] {
- lappend revs [$w.source.l get $i]
+method _refs {} {
+ set r {}
+ foreach i [$w_list curselection] {
+ lappend r [lindex [lindex $list $i] 0]
}
+ return $r
+}
+
+method _visualize {} {
+ set revs [_refs $this]
if {$revs eq {}} return
lappend revs --not HEAD
do_gitk $revs
}
-proc _start {w} {
- global HEAD ui_status_value current_branch
+method _start {} {
+ global HEAD current_branch
set cmd [list git merge]
- set names {}
- set revcnt 0
- foreach i [$w.source.l curselection] {
- set b [$w.source.l get $i]
- lappend cmd $b
- lappend names $b
- incr revcnt
- }
+ set names [_refs $this]
+ set revcnt [llength $names]
+ append cmd { } $names
if {$revcnt == 0} {
return
@@ -121,15 +125,16 @@ Please select fewer branches. To merge more than 15 branches, merge the branche
}
set msg "Merging $current_branch, [join $names {, }]"
- set ui_status_value "$msg..."
+ ui_status "$msg..."
set cons [console::new "Merge" $msg]
- console::exec $cons $cmd [namespace code [list _finish $revcnt]]
- bind $w <Destroy> {}
+ console::exec $cons $cmd [cb _finish $revcnt $cons]
+
+ wm protocol $w WM_DELETE_WINDOW {}
destroy $w
}
-proc _finish {revcnt w ok} {
- console::done $w $ok
+method _finish {revcnt cons ok} {
+ console::done $cons $ok
if {$ok} {
set msg {Merge completed successfully.}
} else {
You can attempt this merge again by merging only one branch at a time." $w
- set fd [open "| git read-tree --reset -u HEAD" r]
+ set fd [git_read read-tree --reset -u HEAD]
fconfigure $fd -blocking 0 -translation binary
- fileevent $fd readable \
- [namespace code [list _reset_wait $fd]]
- set ui_status_value {Aborting... please wait...}
+ fileevent $fd readable [cb _reset_wait $fd]
+ ui_status {Aborting... please wait...}
return
}
set msg {Merge failed. Conflict resolution is required.}
}
unlock_index
- rescan [list set ui_status_value $msg]
+ rescan [list ui_status $msg]
+ delete_this
}
-proc dialog {} {
+constructor dialog {} {
global current_branch
+ global M1B
+
+ if {![_can_merge $this]} {
+ delete_this
+ return
+ }
+
+ set fmt {list %(objectname) %(*objectname) %(refname) %(subject)}
+ set fr_fd [git_read for-each-ref \
+ --tcl \
+ --format=$fmt \
+ refs/heads \
+ refs/remotes \
+ refs/tags \
+ ]
+ fconfigure $fr_fd -translation binary
+ while {[gets $fr_fd line] > 0} {
+ set line [eval $line]
+ set ref [lindex $line 2]
+ regsub ^refs/(heads|remotes|tags)/ $ref {} ref
+ set subj($ref) [lindex $line 3]
+ lappend sha1([lindex $line 0]) $ref
+ if {[lindex $line 1] ne {}} {
+ lappend sha1([lindex $line 1]) $ref
+ }
+ }
+ close $fr_fd
- if {![_can_merge]} return
+ set list [list]
+ set fr_fd [git_read rev-list --all --not HEAD]
+ while {[gets $fr_fd line] > 0} {
+ if {[catch {set ref $sha1($line)}]} continue
+ foreach n $ref {
+ lappend list [list $n $line]
+ }
+ }
+ close $fr_fd
+ set list [lsort -unique $list]
- set w .merge_setup
- toplevel $w
- wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
+ make_toplevel top w
+ wm title $top "[appname] ([reponame]): Merge"
+ if {$top ne {.}} {
+ wm geometry $top "+[winfo rootx .]+[winfo rooty .]"
+ }
+
+ set _visualize [cb _visualize]
+ set _start [cb _start]
label $w.header \
-text "Merge Into $current_branch" \
pack $w.header -side top -fill x
frame $w.buttons
- button $w.buttons.visualize -text Visualize \
- -command [namespace code [list _visualize $w]]
+ button $w.buttons.visualize -text Visualize -command $_visualize
pack $w.buttons.visualize -side left
- button $w.buttons.create -text Merge \
- -command [namespace code [list _start $w]]
+ button $w.buttons.create -text Merge -command $_start
pack $w.buttons.create -side right
- button $w.buttons.cancel -text {Cancel} \
- -command [list destroy $w]
+ button $w.buttons.cancel \
+ -text {Cancel} \
+ -command [cb _cancel]
pack $w.buttons.cancel -side right -padx 5
pack $w.buttons -side bottom -fill x -pady 10 -padx 10
labelframe $w.source -text {Source Branches}
- listbox $w.source.l \
+ set w_list $w.source.l
+ listbox $w_list \
-height 10 \
-width 70 \
+ -font font_diff \
-selectmode extended \
-yscrollcommand [list $w.source.sby set]
- scrollbar $w.source.sby -command [list $w.source.l yview]
+ scrollbar $w.source.sby -command [list $w_list yview]
pack $w.source.sby -side right -fill y
- pack $w.source.l -side left -fill both -expand 1
+ pack $w_list -side left -fill both -expand 1
pack $w.source -fill both -expand 1 -pady 5 -padx 5
- set cmd [list git for-each-ref]
- lappend cmd {--format=%(objectname) %(*objectname) %(refname)}
- lappend cmd refs/heads
- lappend cmd refs/remotes
- lappend cmd refs/tags
- set fr_fd [open "| $cmd" r]
- fconfigure $fr_fd -translation binary
- while {[gets $fr_fd line] > 0} {
- set line [split $line { }]
- set sha1([lindex $line 0]) [lindex $line 2]
- set sha1([lindex $line 1]) [lindex $line 2]
+ foreach ref $list {
+ set n [lindex $ref 0]
+ if {[string length $n] > 20} {
+ set n "[string range $n 0 16]..."
+ }
+ $w_list insert end [format {%s %-20s %s} \
+ [string range [lindex $ref 1] 0 5] \
+ $n \
+ $subj([lindex $ref 0])]
}
- close $fr_fd
- set to_show {}
- set fr_fd [open "| git rev-list --all --not HEAD"]
- while {[gets $fr_fd line] > 0} {
- if {[catch {set ref $sha1($line)}]} continue
- regsub ^refs/(heads|remotes|tags)/ $ref {} ref
- lappend to_show $ref
- }
- close $fr_fd
+ bind $w_list <Key-K> [list event generate %W <Shift-Key-Up>]
+ bind $w_list <Key-J> [list event generate %W <Shift-Key-Down>]
+ bind $w_list <Key-k> [list event generate %W <Key-Up>]
+ bind $w_list <Key-j> [list event generate %W <Key-Down>]
+ bind $w_list <Key-h> [list event generate %W <Key-Left>]
+ bind $w_list <Key-l> [list event generate %W <Key-Right>]
+ bind $w_list <Key-v> $_visualize
+
+ bind $w <$M1B-Key-Return> $_start
+ bind $w <Visibility> [cb _visible]
+ bind $w <Key-Escape> [cb _cancel]
+ wm protocol $w WM_DELETE_WINDOW [cb _cancel]
+ tkwait window $w
+}
- foreach ref [lsort -unique $to_show] {
- $w.source.l insert end $ref
- }
+method _visible {} {
+ grab $w
+ focus $w_list
+}
+
+method _cancel {} {
+ wm protocol $w WM_DELETE_WINDOW {}
+ unlock_index
+ destroy $w
+ delete_this
+}
- bind $w <Visibility> "grab $w"
- bind $w <Key-Escape> "unlock_index;destroy $w"
- bind $w <Destroy> unlock_index
- wm title $w "[appname] ([reponame]): Merge"
- tkwait window $w
}
+namespace eval merge {
+
proc reset_hard {} {
global HEAD commit_type file_states
Aborting the current $op will cause *ALL* uncommitted changes to be lost.
Continue with aborting the current $op?"] eq {yes}} {
- set fd [open "| git read-tree --reset -u HEAD" r]
+ set fd [git_read read-tree --reset -u HEAD]
fconfigure $fd -blocking 0 -translation binary
fileevent $fd readable [namespace code [list _reset_wait $fd]]
- set ui_status_value {Aborting... please wait...}
+ ui_status {Aborting... please wait...}
} else {
unlock_index
}
catch {file delete [gitdir MERGE_MSG]}
catch {file delete [gitdir GITGUI_MSG]}
- rescan {set ui_status_value {Abort completed. Ready.}}
+ rescan {ui_status {Abort completed. Ready.}}
}
}