set w [new_console "fetch $remote" \
"Fetching new changes from $remote"]
set cmd [list git fetch]
- lappend cmd -v
lappend cmd $remote
console_exec $w $cmd
}
+proc pull_remote {remote branch} {
+ set w [new_console "pull $remote $branch" \
+ "Pulling new changes from branch $branch in $remote"]
+ set cmd [list git pull]
+ lappend cmd $remote
+ lappend cmd $branch
+ console_exec $w $cmd [list post_pull_remote $remote $branch]
+}
+
+proc post_pull_remote {remote branch success} {
+ if {$success} {
+ update_status "Successfully pulled $branch from $remote."
+ } else {
+ update_status "Conflicts detected while pulling $branch from $remote."
+ }
+}
+
proc push_to {remote} {
set w [new_console "push $remote" \
"Pushing changes to $remote"]
set cmd [list git push]
- lappend -v
lappend cmd $remote
console_exec $w $cmd
}
##
## config (fetch push pull)
+proc load_repo_config {} {
+ global repo_config
+
+ array unset repo_config
+ catch {
+ set fd_rc [open "| git repo-config --list" r]
+ while {[gets $fd_rc line] >= 0} {
+ if {[regexp {^([^=]+)=(.*)$} $line line name value]} {
+ lappend repo_config($name) $value
+ }
+ }
+ close $fd_rc
+ }
+}
+
proc load_all_remotes {} {
- global gitdir all_remotes
+ global gitdir all_remotes repo_config
set all_remotes [list]
set rm_dir [file join $gitdir remotes]
if {[file isdirectory $rm_dir]} {
- set all_remotes [concat $all_remotes \
- [glob -types f -tails -directory $rm_dir * *]]
+ set all_remotes [concat $all_remotes [glob \
+ -types f \
+ -tails \
+ -nocomplain \
+ -directory $rm_dir *]]
}
- set fd_rc [open "| git repo-config --list" r]
- while {[gets $fd_rc line] >= 0} {
- if {[regexp ^remote\.(.*)\.url= $line line name]} {
+ foreach line [array names repo_config remote.*.url] {
+ if {[regexp ^remote\.(.*)\.url\$ $line line name]} {
lappend all_remotes $name
}
}
- close $fd_rc
set all_remotes [lsort -unique $all_remotes]
}
proc populate_remote_menu {m pfx op} {
- global gitdir all_remotes mainfont
+ global all_remotes mainfont
foreach remote $all_remotes {
$m add command -label "$pfx $remote..." \
}
}
+proc populate_pull_menu {m} {
+ global gitdir repo_config all_remotes mainfont
+
+ foreach remote $all_remotes {
+ set rb {}
+ if {[array get repo_config remote.$remote.url] != {}} {
+ if {[array get repo_config remote.$remote.fetch] != {}} {
+ regexp {^([^:]+):} \
+ [lindex $repo_config(remote.$remote.fetch) 0] \
+ line rb
+ }
+ } else {
+ catch {
+ set fd [open [file join $gitdir remotes $remote] r]
+ while {[gets $fd line] >= 0} {
+ if {[regexp {^Pull:[ \t]*([^:]+):} $line line rb]} {
+ break
+ }
+ }
+ close $fd
+ }
+ }
+
+ set rb_short $rb
+ regsub ^refs/heads/ $rb {} rb_short
+ if {$rb_short != {}} {
+ $m add command \
+ -label "Branch $rb_short from $remote..." \
+ -command [list pull_remote $remote $rb] \
+ -font $mainfont
+ }
+ }
+}
+
######################################################################
##
## icons
pack $w.ok -side bottom
bind $top <Visibility> "grab $top; focus $top"
bind $top <Key-Return> "destroy $top"
- wm title $top "error: $appname ([file normalize [file dirname $gitdir]])"
+ wm title $w "$appname ([lindex [file split \
+ [file normalize [file dirname $gitdir]]] \
+ end]): error"
tkwait window $top
}
bind $w <Visibility> "grab $w; focus $w"
bind $w <Key-Return> "destroy $w"
- wm title $w "error: $appname ([file normalize [file dirname $gitdir]])"
+ wm title $w "$appname ([lindex [file split \
+ [file normalize [file dirname $gitdir]]] \
+ end]): error"
tkwait window $w
}
set next_console_id 0
proc new_console {short_title long_title} {
- global next_console_id console_cr
+ global next_console_id console_data
+ set w .console[incr next_console_id]
+ set console_data($w) [list $short_title $long_title]
+ return [console_init $w]
+}
+
+proc console_init {w} {
+ global console_cr console_data
global gitdir appname mainfont difffont
- set w .console[incr next_console_id]
set console_cr($w) 1.0
toplevel $w
frame $w.m
- label $w.m.l1 -text "$long_title:" \
+ label $w.m.l1 -text "[lindex $console_data($w) 1]:" \
-anchor w \
-justify left \
-font [concat $mainfont bold]
pack $w.ok -side bottom
bind $w <Visibility> "focus $w"
- bind $w <Destroy> break
- wm title $w "$appname ([file dirname [file normalize [file dirname $gitdir]]]): $short_title"
+ wm title $w "$appname ([lindex [file split \
+ [file normalize [file dirname $gitdir]]] \
+ end]): [lindex $console_data($w) 0]"
return $w
}
-proc console_exec {w cmd} {
+proc console_exec {w cmd {after {}}} {
global tcl_platform
# -- Windows tosses the enviroment when we exec our child.
set fd_f [open $cmd r]
fconfigure $fd_f -blocking 0 -translation binary
- fileevent $fd_f readable [list console_read $w $fd_f]
+ fileevent $fd_f readable [list console_read $w $fd_f $after]
}
-proc console_read {w fd} {
- global console_cr
+proc console_read {w fd after} {
+ global console_cr console_data
- $w.m.t conf -state normal
set buf [read $fd]
- set c 0
- set n [string length $buf]
- while {$c < $n} {
- set cr [string first "\r" $buf $c]
- set lf [string first "\n" $buf $c]
- if {$cr < 0} {set cr [expr $n + 1]}
- if {$lf < 0} {set lf [expr $n + 1]}
-
- if {$lf < $cr} {
- $w.m.t insert end [string range $buf $c $lf]
- set console_cr($w) [$w.m.t index {end -1c}]
- set c $lf
- incr c
- } else {
- $w.m.t delete $console_cr($w) end
- $w.m.t insert end "\n"
- $w.m.t insert end [string range $buf $c $cr]
- set c $cr
- incr c
+ if {$buf != {}} {
+ if {![winfo exists $w]} {console_init $w}
+ $w.m.t conf -state normal
+ set c 0
+ set n [string length $buf]
+ while {$c < $n} {
+ set cr [string first "\r" $buf $c]
+ set lf [string first "\n" $buf $c]
+ if {$cr < 0} {set cr [expr $n + 1]}
+ if {$lf < 0} {set lf [expr $n + 1]}
+
+ if {$lf < $cr} {
+ $w.m.t insert end [string range $buf $c $lf]
+ set console_cr($w) [$w.m.t index {end -1c}]
+ set c $lf
+ incr c
+ } else {
+ $w.m.t delete $console_cr($w) end
+ $w.m.t insert end "\n"
+ $w.m.t insert end [string range $buf $c $cr]
+ set c $cr
+ incr c
+ }
}
+ $w.m.t conf -state disabled
+ $w.m.t see end
}
- $w.m.t conf -state disabled
- $w.m.t see end
fconfigure $fd -blocking 1
if {[eof $fd]} {
if {[catch {close $fd}]} {
+ if {![winfo exists $w]} {console_init $w}
$w.m.s conf -background red -text {Error: Command Failed}
- } else {
+ $w.ok conf -text Close
+ $w.ok conf -state normal
+ set ok 0
+ } elseif {[winfo exists $w]} {
$w.m.s conf -background green -text {Success}
+ $w.ok conf -text Close
+ $w.ok conf -state normal
+ set ok 1
}
- $w.ok conf -text Close
- $w.ok conf -state normal
array unset console_cr $w
+ array unset console_data $w
+ if {$after != {}} {
+ uplevel #0 $after $ok
+ }
return
}
fconfigure $fd -blocking 0
wm title . "$appname ([file normalize [file dirname $gitdir]])"
focus -force $ui_comm
+load_repo_config
load_all_remotes
populate_remote_menu .mbar.fetch From fetch_from
populate_remote_menu .mbar.push To push_to
+populate_pull_menu .mbar.pull
update_status