Merge with master for gitk and doc updates.

This commit is contained in:
Junio C Hamano
2005-08-18 11:48:22 -07:00
5 changed files with 711 additions and 213 deletions

View File

@ -1,7 +1,7 @@
MAN1_TXT=$(wildcard git-*.txt) MAN1_TXT=$(wildcard git-*.txt)
MAN7_TXT=git.txt MAN7_TXT=git.txt
DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) glossary.html
DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
@ -54,3 +54,8 @@ clean:
%.xml : %.txt %.xml : %.txt
asciidoc -b docbook -d manpage $< asciidoc -b docbook -d manpage $<
glossary.html : glossary.txt sort_glossary.pl
cat $< | \
perl sort_glossary.pl | \
asciidoc -b xhtml11 - > glossary.html

View File

@ -3,21 +3,27 @@ object::
the SHA1 of its contents. Consequently, an object can not the SHA1 of its contents. Consequently, an object can not
be changed. be changed.
object name::
The unique identifier of an object. The hash of the object's contents
using the Secure Hash Algorithm 1 and usually represented by the 40
character hexadecimal encoding of the hash of the object (possibly
followed by a white space).
SHA1:: SHA1::
A 20-byte sequence (or 41-byte file containing the hex Synonym for object name.
representation and a newline). It is calculated from the
contents of an object by the Secure Hash Algorithm 1. object identifier::
Synonym for object name.
hash::
In git's context, synonym to object name.
object database:: object database::
Stores a set of "objects", and an individial object is identified Stores a set of "objects", and an individial object is identified
by its SHA1 (its ref). The objects are either stored as single by its object name. The object usually live in $GIT_DIR/objects/.
files, or live inside of packs.
object name::
Synonym for SHA1.
blob object:: blob object::
Untyped object, i.e. the contents of a file. Untyped object, e.g. the contents of a file.
tree object:: tree object::
An object containing a list of blob and/or tree objects. An object containing a list of blob and/or tree objects.
@ -29,42 +35,43 @@ tree::
dependent blob and tree objects (i.e. a stored representation dependent blob and tree objects (i.e. a stored representation
of a working tree). of a working tree).
cache:: index::
A collection of files whose contents are stored as objects. A collection of files with stat information, whose contents are
The cache is a stored version of your working tree. Well, can stored as objects. The cache is a stored version of your working
also contain a second, and even a third version of a working tree. Truth be told, it can also contain a second, and even a third
tree, which are used when merging. version of a working tree, which are used when merging.
cache entry:: index entry::
The information regarding a particular file, stored in the index. The information regarding a particular file, stored in the index.
A cache entry can be unmerged, if a merge was started, but not An index entry can be unmerged, if a merge was started, but not
yet finished (i.e. if the cache contains multiple versions of yet finished (i.e. if the cache contains multiple versions of
that file). that file).
index:: unmerged index:
Contains information about the cache contents, in particular An index which contains unmerged index entries.
timestamps and mode flags ("stat information") for the files
stored in the cache. An unmerged index is an index which contains cache::
unmerged cache entries. Obsolete for: index.
working tree:: working tree::
The set of files and directories currently being worked on. The set of files and directories currently being worked on,
Think "ls -laR" i.e. you can work in your working tree without using git at all.
directory:: directory::
The list you get with "ls" :-) The list you get with "ls" :-)
checkout::
The action of updating the working tree to a revision which was
stored in the object database.
revision:: revision::
A particular state of files and directories which was stored in A particular state of files and directories which was stored in
the object database. It is referenced by a commit object. the object database. It is referenced by a commit object.
checkout::
The action of updating the working tree to a revision which was
stored in the object database.
commit:: commit::
The action of storing the current state of the cache in the As a verb: The action of storing the current state of the cache in the
object database. The result is a revision. object database. The result is a revision.
As a noun: Short hand for commit object.
commit object:: commit object::
An object which contains the information about a particular An object which contains the information about a particular
@ -72,14 +79,15 @@ commit object::
tree object which corresponds to the top directory of the tree object which corresponds to the top directory of the
stored revision. stored revision.
parent::
A commit object contains a (possibly empty) list of the logical
predecessor(s) in the line of development, i.e. its parents.
changeset:: changeset::
BitKeeper/cvsps speak for "commit". Since git does not store BitKeeper/cvsps speak for "commit". Since git does not store
changes, but states, it really does not make sense to use changes, but states, it really does not make sense to use
the term "changesets" with git. the term "changesets" with git.
ent::
Favorite synonym to "tree-ish" by some total geeks.
clean:: clean::
A working tree is clean, if it corresponds to the revision A working tree is clean, if it corresponds to the revision
referenced by the current head. referenced by the current head.
@ -94,13 +102,12 @@ head::
branch:: branch::
A non-cyclical graph of revisions, i.e. the complete history of A non-cyclical graph of revisions, i.e. the complete history of
a particular revision, which does not (yet) have children, which a particular revision, which is called the branch head. The
is called the branch head. The branch heads are stored in branch heads are stored in $GIT_DIR/refs/heads/.
$GIT_DIR/refs/heads/.
ref:: ref::
A 40-byte hex representation of a SHA1 pointing to a particular A 40-byte hex representation of a SHA1 pointing to a particular
object. These are stored in $GIT_DIR/refs/. object. These may be stored in $GIT_DIR/refs/.
head ref:: head ref::
A ref pointing to a head. Often, this is abbreviated to "head". A ref pointing to a head. Often, this is abbreviated to "head".
@ -108,7 +115,10 @@ head ref::
tree-ish:: tree-ish::
A ref pointing to either a commit object, a tree object, or a A ref pointing to either a commit object, a tree object, or a
tag object pointing to a commit or tree object. tag object pointing to a tag or commit or tree object.
ent::
Favorite synonym to "tree-ish" by some total geeks.
tag object:: tag object::
An object containing a ref pointing to another object. It can An object containing a ref pointing to another object. It can
@ -120,6 +130,8 @@ tag::
a tag is not changed by a commit. Tags (not tag objects) are a tag is not changed by a commit. Tags (not tag objects) are
stored in $GIT_DIR/refs/tags/. A git tag has nothing to do with stored in $GIT_DIR/refs/tags/. A git tag has nothing to do with
a Lisp tag (which is called object type in git's context). a Lisp tag (which is called object type in git's context).
A tag is most typically used to mark a particular point in the
commit ancestry chain.
merge:: merge::
To merge branches means to try to accumulate the changes since a To merge branches means to try to accumulate the changes since a
@ -133,9 +145,18 @@ resolve::
repository:: repository::
A collection of refs together with an object database containing A collection of refs together with an object database containing
all objects, which are reachable from the refs. A repository can all objects, which are reachable from the refs, possibly accompanied
by meta data from one or more porcelains. A repository can
share an object database with other repositories. share an object database with other repositories.
git archive::
Synonym for repository (for arch people).
file system::
Linus Torvalds originally designed git to be a user space file
system, i.e. the infrastructure to hold files and directories.
That ensured the efficiency and speed of git.
alternate object database:: alternate object database::
Via the alternates mechanism, a repository can inherit part of its Via the alternates mechanism, a repository can inherit part of its
object database from another object database, which is called object database from another object database, which is called
@ -150,10 +171,6 @@ chain::
reference to its successor (for example, the successor of a commit reference to its successor (for example, the successor of a commit
could be one of its parents). could be one of its parents).
parent::
A commit object contains a (possibly empty) list of the logical
predecessor(s) in the line of development, i.e. its parents.
fetch:: fetch::
Fetching a branch means to get the branch's head ref from a Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from remote repository, to find out which objects are missing from
@ -176,8 +193,8 @@ pack::
space or to transmit them efficiently). space or to transmit them efficiently).
pack index:: pack index::
Contains offsets into a pack, so the pack can be used instead of The list of identifiers, and other information, of the objects in a
the unpacked objects. pack, to assist in efficiently accessing the contents of a pack.
plumbing:: plumbing::
Cute name for core git. Cute name for core git.
@ -196,3 +213,4 @@ SCM::
dircache:: dircache::
You are *waaaaay* behind. You are *waaaaay* behind.

