git-gui: Reorganized startup procedure to ensure gitdir is right.
[gitweb.git] / git-gui
diff --git a/git-gui b/git-gui
index 8ad3f2d033d29b47471c89f28dc44b8e912e8805..87dcbaef4ca16e5f917ecf199f804fdecede57d5 100755 (executable)
--- a/git-gui
+++ b/git-gui
@@ -92,7 +92,7 @@ proc update_status {{final Ready.}} {
        }
 
        if {![$ui_comm edit modified]
-           || [string trim [$ui_comm get 0.0 end]] == {}} {
+               || [string trim [$ui_comm get 0.0 end]] == {}} {
                if {[load_message GITGUI_MSG]} {
                } elseif {[load_message MERGE_MSG]} {
                } elseif {[load_message SQUASH_MSG]} {
@@ -584,6 +584,28 @@ proc commit_stage2 {fd_wt curHEAD msg} {
        update_status "Changes committed as $cmt_id."
 }
 
+######################################################################
+##
+## fetch pull push
+
+proc fetch_from {remote} {
+       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 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
+}
+
 ######################################################################
 ##
 ## ui helpers
@@ -765,6 +787,41 @@ proc toggle_mode {path} {
        }
 }
 
+######################################################################
+##
+## config (fetch push pull)
+
+proc load_all_remotes {} {
+       global gitdir all_remotes
+
+       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 fd_rc [open "| git repo-config --list" r]
+       while {[gets $fd_rc line] >= 0} {
+               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
+
+       foreach remote $all_remotes {
+               $m add command -label "$pfx $remote..." \
+                       -command [list $op $remote] \
+                       -font $mainfont
+       }
+}
+
 ######################################################################
 ##
 ## icons
@@ -882,12 +939,13 @@ proc error_popup {msg} {
 }
 
 proc show_msg {w top msg} {
-       global gitdir appname
+       global gitdir appname mainfont
 
        message $w.m -text $msg -justify left -aspect 400
        pack $w.m -side top -fill x -padx 5 -pady 10
        button $w.ok -text OK \
                -width 15 \
+               -font $mainfont \
                -command "destroy $top"
        pack $w.ok -side bottom
        bind $top <Visibility> "grab $top; focus $top"
@@ -931,6 +989,7 @@ proc hook_failed_popup {hook msg} {
 
        button $w.ok -text OK \
                -width 15 \
+               -font $mainfont \
                -command "destroy $w"
        pack $w.ok -side bottom
 
@@ -940,11 +999,85 @@ proc hook_failed_popup {hook msg} {
        tkwait window $w
 }
 
+set next_console_id 0
+
+proc new_console {short_title long_title} {
+       global next_console_id gitdir appname mainfont difffont
+
+       set w .console[incr next_console_id]
+       toplevel $w
+       frame $w.m
+       label $w.m.l1 -text "$long_title:" \
+               -anchor w \
+               -justify left \
+               -font [concat $mainfont bold]
+       text $w.m.t \
+               -background white -borderwidth 1 \
+               -relief sunken \
+               -width 80 -height 10 \
+               -font $difffont \
+               -state disabled \
+               -yscrollcommand [list $w.m.sby set]
+       scrollbar $w.m.sby -command [list $w.m.t yview]
+       pack $w.m.l1 -side top -fill x
+       pack $w.m.sby -side right -fill y
+       pack $w.m.t -side left -fill both -expand 1
+       pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
+
+       button $w.ok -text {OK} \
+               -width 15 \
+               -font $mainfont \
+               -state disabled \
+               -command "destroy $w"
+       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"
+       return $w
+}
+
+proc console_exec {w cmd} {
+       global tcl_platform
+
+       # -- Windows tosses the enviroment when we exec our child.
+       #    But most users need that so we have to relogin. :-(
+       #
+       if {$tcl_platform(platform) == {windows}} {
+               set cmd [list sh --login -c "cd \"[pwd]\" && [join $cmd { }]"]
+       }
+
+       # -- Tcl won't let us redirect both stdout and stderr to
+       #    the same pipe.  So pass it through cat...
+       #
+       set cmd [concat | $cmd |& cat]
+
+       set fd_f [open $cmd r]
+       fconfigure $fd_f -blocking 0 -translation auto
+       fileevent $fd_f readable [list console_read $w $fd_f]
+}
+
+proc console_read {w fd} {
+       $w.m.t conf -state normal
+       while {[gets $fd line] >= 0} {
+               $w.m.t insert end $line
+               $w.m.t insert end "\n"
+       }
+       $w.m.t conf -state disabled
+       $w.m.t see end
+
+       if {[eof $fd]} {
+               close $fd
+               $w.ok conf -state normal
+       }
+}
+
 ######################################################################
 ##
 ## ui commands
 
 set starting_gitk_msg {Please wait... Starting gitk...}
+
 proc do_gitk {} {
        global tcl_platform ui_status_value starting_gitk_msg
 
@@ -955,7 +1088,7 @@ proc do_gitk {} {
                }
        }
 
-    if {$tcl_platform(platform) == "windows"} {
+       if {$tcl_platform(platform) == {windows}} {
                exec sh -c gitk &
        } else {
                exec gitk &
@@ -1083,6 +1216,7 @@ menu .mbar -tearoff 0
 .mbar add cascade -label Commit -menu .mbar.commit
 .mbar add cascade -label Fetch -menu .mbar.fetch
 .mbar add cascade -label Pull -menu .mbar.pull
+.mbar add cascade -label Push -menu .mbar.push
 . configure -menu .mbar
 
 # -- Project Menu
@@ -1131,6 +1265,9 @@ menu .mbar.fetch
 # -- Pull Menu
 menu .mbar.pull
 
+# -- Push Menu
+menu .mbar.push
+
 # -- Main Window Layout
 panedwindow .vpane -orient vertical
 panedwindow .vpane.files -orient horizontal
@@ -1328,21 +1465,30 @@ unset i M1B M1T
 ##
 ## main
 
-if {[catch {set gitdir [exec git rev-parse --git-dir]} err]} {
+set appname [lindex [file split $argv0] end]
+set gitdir {}
+
+if {[catch {set cdup [exec git rev-parse --show-cdup]} err]} {
        show_msg {} . "Cannot find the git directory: $err"
        exit 1
 }
-set cdup [exec git rev-parse --show-cdup]
 if {$cdup != ""} {
        cd $cdup
 }
 unset cdup
 
-set appname [lindex [file split $argv0] end]
+if {[catch {set gitdir [exec git rev-parse --git-dir]} err]} {
+       show_msg {} . "Cannot find the git directory: $err"
+       exit 1
+}
+
 if {$appname == {git-citool}} {
        set single_commit 1
 }
 
 wm title . "$appname ([file normalize [file dirname $gitdir]])"
 focus -force $ui_comm
+load_all_remotes
+populate_remote_menu .mbar.fetch From fetch_from
+populate_remote_menu .mbar.push To push_to
 update_status