diff --git a/gitk b/gitk index 628f6e5c5b..bdd12236b8 100755 --- a/gitk +++ b/gitk @@ -2362,6 +2362,7 @@ proc makewindow {} { {mc "Mark this commit" command markhere} {mc "Return to mark" command gotomark} {mc "Find descendant of this and mark" command find_common_desc} + {mc "Compare with marked commit" command compare_commits} } $rowctxmenu configure -tearoff 0 @@ -8037,9 +8038,11 @@ proc rowmenu {x y id} { if {[info exists markedid] && $markedid ne $id} { $menu entryconfigure 9 -state normal $menu entryconfigure 10 -state normal + $menu entryconfigure 11 -state normal } else { $menu entryconfigure 9 -state disabled $menu entryconfigure 10 -state disabled + $menu entryconfigure 11 -state disabled } } else { set menu $fakerowmenu @@ -8103,6 +8106,92 @@ proc find_common_desc {} { #puts "took [expr {$t2-$t1}]ms" } +proc compare_commits {} { + global markedid rowmenuid curview children + + if {![info exists markedid]} return + if {![commitinview $markedid $curview]} return + addtohistory [list do_cmp_commits $markedid $rowmenuid] + do_cmp_commits $markedid $rowmenuid +} + +proc getpatchid {id} { + global patchids + + if {![info exists patchids($id)]} { + set x [exec git diff-tree -p --root $id | git patch-id] + set patchids($id) [lindex $x 0] + } + return $patchids($id) +} + +proc do_cmp_commits {a b} { + global ctext curview parents children patchids commitinfo + + $ctext conf -state normal + clear_ctext + init_flist {} + for {set i 0} {$i < 100} {incr i} { + set shorta [string range $a 0 7] + set shortb [string range $b 0 7] + set skipa 0 + set skipb 0 + if {[llength $parents($curview,$a)] > 1} { + appendwithlinks [mc "Skipping merge commit %s\n" $shorta] {} + set skipa 1 + } else { + set patcha [getpatchid $a] + } + if {[llength $parents($curview,$b)] > 1} { + appendwithlinks [mc "Skipping merge commit %s\n" $shortb] {} + set skipb 1 + } else { + set patchb [getpatchid $b] + } + if {!$skipa && !$skipb} { + set heada [lindex $commitinfo($a) 0] + set headb [lindex $commitinfo($b) 0] + if {$patcha eq $patchb} { + if {$heada eq $headb} { + appendwithlinks [mc "Commit %s == %s %s\n" \ + $shorta $shortb $heada] {} + } else { + appendwithlinks [mc "Commit %s %s\n" $shorta $heada] {} + appendwithlinks [mc " is the same patch as\n"] {} + appendwithlinks [mc " %s %s\n" $shortb $headb] {} + } + set skipa 1 + set skipb 1 + } else { + $ctext insert end "\n" + appendwithlinks [mc "Commit %s %s\n" $shorta $heada] {} + appendwithlinks [mc " differs from\n"] {} + appendwithlinks [mc " %s %s\n" $shortb $headb] {} + appendwithlinks [mc "- stopping\n"] + break + } + } + if {$skipa} { + if {[llength $children($curview,$a)] != 1} { + $ctext insert end "\n" + appendwithlinks [mc "Commit %s has %s children - stopping\n" \ + $shorta [llength $children($curview,$a)]] {} + break + } + set a [lindex $children($curview,$a) 0] + } + if {$skipb} { + if {[llength $children($curview,$b)] != 1} { + appendwithlinks [mc "Commit %s has %s children - stopping\n" \ + $shortb [llength $children($curview,$b)]] {} + break + } + set b [lindex $children($curview,$b) 0] + } + } + $ctext conf -state disabled +} + proc diffvssel {dirn} { global rowmenuid selectedline