summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/Makefile7
-rw-r--r--Documentation/glossary.txt104
-rw-r--r--Documentation/howto/using-topic-branches.txt115
-rw-r--r--Documentation/sort_glossary.pl70
-rwxr-xr-xgitk628
5 files changed, 711 insertions, 213 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 336578497d..7fad5ba0e9 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,7 +1,7 @@
MAN1_TXT=$(wildcard 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_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
@@ -54,3 +54,8 @@ clean:
%.xml : %.txt
asciidoc -b docbook -d manpage $<
+glossary.html : glossary.txt sort_glossary.pl
+ cat $< | \
+ perl sort_glossary.pl | \
+ asciidoc -b xhtml11 - > glossary.html
+
diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt
index bac3c532fa..015d51018d 100644
--- a/Documentation/glossary.txt
+++ b/Documentation/glossary.txt
@@ -3,21 +3,27 @@ object::
the SHA1 of its contents. Consequently, an object can not
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::
- A 20-byte sequence (or 41-byte file containing the hex
- representation and a newline). It is calculated from the
- contents of an object by the Secure Hash Algorithm 1.
+ Synonym for object name.
+
+object identifier::
+ Synonym for object name.
+
+hash::
+ In git's context, synonym to object name.
object database::
Stores a set of "objects", and an individial object is identified
- by its SHA1 (its ref). The objects are either stored as single
- files, or live inside of packs.
-
-object name::
- Synonym for SHA1.
+ by its object name. The object usually live in $GIT_DIR/objects/.
blob object::
- Untyped object, i.e. the contents of a file.
+ Untyped object, e.g. the contents of a file.
tree object::
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
of a working tree).
-cache::
- A collection of files whose contents are stored as objects.
- The cache is a stored version of your working tree. Well, can
- also contain a second, and even a third version of a working
- tree, which are used when merging.
+index::
+ A collection of files with stat information, whose contents are
+ stored as objects. The cache is a stored version of your working
+ tree. Truth be told, it can also contain a second, and even a third
+ version of a working tree, which are used when merging.
-cache entry::
+index entry::
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
that file).
-index::
- Contains information about the cache contents, in particular
- timestamps and mode flags ("stat information") for the files
- stored in the cache. An unmerged index is an index which contains
- unmerged cache entries.
+unmerged index:
+ An index which contains unmerged index entries.
+
+cache::
+ Obsolete for: index.
working tree::
- The set of files and directories currently being worked on.
- Think "ls -laR"
+ The set of files and directories currently being worked on,
+ i.e. you can work in your working tree without using git at all.
directory::
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::
A particular state of files and directories which was stored in
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::
- 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.
+ As a noun: Short hand for commit object.
commit object::
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
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::
BitKeeper/cvsps speak for "commit". Since git does not store
changes, but states, it really does not make sense to use
the term "changesets" with git.
-ent::
- Favorite synonym to "tree-ish" by some total geeks.
-
clean::
A working tree is clean, if it corresponds to the revision
referenced by the current head.
@@ -94,13 +102,12 @@ head::
branch::
A non-cyclical graph of revisions, i.e. the complete history of
- a particular revision, which does not (yet) have children, which
- is called the branch head. The branch heads are stored in
- $GIT_DIR/refs/heads/.
+ a particular revision, which is called the branch head. The
+ branch heads are stored in $GIT_DIR/refs/heads/.
ref::
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::
A ref pointing to a head. Often, this is abbreviated to "head".
@@ -108,7 +115,10 @@ head ref::
tree-ish::
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::
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
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 tag is most typically used to mark a particular point in the
+ commit ancestry chain.
merge::
To merge branches means to try to accumulate the changes since a
@@ -133,9 +145,18 @@ resolve::
repository::
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.
+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::
Via the alternates mechanism, a repository can inherit part of its
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
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::
Fetching a branch means to get the branch's head ref from a
remote repository, to find out which objects are missing from
@@ -176,8 +193,8 @@ pack::
space or to transmit them efficiently).
pack index::
- Contains offsets into a pack, so the pack can be used instead of
- the unpacked objects.
+ The list of identifiers, and other information, of the objects in a
+ pack, to assist in efficiently accessing the contents of a pack.
plumbing::
Cute name for core git.
@@ -196,3 +213,4 @@ SCM::
dircache::
You are *waaaaay* behind.
+
diff --git a/Documentation/howto/using-topic-branches.txt b/Documentation/howto/using-topic-branches.txt
index de28cf7ce7..52fa4c012a 100644
--- a/Documentation/howto/using-topic-branches.txt
+++ b/Documentation/howto/using-topic-branches.txt
@@ -70,8 +70,8 @@ them too:
Now create the branches in which you are going to work, these start
out at the current tip of the linus branch.
- $ git checkout -b test linus
- $ git checkout -b release linus
+ $ git branch test linus
+ $ git branch release linus
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
+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
pull" request to Linus you can use:
@@ -151,3 +156,109 @@ pull" request to Linus you can use:
and
$ 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
diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl
new file mode 100644
index 0000000000..babbea0415
--- /dev/null
+++ b/Documentation/sort_glossary.pl
@@ -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
+';
+
diff --git a/gitk b/gitk
index 6dc4b24f06..f54b4c4607 100755
--- a/gitk
+++ b/gitk
@@ -59,7 +59,7 @@ proc getcommits {rargs} {
}
proc getcommitlines {commfd} {
- global commits parents cdate children nchildren
+ global commits parents cdate children
global commitlisted phase commitinfo nextupdate
global stopped redisplaying leftover
@@ -156,6 +156,7 @@ proc readcommit {id} {
proc parsecommit {id contents listed} {
global commitinfo children nchildren parents nparents cdate ncleft
+ global grafts
set inhdr 1
set comment {}
@@ -171,13 +172,32 @@ proc parsecommit {id contents listed} {
}
set parents($id) {}
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"] {
if {$inhdr} {
if {$line == {}} {
set inhdr 0
} else {
set tag [lindex $line 0]
- if {$tag == "parent"} {
+ if {$tag == "parent" && !$grafted} {
set p [lindex $line 1]
if {![info exists nchildren($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 {
set w .error
toplevel $w
@@ -704,21 +750,24 @@ proc assigncolor {id} {
}
proc initgraph {} {
- global canvy canvy0 lineno numcommits lthickness nextcolor linespc
- global mainline sidelines
+ global canvy canvy0 lineno numcommits nextcolor linespc
+ global mainline mainlinearrow sidelines
global nchildren ncleft
+ global displist nhyperspace
allcanvs delete all
set nextcolor 0
set canvy $canvy0
set lineno -1
set numcommits 0
- set lthickness [expr {int($linespc / 9) + 1}]
catch {unset mainline}
+ catch {unset mainlinearrow}
catch {unset sidelines}
foreach id [array names nchildren] {
set ncleft($id) $nchildren($id)
}
+ set displist {}
+ set nhyperspace 0
}
proc bindline {t id} {
@@ -730,19 +779,21 @@ proc bindline {t id} {
$canv bind $t <Button-1> "lineclick %x %y $id 1"
}
+# level here is an index in displist
proc drawcommitline {level} {
- global parents children nparents nchildren todo
+ global parents children nparents displist
global canv canv2 canv3 mainfont namefont canvy linespc
global lineid linehtag linentag linedtag commitinfo
global colormap numcommits currentparents dupparents
- global oldlevel oldnlines oldtodo
global idtags idline idheads
- global lineno lthickness mainline sidelines
- global commitlisted rowtextx idpos
+ global lineno lthickness mainline mainlinearrow sidelines
+ global commitlisted rowtextx idpos lastuse displist
+ global oldnlines olddlevel olddisplist
incr numcommits
incr lineno
- set id [lindex $todo $level]
+ set id [lindex $displist $level]
+ set lastuse($id) $lineno
set lineid($lineno) $id
set idline($id) $lineno
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]]
if {[info exists mainline($id)]} {
lappend mainline($id) $x $y1
+ if {$mainlinearrow($id) ne "none"} {
+ set mainline($id) [trimdiagstart $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
bindline $t $id
}
@@ -782,8 +837,9 @@ proc drawcommitline {level} {
foreach ls $sidelines($id) {
set coords [lindex $ls 0]
set thick [lindex $ls 1]
+ set arrow [lindex $ls 2]
set t [$canv create line $coords -fill $colormap($id) \
- -width [expr {$thick * $lthickness}]]
+ -width [expr {$thick * $lthickness}] -arrow $arrow]
$canv lower $t
bindline $t $id
}
@@ -794,7 +850,7 @@ proc drawcommitline {level} {
-fill $ofill -outline black -width 1]
$canv raise $t
$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} {
set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
}
@@ -813,6 +869,10 @@ proc drawcommitline {level} {
-text $name -font $namefont]
set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
-text $date -font $mainfont]
+
+ set olddlevel $level
+ set olddisplist $displist
+ set oldnlines [llength $displist]
}
proc drawtags {id x xt y1} {
@@ -867,46 +927,11 @@ proc drawtags {id x xt y1} {
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} {
- global oldtodo crossings cornercrossings
+ global olddisplist crossings cornercrossings
for {set i $lo} {[incr i] < $hi} {} {
- set p [lindex $oldtodo $i]
+ set p [lindex $olddisplist $i]
if {$p == {}} continue
if {$i == $corner} {
if {![info exists cornercrossings($id)]
@@ -942,37 +967,218 @@ proc xcoord {i level ln} {
return $x
}
-proc drawslants {level} {
- global canv mainline sidelines canvx0 canvy xspc1 xspc2 lthickness
- global oldlevel oldtodo todo currentparents dupparents
+# it seems Tk can't draw arrows on the end of diagonal line segments...
+proc trimdiagend {line} {
+ 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 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
set lj [expr {$lineno + 1}]
set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
- set n [llength $todo]
- if {$n <= 1 || $canvx0 + $n * $xspc2 <= $maxw} {
+ if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} {
set xspc1($lj) $xspc2
} else {
- set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($n - 1)}]
+ set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}]
if {$xspc1($lj) < $lthickness} {
set xspc1($lj) $lthickness
}
}
-
- set y1 [expr $canvy - $linespc]
- set y2 $canvy
+
+ foreach idi $reins {
+ 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
- foreach id $oldtodo {
+ foreach id $olddisplist {
incr i
if {$id == {}} continue
- set xi [xcoord $i $oldlevel $lineno]
- if {$i == $oldlevel} {
+ if {$onscreen($id) <= 0} continue
+ set xi [xcoord $i $olddlevel $lineno]
+ if {$i == $olddlevel} {
foreach p $currentparents {
- set j [lsearch -exact $todo $p]
+ set j [lsearch -exact $displist $p]
set coords [list $xi $y1]
- set xj [xcoord $j $level $lj]
+ set xj [xcoord $j $dlevel $lj]
if {$xj < $xi - $linespc} {
lappend coords [expr {$xj + $linespc}] $y1
notecrossings $p $j $i [expr {$j + 1}]
@@ -983,9 +1189,10 @@ proc drawslants {level} {
if {[lsearch -exact $dupparents $p] >= 0} {
# draw a double-width line to indicate the doubled parent
lappend coords $xj $y2
- lappend sidelines($p) [list $coords 2]
+ lappend sidelines($p) [list $coords 2 none]
if {![info exists mainline($p)]} {
set mainline($p) [list $xj $y2]
+ set mainlinearrow($p) none
}
} else {
# normal case, no parent duplicated
@@ -999,24 +1206,25 @@ proc drawslants {level} {
lappend coords $xj $yb
}
set mainline($p) $coords
+ set mainlinearrow($p) none
} else {
lappend coords $xj $yb
if {$yb < $y2} {
lappend coords $xj $y2
}
- lappend sidelines($p) [list $coords 1]
+ lappend sidelines($p) [list $coords 1 none]
}
}
}
} else {
set j $i
- if {[lindex $todo $i] != $id} {
- set j [lsearch -exact $todo $id]
+ if {[lindex $displist $i] != $id} {
+ set j [lsearch -exact $displist $id]
}
if {$j != $i || $xspc1($lineno) != $xspc1($lj)
- || ($oldlevel <= $i && $i <= $level)
- || ($level <= $i && $i <= $oldlevel)} {
- set xj [xcoord $j $level $lj]
+ || ($olddlevel <= $i && $i <= $dlevel)
+ || ($dlevel <= $i && $i <= $olddlevel)} {
+ set xj [xcoord $j $dlevel $lj]
set dx [expr {abs($xi - $xj)}]
set yb $y2
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}} {
- global parents children nchildren ncleft todo
- global canv canv2 canv3 mainfont namefont canvy linespc
+ global ncleft todo
global datemode cdate
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
set todol [llength $todo]
@@ -1076,73 +1415,43 @@ proc decidenext {{noread 0}} {
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
}
proc drawcommit {id} {
global phase todo nchildren datemode nextupdate
- global startcommits numcommits ncmupdate
+ global numcommits ncmupdate displayorder todo onscreen
if {$phase != "incrdraw"} {
set phase incrdraw
- set todo $id
- set startcommits $id
+ set displayorder {}
+ set todo {}
initgraph
- drawcommitline 0
- updatetodo 0 $datemode
- } else {
- if {$nchildren($id) == 0} {
- lappend todo $id
- lappend startcommits $id
+ }
+ if {$nchildren($id) == 0} {
+ lappend todo $id
+ set onscreen($id) 0
+ }
+ set level [decidenext 1]
+ if {$level == {} || $id != [lindex $todo $level]} {
+ return
+ }
+ while 1 {
+ lappend displayorder [lindex $todo $level]
+ if {[updatetodo $level $datemode]} {
+ set level [decidenext 1]
+ if {$level == {}} break
}
- set level [decidenext 1]
- if {$level == {} || $id != [lindex $todo $level]} {
- return
- }
- while 1 {
- drawslants $level
- drawcommitline $level
- if {[updatetodo $level $datemode]} {
- set level [decidenext 1]
- if {$level == {}} break
- }
- set id [lindex $todo $level]
- if {![info exists commitlisted($id)]} {
- break
- }
- if {[clock clicks -milliseconds] >= $nextupdate
- && $numcommits >= $ncmupdate} {
- doupdate 1
- if {$stopped} break
- }
+ set id [lindex $todo $level]
+ if {![info exists commitlisted($id)]} {
+ break
}
}
+ drawmore 1
}
proc finishcommits {} {
global phase
- global startcommits
global canv mainfont ctext maincursor textcursor
if {$phase != "incrdraw"} {
@@ -1151,9 +1460,7 @@ proc finishcommits {} {
-font $mainfont -tags textitems
set phase {}
} else {
- set level [decidenext]
- drawslants $level
- drawrest $level [llength $startcommits]
+ drawrest
}
. config -cursor $maincursor
settextcursor $textcursor
@@ -1171,54 +1478,38 @@ proc settextcursor {c} {
}
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 nextupdate [expr $startmsecs + 100]
set ncmupdate 1
initgraph
- set todo [lindex $startcommits 0]
- drawrest 0 1
+ foreach id $displayorder {
+ set onscreen($id) 0
+ }
+ drawmore 0
}
-proc drawrest {level startix} {
+proc drawrest {} {
global phase stopped redisplaying selectedline
- global datemode currentparents todo
+ global datemode todo displayorder
global numcommits ncmupdate
- global nextupdate startmsecs startcommits idline
+ global nextupdate startmsecs idline
+ set level [decidenext]
if {$level >= 0} {
set phase drawgraph
- set startid [lindex $startcommits $startix]
- set startline -1
- if {$startid != {}} {
- set startline $idline($startid)
- }
while 1 {
- if {$stopped} break
- drawcommitline $level
+ lappend displayorder [lindex $todo $level]
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} {
set level [decidenext]
if {$level < 0} break
- drawslants $level
- }
- if {[clock clicks -milliseconds] >= $nextupdate
- && $numcommits >= $ncmupdate} {
- doupdate 0
}
}
+ drawmore 0
}
set phase {}
set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
@@ -1730,7 +2021,7 @@ proc commit_descriptor {p} {
proc selectline {l isnew} {
global canv canv2 canv3 ctext commitinfo selectedline
global lineid linehtag linentag linedtag
- global canvy0 linespc parents nparents children nchildren
+ global canvy0 linespc parents nparents children
global cflist currentid sha1entry
global commentend idtags idline
@@ -2654,12 +2945,13 @@ proc listboxsel {} {
proc setcoords {} {
global linespc charspc canvx0 canvy0 mainfont
- global xspc1 xspc2
+ global xspc1 xspc2 lthickness
set linespc [font metrics $mainfont -linespace]
set charspc [font measure $mainfont "m"]
set canvy0 [expr 3 + 0.5 * $linespc]
set canvx0 [expr 3 + 0.5 * $linespc]
+ set lthickness [expr {int($linespc / 9) + 1}]
set xspc1(0) $linespc
set xspc2 $linespc
}
@@ -3170,6 +3462,7 @@ set textfont {Courier 9}
set findmergefiles 0
set gaudydiff 0
set maxgraphpct 50
+set maxwidth 16
set colors {green red blue magenta darkgrey brown orange}
@@ -3202,4 +3495,5 @@ set patchnum 0
setcoords
makewindow
readrefs
+readgrafts
getcommits $revtreeargs