# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
+proc gitdir {} {
+ global env
+ if {[info exists env(GIT_DIR)]} {
+ return $env(GIT_DIR)
+ } else {
+ return ".git"
+ }
+}
+
proc getcommits {rargs} {
global commits commfd phase canv mainfont env
global startmsecs nextupdate
global ctext maincursor textcursor leftover
# check that we can find a .git directory somewhere...
- if {[info exists env(GIT_DIR)]} {
- set gitdir $env(GIT_DIR)
- } else {
- set gitdir ".git"
- }
+ set gitdir [gitdir]
if {![file isdirectory $gitdir]} {
error_popup "Cannot find the git directory \"$gitdir\"."
exit 1
set parsed_args $rargs
}
if [catch {
- set commfd [open "|git-rev-list --header --merge-order $parsed_args" r]
+ set commfd [open "|git-rev-list --header --topo-order $parsed_args" r]
} err] {
puts stderr "Error executing git-rev-list: $err"
exit 1
proc readrefs {} {
global tagids idtags headids idheads
- set tags [glob -nocomplain -types f .git/refs/tags/*]
+ set tags [glob -nocomplain -types f [gitdir]/refs/tags/*]
foreach f $tags {
catch {
set fd [open $f r]
close $fd
}
}
- set heads [glob -nocomplain -types f .git/refs/heads/*]
+ set heads [glob -nocomplain -types f [gitdir]/refs/heads/*]
foreach f $heads {
catch {
set fd [open $f r]
proc savestuff {w} {
global canv canv2 canv3 ctext cflist mainfont textfont
- global stuffsaved
+ global stuffsaved findmergefiles gaudydiff
+
if {$stuffsaved} return
if {![winfo viewable .]} return
catch {
set diffpindex -1
set diffmergegca [findgca $parents($id)]
if {[info exists mergefilelist($id)]} {
- showmergediff
+ if {$mergefilelist($id) ne {}} {
+ showmergediff
+ }
} else {
contmergediff {}
}
proc contmergediff {ids} {
global diffmergeid diffpindex parents nparents diffmergegca
- global treediffs mergefilelist diffids
+ global treediffs mergefilelist diffids treepending
# diff the child against each of the parents, and diff
# each of the parents against the GCA.
proc showmergediff {} {
global cflist diffmergeid mergefilelist parents
- global diffopts diffinhunk currentfile diffblocked
- global groupfilelast mergefds
+ global diffopts diffinhunk currentfile currenthunk filelines
+ global diffblocked groupfilelast mergefds groupfilenum grouphunks
set files $mergefilelist($diffmergeid)
foreach f $files {
catch {unset currentfile}
catch {unset currenthunk}
catch {unset filelines}
+ catch {unset groupfilenum}
+ catch {unset grouphunks}
set groupfilelast -1
foreach p $parents($diffmergeid) {
set cmd [list | git-diff-tree -p $p $diffmergeid]
set pnum 0
foreach p $parents($id) {
set startline [expr {$grouplinestart + $diffoffset($p)}]
- set offset($p) $diffoffset($p)
set ol $startline
set nl $grouplinestart
if {[info exists grouphunks($p)]} {
set events [lsort -integer -index 0 $events]
set nevents [llength $events]
set nmerge $nparents($diffmergeid)
- set i 0
set l $grouplinestart
- while {$i < $nevents} {
+ for {set i 0} {$i < $nevents} {set i $j} {
set nl [lindex $events $i 0]
while {$l < $nl} {
$ctext insert end " $filelines($id,$f,$l)\n"
}
set nlc [expr {$enl - $l}]
set ncol mresult
+ set bestpn -1
if {[llength $active] == $nmerge - 1} {
+ # no diff for one of the parents, i.e. it's identical
for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
if {![info exists delta($pnum)]} {
if {$pnum < $mergemax} {
break
}
}
+ } elseif {[llength $active] == $nmerge} {
+ # all parents are different, see if one is very similar
+ set bestsim 30
+ for {set pnum 0} {$pnum < $nmerge} {incr pnum} {
+ set sim [similarity $pnum $l $nlc $f \
+ [lrange $events $i [expr {$j-1}]]]
+ if {$sim > $bestsim} {
+ set bestsim $sim
+ set bestpn $pnum
+ }
+ }
+ if {$bestpn >= 0} {
+ lappend ncol m$bestpn
+ }
}
set pnum -1
foreach p $parents($id) {
incr pnum
- if {![info exists delta($pnum)]} continue
+ if {![info exists delta($pnum)] || $pnum == $bestpn} continue
set olc [expr {$nlc + $delta($pnum)}]
set ol [expr {$l + $diffoffset($p)}]
incr diffoffset($p) $delta($pnum)
incr ol
}
}
- for {} {$nlc > 0} {incr nlc -1} {
+ set endl [expr {$l + $nlc}]
+ if {$bestpn >= 0} {
+ # show this pretty much as a normal diff
+ set p [lindex $parents($id) $bestpn]
+ set ol [expr {$l + $diffoffset($p)}]
+ incr diffoffset($p) $delta($bestpn)
+ unset delta($bestpn)
+ for {set k $i} {$k < $j} {incr k} {
+ set e [lindex $events $k]
+ if {[lindex $e 2] != $bestpn} continue
+ set nl [lindex $e 0]
+ set ol [expr {$ol + $nl - $l}]
+ for {} {$l < $nl} {incr l} {
+ $ctext insert end "+$filelines($id,$f,$l)\n" $ncol
+ }
+ set c [lindex $e 3]
+ for {} {$c > 0} {incr c -1} {
+ $ctext insert end "-$filelines($p,$f,$ol)\n" m$bestpn
+ incr ol
+ }
+ set nl [lindex $e 1]
+ for {} {$l < $nl} {incr l} {
+ $ctext insert end "+$filelines($id,$f,$l)\n" mresult
+ }
+ }
+ }
+ for {} {$l < $endl} {incr l} {
$ctext insert end "+$filelines($id,$f,$l)\n" $ncol
- incr l
}
- set i $j
}
while {$l < $grouplineend} {
$ctext insert end " $filelines($id,$f,$l)\n"
$ctext conf -state disabled
}
+proc similarity {pnum l nlc f events} {
+ global diffmergeid parents diffoffset filelines
+
+ set id $diffmergeid
+ set p [lindex $parents($id) $pnum]
+ set ol [expr {$l + $diffoffset($p)}]
+ set endl [expr {$l + $nlc}]
+ set same 0
+ set diff 0
+ foreach e $events {
+ if {[lindex $e 2] != $pnum} continue
+ set nl [lindex $e 0]
+ set ol [expr {$ol + $nl - $l}]
+ for {} {$l < $nl} {incr l} {
+ incr same [string length $filelines($id,$f,$l)]
+ incr same
+ }
+ set oc [lindex $e 3]
+ for {} {$oc > 0} {incr oc -1} {
+ incr diff [string length $filelines($p,$f,$ol)]
+ incr diff
+ incr ol
+ }
+ set nl [lindex $e 1]
+ for {} {$l < $nl} {incr l} {
+ incr diff [string length $filelines($id,$f,$l)]
+ incr diff
+ }
+ }
+ for {} {$l < $endl} {incr l} {
+ incr same [string length $filelines($id,$f,$l)]
+ incr same
+ }
+ if {$same == 0} {
+ return 0
+ }
+ return [expr {200 * $same / (2 * $same + $diff)}]
+}
+
proc startdiff {ids} {
global treediffs diffids treepending diffmergeid
$ctext conf -state disabled
$ctext tag delete Comments
$ctext tag remove found 1.0 end
- startdiff $newid [list $oldid]
+ startdiff [list $newid $oldid]
}
proc mkpatch {} {
return
}
if {[catch {
- set dir ".git"
- if {[info exists env(GIT_DIR)]} {
- set dir $env(GIT_DIR)
- }
+ set dir [gitdir]
set fname [file join $dir "refs/tags" $tag]
set f [open $fname w]
puts $f $id