Subject: [PATCH 1/6] Enable ability to visualise the results of git cherry C1 C2

From: Pierre Dumuid <[email-masked]>
Date: Thu, 15 Dec 2016 21:58:42 +1030

It's a bit clunky but it works!!

Usage:
 - mark commit one (e.g. v45)
 - Select commit two.
 - Switch the gdttype to the option, "git-cherry between marked commit and:"

Signed-off-by: Pierre Dumuid <[email-masked]>
---
 gitk | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 107 insertions(+), 3 deletions(-)

diff --git a/gitk b/gitk
index a14d7a1..50d1ef4 100755
--- a/gitk
+++ b/gitk
@@ -2319,7 +2319,9 @@ proc makewindow {} {
 		[mc "containing:"] \
 		[mc "touching paths:"] \
 		[mc "adding/removing string:"] \
-		[mc "changing lines matching:"]]
+		[mc "changing lines matching:"] \
+		[mc "git-cherry between marked commit and:"] \
+	       ]
     trace add variable gdttype write gdttype_change
     pack .tf.lbar.gdttype -side left -fill y
 
@@ -4707,6 +4709,18 @@ proc gdttype_change {name ix op} {
     global gdttype highlight_files findstring findpattern
 
     stopfinding
+
+    if {$gdttype eq [mc "git-cherry between marked commit and:"]} {
+	if {$highlight_files ne {}} {
+	    set highlight_files {}
+	    hfiles_change
+	}
+	findcom_change
+	update_gitcherrylist
+	drawvisible
+	return
+    }
+
     if {$findstring ne {}} {
 	if {$gdttype eq [mc "containing:"]} {
 	    if {$highlight_files ne {}} {
@@ -4733,6 +4747,9 @@ proc find_change {name ix op} {
     stopfinding
     if {$gdttype eq [mc "containing:"]} {
 	findcom_change
+    } elseif {$gdttype eq [mc "git-cherry between marked commit and:"]} {
+	findcom_change
+	update_gitcherrylist
     } else {
 	if {$highlight_files ne $findstring} {
 	    set highlight_files $findstring
@@ -4742,6 +4759,54 @@ proc find_change {name ix op} {
     drawvisible
 }
 
+proc update_gitcherrylist {} {
+    global gitcherryids
+    global markedid
+    global findstring
+    global fstring
+    global currentid
+    global iddrawn
+
+    unset -nocomplain gitcherryids
+    set fs $findstring
+
+    if {$findstring eq {}} {
+	$fstring delete 0 end
+	$fstring insert 0 $currentid
+    }
+
+    if {![info exists markedid]} {
+	error_popup [mc "Please mark a git commit before using this find method!"]
+	return
+    }
+
+    #puts [join [list "Running cherry between: `" $markedid "` and `" $findstring "`"] ""]
+
+    if {[catch {set cherryOutput [exec git cherry $markedid $findstring]}]} {
+	puts "ERROR: An error occured running git-cherry!"
+	return
+    }
+
+    set cherryLines [split $cherryOutput "\n"]
+    foreach cherryLine $cherryLines {
+	set op [lindex [split $cherryLine " "] 0]
+	set gitSha [lindex [split $cherryLine " "] 1]
+
+	#puts [join [list "line is: `" $cherryLine "`, op:`" $op "`, gitSha:`" $gitSha "`"] ""]
+	if {$op eq "+"} {
+	    set gitcherryids($gitSha) 1
+	    if ([info exists iddrawn($gitSha)]) {
+		bolden $gitSha mainfontbold
+	    }
+
+	}
+    }
+    # puts "list is as follows"
+    #foreach {gitsha setBold} [array get gitcherryids] {
+    # 	puts [concat $gitsha = $setBold]
+    #}
+}
+
 proc findcom_change args {
     global nhighlights boldnameids
     global findpattern findtype findstring gdttype
@@ -4802,6 +4867,9 @@ proc do_file_hl {serial} {
 	set gdtargs [list "-S$highlight_files"]
     } elseif {$gdttype eq [mc "changing lines matching:"]} {
 	set gdtargs [list "-G$highlight_files"]
+    } elseif {$gdttype eq [mc "git-cherry between marked commit and:"]} {
+	# Skipping opening the file handle, filehighlight
+	return
     } else {
 	# must be "containing:", i.e. we're searching commit info
 	return
@@ -4882,6 +4950,17 @@ proc doesmatch {f} {
     }
 }
 
+proc askcherryhighlight {row id} {
+    global nhighlights gitcherryids
+
+    set isbold 0
+    if {[info exists gitcherryids($id)]} {
+	set isbold 1
+    }
+
+    set nhighlights($id) $isbold
+}
+
 proc askfindhighlight {row id} {
     global nhighlights commitinfo iddrawn
     global findloc
@@ -6216,6 +6295,7 @@ proc drawcmitrow {row} {
     global filehighlight fhighlights findpattern nhighlights
     global hlview vhighlights
     global highlight_related rhighlights
+    global gdttype
 
     if {$row >= $numcommits} return
 
@@ -6226,6 +6306,11 @@ proc drawcmitrow {row} {
     if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
 	askfilehighlight $row $id
     }
+
+    if {$gdttype eq [mc "git-cherry between marked commit and:"] && ![info exists nhighlights($id)]} {
+	askcherryhighlight $row $id
+    }
+
     if {$findpattern ne {} && ![info exists nhighlights($id)]} {
 	askfindhighlight $row $id
     }
@@ -6776,7 +6861,9 @@ proc dofind {{dirn 1} {wrap 1}} {
     }
     set findcurline $findstartline
     nowbusy finding [mc "Searching"]
-    if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
+    if {$gdttype eq [mc "git-cherry between marked commit and:"]} {
+	# Don't do anything related to open do_file_hl since we'll just have a list
+    } elseif {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
 	after cancel do_file_hl $fh_serial
 	do_file_hl $fh_serial
     }
@@ -6803,6 +6890,7 @@ proc findmore {} {
     global findstartline findcurline findallowwrap
     global find_dirn gdttype fhighlights fprogcoord
     global curview varcorder vrownum varccommits vrowmod
+    global gitcherryids
 
     if {![info exists find_dirn]} {
 	return 0
@@ -6848,7 +6936,23 @@ proc findmore {} {
     set arow [lindex $vrownum($curview) $ai]
     set ids [lindex $varccommits($curview,$a)]
     set arowend [expr {$arow + [llength $ids]}]
-    if {$gdttype eq [mc "containing:"]} {
+
+    if {$gdttype eq [mc "git-cherry between marked commit and:"]} {
+	for {} {$n > 0} {incr n -1; incr l $find_dirn} {
+	    if {$l < $arow || $l >= $arowend} {
+		incr ai $find_dirn
+		set a [lindex $varcorder($curview) $ai]
+		set arow [lindex $vrownum($curview) $ai]
+		set ids [lindex $varccommits($curview,$a)]
+		set arowend [expr {$arow + [llength $ids]}]
+	    }
+	    set id [lindex $ids [expr {$l - $arow}]]
+	    if {[info exists gitcherryids($id)]} {
+		set found 1
+	    }
+	    if {$found} break
+	}
+    } elseif {$gdttype eq [mc "containing:"]} {
 	for {} {$n > 0} {incr n -1; incr l $find_dirn} {
 	    if {$l < $arow || $l >= $arowend} {
 		incr ai $find_dirn
-- 
2.10.2