WIP: hg fast-export
[git/dscho.git] / my-asciiart.perl
bloba6a28014e159ecb17038110963533f8623394079
1 #!/usr/bin/perl
3 if ($#ARGV < 1) {
4 print STDERR "Usage: $ARGV0 <revision range>\n";
5 exit(1);
8 open INPUT, 'git rev-list --parents ' . join(' ', @ARGV) . '|';
10 %commits=();
11 @list=();
13 sub add_parents ($$) {
14 my $parents = $_[0];
15 my $y = $_[1];
16 foreach my $parent (split / /,$parents) {
17 if ($commits->{$parent} == undef) {
18 $commits->{$parent} = {
19 'y' => $y++,
20 'sha1' => $parent
22 } else {
23 if ($commits->{$parent}->{y} < $y) {
24 $commits->{$parent}->{y} = $y++;
25 } else {
26 $y = $commits->{$parent}->{y} + 1;
32 # expects output of `rev-list --parents --topo-order`
33 $i = 0;
34 while (<INPUT>) {
35 if (/^([0-9a-f]{40}) ?(.*)$/) {
36 $sha1 = $1;
37 $parents = $2;
38 if ($commits->{$sha1} == undef) {
39 $commits->{$sha1} = {
40 'y' => 0,
41 'sha1' => $sha1,
43 } else {
44 $commits->{$sha1}->{index} = $#list;
46 $commits->{$sha1}->{parents} = $parents;
47 $list[$i] = $commits->{$sha1};
48 $commits->{$sha1}->{index} = $i++;
49 add_parents($parents, $commits->{$sha1}->{y});
52 close INPUT;
54 if ($#list >= 26) {
55 print STDERR "Cannot draw more than 26 revs.";
56 exit(1);
59 # make labels
60 $height = 0;
61 for ($i = 0; $i <= $#list; $i++) {
62 $list[$i]->{x} = $#list - $i;
63 $list[$i]->{label} = chr(0x41 + $list[$i]->{x});
64 if ($height < $list[$i]->{y}) {
65 $height = $list[$i]->{y};
69 # make a canvas
70 $width = $#list * 2 + 1;
71 $height = $height * 2 + 1;
72 @canvas = ();
73 for ($i = 0; $i < $height; $i++) {
74 $canvas[$i] = ' ' x $width . "\n";
77 sub set_cell ($$$) {
78 my $x = $_[0];
79 my $y = $_[1];
80 my $c = $_[2];
81 $canvas[$y] = substr($canvas[$y], 0, $x) . $c .
82 substr($canvas[$y], $x + 1);
85 sub get_cell ($$) {
86 my $x = $_[0];
87 my $y = $_[1];
88 return substr($canvas[$y], $x, 1);
91 sub msg($) {
92 my $info = $_[0];
93 return $info->{label} . ": " . $info->{x} . ", " . $info->{y};
96 sub draw_line ($$) {
97 my $commit1 = $_[0];
98 my $commit2 = $_[1];
99 my $x1 = $commit1->{x};
100 my $y1 = $commit1->{y};
101 my $x2 = $commit2->{x};
102 my $y2 = $commit2->{y};
103 if ($y1 == $y2) {
104 for (my $i = $x1 * 2 - 1; $i > $x2 * 2; $i--) {
105 set_cell($i, $y1 * 2, "-");
107 } else {
108 my $is_straight = 0;
109 my $factor = ($y2 - $y1) / ($x1 - $x2);
110 my $i;
111 if ($x1 - $x2 == $y2 - $y1) {
112 $is_straight = 1;
113 for ($i = $x1 * 2 - 1; $i > $x2 * 2; $i -= 2) {
114 my $y = $y1 * 2 + ($x1 * 2 - $i) * $factor;
115 my $c = get_cell($i, int($y));
116 if ($c ne ' ' && $c ne '-') {
117 $is_straight = 0;
121 if ($is_straight) {
122 for ($i = $x1 * 2 - 1; $i > $x2 * 2; $i--) {
123 my $y = $y1 * 2 + ($x1 * 2 - $i) * $factor;
124 my $c = (get_cell($i, int($y)) ne ' ') ?
125 '+' : '/';
126 set_cell($i, int($y), $c);
128 } else {
129 set_cell($x1 * 2 - 1, $y1 * 2 + 1, '\'');
130 for ($i = $x1 * 2 - 2; $i > $x2 * 2 + 1; $i--) {
131 set_cell($i, $y1 * 2 + 1, '-');
133 set_cell($x2 * 2 + 1, $y1 * 2 + 1, ',');
134 for ($i = $y1 * 2 + 2; $i < $y2 * 2; $i++) {
135 my $c = (get_cell($x2 * 2, $i) ne ' ') ?
136 '+' : '|';
137 set_cell($x2 * 2, $i, $c);
143 # draw it
144 for ($i = 0; $i <= $#list; $i++) {
145 $info = $list[$i];
146 $x = $info->{x} * 2;
147 $y = $info->{y} * 2;
148 set_cell ($x, $y, $info->{label});
149 foreach my $parent (split / /,$info->{parents}) {
150 if ($commits->{$parent}->{index} != undef) {
151 draw_line($info, $commits->{$parent});
156 print @canvas;