|
|
|
@ -7,17 +7,22 @@ exec wish "$0" -- "${1+$@}"
@@ -7,17 +7,22 @@ exec wish "$0" -- "${1+$@}"
|
|
|
|
|
# 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 |
|
|
|
@ -212,7 +217,7 @@ proc parsecommit {id contents listed} {
@@ -212,7 +217,7 @@ proc parsecommit {id contents listed} {
|
|
|
|
|
|
|
|
|
|
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] |
|
|
|
@ -241,7 +246,7 @@ proc readrefs {} {
@@ -241,7 +246,7 @@ proc readrefs {} {
|
|
|
|
|
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] |
|
|
|
@ -273,7 +278,7 @@ proc makewindow {} {
@@ -273,7 +278,7 @@ proc makewindow {} {
|
|
|
|
|
global findtype findtypemenu findloc findstring fstring geometry |
|
|
|
|
global entries sha1entry sha1string sha1but |
|
|
|
|
global maincursor textcursor |
|
|
|
|
global rowctxmenu gaudydiff |
|
|
|
|
global rowctxmenu gaudydiff mergemax |
|
|
|
|
|
|
|
|
|
menu .bar |
|
|
|
|
.bar add cascade -label "File" -menu .bar.file |
|
|
|
@ -373,6 +378,15 @@ proc makewindow {} {
@@ -373,6 +378,15 @@ proc makewindow {} {
|
|
|
|
|
$ctext tag conf hunksep -fore blue |
|
|
|
|
$ctext tag conf d0 -fore red |
|
|
|
|
$ctext tag conf d1 -fore "#00a000" |
|
|
|
|
$ctext tag conf m0 -fore red |
|
|
|
|
$ctext tag conf m1 -fore blue |
|
|
|
|
$ctext tag conf m2 -fore green |
|
|
|
|
$ctext tag conf m3 -fore purple |
|
|
|
|
$ctext tag conf m4 -fore brown |
|
|
|
|
$ctext tag conf mmax -fore darkgrey |
|
|
|
|
set mergemax 5 |
|
|
|
|
$ctext tag conf mresult -font [concat $textfont bold] |
|
|
|
|
$ctext tag conf msep -font [concat $textfont bold] |
|
|
|
|
$ctext tag conf found -back yellow |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -466,7 +480,8 @@ proc click {w} {
@@ -466,7 +480,8 @@ proc click {w} {
|
|
|
|
|
|
|
|
|
|
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 { |
|
|
|
@ -1504,7 +1519,7 @@ proc donefilediff {} {
@@ -1504,7 +1519,7 @@ proc donefilediff {} {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc findcont {ids} { |
|
|
|
|
global findids treediffs parents nparents treepending |
|
|
|
|
global findids treediffs parents nparents |
|
|
|
|
global ffileline findstartline finddidsel |
|
|
|
|
global lineid numcommits matchinglines findinprogress |
|
|
|
|
global findmergefiles |
|
|
|
@ -1692,27 +1707,548 @@ proc selectline {l} {
@@ -1692,27 +1707,548 @@ proc selectline {l} {
|
|
|
|
|
|
|
|
|
|
$cflist delete 0 end |
|
|
|
|
$cflist insert end "Comments" |
|
|
|
|
startdiff $id $parents($id) |
|
|
|
|
if {$nparents($id) == 1} { |
|
|
|
|
startdiff [concat $id $parents($id)] |
|
|
|
|
} elseif {$nparents($id) > 1} { |
|
|
|
|
mergediff $id |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc selnextline {dir} { |
|
|
|
|
global selectedline |
|
|
|
|
if {![info exists selectedline]} return |
|
|
|
|
set l [expr $selectedline + $dir] |
|
|
|
|
unmarkmatches |
|
|
|
|
selectline $l |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc startdiff {id vs} { |
|
|
|
|
global diffpending diffpindex |
|
|
|
|
global diffindex difffilestart |
|
|
|
|
global curdifftag curtagstart |
|
|
|
|
proc mergediff {id} { |
|
|
|
|
global parents diffmergeid diffmergegca mergefilelist diffpindex |
|
|
|
|
|
|
|
|
|
set diffpending $vs |
|
|
|
|
set diffpindex 0 |
|
|
|
|
set diffindex 0 |
|
|
|
|
catch {unset difffilestart} |
|
|
|
|
set curdifftag Comments |
|
|
|
|
set curtagstart 0.0 |
|
|
|
|
contdiff [list $id [lindex $vs 0]] |
|
|
|
|
set diffmergeid $id |
|
|
|
|
set diffpindex -1 |
|
|
|
|
set diffmergegca [findgca $parents($id)] |
|
|
|
|
if {[info exists mergefilelist($id)]} { |
|
|
|
|
showmergediff |
|
|
|
|
} else { |
|
|
|
|
contmergediff {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc findgca {ids} { |
|
|
|
|
set gca {} |
|
|
|
|
foreach id $ids { |
|
|
|
|
if {$gca eq {}} { |
|
|
|
|
set gca $id |
|
|
|
|
} else { |
|
|
|
|
if {[catch { |
|
|
|
|
set gca [exec git-merge-base $gca $id] |
|
|
|
|
} err]} { |
|
|
|
|
return {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return $gca |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc contmergediff {ids} { |
|
|
|
|
global diffmergeid diffpindex parents nparents diffmergegca |
|
|
|
|
global treediffs mergefilelist diffids |
|
|
|
|
|
|
|
|
|
# diff the child against each of the parents, and diff |
|
|
|
|
# each of the parents against the GCA. |
|
|
|
|
while 1 { |
|
|
|
|
if {[lindex $ids 0] == $diffmergeid && $diffmergegca ne {}} { |
|
|
|
|
set ids [list [lindex $ids 1] $diffmergegca] |
|
|
|
|
} else { |
|
|
|
|
if {[incr diffpindex] >= $nparents($diffmergeid)} break |
|
|
|
|
set p [lindex $parents($diffmergeid) $diffpindex] |
|
|
|
|
set ids [list $diffmergeid $p] |
|
|
|
|
} |
|
|
|
|
if {![info exists treediffs($ids)]} { |
|
|
|
|
set diffids $ids |
|
|
|
|
if {![info exists treepending]} { |
|
|
|
|
gettreediffs $ids |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# If a file in some parent is different from the child and also |
|
|
|
|
# different from the GCA, then it's interesting. |
|
|
|
|
# If we don't have a GCA, then a file is interesting if it is |
|
|
|
|
# different from the child in all the parents. |
|
|
|
|
if {$diffmergegca ne {}} { |
|
|
|
|
set files {} |
|
|
|
|
foreach p $parents($diffmergeid) { |
|
|
|
|
set gcadiffs $treediffs([list $p $diffmergegca]) |
|
|
|
|
foreach f $treediffs([list $diffmergeid $p]) { |
|
|
|
|
if {[lsearch -exact $files $f] < 0 |
|
|
|
|
&& [lsearch -exact $gcadiffs $f] >= 0} { |
|
|
|
|
lappend files $f |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
set files [lsort $files] |
|
|
|
|
} else { |
|
|
|
|
set p [lindex $parents($diffmergeid) 0] |
|
|
|
|
set files $treediffs([list $diffmergeid $p]) |
|
|
|
|
for {set i 1} {$i < $nparents($diffmergeid) && $files ne {}} {incr i} { |
|
|
|
|
set p [lindex $parents($diffmergeid) $i] |
|
|
|
|
set df $treediffs([list $diffmergeid $p]) |
|
|
|
|
set nf {} |
|
|
|
|
foreach f $files { |
|
|
|
|
if {[lsearch -exact $df $f] >= 0} { |
|
|
|
|
lappend nf $f |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
set files $nf |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
set mergefilelist($diffmergeid) $files |
|
|
|
|
if {$files ne {}} { |
|
|
|
|
showmergediff |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc showmergediff {} { |
|
|
|
|
global cflist diffmergeid mergefilelist parents |
|
|
|
|
global diffopts diffinhunk currentfile diffblocked |
|
|
|
|
global groupfilelast mergefds |
|
|
|
|
|
|
|
|
|
set files $mergefilelist($diffmergeid) |
|
|
|
|
foreach f $files { |
|
|
|
|
$cflist insert end $f |
|
|
|
|
} |
|
|
|
|
set env(GIT_DIFF_OPTS) $diffopts |
|
|
|
|
set flist {} |
|
|
|
|
catch {unset currentfile} |
|
|
|
|
catch {unset currenthunk} |
|
|
|
|
catch {unset filelines} |
|
|
|
|
set groupfilelast -1 |
|
|
|
|
foreach p $parents($diffmergeid) { |
|
|
|
|
set cmd [list | git-diff-tree -p $p $diffmergeid] |
|
|
|
|
set cmd [concat $cmd $mergefilelist($diffmergeid)] |
|
|
|
|
if {[catch {set f [open $cmd r]} err]} { |
|
|
|
|
error_popup "Error getting diffs: $err" |
|
|
|
|
foreach f $flist { |
|
|
|
|
catch {close $f} |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
lappend flist $f |
|
|
|
|
set ids [list $diffmergeid $p] |
|
|
|
|
set mergefds($ids) $f |
|
|
|
|
set diffinhunk($ids) 0 |
|
|
|
|
set diffblocked($ids) 0 |
|
|
|
|
fconfigure $f -blocking 0 |
|
|
|
|
fileevent $f readable [list getmergediffline $f $ids $diffmergeid] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc getmergediffline {f ids id} { |
|
|
|
|
global diffmergeid diffinhunk diffoldlines diffnewlines |
|
|
|
|
global currentfile currenthunk |
|
|
|
|
global diffoldstart diffnewstart diffoldlno diffnewlno |
|
|
|
|
global diffblocked mergefilelist |
|
|
|
|
global noldlines nnewlines difflcounts filelines |
|
|
|
|
|
|
|
|
|
set n [gets $f line] |
|
|
|
|
if {$n < 0} { |
|
|
|
|
if {![eof $f]} return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if {!([info exists diffmergeid] && $diffmergeid == $id)} { |
|
|
|
|
if {$n < 0} { |
|
|
|
|
close $f |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if {$diffinhunk($ids) != 0} { |
|
|
|
|
set fi $currentfile($ids) |
|
|
|
|
if {$n > 0 && [regexp {^[-+ \\]} $line match]} { |
|
|
|
|
# continuing an existing hunk |
|
|
|
|
set line [string range $line 1 end] |
|
|
|
|
set p [lindex $ids 1] |
|
|
|
|
if {$match eq "-" || $match eq " "} { |
|
|
|
|
set filelines($p,$fi,$diffoldlno($ids)) $line |
|
|
|
|
incr diffoldlno($ids) |
|
|
|
|
} |
|
|
|
|
if {$match eq "+" || $match eq " "} { |
|
|
|
|
set filelines($id,$fi,$diffnewlno($ids)) $line |
|
|
|
|
incr diffnewlno($ids) |
|
|
|
|
} |
|
|
|
|
if {$match eq " "} { |
|
|
|
|
if {$diffinhunk($ids) == 2} { |
|
|
|
|
lappend difflcounts($ids) \ |
|
|
|
|
[list $noldlines($ids) $nnewlines($ids)] |
|
|
|
|
set noldlines($ids) 0 |
|
|
|
|
set diffinhunk($ids) 1 |
|
|
|
|
} |
|
|
|
|
incr noldlines($ids) |
|
|
|
|
} elseif {$match eq "-" || $match eq "+"} { |
|
|
|
|
if {$diffinhunk($ids) == 1} { |
|
|
|
|
lappend difflcounts($ids) [list $noldlines($ids)] |
|
|
|
|
set noldlines($ids) 0 |
|
|
|
|
set nnewlines($ids) 0 |
|
|
|
|
set diffinhunk($ids) 2 |
|
|
|
|
} |
|
|
|
|
if {$match eq "-"} { |
|
|
|
|
incr noldlines($ids) |
|
|
|
|
} else { |
|
|
|
|
incr nnewlines($ids) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
# and if it's \ No newline at end of line, then what? |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
# end of a hunk |
|
|
|
|
if {$diffinhunk($ids) == 1 && $noldlines($ids) != 0} { |
|
|
|
|
lappend difflcounts($ids) [list $noldlines($ids)] |
|
|
|
|
} elseif {$diffinhunk($ids) == 2 |
|
|
|
|
&& ($noldlines($ids) != 0 || $nnewlines($ids) != 0)} { |
|
|
|
|
lappend difflcounts($ids) [list $noldlines($ids) $nnewlines($ids)] |
|
|
|
|
} |
|
|
|
|
set currenthunk($ids) [list $currentfile($ids) \ |
|
|
|
|
$diffoldstart($ids) $diffnewstart($ids) \ |
|
|
|
|
$diffoldlno($ids) $diffnewlno($ids) \ |
|
|
|
|
$difflcounts($ids)] |
|
|
|
|
set diffinhunk($ids) 0 |
|
|
|
|
# -1 = need to block, 0 = unblocked, 1 = is blocked |
|
|
|
|
set diffblocked($ids) -1 |
|
|
|
|
processhunks |
|
|
|
|
if {$diffblocked($ids) == -1} { |
|
|
|
|
fileevent $f readable {} |
|
|
|
|
set diffblocked($ids) 1 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if {$n < 0} { |
|
|
|
|
# eof |
|
|
|
|
if {!$diffblocked($ids)} { |
|
|
|
|
close $f |
|
|
|
|
set currentfile($ids) [llength $mergefilelist($diffmergeid)] |
|
|
|
|
set currenthunk($ids) [list $currentfile($ids) 0 0 0 0 {}] |
|
|
|
|
processhunks |
|
|
|
|
} |
|
|
|
|
} elseif {[regexp {^diff --git a/(.*) b/} $line match fname]} { |
|
|
|
|
# start of a new file |
|
|
|
|
set currentfile($ids) \ |
|
|
|
|
[lsearch -exact $mergefilelist($diffmergeid) $fname] |
|
|
|
|
} elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \ |
|
|
|
|
$line match f1l f1c f2l f2c rest]} { |
|
|
|
|
if {[info exists currentfile($ids)] && $currentfile($ids) >= 0} { |
|
|
|
|
# start of a new hunk |
|
|
|
|
if {$f1l == 0 && $f1c == 0} { |
|
|
|
|
set f1l 1 |
|
|
|
|
} |
|
|
|
|
if {$f2l == 0 && $f2c == 0} { |
|
|
|
|
set f2l 1 |
|
|
|
|
} |
|
|
|
|
set diffinhunk($ids) 1 |
|
|
|
|
set diffoldstart($ids) $f1l |
|
|
|
|
set diffnewstart($ids) $f2l |
|
|
|
|
set diffoldlno($ids) $f1l |
|
|
|
|
set diffnewlno($ids) $f2l |
|
|
|
|
set difflcounts($ids) {} |
|
|
|
|
set noldlines($ids) 0 |
|
|
|
|
set nnewlines($ids) 0 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc processhunks {} { |
|
|
|
|
global diffmergeid parents nparents currenthunk |
|
|
|
|
global mergefilelist diffblocked mergefds |
|
|
|
|
global grouphunks grouplinestart grouplineend groupfilenum |
|
|
|
|
|
|
|
|
|
set nfiles [llength $mergefilelist($diffmergeid)] |
|
|
|
|
while 1 { |
|
|
|
|
set fi $nfiles |
|
|
|
|
set lno 0 |
|
|
|
|
# look for the earliest hunk |
|
|
|
|
foreach p $parents($diffmergeid) { |
|
|
|
|
set ids [list $diffmergeid $p] |
|
|
|
|
if {![info exists currenthunk($ids)]} return |
|
|
|
|
set i [lindex $currenthunk($ids) 0] |
|
|
|
|
set l [lindex $currenthunk($ids) 2] |
|
|
|
|
if {$i < $fi || ($i == $fi && $l < $lno)} { |
|
|
|
|
set fi $i |
|
|
|
|
set lno $l |
|
|
|
|
set pi $p |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if {$fi < $nfiles} { |
|
|
|
|
set ids [list $diffmergeid $pi] |
|
|
|
|
set hunk $currenthunk($ids) |
|
|
|
|
unset currenthunk($ids) |
|
|
|
|
if {$diffblocked($ids) > 0} { |
|
|
|
|
fileevent $mergefds($ids) readable \ |
|
|
|
|
[list getmergediffline $mergefds($ids) $ids $diffmergeid] |
|
|
|
|
} |
|
|
|
|
set diffblocked($ids) 0 |
|
|
|
|
|
|
|
|
|
if {[info exists groupfilenum] && $groupfilenum == $fi |
|
|
|
|
&& $lno <= $grouplineend} { |
|
|
|
|
# add this hunk to the pending group |
|
|
|
|
lappend grouphunks($pi) $hunk |
|
|
|
|
set endln [lindex $hunk 4] |
|
|
|
|
if {$endln > $grouplineend} { |
|
|
|
|
set grouplineend $endln |
|
|
|
|
} |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# succeeding stuff doesn't belong in this group, so |
|
|
|
|
# process the group now |
|
|
|
|
if {[info exists groupfilenum]} { |
|
|
|
|
processgroup |
|
|
|
|
unset groupfilenum |
|
|
|
|
unset grouphunks |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if {$fi >= $nfiles} break |
|
|
|
|
|
|
|
|
|
# start a new group |
|
|
|
|
set groupfilenum $fi |
|
|
|
|
set grouphunks($pi) [list $hunk] |
|
|
|
|
set grouplinestart $lno |
|
|
|
|
set grouplineend [lindex $hunk 4] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc processgroup {} { |
|
|
|
|
global groupfilelast groupfilenum difffilestart |
|
|
|
|
global mergefilelist diffmergeid ctext filelines |
|
|
|
|
global parents diffmergeid diffoffset |
|
|
|
|
global grouphunks grouplinestart grouplineend nparents |
|
|
|
|
global mergemax |
|
|
|
|
|
|
|
|
|
$ctext conf -state normal |
|
|
|
|
set id $diffmergeid |
|
|
|
|
set f $groupfilenum |
|
|
|
|
if {$groupfilelast != $f} { |
|
|
|
|
$ctext insert end "\n" |
|
|
|
|
set here [$ctext index "end - 1c"] |
|
|
|
|
set difffilestart($f) $here |
|
|
|
|
set mark fmark.[expr {$f + 1}] |
|
|
|
|
$ctext mark set $mark $here |
|
|
|
|
$ctext mark gravity $mark left |
|
|
|
|
set header [lindex $mergefilelist($id) $f] |
|
|
|
|
set l [expr {(78 - [string length $header]) / 2}] |
|
|
|
|
set pad [string range "----------------------------------------" 1 $l] |
|
|
|
|
$ctext insert end "$pad $header $pad\n" filesep |
|
|
|
|
set groupfilelast $f |
|
|
|
|
foreach p $parents($id) { |
|
|
|
|
set diffoffset($p) 0 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$ctext insert end "@@" msep |
|
|
|
|
set nlines [expr {$grouplineend - $grouplinestart}] |
|
|
|
|
set events {} |
|
|
|
|
set pnum 0 |
|
|
|
|
foreach p $parents($id) { |
|
|
|
|
set startline [expr {$grouplinestart + $diffoffset($p)}] |
|
|
|
|
set ol $startline |
|
|
|
|
set nl $grouplinestart |
|
|
|
|
if {[info exists grouphunks($p)]} { |
|
|
|
|
foreach h $grouphunks($p) { |
|
|
|
|
set l [lindex $h 2] |
|
|
|
|
if {$nl < $l} { |
|
|
|
|
for {} {$nl < $l} {incr nl} { |
|
|
|
|
set filelines($p,$f,$ol) $filelines($id,$f,$nl) |
|
|
|
|
incr ol |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
foreach chunk [lindex $h 5] { |
|
|
|
|
if {[llength $chunk] == 2} { |
|
|
|
|
set olc [lindex $chunk 0] |
|
|
|
|
set nlc [lindex $chunk 1] |
|
|
|
|
set nnl [expr {$nl + $nlc}] |
|
|
|
|
lappend events [list $nl $nnl $pnum $olc $nlc] |
|
|
|
|
incr ol $olc |
|
|
|
|
set nl $nnl |
|
|
|
|
} else { |
|
|
|
|
incr ol [lindex $chunk 0] |
|
|
|
|
incr nl [lindex $chunk 0] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if {$nl < $grouplineend} { |
|
|
|
|
for {} {$nl < $grouplineend} {incr nl} { |
|
|
|
|
set filelines($p,$f,$ol) $filelines($id,$f,$nl) |
|
|
|
|
incr ol |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
set nlines [expr {$ol - $startline}] |
|
|
|
|
$ctext insert end " -$startline,$nlines" msep |
|
|
|
|
incr pnum |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
set nlines [expr {$grouplineend - $grouplinestart}] |
|
|
|
|
$ctext insert end " +$grouplinestart,$nlines @@\n" msep |
|
|
|
|
|
|
|
|
|
set events [lsort -integer -index 0 $events] |
|
|
|
|
set nevents [llength $events] |
|
|
|
|
set nmerge $nparents($diffmergeid) |
|
|
|
|
set l $grouplinestart |
|
|
|
|
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" |
|
|
|
|
incr l |
|
|
|
|
} |
|
|
|
|
set e [lindex $events $i] |
|
|
|
|
set enl [lindex $e 1] |
|
|
|
|
set j $i |
|
|
|
|
set active {} |
|
|
|
|
while 1 { |
|
|
|
|
set pnum [lindex $e 2] |
|
|
|
|
set olc [lindex $e 3] |
|
|
|
|
set nlc [lindex $e 4] |
|
|
|
|
if {![info exists delta($pnum)]} { |
|
|
|
|
set delta($pnum) [expr {$olc - $nlc}] |
|
|
|
|
lappend active $pnum |
|
|
|
|
} else { |
|
|
|
|
incr delta($pnum) [expr {$olc - $nlc}] |
|
|
|
|
} |
|
|
|
|
if {[incr j] >= $nevents} break |
|
|
|
|
set e [lindex $events $j] |
|
|
|
|
if {[lindex $e 0] >= $enl} break |
|
|
|
|
if {[lindex $e 1] > $enl} { |
|
|
|
|
set enl [lindex $e 1] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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} { |
|
|
|
|
lappend ncol m$pnum |
|
|
|
|
} else { |
|
|
|
|
lappend ncol mmax |
|
|
|
|
} |
|
|
|
|
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)] || $pnum == $bestpn} continue |
|
|
|
|
set olc [expr {$nlc + $delta($pnum)}] |
|
|
|
|
set ol [expr {$l + $diffoffset($p)}] |
|
|
|
|
incr diffoffset($p) $delta($pnum) |
|
|
|
|
unset delta($pnum) |
|
|
|
|
for {} {$olc > 0} {incr olc -1} { |
|
|
|
|
$ctext insert end "-$filelines($p,$f,$ol)\n" m$pnum |
|
|
|
|
incr ol |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
while {$l < $grouplineend} { |
|
|
|
|
$ctext insert end " $filelines($id,$f,$l)\n" |
|
|
|
|
incr l |
|
|
|
|
} |
|
|
|
|
$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 contdiff {ids} { |
|
|
|
|
global treediffs diffids treepending |
|
|
|
|
proc startdiff {ids} { |
|
|
|
|
global treediffs diffids treepending diffmergeid |
|
|
|
|
|
|
|
|
|
set diffids $ids |
|
|
|
|
catch {unset diffmergeid} |
|
|
|
|
if {![info exists treediffs($ids)]} { |
|
|
|
|
if {![info exists treepending]} { |
|
|
|
|
gettreediffs $ids |
|
|
|
@ -1722,47 +2258,39 @@ proc contdiff {ids} {
@@ -1722,47 +2258,39 @@ proc contdiff {ids} {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc selnextline {dir} { |
|
|
|
|
global selectedline |
|
|
|
|
if {![info exists selectedline]} return |
|
|
|
|
set l [expr $selectedline + $dir] |
|
|
|
|
unmarkmatches |
|
|
|
|
selectline $l |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc addtocflist {ids} { |
|
|
|
|
global treediffs cflist diffpindex |
|
|
|
|
|
|
|
|
|
set colors {black blue green red cyan magenta} |
|
|
|
|
set color [lindex $colors [expr {$diffpindex % [llength $colors]}]] |
|
|
|
|
global treediffs cflist |
|
|
|
|
foreach f $treediffs($ids) { |
|
|
|
|
$cflist insert end $f |
|
|
|
|
$cflist itemconf end -foreground $color |
|
|
|
|
} |
|
|
|
|
getblobdiffs $ids |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc gettreediffs {ids} { |
|
|
|
|
global treediffs parents treepending |
|
|
|
|
global treediff parents treepending |
|
|
|
|
set treepending $ids |
|
|
|
|
set treediffs($ids) {} |
|
|
|
|
set treediff {} |
|
|
|
|
set id [lindex $ids 0] |
|
|
|
|
set p [lindex $ids 1] |
|
|
|
|
if [catch {set gdtf [open "|git-diff-tree -r $p $id" r]}] return |
|
|
|
|
fconfigure $gdtf -blocking 0 |
|
|
|
|
fileevent $gdtf readable "gettreediffline $gdtf {$ids}" |
|
|
|
|
fileevent $gdtf readable [list gettreediffline $gdtf $ids] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc gettreediffline {gdtf ids} { |
|
|
|
|
global treediffs treepending diffids |
|
|
|
|
global treediff treediffs treepending diffids diffmergeid |
|
|
|
|
|
|
|
|
|
set n [gets $gdtf line] |
|
|
|
|
if {$n < 0} { |
|
|
|
|
if {![eof $gdtf]} return |
|
|
|
|
close $gdtf |
|
|
|
|
set treediffs($ids) $treediff |
|
|
|
|
unset treepending |
|
|
|
|
if {[info exists diffids]} { |
|
|
|
|
if {$ids != $diffids} { |
|
|
|
|
gettreediffs $diffids |
|
|
|
|
if {$ids != $diffids} { |
|
|
|
|
gettreediffs $diffids |
|
|
|
|
} else { |
|
|
|
|
if {[info exists diffmergeid]} { |
|
|
|
|
contmergediff $ids |
|
|
|
|
} else { |
|
|
|
|
addtocflist $ids |
|
|
|
|
} |
|
|
|
@ -1770,31 +2298,35 @@ proc gettreediffline {gdtf ids} {
@@ -1770,31 +2298,35 @@ proc gettreediffline {gdtf ids} {
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
set file [lindex $line 5] |
|
|
|
|
lappend treediffs($ids) $file |
|
|
|
|
lappend treediff $file |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc getblobdiffs {ids} { |
|
|
|
|
global diffopts blobdifffd diffids env |
|
|
|
|
global nextupdate diffinhdr |
|
|
|
|
global diffopts blobdifffd diffids env curdifftag curtagstart |
|
|
|
|
global difffilestart nextupdate diffinhdr treediffs |
|
|
|
|
|
|
|
|
|
set id [lindex $ids 0] |
|
|
|
|
set p [lindex $ids 1] |
|
|
|
|
set env(GIT_DIFF_OPTS) $diffopts |
|
|
|
|
if [catch {set bdf [open "|git-diff-tree -r -p $p $id" r]} err] { |
|
|
|
|
set cmd [list | git-diff-tree -r -p -C $p $id] |
|
|
|
|
if {[catch {set bdf [open $cmd r]} err]} { |
|
|
|
|
puts "error getting diffs: $err" |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
set diffinhdr 0 |
|
|
|
|
fconfigure $bdf -blocking 0 |
|
|
|
|
set blobdifffd($ids) $bdf |
|
|
|
|
fileevent $bdf readable [list getblobdiffline $bdf $ids] |
|
|
|
|
set curdifftag Comments |
|
|
|
|
set curtagstart 0.0 |
|
|
|
|
catch {unset difffilestart} |
|
|
|
|
fileevent $bdf readable [list getblobdiffline $bdf $diffids] |
|
|
|
|
set nextupdate [expr {[clock clicks -milliseconds] + 100}] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc getblobdiffline {bdf ids} { |
|
|
|
|
global diffids blobdifffd ctext curdifftag curtagstart |
|
|
|
|
global diffnexthead diffnextnote diffindex difffilestart |
|
|
|
|
global nextupdate diffpending diffpindex diffinhdr |
|
|
|
|
global diffnexthead diffnextnote difffilestart |
|
|
|
|
global nextupdate diffinhdr treediffs |
|
|
|
|
global gaudydiff |
|
|
|
|
|
|
|
|
|
set n [gets $bdf line] |
|
|
|
@ -1803,11 +2335,6 @@ proc getblobdiffline {bdf ids} {
@@ -1803,11 +2335,6 @@ proc getblobdiffline {bdf ids} {
|
|
|
|
|
close $bdf |
|
|
|
|
if {$ids == $diffids && $bdf == $blobdifffd($ids)} { |
|
|
|
|
$ctext tag add $curdifftag $curtagstart end |
|
|
|
|
if {[incr diffpindex] < [llength $diffpending]} { |
|
|
|
|
set id [lindex $ids 0] |
|
|
|
|
set p [lindex $diffpending $diffpindex] |
|
|
|
|
contdiff [list $id $p] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return |
|
|
|
@ -1816,18 +2343,29 @@ proc getblobdiffline {bdf ids} {
@@ -1816,18 +2343,29 @@ proc getblobdiffline {bdf ids} {
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
$ctext conf -state normal |
|
|
|
|
if {[regexp {^diff --git a/(.*) b/} $line match fname]} { |
|
|
|
|
if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} { |
|
|
|
|
# start of a new file |
|
|
|
|
$ctext insert end "\n" |
|
|
|
|
$ctext tag add $curdifftag $curtagstart end |
|
|
|
|
set curtagstart [$ctext index "end - 1c"] |
|
|
|
|
set header $fname |
|
|
|
|
set header $newname |
|
|
|
|
set here [$ctext index "end - 1c"] |
|
|
|
|
set difffilestart($diffindex) $here |
|
|
|
|
incr diffindex |
|
|
|
|
# start mark names at fmark.1 for first file |
|
|
|
|
$ctext mark set fmark.$diffindex $here |
|
|
|
|
$ctext mark gravity fmark.$diffindex left |
|
|
|
|
set i [lsearch -exact $treediffs($diffids) $fname] |
|
|
|
|
if {$i >= 0} { |
|
|
|
|
set difffilestart($i) $here |
|
|
|
|
incr i |
|
|
|
|
$ctext mark set fmark.$i $here |
|
|
|
|
$ctext mark gravity fmark.$i left |
|
|
|
|
} |
|
|
|
|
if {$newname != $fname} { |
|
|
|
|
set i [lsearch -exact $treediffs($diffids) $newname] |
|
|
|
|
if {$i >= 0} { |
|
|
|
|
set difffilestart($i) $here |
|
|
|
|
incr i |
|
|
|
|
$ctext mark set fmark.$i $here |
|
|
|
|
$ctext mark gravity fmark.$i left |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
set curdifftag "f:$fname" |
|
|
|
|
$ctext tag delete $curdifftag |
|
|
|
|
set l [expr {(78 - [string length $header]) / 2}] |
|
|
|
@ -1887,14 +2425,19 @@ proc nextfile {} {
@@ -1887,14 +2425,19 @@ proc nextfile {} {
|
|
|
|
|
set here [$ctext index @0,0] |
|
|
|
|
for {set i 0} {[info exists difffilestart($i)]} {incr i} { |
|
|
|
|
if {[$ctext compare $difffilestart($i) > $here]} { |
|
|
|
|
$ctext yview $difffilestart($i) |
|
|
|
|
break |
|
|
|
|
if {![info exists pos] |
|
|
|
|
|| [$ctext compare $difffilestart($i) < $pos]} { |
|
|
|
|
set pos $difffilestart($i) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if {[info exists pos]} { |
|
|
|
|
$ctext yview $pos |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc listboxsel {} { |
|
|
|
|
global ctext cflist currentid treediffs |
|
|
|
|
global ctext cflist currentid |
|
|
|
|
if {![info exists currentid]} return |
|
|
|
|
set sel [lsort [$cflist curselection]] |
|
|
|
|
if {$sel eq {}} return |
|
|
|
@ -2157,7 +2700,7 @@ proc diffvssel {dirn} {
@@ -2157,7 +2700,7 @@ proc diffvssel {dirn} {
|
|
|
|
|
$ctext conf -state disabled |
|
|
|
|
$ctext tag delete Comments |
|
|
|
|
$ctext tag remove found 1.0 end |
|
|
|
|
startdiff [list $newid $oldid] |
|
|
|
|
startdiff $newid [list $oldid] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
proc mkpatch {} { |
|
|
|
@ -2291,10 +2834,7 @@ proc domktag {} {
@@ -2291,10 +2834,7 @@ proc domktag {} {
|
|
|
|
|
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 |
|
|
|
|