提交 314f5de1 编写于 作者: T Thomas Arcila 提交者: Paul Mackerras

gitk: Allow users to view diffs in external diff viewer

This allows gitk to run an external diff viewer such as meld.

Right-click on a file in the file list view gives "External diff"
popup menu entry, which launches the selected external diff tool.
The menu entry is only active in "Patch" mode, not in "Tree" mode.

The program to run to display the diff is configurable through
Edit/Preference/External diff tool.  The program is run with two
arguments, being the names of files containing the two versions to
diff.  Gitk will create temporary directories called
.gitk-tmp.<pid>/<n> to place these files in, and remove them when
it's finished.

If the file doesn't exist in one or other revision, gitk will supply
/dev/null as the name of the file on that side of the diff.  This may
need to be adjusted for Windows or MacOS.

[paulus@samba.org - cleaned up and rewrote some parts of the patch.]
Signed-off-by: NThomas Arcila <thomas.arcila@gmail.com>
Signed-off-by: NPaul Mackerras <paulus@samba.org>
上级 f4c54b3c
......@@ -1088,6 +1088,8 @@ proc makewindow {} {
-command {flist_hl 0}
$flist_menu add command -label [mc "Highlight this only"] \
-command {flist_hl 1}
$flist_menu add command -label [mc "External diff"] \
-command {external_diff}
}
# Windows sends all mouse wheel events to the current focused window, not
......@@ -1192,7 +1194,7 @@ proc savestuff {w} {
global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
global autoselect
global autoselect extdifftool
if {$stuffsaved} return
if {![winfo viewable .]} return
......@@ -1218,6 +1220,7 @@ proc savestuff {w} {
puts $f [list set diffcolors $diffcolors]
puts $f [list set diffcontext $diffcontext]
puts $f [list set selectbgcolor $selectbgcolor]
puts $f [list set extdifftool $extdifftool]
puts $f "set geometry(main) [wm geometry .]"
puts $f "set geometry(topwidth) [winfo width .tf]"
......@@ -1768,6 +1771,12 @@ proc pop_flist_menu {w X Y x y} {
set e [lindex $treediffs($diffids) [expr {$l-2}]]
}
set flist_menu_file $e
set xdiffstate "normal"
if {$cmitmode eq "tree"} {
set xdiffstate "disabled"
}
# Disable "External diff" item in tree mode
$flist_menu entryconf 2 -state $xdiffstate
tk_popup $flist_menu $X $Y
}
......@@ -1783,6 +1792,113 @@ proc flist_hl {only} {
set gdttype [mc "touching paths:"]
}
proc save_file_from_commit {filename output what} {
global nullfile
if {[catch {exec git show $filename -- > $output} err]} {
if {[string match "fatal: bad revision *" $err]} {
return $nullfile
}
error_popup "Error getting \"$filename\" from $what: $err"
return {}
}
return $output
}
proc external_diff_get_one_file {diffid filename diffdir} {
global nullid nullid2 nullfile
global gitdir
if {$diffid == $nullid} {
set difffile [file join [file dirname $gitdir] $filename]
if {[file exists $difffile]} {
return $difffile
}
return $nullfile
}
if {$diffid == $nullid2} {
set difffile [file join $diffdir "\[index\] [file tail $filename]"]
return [save_file_from_commit :$filename $difffile index]
}
set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
return [save_file_from_commit $diffid:$filename $difffile \
"revision $diffid"]
}
proc external_diff {} {
global gitktmpdir nullid nullid2
global flist_menu_file
global diffids
global diffnum
global gitdir extdifftool
if {[llength $diffids] == 1} {
# no reference commit given
set diffidto [lindex $diffids 0]
if {$diffidto eq $nullid} {
# diffing working copy with index
set diffidfrom $nullid2
} elseif {$diffidto eq $nullid2} {
# diffing index with HEAD
set diffidfrom "HEAD"
} else {
# use first parent commit
global parentlist selectedline
set diffidfrom [lindex $parentlist $selectedline 0]
}
} else {
set diffidfrom [lindex $diffids 0]
set diffidto [lindex $diffids 1]
}
# make sure that several diffs wont collide
if {![info exists gitktmpdir]} {
set gitktmpdir [file join [file dirname $gitdir] \
[format ".gitk-tmp.%s" [pid]]]
if {[catch {file mkdir $gitktmpdir} err]} {
error_popup "Error creating temporary directory $gitktmpdir: $err"
unset gitktmpdir
return
}
set diffnum 0
}
incr diffnum
set diffdir [file join $gitktmpdir $diffnum]
if {[catch {file mkdir $diffdir} err]} {
error_popup "Error creating temporary directory $diffdir: $err"
return
}
# gather files to diff
set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
if {$difffromfile ne {} && $difftofile ne {}} {
set cmd [concat | [shellsplit $extdifftool] \
[list $difffromfile $difftofile]]
if {[catch {set fl [open $cmd r]} err]} {
file delete -force $diffdir
error_popup [mc "$extdifftool: command failed: $err"]
} else {
fconfigure $fl -blocking 0
filerun $fl [list delete_at_eof $fl $diffdir]
}
}
}
# delete $dir when we see eof on $f (presumably because the child has exited)
proc delete_at_eof {f dir} {
while {[gets $f line] >= 0} {}
if {[eof $f]} {
if {[catch {close $f} err]} {
error_popup "External diff viewer failed: $err"
}
file delete -force $dir
return 0
}
return 1
}
# Functions for adding and removing shell-type quoting
proc shellquote {str} {
......@@ -7881,9 +7997,15 @@ proc showtag {tag isnew} {
proc doquit {} {
global stopped
global gitktmpdir
set stopped 100
savestuff .
destroy .
if {[info exists gitktmpdir]} {
catch {file delete -force $gitktmpdir}
}
}
proc mkfontdisp {font top which} {
......@@ -8012,7 +8134,7 @@ proc doprefs {} {
global maxwidth maxgraphpct
global oldprefs prefstop showneartags showlocalchanges
global bgcolor fgcolor ctext diffcolors selectbgcolor
global tabstop limitdiffs autoselect
global tabstop limitdiffs autoselect extdifftool
set top .gitkprefs
set prefstop $top
......@@ -8064,6 +8186,15 @@ proc doprefs {} {
pack $top.ldiff.b $top.ldiff.l -side left
grid x $top.ldiff -sticky w
entry $top.extdifft -textvariable extdifftool
frame $top.extdifff
label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
-padx 10
button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
-command choose_extdiff
pack $top.extdifff.l $top.extdifff.b -side left
grid x $top.extdifff $top.extdifft -sticky w
label $top.cdisp -text [mc "Colors: press to choose"]
grid $top.cdisp - -sticky w -pady 10
label $top.bg -padx 40 -relief sunk -background $bgcolor
......@@ -8111,6 +8242,15 @@ proc doprefs {} {
bind $top <Visibility> "focus $top.buts.ok"
}
proc choose_extdiff {} {
global extdifftool
set prog [tk_getOpenFile -title "External diff tool" -multiple false]
if {$prog ne {}} {
set extdifftool $prog
}
}
proc choosecolor {v vi w x cmd} {
global $v
......@@ -8539,6 +8679,8 @@ set limitdiffs 1
set datetimeformat "%Y-%m-%d %H:%M:%S"
set autoselect 1
set extdifftool "meld"
set colors {green red blue magenta darkgrey brown orange}
set bgcolor white
set fgcolor black
......@@ -8685,6 +8827,7 @@ if {$mergeonly} {
set nullid "0000000000000000000000000000000000000000"
set nullid2 "0000000000000000000000000000000000000001"
set nullfile "/dev/null"
set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册