View File

@ -70,8 +70,8 @@ them too:
Now create the branches in which you are going to work, these start Now create the branches in which you are going to work, these start
out at the current tip of the linus branch. out at the current tip of the linus branch.
$ git checkout -b test linus $ git branch test linus
$ git checkout -b release linus $ git branch release linus
These can be easily kept up to date by merging from the "linus" branch: These can be easily kept up to date by merging from the "linus" branch:
@ -144,6 +144,11 @@ is empty. At this point the branch can be deleted:
$ rm .git/refs/heads/branchname $ rm .git/refs/heads/branchname
Some changes are so trivial that it is not necessary to create a separate
branch and then merge into each of the test and release branches. For
these changes, just apply directly to the "release" branch, and then
merge that into the "test" branch.
To create diffstat and shortlog summaries of changes to include in a "please To create diffstat and shortlog summaries of changes to include in a "please
pull" request to Linus you can use: pull" request to Linus you can use:
@ -151,3 +156,109 @@ pull" request to Linus you can use:
and and
$ git-whatchanged release ^linus | git-shortlog $ git-whatchanged release ^linus | git-shortlog
Here are some of the scripts that I use to simplify all this even further.
==== update script ====
# Update a branch in my GIT tree. If the branch to be updated
# is "linus", then pull from kernel.org. Otherwise merge local
# linus branch into test|release branch
case "$1" in
test|release)
git checkout $1 && git resolve $1 linus "Auto-update from upstream"
;;
linus)
before=$(cat .git/HEAD)
git checkout linus && git pull linus
after=$(cat .git/HEAD)
if [ $before != $after ]
then
git-whatchanged $after ^$before | git-shortlog
fi
;;
*)
echo "Usage: $0 linus|test|release" 1>&2
exit 1
;;
esac
==== merge script ====
# Merge a branch into either the test or release branch
pname=$0
usage()
{
echo "Usage: $pname branch test|release" 1>&2
exit 1
}
if [ ! -f .git/refs/heads/"$1" ]
then
echo "Can't see branch <$1>" 1>&2
usage
fi
case "$2" in
test|release)
if [ $(git-rev-list $1 ^$2 | wc -c) -eq 0 ]
then
echo $1 already merged into $2 1>&2
exit 1
fi
git checkout $2 && git resolve $2 $1 "Pull $1 into $2 branch"
;;
*)
usage
;;
esac
==== status script ====
# report on status of my ia64 GIT tree
gb=$(tput setab 2)
rb=$(tput setab 1)
restore=$(tput setab 9)
if [ `git-rev-tree release ^test | wc -c` -gt 0 ]
then
echo $rb Warning: commits in release that are not in test $restore
git-whatchanged release ^test
fi
for branch in `ls .git/refs/heads`
do
if [ $branch = linus -o $branch = test -o $branch = release ]
then
continue
fi
echo -n $gb ======= $branch ====== $restore " "
status=
for ref in test release linus
do
if [ `git-rev-tree $branch ^$ref | wc -c` -gt 0 ]
then
status=$status${ref:0:1}
fi
done
case $status in
trl)
echo $rb Need to pull into test $restore
;;
rl)
echo "In test"
;;
l)
echo "Waiting for linus"
;;
"")
echo $rb All done $restore
;;
*)
echo $rb "<$status>" $restore
;;
esac
git-whatchanged $branch ^linus | git-shortlog
done

