Merge git://repo.or.cz/git-gui
* git://repo.or.cz/git-gui: git-gui: "Stage Line": Treat independent changes in adjacent lines better git-gui: Fix "Stage/Unstage Line" with one line of context. git-gui: Correct 'Visualize Branches' on Mac OS X to start gitk git-gui: Look for gitk in $PATH, not $LIBEXEC/git-core Add a menu item to invoke full copy detection in blame. Kill the blame back-end on window close. Add options to control the search for copies in blame. Fix pre-commit hooks under MinGW/MSYS
This commit is contained in:
commit
392f130091
@ -473,10 +473,10 @@ proc githook_read {hook_name args} {
|
||||
set pchook [gitdir hooks $hook_name]
|
||||
lappend args 2>@1
|
||||
|
||||
# On Cygwin [file executable] might lie so we need to ask
|
||||
# On Windows [file executable] might lie so we need to ask
|
||||
# the shell if the hook is executable. Yes that's annoying.
|
||||
#
|
||||
if {[is_Cygwin]} {
|
||||
if {[is_Windows]} {
|
||||
upvar #0 _sh interp
|
||||
if {![info exists interp]} {
|
||||
set interp [_which sh]
|
||||
@ -497,6 +497,20 @@ proc githook_read {hook_name args} {
|
||||
return {}
|
||||
}
|
||||
|
||||
proc kill_file_process {fd} {
|
||||
set process [pid $fd]
|
||||
|
||||
catch {
|
||||
if {[is_Windows]} {
|
||||
# Use a Cygwin-specific flag to allow killing
|
||||
# native Windows processes
|
||||
exec kill -f $process
|
||||
} else {
|
||||
exec kill $process
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc sq {value} {
|
||||
regsub -all ' $value "'\\''" value
|
||||
return "'$value'"
|
||||
@ -642,6 +656,8 @@ set default_config(user.email) {}
|
||||
set default_config(gui.matchtrackingbranch) false
|
||||
set default_config(gui.pruneduringfetch) false
|
||||
set default_config(gui.trustmtime) false
|
||||
set default_config(gui.fastcopyblame) false
|
||||
set default_config(gui.copyblamethreshold) 40
|
||||
set default_config(gui.diffcontext) 5
|
||||
set default_config(gui.commitmsgwidth) 75
|
||||
set default_config(gui.newbranchtemplate) {}
|
||||
@ -1670,10 +1686,10 @@ proc do_gitk {revs} {
|
||||
# -- Always start gitk through whatever we were loaded with. This
|
||||
# lets us bypass using shell process on Windows systems.
|
||||
#
|
||||
set exe [file join [file dirname $::_git] gitk]
|
||||
set exe [_which gitk]
|
||||
set cmd [list [info nameofexecutable] $exe]
|
||||
if {! [file exists $exe]} {
|
||||
error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe]
|
||||
if {$exe eq {}} {
|
||||
error_popup [mc "Couldn't find gitk in PATH"]
|
||||
} else {
|
||||
global env
|
||||
|
||||
|
@ -33,13 +33,6 @@ variable group_colors {
|
||||
#ececec
|
||||
}
|
||||
|
||||
# Switches for original location detection
|
||||
#
|
||||
variable original_options [list -C -C]
|
||||
if {[git-version >= 1.5.3]} {
|
||||
lappend original_options -w ; # ignore indentation changes
|
||||
}
|
||||
|
||||
# Current blame data; cleared/reset on each load
|
||||
#
|
||||
field commit ; # input commit to blame
|
||||
@ -263,6 +256,9 @@ constructor new {i_commit i_path} {
|
||||
$w.ctxm add command \
|
||||
-label [mc "Copy Commit"] \
|
||||
-command [cb _copycommit]
|
||||
$w.ctxm add command \
|
||||
-label [mc "Do Full Copy Detection"] \
|
||||
-command [cb _fullcopyblame]
|
||||
|
||||
foreach i $w_columns {
|
||||
for {set g 0} {$g < [llength $group_colors]} {incr g} {
|
||||
@ -333,19 +329,27 @@ constructor new {i_commit i_path} {
|
||||
bind $w.file_pane <Configure> \
|
||||
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
|
||||
|
||||
wm protocol $top WM_DELETE_WINDOW "destroy $top"
|
||||
bind $top <Destroy> [cb _kill]
|
||||
|
||||
_load $this {}
|
||||
}
|
||||
|
||||
method _kill {} {
|
||||
if {$current_fd ne {}} {
|
||||
kill_file_process $current_fd
|
||||
catch {close $current_fd}
|
||||
set current_fd {}
|
||||
}
|
||||
}
|
||||
|
||||
method _load {jump} {
|
||||
variable group_colors
|
||||
|
||||
_hide_tooltip $this
|
||||
|
||||
if {$total_lines != 0 || $current_fd ne {}} {
|
||||
if {$current_fd ne {}} {
|
||||
catch {close $current_fd}
|
||||
set current_fd {}
|
||||
}
|
||||
_kill $this
|
||||
|
||||
foreach i $w_columns {
|
||||
$i conf -state normal
|
||||
@ -511,7 +515,6 @@ method _exec_blame {cur_w cur_d options cur_s} {
|
||||
method _read_blame {fd cur_w cur_d} {
|
||||
upvar #0 $cur_d line_data
|
||||
variable group_colors
|
||||
variable original_options
|
||||
|
||||
if {$fd ne $current_fd} {
|
||||
catch {close $fd}
|
||||
@ -684,6 +687,18 @@ method _read_blame {fd cur_w cur_d} {
|
||||
if {[eof $fd]} {
|
||||
close $fd
|
||||
if {$cur_w eq $w_asim} {
|
||||
# Switches for original location detection
|
||||
set threshold [get_config gui.copyblamethreshold]
|
||||
set original_options [list "-C$threshold"]
|
||||
|
||||
if {![is_config_true gui.fastcopyblame]} {
|
||||
# thorough copy search; insert before the threshold
|
||||
set original_options [linsert $original_options 0 -C]
|
||||
}
|
||||
if {[git-version >= 1.5.3]} {
|
||||
lappend original_options -w ; # ignore indentation changes
|
||||
}
|
||||
|
||||
_exec_blame $this $w_amov @amov_data \
|
||||
$original_options \
|
||||
[mc "Loading original location annotations..."]
|
||||
@ -696,6 +711,72 @@ method _read_blame {fd cur_w cur_d} {
|
||||
}
|
||||
} ifdeleted { catch {close $fd} }
|
||||
|
||||
method _find_commit_bound {data_list start_idx delta} {
|
||||
upvar #0 $data_list line_data
|
||||
set pos $start_idx
|
||||
set limit [expr {[llength $line_data] - 1}]
|
||||
set base_commit [lindex $line_data $pos 0]
|
||||
|
||||
while {$pos > 0 && $pos < $limit} {
|
||||
set new_pos [expr {$pos + $delta}]
|
||||
if {[lindex $line_data $new_pos 0] ne $base_commit} {
|
||||
return $pos
|
||||
}
|
||||
|
||||
set pos $new_pos
|
||||
}
|
||||
|
||||
return $pos
|
||||
}
|
||||
|
||||
method _fullcopyblame {} {
|
||||
if {$current_fd ne {}} {
|
||||
tk_messageBox \
|
||||
-icon error \
|
||||
-type ok \
|
||||
-title [mc "Busy"] \
|
||||
-message [mc "Annotation process is already running."]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
# Switches for original location detection
|
||||
set threshold [get_config gui.copyblamethreshold]
|
||||
set original_options [list -C -C "-C$threshold"]
|
||||
|
||||
if {[git-version >= 1.5.3]} {
|
||||
lappend original_options -w ; # ignore indentation changes
|
||||
}
|
||||
|
||||
# Find the line range
|
||||
set pos @$::cursorX,$::cursorY
|
||||
set lno [lindex [split [$::cursorW index $pos] .] 0]
|
||||
set min_amov_lno [_find_commit_bound $this @amov_data $lno -1]
|
||||
set max_amov_lno [_find_commit_bound $this @amov_data $lno 1]
|
||||
set min_asim_lno [_find_commit_bound $this @asim_data $lno -1]
|
||||
set max_asim_lno [_find_commit_bound $this @asim_data $lno 1]
|
||||
|
||||
if {$min_asim_lno < $min_amov_lno} {
|
||||
set min_amov_lno $min_asim_lno
|
||||
}
|
||||
|
||||
if {$max_asim_lno > $max_amov_lno} {
|
||||
set max_amov_lno $max_asim_lno
|
||||
}
|
||||
|
||||
lappend original_options -L "$min_amov_lno,$max_amov_lno"
|
||||
|
||||
# Clear lines
|
||||
for {set i $min_amov_lno} {$i <= $max_amov_lno} {incr i} {
|
||||
lset amov_data $i [list ]
|
||||
}
|
||||
|
||||
# Start the back-end process
|
||||
_exec_blame $this $w_amov @amov_data \
|
||||
$original_options \
|
||||
[mc "Running thorough copy detection..."]
|
||||
}
|
||||
|
||||
method _click {cur_w pos} {
|
||||
set lno [lindex [split [$cur_w index $pos] .] 0]
|
||||
_showcommit $this $cur_w $lno
|
||||
|
@ -411,6 +411,53 @@ proc apply_line {x y} {
|
||||
set hh [lindex [split $hh ,] 0]
|
||||
set hln [lindex [split $hh -] 1]
|
||||
|
||||
# There is a special situation to take care of. Consider this hunk:
|
||||
#
|
||||
# @@ -10,4 +10,4 @@
|
||||
# context before
|
||||
# -old 1
|
||||
# -old 2
|
||||
# +new 1
|
||||
# +new 2
|
||||
# context after
|
||||
#
|
||||
# We used to keep the context lines in the order they appear in the
|
||||
# hunk. But then it is not possible to correctly stage only
|
||||
# "-old 1" and "+new 1" - it would result in this staged text:
|
||||
#
|
||||
# context before
|
||||
# old 2
|
||||
# new 1
|
||||
# context after
|
||||
#
|
||||
# (By symmetry it is not possible to *un*stage "old 2" and "new 2".)
|
||||
#
|
||||
# We resolve the problem by introducing an asymmetry, namely, when
|
||||
# a "+" line is *staged*, it is moved in front of the context lines
|
||||
# that are generated from the "-" lines that are immediately before
|
||||
# the "+" block. That is, we construct this patch:
|
||||
#
|
||||
# @@ -10,4 +10,5 @@
|
||||
# context before
|
||||
# +new 1
|
||||
# old 1
|
||||
# old 2
|
||||
# context after
|
||||
#
|
||||
# But we do *not* treat "-" lines that are *un*staged in a special
|
||||
# way.
|
||||
#
|
||||
# With this asymmetry it is possible to stage the change
|
||||
# "old 1" -> "new 1" directly, and to stage the change
|
||||
# "old 2" -> "new 2" by first staging the entire hunk and
|
||||
# then unstaging the change "old 1" -> "new 1".
|
||||
|
||||
# This is non-empty if and only if we are _staging_ changes;
|
||||
# then it accumulates the consecutive "-" lines (after converting
|
||||
# them to context lines) in order to be moved after the "+" change
|
||||
# line.
|
||||
set pre_context {}
|
||||
|
||||
set n 0
|
||||
set i_l [$ui_diff index "$i_l + 1 lines"]
|
||||
set patch {}
|
||||
@ -422,16 +469,27 @@ proc apply_line {x y} {
|
||||
[$ui_diff compare $the_l < $next_l]} {
|
||||
# the line to stage/unstage
|
||||
set ln [$ui_diff get $i_l $next_l]
|
||||
set patch "$patch$ln"
|
||||
if {$c1 eq {-}} {
|
||||
set n [expr $n+1]
|
||||
set patch "$patch$pre_context$ln"
|
||||
} else {
|
||||
set patch "$patch$ln$pre_context"
|
||||
}
|
||||
set pre_context {}
|
||||
} elseif {$c1 ne {-} && $c1 ne {+}} {
|
||||
# context line
|
||||
set ln [$ui_diff get $i_l $next_l]
|
||||
set patch "$patch$ln"
|
||||
set patch "$patch$pre_context$ln"
|
||||
set n [expr $n+1]
|
||||
set pre_context {}
|
||||
} elseif {$c1 eq $to_context} {
|
||||
# turn change line into context line
|
||||
set ln [$ui_diff get "$i_l + 1 chars" $next_l]
|
||||
set patch "$patch $ln"
|
||||
if {$c1 eq {-}} {
|
||||
set pre_context "$pre_context $ln"
|
||||
} else {
|
||||
set patch "$patch $ln"
|
||||
}
|
||||
set n [expr $n+1]
|
||||
}
|
||||
set i_l $next_l
|
||||
|
@ -123,6 +123,8 @@ proc do_options {} {
|
||||
{b gui.trustmtime {mc "Trust File Modification Timestamps"}}
|
||||
{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}
|
||||
{b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
|
||||
{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
|
||||
{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
|
||||
{i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
|
||||
{i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}}
|
||||
{t gui.newbranchtemplate {mc "New Branch Name Template"}}
|
||||
|
@ -7,7 +7,7 @@ if {[string first -psn [lindex $argv 0]] == 0} {
|
||||
}
|
||||
|
||||
if {[file tail [lindex $argv 0]] eq {gitk}} {
|
||||
set argv0 [file join $gitexecdir gitk]
|
||||
set argv0 [lindex $argv 0]
|
||||
set AppMain_source $argv0
|
||||
} else {
|
||||
set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]]
|
||||
|
Loading…
Reference in New Issue
Block a user