Check for IO errors after running a command
[gitweb.git] / git-gui / git-gui.sh
index 46358258bb65ceba68441c51fd69f212e9f817d3..3237f3d59627d60e3d5ac18ee588a61b0ce87576 100755 (executable)
@@ -22,13 +22,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA}
 
 ######################################################################
 ##
-## configure our library
+## Tcl/Tk sanity check
 
-set oguilib {@@GITGUI_LIBDIR@@}
-if {[string match @@* $oguilib]} {
-       set oguilib [file join [file dirname [file normalize $argv0]] lib]
+if {[catch {package require Tcl 8.4} err]
+ || [catch {package require Tk  8.4} err]
+} {
+       catch {wm withdraw .}
+       tk_messageBox \
+               -icon error \
+               -type ok \
+               -title "git-gui: fatal error" \
+               -message $err
+       exit 1
 }
-set auto_path [concat [list $oguilib] $auto_path]
+
+######################################################################
+##
+## enable verbose loading?
 
 if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} {
        unset _verbose
@@ -44,6 +54,54 @@ if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} {
        }
 }
 
+######################################################################
+##
+## configure our library
+
+set oguilib {@@GITGUI_LIBDIR@@}
+set oguirel {@@GITGUI_RELATIVE@@}
+if {$oguirel eq {1}} {
+       set oguilib [file dirname [file dirname [file normalize $argv0]]]
+       set oguilib [file join $oguilib share git-gui lib]
+} elseif {[string match @@* $oguirel]} {
+       set oguilib [file join [file dirname [file normalize $argv0]] lib]
+}
+
+set idx [file join $oguilib tclIndex]
+if {[catch {set fd [open $idx r]} err]} {
+       catch {wm withdraw .}
+       tk_messageBox \
+               -icon error \
+               -type ok \
+               -title "git-gui: fatal error" \
+               -message $err
+       exit 1
+}
+if {[gets $fd] eq {# Autogenerated by git-gui Makefile}} {
+       set idx [list]
+       while {[gets $fd n] >= 0} {
+               if {$n ne {} && ![string match #* $n]} {
+                       lappend idx $n
+               }
+       }
+} else {
+       set idx {}
+}
+close $fd
+
+if {$idx ne {}} {
+       set loaded [list]
+       foreach p $idx {
+               if {[lsearch -exact $loaded $p] >= 0} continue
+               source [file join $oguilib $p]
+               lappend loaded $p
+       }
+       unset loaded p
+} else {
+       set auto_path [concat [list $oguilib] $auto_path]
+}
+unset -nocomplain oguirel idx fd
+
 ######################################################################
 ##
 ## read only globals
@@ -158,6 +216,15 @@ proc is_config_true {name} {
        }
 }
 
+proc get_config {name} {
+       global repo_config
+       if {[catch {set v $repo_config($name)}]} {
+               return {}
+       } else {
+               return $v
+       }
+}
+
 proc load_config {include_global} {
        global repo_config global_config default_config
 
@@ -211,6 +278,17 @@ proc git {args} {
        return [eval exec git $args]
 }
 
+proc current-branch {} {
+       set ref {}
+       set fd [open [gitdir HEAD] r]
+       if {[gets $fd ref] <16
+        || ![regsub {^ref: refs/heads/} $ref {} ref]} {
+               set ref {}
+       }
+       close $fd
+       return $ref
+}
+
 auto_load tk_optionMenu
 rename tk_optionMenu real__tkOptionMenu
 proc tk_optionMenu {w varName args} {
@@ -261,8 +339,14 @@ unset -nocomplain v _junk act_maj act_min req_maj req_min
 ##
 ## repository setup
 
-if {   [catch {set _gitdir $env(GIT_DIR)}]
-       && [catch {set _gitdir [git rev-parse --git-dir]} err]} {
+if {[catch {
+               set _gitdir $env(GIT_DIR)
+               set _prefix {}
+               }]
+       && [catch {
+               set _gitdir [git rev-parse --git-dir]
+               set _prefix [git rev-parse --show-prefix]
+       } err]} {
        catch {wm withdraw .}
        error_popup "Cannot find the git directory:\n\n$err"
        exit 1
@@ -353,15 +437,7 @@ proc repository_state {ctvar hdvar mhvar} {
 
        set mh [list]
 
-       if {[catch {set current_branch [git symbolic-ref HEAD]}]} {
-               set current_branch {}
-       } else {
-               regsub ^refs/((heads|tags|remotes)/)? \
-                       $current_branch \
-                       {} \
-                       current_branch
-       }
-
+       set current_branch [current-branch]
        if {[catch {set hd [git rev-parse --verify HEAD]}]} {
                set hd {}
                set ct initial
@@ -418,7 +494,8 @@ proc rescan {after {honor_trustmtime 1}} {
 
        if {![$ui_comm edit modified]
                || [string trim [$ui_comm get 0.0 end]] eq {}} {
-               if {[load_message GITGUI_MSG]} {
+               if {[string match amend* $commit_type]} {
+               } elseif {[load_message GITGUI_MSG]} {
                } elseif {[load_message MERGE_MSG]} {
                } elseif {[load_message SQUASH_MSG]} {
                }
@@ -971,6 +1048,7 @@ proc incr_font_size {font {amt 1}} {
        incr sz $amt
        font configure $font -size $sz
        font configure ${font}bold -size $sz
+       font configure ${font}italic -size $sz
 }
 
 ######################################################################
@@ -1163,25 +1241,28 @@ catch {
        destroy .dummy
 }
 
+font create font_uiitalic
 font create font_uibold
 font create font_diffbold
+font create font_diffitalic
 
 foreach class {Button Checkbutton Entry Label
                Labelframe Listbox Menu Message
-               Radiobutton Text} {
+               Radiobutton Spinbox Text} {
        option add *$class.font font_ui
 }
 unset class
 
-if {[is_Windows]} {
-       set M1B Control
-       set M1T Ctrl
-} elseif {[is_MacOSX]} {
+if {[is_Windows] || [is_MacOSX]} {
+       option add *Menu.tearOff 0
+}
+
+if {[is_MacOSX]} {
        set M1B M1
        set M1T Cmd
 } else {
-       set M1B M1
-       set M1T M1
+       set M1B Control
+       set M1T Ctrl
 }
 
 proc apply_config {} {
@@ -1199,16 +1280,20 @@ proc apply_config {} {
                }
                foreach {cn cv} [font configure $font] {
                        font configure ${font}bold $cn $cv
+                       font configure ${font}italic $cn $cv
                }
                font configure ${font}bold -weight bold
+               font configure ${font}italic -slant italic
        }
 }
 
+set default_config(merge.diffstat) true
 set default_config(merge.summary) false
 set default_config(merge.verbosity) 2
 set default_config(user.name) {}
 set default_config(user.email) {}
 
+set default_config(gui.pruneduringfetch) false
 set default_config(gui.trustmtime) false
 set default_config(gui.diffcontext) 5
 set default_config(gui.newbranchtemplate) {}
@@ -1288,7 +1373,7 @@ menu .mbar.repository
 
 .mbar.repository add command \
        -label {Browse Current Branch} \
-       -command {new_browser $current_branch}
+       -command {browser::new $current_branch}
 trace add variable current_branch write ".mbar.repository entryconf [.mbar.repository index last] -label \"Browse \$current_branch\" ;#"
 .mbar.repository add separator
 
@@ -1370,6 +1455,11 @@ if {[is_enabled branch]} {
        lappend disable_on_lock [list .mbar.branch entryconf \
                [.mbar.branch index last] -state]
 
+       .mbar.branch add command -label {Rename...} \
+               -command branch_rename::dialog
+       lappend disable_on_lock [list .mbar.branch entryconf \
+               [.mbar.branch index last] -state]
+
        .mbar.branch add command -label {Delete...} \
                -command do_delete_branch
        lappend disable_on_lock [list .mbar.branch entryconf \
@@ -1467,6 +1557,8 @@ if {[is_enabled transport]} {
        menu .mbar.push
        .mbar.push add command -label {Push...} \
                -command do_push_anywhere
+       .mbar.push add command -label {Delete...} \
+               -command remote_branch_delete::dialog
 }
 
 if {[is_MacOSX]} {
@@ -1566,31 +1658,65 @@ unset browser doc_path doc_url
 
 # -- Standard bindings
 #
-bind .   <Destroy> do_quit
+wm protocol . WM_DELETE_WINDOW do_quit
 bind all <$M1B-Key-q> do_quit
 bind all <$M1B-Key-Q> do_quit
 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
 bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
 
+set subcommand_args {}
+proc usage {} {
+       puts stderr "usage: $::argv0 $::subcommand $::subcommand_args"
+       exit 1
+}
+
 # -- Not a normal commit type invocation?  Do that instead!
 #
 switch -- $subcommand {
 browser {
-       if {[llength $argv] != 1} {
-               puts stderr "usage: $argv0 browser commit"
-               exit 1
+       set subcommand_args {rev?}
+       switch [llength $argv] {
+       0 { set current_branch [current-branch] }
+       1 { set current_branch [lindex $argv 0] }
+       default usage
        }
-       set current_branch [lindex $argv 0]
-       new_browser $current_branch
+       browser::new $current_branch
        return
 }
 blame {
-       if {[llength $argv] != 2} {
-               puts stderr "usage: $argv0 blame commit path"
-               exit 1
+       set subcommand_args {rev? path?}
+       set head {}
+       set path {}
+       set is_path 0
+       foreach a $argv {
+               if {$is_path || [file exists $_prefix$a]} {
+                       if {$path ne {}} usage
+                       set path $_prefix$a
+                       break
+               } elseif {$a eq {--}} {
+                       if {$path ne {}} {
+                               if {$head ne {}} usage
+                               set head $path
+                               set path {}
+                       }
+                       set is_path 1
+               } elseif {$head eq {}} {
+                       if {$head ne {}} usage
+                       set head $a
+               } else {
+                       usage
+               }
+       }
+       unset is_path
+
+       if {$head eq {}} {
+               set current_branch [current-branch]
+       } else {
+               set current_branch $head
        }
-       set current_branch [lindex $argv 0]
-       show_blame $current_branch [lindex $argv 1]
+
+       if {$path eq {}} usage
+       blame::new $head $path
        return
 }
 citool -
@@ -1638,8 +1764,8 @@ pack .vpane -anchor n -side top -fill both -expand 1
 # -- Index File List
 #
 frame .vpane.files.index -height 100 -width 200
-label .vpane.files.index.title -text {Changes To Be Committed} \
-       -background green
+label .vpane.files.index.title -text {Staged Changes (Will Be Committed)} \
+       -background lightgreen
 text $ui_index -background white -borderwidth 0 \
        -width 20 -height 10 \
        -wrap none \
@@ -1658,8 +1784,8 @@ pack $ui_index -side left -fill both -expand 1
 # -- Working Directory File List
 #
 frame .vpane.files.workdir -height 100 -width 200
-label .vpane.files.workdir.title -text {Changed But Not Updated} \
-       -background red
+label .vpane.files.workdir.title -text {Unstaged Changes (Will Not Be Committed)} \
+       -background lightsalmon
 text $ui_workdir -background white -borderwidth 0 \
        -width 20 -height 10 \
        -wrap none \
@@ -1676,10 +1802,8 @@ pack $ui_workdir -side left -fill both -expand 1
 .vpane.files add .vpane.files.workdir -sticky nsew
 
 foreach i [list $ui_index $ui_workdir] {
-       $i tag conf in_diff -font font_uibold
-       $i tag conf in_sel \
-               -background [$i cget -foreground] \
-               -foreground [$i cget -background]
+       $i tag conf in_diff -background lightgray
+       $i tag conf in_sel  -background lightgray
 }
 unset i
 
@@ -1837,18 +1961,18 @@ proc trace_current_diff_path {varname args} {
 }
 trace add variable current_diff_path write trace_current_diff_path
 
-frame .vpane.lower.diff.header -background orange
+frame .vpane.lower.diff.header -background gold
 label .vpane.lower.diff.header.status \
-       -background orange \
+       -background gold \
        -width $max_status_desc \
        -anchor w \
        -justify left
 label .vpane.lower.diff.header.file \
-       -background orange \
+       -background gold \
        -anchor w \
        -justify left
 label .vpane.lower.diff.header.path \
-       -background orange \
+       -background gold \
        -anchor w \
        -justify left
 pack .vpane.lower.diff.header.status -side left
@@ -1962,17 +2086,17 @@ lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
 $ctxm add separator
 $ctxm add command \
        -label {Show Less Context} \
-       -command {if {$repo_config(gui.diffcontext) >= 2} {
+       -command {if {$repo_config(gui.diffcontext) >= 1} {
                incr repo_config(gui.diffcontext) -1
                reshow_diff
        }}
 lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
 $ctxm add command \
        -label {Show More Context} \
-       -command {
+       -command {if {$repo_config(gui.diffcontext) < 99} {
                incr repo_config(gui.diffcontext)
                reshow_diff
-       }
+       }}
 lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state]
 $ctxm add separator
 $ctxm add command -label {Options...} \