View File

@ -0,0 +1,70 @@
#!/usr/bin/perl
%terms=();
while(<>) {
if(/^(\S.*)::$/) {
my $term=$1;
if(defined($terms{$term})) {
die "$1 defined twice\n";
}
$terms{$term}="";
LOOP: while(<>) {
if(/^$/) {
last LOOP;
}
if(/^ \S/) {
$terms{$term}.=$_;
} else {
die "Error 1: $_";
}
}
}
}
sub format_tab_80 ($) {
my $text=$_[0];
my $result="";
$text=~s/\s+/ /g;
$text=~s/^\s+//;
while($text=~/^(.{1,72})(|\s+(\S.*)?)$/) {
$result.=" ".$1."\n";
$text=$3;
}
return $result;
}
sub no_spaces ($) {
my $result=$_[0];
$result=~tr/ /_/;
return $result;
}
print 'GIT Glossary
============
Aug 2005
This list is sorted alphabetically:
';
@keys=sort {uc($a) cmp uc($b)} keys %terms;
$pattern='(\b'.join('\b|\b',reverse @keys).'\b)';
foreach $key (@keys) {
$terms{$key}=~s/$pattern/sprintf "<<ref_".no_spaces($1).",$1>>";/eg;
print '[[ref_'.no_spaces($key).']]'.$key."::\n"
.format_tab_80($terms{$key})."\n";
}
print '
Author
------
Written by Johannes Schindelin <Johannes.Schindelin@gmx.de> and
the git-list <git@vger.kernel.org>.
GIT
---
Part of the link:git.html[git] suite
';

598
gitk
View File

