Skip to content

Commit 33a3d9a

Browse files
ToBoMij6t
authored andcommitted
gitk: add external diff file rename detection
If a file is renamed between commits and an external diff is started through gitk on the original or the renamed file name, gitk is unable to open the renamed file in the external diff editor. It fails to fetch the renamed file from git, because it fetches it using its original path in contrast to using the renamed path of the file. Detect the rename and open the external diff with the original and the renamed file instead of no file (fetch the renamed file path and name from git) no matter if the original or the renamed file is selected in gitk. Since moved or renamed file are handled the same way do this also for moved files. Signed-off-by: Tobias Boesch <tobias.boesch@miele.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
1 parent 4a6cc6a commit 33a3d9a

1 file changed

Lines changed: 52 additions & 2 deletions

File tree

gitk

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3806,6 +3806,48 @@ proc external_diff_get_one_file {diffid filename diffdir} {
38063806
"revision $diffid"]
38073807
}
38083808
3809+
proc check_for_renames_in_diff {diffidfrom diffidto filepath} {
3810+
global nullid nullid2
3811+
3812+
if {$diffidfrom eq $nullid} {
3813+
set rev [list $diffidto -R]
3814+
} elseif {$diffidfrom eq $nullid2} {
3815+
set rev [list $diffidto --cached -R]
3816+
} elseif {$diffidto eq $nullid} {
3817+
set rev [list $diffidfrom]
3818+
} elseif {$diffidto eq $nullid2} {
3819+
set rev [list $diffidfrom --cached]
3820+
} else {
3821+
set rev [list $diffidfrom..$diffidto]
3822+
}
3823+
3824+
set renames [list {}]
3825+
if {[catch {eval exec git diff $rev --find-renames --stat --raw --diff-filter=R} cmd_result]} {
3826+
error_popup "[mc "Error getting file rename info for file \"%s\" from commit %s to %s." \
3827+
$filepath $diffidfrom $diffidto] $cmd_result.\n\n"
3828+
}
3829+
set filename [file tail $filepath]
3830+
set esc_chars {\\ | ? ^ * . $ \[ \] + \( \) \{ \}}
3831+
foreach char $esc_chars {
3832+
set filename [string map [list $char \\$char] $filename]
3833+
}
3834+
set regex_base {\d+\s\d+\s\S+\s\S+\s\S+\s+}
3835+
set regex_ren_from $regex_base[subst -nobackslashes -nocommands {(\S+$filename)\s+(\S+)}]
3836+
set regex_ren_to $regex_base[subst -nobackslashes -nocommands {(\S+)\s+(\S+$filename)}]
3837+
if {[regexp -line -- $regex_ren_from $cmd_result whole_match ren_from ren_to]} {
3838+
if {$ren_from ne {} && $ren_to ne {}} {
3839+
lappend renames $ren_from
3840+
lappend renames $ren_to
3841+
}
3842+
} elseif {[regexp -line -- $regex_ren_to $cmd_result whole_match ren_from ren_to]} {
3843+
if {$ren_from ne {} && $ren_to ne {}} {
3844+
lappend renames $ren_from
3845+
lappend renames $ren_to
3846+
}
3847+
}
3848+
return $renames
3849+
}
3850+
38093851
proc external_diff {} {
38103852
global nullid nullid2
38113853
global flist_menu_file
@@ -3836,8 +3878,16 @@ proc external_diff {} {
38363878
if {$diffdir eq {}} return
38373879
38383880
# gather files to diff
3839-
set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3840-
set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3881+
set renamed_filenames [check_for_renames_in_diff $diffidfrom $diffidto $flist_menu_file]
3882+
set rename_from_filename [lindex $renamed_filenames 1]
3883+
set rename_to_filename [lindex $renamed_filenames 2]
3884+
if { ($rename_from_filename != {}) && ($rename_to_filename != {}) } {
3885+
set difffromfile [external_diff_get_one_file $diffidfrom $rename_from_filename $diffdir]
3886+
set difftofile [external_diff_get_one_file $diffidto $rename_to_filename $diffdir]
3887+
} else {
3888+
set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3889+
set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3890+
}
38413891
38423892
if {$difffromfile ne {} && $difftofile ne {}} {
38433893
set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]

0 commit comments

Comments
 (0)