Skip to content

Commit 7d076d5

Browse files
committed
git-gui: handle shell script text filters when loading for blame.
When loading a file into the blame window git-gui does all the work and must handle the text conversion filters if defined. On Windows it is necessary to detect the need for a shell script explicitly. Such filter commands are run using non-blocking I/O but this has the unfortunate side effect of losing any error that might be reported when the pipe is closed. Switching to blocking mode just before closing enables reporting of errors in the filter scripts to the user. Tested-by: Sebastian Schuberth <[email protected]> Signed-off-by: Pat Thoyts <[email protected]>
1 parent 215d4fd commit 7d076d5

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

git-gui.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,35 @@ proc _which {what args} {
464464
return {}
465465
}
466466
467+
# Test a file for a hashbang to identify executable scripts on Windows.
468+
proc is_shellscript {filename} {
469+
if {![file exists $filename]} {return 0}
470+
set f [open $filename r]
471+
fconfigure $f -encoding binary
472+
set magic [read $f 2]
473+
close $f
474+
return [expr {$magic eq "#!"}]
475+
}
476+
477+
# Run a command connected via pipes on stdout.
478+
# This is for use with textconv filters and uses sh -c "..." to allow it to
479+
# contain a command with arguments. On windows we must check for shell
480+
# scripts specifically otherwise just call the filter command.
481+
proc open_cmd_pipe {cmd path} {
482+
global env
483+
if {![file executable [shellpath]]} {
484+
set exe [auto_execok [lindex $cmd 0]]
485+
if {[is_shellscript [lindex $exe 0]]} {
486+
set run [linsert [auto_execok sh] end -c "$cmd \"\$0\"" $path]
487+
} else {
488+
set run [concat $exe [lrange $cmd 1 end] $path]
489+
}
490+
} else {
491+
set run [list [shellpath] -c "$cmd \"\$0\"" $path]
492+
}
493+
return [open |$run r]
494+
}
495+
467496
proc _lappend_nice {cmd_var} {
468497
global _nice
469498
upvar $cmd_var cmd

lib/blame.tcl

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,7 @@ method _load {jump} {
476476
}
477477
if {$commit eq {}} {
478478
if {$do_textconv ne 0} {
479-
# Run textconv with sh -c "..." to allow it to
480-
# contain command + arguments. On windows, just
481-
# call the filter command.
482-
if {![file executable [shellpath]]} {
483-
set fd [open |[linsert $textconv end $path] r]
484-
} else {
485-
set fd [open |[list [shellpath] -c "$textconv \"\$0\"" $path] r]
486-
}
479+
set fd [open_cmd_pipe $textconv $path]
487480
} else {
488481
set fd [open $path r]
489482
}
@@ -575,7 +568,11 @@ method _read_file {fd jump} {
575568
foreach i $w_columns {$i conf -state disabled}
576569

577570
if {[eof $fd]} {
578-
close $fd
571+
fconfigure $fd -blocking 1; # enable error reporting on close
572+
if {[catch {close $fd} err]} {
573+
tk_messageBox -icon error -title [mc Error] \
574+
-message $err
575+
}
579576

580577
# If we don't force Tk to update the widgets *right now*
581578
# none of our jump commands will cause a change in the UI.
@@ -1065,7 +1062,7 @@ method _gitkcommit {} {
10651062
set radius [get_config gui.blamehistoryctx]
10661063
set cmdline [list --select-commit=$cmit]
10671064

1068-
if {$radius > 0} {
1065+
if {$radius > 0} {
10691066
set author_time {}
10701067
set committer_time {}
10711068

@@ -1173,7 +1170,7 @@ method _read_diff_load_commit {fd cparent new_path tline} {
11731170
}
11741171

11751172
if {[eof $fd]} {
1176-
close $fd;
1173+
close $fd
11771174
set current_fd {}
11781175

11791176
_load_new_commit $this \

0 commit comments

Comments
 (0)