@ -59,7 +59,7 @@ proc getcommits {rargs} {
} }
proc getcommitlines {commfd} { proc getcommitlines {commfd} {
global commits parents cdate children nchildren global commits parents cdate children
global commitlisted phase commitinfo nextupdate global commitlisted phase commitinfo nextupdate
global stopped redisplaying leftover global stopped redisplaying leftover
@ -156,6 +156,7 @@ proc readcommit {id} {
proc parsecommit {id contents listed} { proc parsecommit {id contents listed} {
global commitinfo children nchildren parents nparents cdate ncleft global commitinfo children nchildren parents nparents cdate ncleft
global grafts
set inhdr 1 set inhdr 1
set comment {} set comment {}
@ -171,13 +172,32 @@ proc parsecommit {id contents listed} {
} }
set parents($id) {} set parents($id) {}
set nparents($id) 0 set nparents($id) 0
set grafted 0
if {[info exists grafts($id)]} {
set grafted 1
set parents($id) $grafts($id)
set nparents($id) [llength $grafts($id)]
if {$listed} {
foreach p $grafts($id) {
if {![info exists nchildren($p)]} {
set children($p) [list $id]
set nchildren($p) 1
set ncleft($p) 1
} elseif {[lsearch -exact $children($p) $id] < 0} {
lappend children($p) $id
incr nchildren($p)
incr ncleft($p)
}
}
}
}
foreach line [split $contents "\n"] { foreach line [split $contents "\n"] {
if {$inhdr} { if {$inhdr} {
if {$line == {}} { if {$line == {}} {
set inhdr 0 set inhdr 0
} else { } else {
set tag [lindex $line 0] set tag [lindex $line 0]
if {$tag == "parent"} { if {$tag == "parent" && !$grafted} {
set p [lindex $line 1] set p [lindex $line 1]
if {![info exists nchildren($p)]} { if {![info exists nchildren($p)]} {
set children($p) {} set children($p) {}
@ -273,6 +293,32 @@ proc readrefs {} {
} }
} }
proc readgrafts {} {
global grafts env
catch {
set graftfile info/grafts
if {[info exists env(GIT_GRAFT_FILE)]} {
set graftfile $env(GIT_GRAFT_FILE)
}
set fd [open [gitdir]/$graftfile r]
while {[gets $fd line] >= 0} {
if {[string match "#*" $line]} continue
set ok 1
foreach x $line {
if {![regexp {^[0-9a-f]{40}$} $x]} {
set ok 0
break
}
}
if {$ok} {
set id [lindex $line 0]
set grafts($id) [lrange $line 1 end]
}
}
close $fd
}
}
proc error_popup msg { proc error_popup msg {
set w .error set w .error
toplevel $w toplevel $w
@ -704,21 +750,24 @@ proc assigncolor {id} {
} }
proc initgraph {} { proc initgraph {} {
global canvy canvy0 lineno numcommits lthickness nextcolor linespc global canvy canvy0 lineno numcommits nextcolor linespc
global mainline sidelines global mainline mainlinearrow sidelines
global nchildren ncleft global nchildren ncleft
global displist nhyperspace
allcanvs delete all allcanvs delete all
set nextcolor 0 set nextcolor 0
set canvy $canvy0 set canvy $canvy0
set lineno -1 set lineno -1
set numcommits 0 set numcommits 0
set lthickness [expr {int($linespc / 9) + 1}]
catch {unset mainline} catch {unset mainline}
catch {unset mainlinearrow}
catch {unset sidelines} catch {unset sidelines}
foreach id [array names nchildren] { foreach id [array names nchildren] {
set ncleft($id) $nchildren($id) set ncleft($id) $nchildren($id)
} }
set displist {}
set nhyperspace 0
} }
proc bindline {t id} { proc bindline {t id} {
@ -730,19 +779,21 @@ proc bindline {t id} {
$canv bind $t <Button-1> "lineclick %x %y $id 1" $canv bind $t <Button-1> "lineclick %x %y $id 1"
} }
# level here is an index in displist
proc drawcommitline {level} { proc drawcommitline {level} {
global parents children nparents nchildren todo global parents children nparents displist
global canv canv2 canv3 mainfont namefont canvy linespc global canv canv2 canv3 mainfont namefont canvy linespc
global lineid linehtag linentag linedtag commitinfo global lineid linehtag linentag linedtag commitinfo
global colormap numcommits currentparents dupparents global colormap numcommits currentparents dupparents
global oldlevel oldnlines oldtodo
global idtags idline idheads global idtags idline idheads
global lineno lthickness mainline sidelines global lineno lthickness mainline mainlinearrow sidelines
global commitlisted rowtextx idpos global commitlisted rowtextx idpos lastuse displist
global oldnlines olddlevel olddisplist
incr numcommits incr numcommits
incr lineno incr lineno
set id [lindex $todo $level] set id [lindex $displist $level]
set lastuse($id) $lineno
set lineid($lineno) $id set lineid($lineno) $id
set idline($id) $lineno set idline($id) $lineno
set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}] set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
@ -773,8 +824,12 @@ proc drawcommitline {level} {
[list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]] [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
if {[info exists mainline($id)]} { if {[info exists mainline($id)]} {
lappend mainline($id) $x $y1 lappend mainline($id) $x $y1
if {$mainlinearrow($id) ne "none"} {
set mainline($id) [trimdiagstart $mainline($id)]
}
set t [$canv create line $mainline($id) \ set t [$canv create line $mainline($id) \
-width $lthickness -fill $colormap($id)] -width $lthickness -fill $colormap($id) \
-arrow $mainlinearrow($id)]
$canv lower $t $canv lower $t
bindline $t $id bindline $t $id
} }
@ -782,8 +837,9 @@ proc drawcommitline {level} {
foreach ls $sidelines($id) { foreach ls $sidelines($id) {
set coords [lindex $ls 0] set coords [lindex $ls 0]
set thick [lindex $ls 1] set thick [lindex $ls 1]
set arrow [lindex $ls 2]
set t [$canv create line $coords -fill $colormap($id) \ set t [$canv create line $coords -fill $colormap($id) \
-width [expr {$thick * $lthickness}]] -width [expr {$thick * $lthickness}] -arrow $arrow]
$canv lower $t $canv lower $t
bindline $t $id bindline $t $id
} }
@ -794,7 +850,7 @@ proc drawcommitline {level} {
-fill $ofill -outline black -width 1] -fill $ofill -outline black -width 1]
$canv raise $t $canv raise $t
$canv bind $t <1> {selcanvline {} %x %y} $canv bind $t <1> {selcanvline {} %x %y}
set xt [xcoord [llength $todo] $level $lineno] set xt [xcoord [llength $displist] $level $lineno]
if {[llength $currentparents] > 2} { if {[llength $currentparents] > 2} {
set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}] set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
} }
@ -813,6 +869,10 @@ proc drawcommitline {level} {
-text $name -font $namefont] -text $name -font $namefont]
set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \ set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
-text $date -font $mainfont] -text $date -font $mainfont]
set olddlevel $level
set olddisplist $displist
set oldnlines [llength $displist]
} }
proc drawtags {id x xt y1} { proc drawtags {id x xt y1} {
@ -867,46 +927,11 @@ proc drawtags {id x xt y1} {
return $xt return $xt
} }
proc updatetodo {level noshortcut} {
global currentparents ncleft todo
global mainline oldlevel oldtodo oldnlines
global canvy linespc mainline
global commitinfo lineno xspc1
set oldlevel $level
set oldtodo $todo
set oldnlines [llength $todo]
if {!$noshortcut && [llength $currentparents] == 1} {
set p [lindex $currentparents 0]
if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
set ncleft($p) 0
set x [xcoord $level $level $lineno]
set y [expr $canvy - $linespc]
set mainline($p) [list $x $y]
set todo [lreplace $todo $level $level $p]
set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
return 0
}
}
set todo [lreplace $todo $level $level]
set i $level
foreach p $currentparents {
incr ncleft($p) -1
set k [lsearch -exact $todo $p]
if {$k < 0} {
set todo [linsert $todo $i $p]
incr i
}
}
return 1
}
proc notecrossings {id lo hi corner} { proc notecrossings {id lo hi corner} {
global oldtodo crossings cornercrossings global olddisplist crossings cornercrossings
for {set i $lo} {[incr i] < $hi} {} { for {set i $lo} {[incr i] < $hi} {} {
set p [lindex $oldtodo $i] set p [lindex $olddisplist $i]
if {$p == {}} continue if {$p == {}} continue
if {$i == $corner} { if {$i == $corner} {
if {![info exists cornercrossings($id)] if {![info exists cornercrossings($id)]
@ -942,37 +967,218 @@ proc xcoord {i level ln} {
return $x return $x
} }
proc drawslants {level} { # it seems Tk can't draw arrows on the end of diagonal line segments...
global canv mainline sidelines canvx0 canvy xspc1 xspc2 lthickness proc trimdiagend {line} {
global oldlevel oldtodo todo currentparents dupparents while {[llength $line] > 4} {
set x1 [lindex $line end-3]
set y1 [lindex $line end-2]
set x2 [lindex $line end-1]
set y2 [lindex $line end]
if {($x1 == $x2) != ($y1 == $y2)} break
set line [lreplace $line end-1 end]
}
return $line
}
proc trimdiagstart {line} {
while {[llength $line] > 4} {
set x1 [lindex $line 0]
set y1 [lindex $line 1]
set x2 [lindex $line 2]
set y2 [lindex $line 3]
if {($x1 == $x2) != ($y1 == $y2)} break
set line [lreplace $line 0 1]
}
return $line
}
proc drawslants {id needonscreen nohs} {
global canv mainline mainlinearrow sidelines
global canvx0 canvy xspc1 xspc2 lthickness
global currentparents dupparents
global lthickness linespc canvy colormap lineno geometry global lthickness linespc canvy colormap lineno geometry
global maxgraphpct global maxgraphpct maxwidth
global displist onscreen lastuse
global parents commitlisted
global oldnlines olddlevel olddisplist
global nhyperspace numcommits nnewparents
if {$lineno < 0} {
lappend displist $id
set onscreen($id) 1
return 0
}
set y1 [expr {$canvy - $linespc}]
set y2 $canvy
# work out what we need to get back on screen
set reins {}
if {$onscreen($id) < 0} {
# next to do isn't displayed, better get it on screen...
lappend reins [list $id 0]
}
# make sure all the previous commits's parents are on the screen
foreach p $currentparents {
if {$onscreen($p) < 0} {
lappend reins [list $p 0]
}
}
# bring back anything requested by caller
if {$needonscreen ne {}} {
lappend reins $needonscreen
}
# try the shortcut
if {$currentparents == $id && $onscreen($id) == 0 && $reins eq {}} {
set dlevel $olddlevel
set x [xcoord $dlevel $dlevel $lineno]
set mainline($id) [list $x $y1]
set mainlinearrow($id) none
set lastuse($id) $lineno
set displist [lreplace $displist $dlevel $dlevel $id]
set onscreen($id) 1
set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
return $dlevel
}
# update displist
set displist [lreplace $displist $olddlevel $olddlevel]
set j $olddlevel
foreach p $currentparents {
set lastuse($p) $lineno
if {$onscreen($p) == 0} {
set displist [linsert $displist $j $p]
set onscreen($p) 1
incr j
}
}
if {$onscreen($id) == 0} {
lappend displist $id
}
# remove the null entry if present
set nullentry [lsearch -exact $displist {}]
if {$nullentry >= 0} {
set displist [lreplace $displist $nullentry $nullentry]
}
# bring back the ones we need now (if we did it earlier
# it would change displist and invalidate olddlevel)
foreach pi $reins {
# test again in case of duplicates in reins
set p [lindex $pi 0]
if {$onscreen($p) < 0} {
set onscreen($p) 1
set lastuse($p) $lineno
set displist [linsert $displist [lindex $pi 1] $p]
incr nhyperspace -1
}
}
set lastuse($id) $lineno
# see if we need to make any lines jump off into hyperspace
set displ [llength $displist]
if {$displ > $maxwidth} {
set ages {}
foreach x $displist {
lappend ages [list $lastuse($x) $x]
}
set ages [lsort -integer -index 0 $ages]
set k 0
while {$displ > $maxwidth} {
set use [lindex $ages $k 0]
set victim [lindex $ages $k 1]
if {$use >= $lineno - 5} break
incr k
if {[lsearch -exact $nohs $victim] >= 0} continue
set i [lsearch -exact $displist $victim]
set displist [lreplace $displist $i $i]
set onscreen($victim) -1
incr nhyperspace
incr displ -1
if {$i < $nullentry} {
incr nullentry -1
}
set x [lindex $mainline($victim) end-1]
lappend mainline($victim) $x $y1
set line [trimdiagend $mainline($victim)]
set arrow "last"
if {$mainlinearrow($victim) ne "none"} {
set line [trimdiagstart $line]
set arrow "both"
}
lappend sidelines($victim) [list $line 1 $arrow]
unset mainline($victim)
}
}
set dlevel [lsearch -exact $displist $id]
# If we are reducing, put in a null entry
if {$displ < $oldnlines} {
# does the next line look like a merge?
# i.e. does it have > 1 new parent?
if {$nnewparents($id) > 1} {
set i [expr {$dlevel + 1}]
} elseif {$nnewparents([lindex $olddisplist $olddlevel]) == 0} {
set i $olddlevel
if {$nullentry >= 0 && $nullentry < $i} {
incr i -1
}
} elseif {$nullentry >= 0} {
set i $nullentry
while {$i < $displ
&& [lindex $olddisplist $i] == [lindex $displist $i]} {
incr i
}
} else {
set i $olddlevel
if {$dlevel >= $i} {
incr i
}
}
if {$i < $displ} {
set displist [linsert $displist $i {}]
incr displ
if {$dlevel >= $i} {
incr dlevel
}
}
}
# decide on the line spacing for the next line # decide on the line spacing for the next line
set lj [expr {$lineno + 1}] set lj [expr {$lineno + 1}]
set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}] set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
set n [llength $todo] if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} {
if {$n <= 1 || $canvx0 + $n * $xspc2 <= $maxw} {
set xspc1($lj) $xspc2 set xspc1($lj) $xspc2
} else { } else {
set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($n - 1)}] set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}]
if {$xspc1($lj) < $lthickness} { if {$xspc1($lj) < $lthickness} {
set xspc1($lj) $lthickness set xspc1($lj) $lthickness
} }
} }
set y1 [expr $canvy - $linespc] foreach idi $reins {
set y2 $canvy set id [lindex $idi 0]
set j [lsearch -exact $displist $id]
set xj [xcoord $j $dlevel $lj]
set mainline($id) [list $xj $y2]
set mainlinearrow($id) first
}
set i -1 set i -1
foreach id $oldtodo { foreach id $olddisplist {
incr i incr i
if {$id == {}} continue if {$id == {}} continue
set xi [xcoord $i $oldlevel $lineno] if {$onscreen($id) <= 0} continue
if {$i == $oldlevel} { set xi [xcoord $i $olddlevel $lineno]
if {$i == $olddlevel} {
foreach p $currentparents { foreach p $currentparents {
set j [lsearch -exact $todo $p] set j [lsearch -exact $displist $p]
set coords [list $xi $y1] set coords [list $xi $y1]
set xj [xcoord $j $level $lj] set xj [xcoord $j $dlevel $lj]
if {$xj < $xi - $linespc} { if {$xj < $xi - $linespc} {
lappend coords [expr {$xj + $linespc}] $y1 lappend coords [expr {$xj + $linespc}] $y1
notecrossings $p $j $i [expr {$j + 1}] notecrossings $p $j $i [expr {$j + 1}]
@ -983,9 +1189,10 @@ proc drawslants {level} {
if {[lsearch -exact $dupparents $p] >= 0} { if {[lsearch -exact $dupparents $p] >= 0} {
# draw a double-width line to indicate the doubled parent # draw a double-width line to indicate the doubled parent
lappend coords $xj $y2 lappend coords $xj $y2
lappend sidelines($p) [list $coords 2] lappend sidelines($p) [list $coords 2 none]
if {![info exists mainline($p)]} { if {![info exists mainline($p)]} {
set mainline($p) [list $xj $y2] set mainline($p) [list $xj $y2]
set mainlinearrow($p) none
} }
} else { } else {
# normal case, no parent duplicated # normal case, no parent duplicated
@ -999,24 +1206,25 @@ proc drawslants {level} {
lappend coords $xj $yb lappend coords $xj $yb
} }
set mainline($p) $coords set mainline($p) $coords
set mainlinearrow($p) none
} else { } else {
lappend coords $xj $yb lappend coords $xj $yb
if {$yb < $y2} { if {$yb < $y2} {
lappend coords $xj $y2 lappend coords $xj $y2
} }
lappend sidelines($p) [list $coords 1] lappend sidelines($p) [list $coords 1 none]
} }
} }
} }
} else { } else {
set j $i set j $i
if {[lindex $todo $i] != $id} { if {[lindex $displist $i] != $id} {
set j [lsearch -exact $todo $id] set j [lsearch -exact $displist $id]
} }
if {$j != $i || $xspc1($lineno) != $xspc1($lj) if {$j != $i || $xspc1($lineno) != $xspc1($lj)
|| ($oldlevel <= $i && $i <= $level) || ($olddlevel <= $i && $i <= $dlevel)
|| ($level <= $i && $i <= $oldlevel)} { || ($dlevel <= $i && $i <= $olddlevel)} {
set xj [xcoord $j $level $lj] set xj [xcoord $j $dlevel $lj]
set dx [expr {abs($xi - $xj)}] set dx [expr {abs($xi - $xj)}]
set yb $y2 set yb $y2
if {0 && $dx < $linespc} { if {0 && $dx < $linespc} {
@ -1026,21 +1234,152 @@ proc drawslants {level} {
} }
} }
} }
return $dlevel
}
# search for x in a list of lists
proc llsearch {llist x} {
set i 0
foreach l $llist {
if {$l == $x || [lsearch -exact $l $x] >= 0} {
return $i
}
incr i
}
return -1
}
proc drawmore {reading} {
global displayorder numcommits ncmupdate nextupdate
global stopped nhyperspace parents commitlisted
global maxwidth onscreen displist currentparents olddlevel
set n [llength $displayorder]
while {$numcommits < $n} {
set id [lindex $displayorder $numcommits]
set ctxend [expr {$numcommits + 10}]
if {!$reading && $ctxend > $n} {
set ctxend $n
}
set dlist {}
if {$numcommits > 0} {
set dlist [lreplace $displist $olddlevel $olddlevel]
set i $olddlevel
foreach p $currentparents {
if {$onscreen($p) == 0} {
set dlist [linsert $dlist $i $p]
incr i
}
}
}
set nohs {}
set reins {}
set isfat [expr {[llength $dlist] > $maxwidth}]
if {$nhyperspace > 0 || $isfat} {
if {$ctxend > $n} break
# work out what to bring back and
# what we want to don't want to send into hyperspace
set room 1
for {set k $numcommits} {$k < $ctxend} {incr k} {
set x [lindex $displayorder $k]
set i [llsearch $dlist $x]
if {$i < 0} {
set i [llength $dlist]
lappend dlist $x
}
if {[lsearch -exact $nohs $x] < 0} {
lappend nohs $x
}
if {$reins eq {} && $onscreen($x) < 0 && $room} {
set reins [list $x $i]
}
set newp {}
if {[info exists commitlisted($x)]} {
set right 0
foreach p $parents($x) {
if {[llsearch $dlist $p] < 0} {
lappend newp $p
if {[lsearch -exact $nohs $p] < 0} {
lappend nohs $p
}
if {$reins eq {} && $onscreen($p) < 0 && $room} {
set reins [list $p [expr {$i + $right}]]
}
}
set right 1
}
}
set l [lindex $dlist $i]
if {[llength $l] == 1} {
set l $newp
} else {
set j [lsearch -exact $l $x]
set l [concat [lreplace $l $j $j] $newp]
}
set dlist [lreplace $dlist $i $i $l]
if {$room && $isfat && [llength $newp] <= 1} {
set room 0
}
}
}
set dlevel [drawslants $id $reins $nohs]
drawcommitline $dlevel
if {[clock clicks -milliseconds] >= $nextupdate
&& $numcommits >= $ncmupdate} {
doupdate $reading
if {$stopped} break
}
}
}
# level here is an index in todo
proc updatetodo {level noshortcut} {
global ncleft todo nnewparents
global commitlisted parents onscreen
set id [lindex $todo $level]
set olds {}
if {[info exists commitlisted($id)]} {
foreach p $parents($id) {
if {[lsearch -exact $olds $p] < 0} {
lappend olds $p
}
}
}
if {!$noshortcut && [llength $olds] == 1} {
set p [lindex $olds 0]
if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
set ncleft($p) 0
set todo [lreplace $todo $level $level $p]
set onscreen($p) 0
set nnewparents($id) 1
return 0
}
}
set todo [lreplace $todo $level $level]
set i $level
set n 0
foreach p $olds {
incr ncleft($p) -1
set k [lsearch -exact $todo $p]
if {$k < 0} {
set todo [linsert $todo $i $p]
set onscreen($p) 0
incr i
incr n
}
}
set nnewparents($id) $n
return 1
} }
proc decidenext {{noread 0}} { proc decidenext {{noread 0}} {
global parents children nchildren ncleft todo global ncleft todo
global canv canv2 canv3 mainfont namefont canvy linespc
global datemode cdate global datemode cdate
global commitinfo global commitinfo
global currentparents oldlevel oldnlines oldtodo
global lineno lthickness
# remove the null entry if present
set nullentry [lsearch -exact $todo {}]
if {$nullentry >= 0} {
set todo [lreplace $todo $nullentry $nullentry]
}
# choose which one to do next time around # choose which one to do next time around
set todol [llength $todo] set todol [llength $todo]
@ -1076,53 +1415,29 @@ proc decidenext {{noread 0}} {
return -1 return -1
} }
# If we are reducing, put in a null entry
if {$todol < $oldnlines} {
if {$nullentry >= 0} {
set i $nullentry
while {$i < $todol
&& [lindex $oldtodo $i] == [lindex $todo $i]} {
incr i
}
} else {
set i $oldlevel
if {$level >= $i} {
incr i
}
}
if {$i < $todol} {
set todo [linsert $todo $i {}]
if {$level >= $i} {
incr level
}
}
}
return $level return $level
} }
proc drawcommit {id} { proc drawcommit {id} {
global phase todo nchildren datemode nextupdate global phase todo nchildren datemode nextupdate
global startcommits numcommits ncmupdate global numcommits ncmupdate displayorder todo onscreen
if {$phase != "incrdraw"} { if {$phase != "incrdraw"} {
set phase incrdraw set phase incrdraw
set todo $id set displayorder {}
set startcommits $id set todo {}
initgraph initgraph
drawcommitline 0 }
updatetodo 0 $datemode
} else {
if {$nchildren($id) == 0} { if {$nchildren($id) == 0} {
lappend todo $id lappend todo $id
lappend startcommits $id set onscreen($id) 0
} }
set level [decidenext 1] set level [decidenext 1]
if {$level == {} || $id != [lindex $todo $level]} { if {$level == {} || $id != [lindex $todo $level]} {
return return
} }
while 1 { while 1 {
drawslants $level lappend displayorder [lindex $todo $level]
drawcommitline $level
if {[updatetodo $level $datemode]} { if {[updatetodo $level $datemode]} {
set level [decidenext 1] set level [decidenext 1]
if {$level == {}} break if {$level == {}} break
@ -1131,18 +1446,12 @@ proc drawcommit {id} {
if {![info exists commitlisted($id)]} { if {![info exists commitlisted($id)]} {
break break
} }
if {[clock clicks -milliseconds] >= $nextupdate
&& $numcommits >= $ncmupdate} {
doupdate 1
if {$stopped} break
}
}
} }
drawmore 1
} }
proc finishcommits {} { proc finishcommits {} {
global phase global phase
global startcommits
global canv mainfont ctext maincursor textcursor global canv mainfont ctext maincursor textcursor
if {$phase != "incrdraw"} { if {$phase != "incrdraw"} {
@ -1151,9 +1460,7 @@ proc finishcommits {} {
-font $mainfont -tags textitems -font $mainfont -tags textitems
set phase {} set phase {}
} else { } else {
set level [decidenext] drawrest
drawslants $level
drawrest $level [llength $startcommits]
} }
. config -cursor $maincursor . config -cursor $maincursor
settextcursor $textcursor settextcursor $textcursor
@ -1171,54 +1478,38 @@ proc settextcursor {c} {
} }
proc drawgraph {} { proc drawgraph {} {
global nextupdate startmsecs startcommits todo ncmupdate global nextupdate startmsecs ncmupdate
global displayorder onscreen
if {$startcommits == {}} return if {$displayorder == {}} return
set startmsecs [clock clicks -milliseconds] set startmsecs [clock clicks -milliseconds]
set nextupdate [expr $startmsecs + 100] set nextupdate [expr $startmsecs + 100]
set ncmupdate 1 set ncmupdate 1
initgraph initgraph
set todo [lindex $startcommits 0] foreach id $displayorder {
drawrest 0 1 set onscreen($id) 0
}
drawmore 0
} }
proc drawrest {level startix} { proc drawrest {} {
global phase stopped redisplaying selectedline global phase stopped redisplaying selectedline
global datemode currentparents todo global datemode todo displayorder
global numcommits ncmupdate global numcommits ncmupdate
global nextupdate startmsecs startcommits idline global nextupdate startmsecs idline
set level [decidenext]
if {$level >= 0} { if {$level >= 0} {
set phase drawgraph set phase drawgraph
set startid [lindex $startcommits $startix]
set startline -1
if {$startid != {}} {
set startline $idline($startid)
}
while 1 { while 1 {
if {$stopped} break lappend displayorder [lindex $todo $level]
drawcommitline $level
set hard [updatetodo $level $datemode] set hard [updatetodo $level $datemode]
if {$numcommits == $startline} {
lappend todo $startid
set hard 1
incr startix
set startid [lindex $startcommits $startix]
set startline -1
if {$startid != {}} {
set startline $idline($startid)
}
}
if {$hard} { if {$hard} {
set level [decidenext] set level [decidenext]
if {$level < 0} break if {$level < 0} break
drawslants $level
}
if {[clock clicks -milliseconds] >= $nextupdate
&& $numcommits >= $ncmupdate} {
doupdate 0
} }
} }
drawmore 0
} }
set phase {} set phase {}
set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs] set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
@ -1730,7 +2021,7 @@ proc commit_descriptor {p} {
proc selectline {l isnew} { proc selectline {l isnew} {
global canv canv2 canv3 ctext commitinfo selectedline global canv canv2 canv3 ctext commitinfo selectedline
global lineid linehtag linentag linedtag global lineid linehtag linentag linedtag
global canvy0 linespc parents nparents children nchildren global canvy0 linespc parents nparents children
global cflist currentid sha1entry global cflist currentid sha1entry
global commentend idtags idline global commentend idtags idline
@ -2654,12 +2945,13 @@ proc listboxsel {} {
proc setcoords {} { proc setcoords {} {
global linespc charspc canvx0 canvy0 mainfont global linespc charspc canvx0 canvy0 mainfont
global xspc1 xspc2 global xspc1 xspc2 lthickness
set linespc [font metrics $mainfont -linespace] set linespc [font metrics $mainfont -linespace]
set charspc [font measure $mainfont "m"] set charspc [font measure $mainfont "m"]
set canvy0 [expr 3 + 0.5 * $linespc] set canvy0 [expr 3 + 0.5 * $linespc]
set canvx0 [expr 3 + 0.5 * $linespc] set canvx0 [expr 3 + 0.5 * $linespc]
set lthickness [expr {int($linespc / 9) + 1}]
set xspc1(0) $linespc set xspc1(0) $linespc
set xspc2 $linespc set xspc2 $linespc
} }
@ -3170,6 +3462,7 @@ set textfont {Courier 9}
set findmergefiles 0 set findmergefiles 0
set gaudydiff 0 set gaudydiff 0
set maxgraphpct 50 set maxgraphpct 50
set maxwidth 16
set colors {green red blue magenta darkgrey brown orange} set colors {green red blue magenta darkgrey brown orange}
@ -3202,4 +3495,5 @@ set patchnum 0
setcoords setcoords
makewindow makewindow
readrefs readrefs
readgrafts
getcommits $revtreeargs getcommits $revtreeargs