-proc findpatches {} {
- global findstring selectedline numcommits
- global findprocpid findprocfile
- global finddidsel ctext displayorder findinprogress
- global findinsertpos
-
- if {$numcommits == 0} return
-
- # make a list of all the ids to search, starting at the one
- # after the selected line (if any)
- if {[info exists selectedline]} {
- set l $selectedline
- } else {
- set l -1
- }
- set inputids {}
- for {set i 0} {$i < $numcommits} {incr i} {
- if {[incr l] >= $numcommits} {
- set l 0
- }
- append inputids [lindex $displayorder $l] "\n"
- }
-
- if {[catch {
- set f [open [list | git-diff-tree --stdin -s -r -S$findstring \
- << $inputids] r]
- } err]} {
- error_popup "Error starting search process: $err"
- return
- }
-
- set findinsertpos end
- set findprocfile $f
- set findprocpid [pid $f]
- fconfigure $f -blocking 0
- fileevent $f readable readfindproc
- set finddidsel 0
- nowbusy find
- set findinprogress 1
-}
-
-proc readfindproc {} {
- global findprocfile finddidsel
- global commitrow matchinglines findinsertpos curview
-
- set n [gets $findprocfile line]
- if {$n < 0} {
- if {[eof $findprocfile]} {
- stopfindproc 1
- if {!$finddidsel} {
- bell
- }
- }
- return
- }
- if {![regexp {^[0-9a-f]{40}} $line id]} {
- error_popup "Can't parse git-diff-tree output: $line"
- stopfindproc
- return
- }
- if {![info exists commitrow($curview,$id)]} {
- puts stderr "spurious id: $id"
- return
- }
- set l $commitrow($curview,$id)
- insertmatch $l $id
-}
-
-proc insertmatch {l id} {
- global matchinglines findinsertpos finddidsel
-
- if {$findinsertpos == "end"} {
- if {$matchinglines != {} && $l < [lindex $matchinglines 0]} {
- set matchinglines [linsert $matchinglines 0 $l]
- set findinsertpos 1
- } else {
- lappend matchinglines $l
- }
- } else {
- set matchinglines [linsert $matchinglines $findinsertpos $l]
- incr findinsertpos
- }
- markheadline $l $id
- if {!$finddidsel} {
- findselectline $l
- set finddidsel 1
- }
-}
-
-proc findfiles {} {
- global selectedline numcommits displayorder ctext
- global ffileline finddidsel parentlist
- global findinprogress findstartline findinsertpos
- global treediffs fdiffid fdiffsneeded fdiffpos
- global findmergefiles
-
- if {$numcommits == 0} return
-
- if {[info exists selectedline]} {
- set l [expr {$selectedline + 1}]
- } else {
- set l 0
- }
- set ffileline $l
- set findstartline $l
- set diffsneeded {}
- set fdiffsneeded {}
- while 1 {
- set id [lindex $displayorder $l]
- if {$findmergefiles || [llength [lindex $parentlist $l]] == 1} {
- if {![info exists treediffs($id)]} {
- append diffsneeded "$id\n"
- lappend fdiffsneeded $id
- }
- }
- if {[incr l] >= $numcommits} {
- set l 0
- }
- if {$l == $findstartline} break
- }
-
- # start off a git-diff-tree process if needed
- if {$diffsneeded ne {}} {
- if {[catch {
- set df [open [list | git-diff-tree -r --stdin << $diffsneeded] r]
- } err ]} {
- error_popup "Error starting search process: $err"
- return
- }
- catch {unset fdiffid}
- set fdiffpos 0
- fconfigure $df -blocking 0
- fileevent $df readable [list readfilediffs $df]
- }
-
- set finddidsel 0
- set findinsertpos end
- set id [lindex $displayorder $l]
- nowbusy find
- set findinprogress 1
- findcont
- update
-}
-
-proc readfilediffs {df} {
- global findid fdiffid fdiffs
-
- set n [gets $df line]
- if {$n < 0} {
- if {[eof $df]} {
- donefilediff
- if {[catch {close $df} err]} {
- stopfindproc
- bell
- error_popup "Error in git-diff-tree: $err"
- } elseif {[info exists findid]} {
- set id $findid
- stopfindproc
- bell
- error_popup "Couldn't find diffs for $id"
- }
- }
- return
- }
- if {[regexp {^([0-9a-f]{40})$} $line match id]} {
- # start of a new string of diffs
- donefilediff
- set fdiffid $id
- set fdiffs {}
- } elseif {[string match ":*" $line]} {
- lappend fdiffs [lindex $line 5]
- }
-}
-
-proc donefilediff {} {
- global fdiffid fdiffs treediffs findid
- global fdiffsneeded fdiffpos
-
- if {[info exists fdiffid]} {
- while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffid
- && $fdiffpos < [llength $fdiffsneeded]} {
- # git-diff-tree doesn't output anything for a commit
- # which doesn't change anything
- set nullid [lindex $fdiffsneeded $fdiffpos]
- set treediffs($nullid) {}
- if {[info exists findid] && $nullid eq $findid} {
- unset findid
- findcont
- }
- incr fdiffpos
- }
- incr fdiffpos
-
- if {![info exists treediffs($fdiffid)]} {
- set treediffs($fdiffid) $fdiffs
- }
- if {[info exists findid] && $fdiffid eq $findid} {
- unset findid
- findcont
- }
- }
-}
-
-proc findcont {} {
- global findid treediffs parentlist
- global ffileline findstartline finddidsel
- global displayorder numcommits matchinglines findinprogress
- global findmergefiles
-
- set l $ffileline
- while {1} {
- set id [lindex $displayorder $l]
- if {$findmergefiles || [llength [lindex $parentlist $l]] == 1} {
- if {![info exists treediffs($id)]} {
- set findid $id
- set ffileline $l
- return
- }
- set doesmatch 0
- foreach f $treediffs($id) {
- set x [findmatches $f]
- if {$x != {}} {
- set doesmatch 1
- break
- }
- }
- if {$doesmatch} {
- insertmatch $l $id
- }
- }
- if {[incr l] >= $numcommits} {
- set l 0
- }
- if {$l == $findstartline} break
- }
- stopfindproc
- if {!$finddidsel} {
- bell
- }
-}
-