{"thread":{"id":"12968","subject":"[PATCH 1/1] Import git-forest","startedAt":"2008-04-02T20:58:14Z","lastAt":"2008-04-03T10:14:18Z","messageCount":8,"participants":["Jan Engelhardt","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"299041","messageId":"1207169895-25949-1-git-send-email-jengelh@computergmbh.de","threadId":"12968","inReplyTo":null,"subject":"[announce+patch] git-forest 20080402","fromName":"Jan Engelhardt","fromEmail":"jengelh@computergmbh.de","sentAt":"2008-04-02T20:58:14Z","receivedAt":"2008-04-02T20:58:14Z","isPatch":true,"sender":{"key":"jengelh@computergmbh.de","avatar":null},"body":"\nHi,\n\n\nhere is the current snapshot of git-forest, a text-based tree \nvisualizer, as a patch to the git.git/contrib/ directory.\n\nWhat's new since the last posting is that it now displays [HEAD]\nalong with a commit, since HEAD does not always need to be the\nfirst commit that is graphed.\n    The --all option now includes graphing a detached HEAD, as can\nhappen on switching to a non-branch and during rebases.\n    Speaking of rebases, git-forest will now also show where you are in \na rebase operation -- quite handy if you forget whether you actually are \nin one (happened to me time and again and when you finally notice, you \nneed to play with HEAD@{x} to restore it) -- it can be suppressed \nwith --no-rebase.\n\nI updated the screenshot at \nhttp://jengelh.hopto.org/images/git-forest.png (URL unchanged).\nColor-agnostic people may use the --no-color option. (Tag colors \nfollow gitk as far as the 16 colors permit.)\n\nThe direct grab URL for the script is still\nhttp://dev.computergmbh.de/gitweb.cgi?p=hxtools;a=blob_plain;f=bin/git-forest\nbut of course a patch is provided below with the intent of getting it \ninto contrib/ at least.\n\n\nthanks,\nJan\n\nN.B.: This was a ridiculous command to get it right...\ncan't this be done easier?\n`git-format-patch -C -M --stat=72 --summary -p --thread -n HEAD^..HEAD &&\ngit-send-email --suppress-from --no-chain --compose --to git@xxx 00*`\n"},{"id":"73567","messageId":"9aca54e6e106be3f26ae289606b9a47a91806d54.1207169779.git.jengelh@computergmbh.de","threadId":"12968","inReplyTo":"1207169895-25949-1-git-send-email-jengelh@computergmbh.de","subject":"[PATCH 1/1] Import git-forest","fromName":"Jan Engelhardt","fromEmail":"jengelh@computergmbh.de","sentAt":"2008-04-02T20:58:15Z","receivedAt":"2008-04-02T20:58:15Z","isPatch":true,"sender":{"key":"jengelh@computergmbh.de","avatar":null},"body":"Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>\n---\n contrib/git-forest/git-forest     |  422 +++++++++++++++++++++++++++++\n contrib/git-forest/git-forest.txt |   53 ++++\n 2 files changed, 475 insertions(+), 0 deletions(-)\n create mode 100755 contrib/git-forest/git-forest\n create mode 100644 contrib/git-forest/git-forest.txt\n\ndiff --git a/contrib/git-forest/git-forest b/contrib/git-forest/git-forest\nnew file mode 100755\nindex 0000000..c38b218\n--- /dev/null\n+++ b/contrib/git-forest/git-forest\n@@ -0,0 +1,422 @@\n+#!/usr/bin/perl\n+#\n+#\tgit-æ£®æ\n+#\ttext-based tree visualisation\n+#\tCopyright Â© Jan Engelhardt <jengelh [at] gmx de>, 2008\n+#\n+#\tThis program is free software; you can redistribute it and/or modify\n+#\tit under the terms of the GNU General Public License as published by\n+#\tthe Free Software Foundation; either version 2 or 3 of the license.\n+#\n+use Getopt::Long;\n+use Git;\n+use strict;\n+use encoding \"utf8\";\n+my $Repo     = Git->repository($ENV{\"GIT_DIR\"} || \".\");\n+my $Show_all = 0;\n+my $Show_rebase = 1;\n+my $Style    = 2;\n+my $With_sha = 0;\n+my %Color    = (\n+\t\"default\" => \"\\e[0m\",\n+\t\"at\"      => \"\\e[1;30m\",\n+\t\"hhead\"   => \"\\e[1;31m\",\n+\t\"head\"    => \"\\e[1;32m\",\n+\t\"ref\"     => \"\\e[1;34m\",\n+\t\"remote\"  => \"\\e[1;35m\",\n+\t\"sha\"     => \"\\e[0;31m\",\n+\t\"tag\"     => \"\\e[1;33m\",\n+\t\"tree\"    => \"\\e[0;33m\",\n+);\n+\n+&main();\n+\n+sub main ()\n+{\n+\t&Getopt::Long::Configure(qw(bundling pass_through));\n+\t&GetOptions(\n+\t\t\"all\"      => \\$Show_all,\n+\t\t\"no-color\" => sub { %Color = (); },\n+\t\t\"no-rebase\" => sub { $Show_rebase = 0; },\n+\t\t\"style=i\"  => \\$Style,\n+\t\t\"sha\"      => \\$With_sha,\n+\t);\n+\tif ($Show_all) {\n+\t\tunshift(@ARGV, \"--all\", \"HEAD\");\n+\t}\n+\t&process();\n+}\n+\n+sub process ()\n+{\n+\tmy(@vine);\n+\tmy $refs = &get_refs();\n+\tmy($fh, $fhc) = $Repo->command_output_pipe(\"log\", \"--date-order\",\n+\t                \"--pretty=format:<%H><%h><%P>%s\", @ARGV);\n+\n+\twhile (defined(my $line = <$fh>)) {\n+\t\tchomp $line;\n+\t\tmy($sha, $mini_sha, $parents, $msg) =\n+\t\t\t($line =~ /^<(.*?)><(.*?)><(.*?)>(.*)/s);\n+\t\tmy @parents = split(\" \", $parents);\n+\n+\t\t&vine_branch(\\@vine, $sha);\n+\t\tmy $ra = &vine_commit(\\@vine, $sha, \\@parents);\n+\n+\t\tif (exists($refs->{$sha})) {\n+\t\t\tprint &vis_post(&vis_commit($ra,\n+\t\t\t      $Color{at}.\"â\".$Color{default}));\n+\t\t\t&ref_print($refs->{$sha});\n+\t\t} else {\n+\t\t\tprint &vis_post(&vis_commit($ra, \" \"));\n+\t\t}\n+\t\tif ($With_sha) {\n+\t\t\tprint $msg, $Color{at}, \"ââ(\", $Color{sha}, $mini_sha,\n+\t\t\t      $Color{at}, \")\", $Color{default}, \"\\n\";\n+\t\t} else {\n+\t\t\tprint $msg, \"\\n\";\n+\t\t}\n+\n+\t\t&vine_merge(\\@vine, $sha, \\@parents);\n+\t}\n+\t$Repo->command_close_pipe($fh, $fhc);\n+}\n+\n+sub get_refs ()\n+{\n+\tmy($fh, $c) = $Repo->command_output_pipe(\"show-ref\");\n+\tmy $ret = {};\n+\n+\twhile (defined(my $ln = <$fh>)) {\n+\t\tchomp $ln;\n+\t\tif (length($ln) == 0) {\n+\t\t\tnext;\n+\t\t}\n+\n+\t\tmy($sha, $name) = ($ln =~ /^(\\S+)\\s+(.*)/s);\n+\t\tif (!exists($ret->{$sha})) {\n+\t\t\t$ret->{$sha} = [];\n+\t\t}\n+\t\tpush(@{$ret->{$sha}}, $name);\n+\t\tif ($name =~ m{^refs/tags/}) {\n+\t\t\tmy $sub_sha = $Repo->command(\"log\", \"-1\",\n+\t\t\t              \"--pretty=format:%H\", $name);\n+\t\t\tchomp $sub_sha;\n+\t\t\tif ($sha ne $sub_sha) {\n+\t\t\t\tpush(@{$ret->{$sub_sha}}, $name);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t$Repo->command_close_pipe($fh, $c);\n+\n+\tmy $rebase = -e $Repo->repo_path().\"/.dotest-merge/git-rebase-todo\" &&\n+\t             $Show_rebase;\n+\tif ($rebase) {\n+\t\tmy $up  = $Repo->command(\"rev-parse\", \".dotest-merge/upstream\");\n+\t\tmy $old = $Repo->command(\"rev-parse\", \".dotest-merge/head\");\n+\t\tchomp $up;\n+\t\tchomp $old;\n+\t\tunshift(@{$ret->{$up}}, \"rebase/upstream\");\n+\t\tunshift(@{$ret->{$old}}, \"rebase/old-HEAD\");\n+\t}\n+\n+\tmy $head = $Repo->command(\"rev-parse\", \"HEAD\");\n+\tchomp $head;\n+\tif ($rebase) {\n+\t\tunshift(@{$ret->{$head}}, \"rebase/inprogress\");\n+\t}\n+\tunshift(@{$ret->{$head}}, \"HEAD\");\n+\n+\treturn $ret;\n+}\n+\n+sub ref_print ($)\n+{\n+\tforeach my $symbol (@{shift @_}) {\n+\t\tprint $Color{at}, \"[\";\n+\t\tif ($symbol eq \"HEAD\" || $symbol =~ m{^rebase/}) {\n+\t\t\tprint $Color{hhead}, $symbol;\n+\t\t} elsif ($symbol =~ m{^refs/(remotes/[^/]+)/(.*)}s) {\n+\t\t\tprint $Color{remote}, $1, $Color{head}, \"/$2\";\n+\t\t} elsif ($symbol =~ m{^refs/heads/(.*)}s) {\n+\t\t\tprint $Color{head}, $1;\n+\t\t} elsif ($symbol =~ m{^refs/tags/(.*)}s) {\n+\t\t\tprint $Color{tag}, $1;\n+\t\t} elsif ($symbol =~ m{^refs/(.*)}s) {\n+\t\t\tprint $Color{ref}, $1;\n+\t\t}\n+\t\tprint $Color{at}, \"]ââ\", $Color{default};\n+\t}\n+}\n+\n+sub vine_branch ($$)\n+{\n+\tmy($vine, $rev) = @_;\n+\tmy $idx;\n+\n+\tmy $left = \"â \";\n+\tmy $matched = 0;\n+\tmy $ret;\n+\n+\tfor ($idx = 0; $idx < scalar(@$vine); ++$idx) {\n+\t\tif (!defined($vine->[$idx])) {\n+\t\t\t$ret .= \"â\";\n+\t\t\tnext;\n+\t\t} elsif ($vine->[$idx] ne $rev) {\n+\t\t\t$ret .= \"âª\";\n+\t\t\tnext;\n+\t\t}\n+\t\tif ($matched == 0) {\n+\t\t\t$ret .= \"â \";\n+\t\t} else {\n+\t\t\t$ret .= \"â©\";\n+\t\t\t$vine->[$idx] = undef;\n+\t\t}\n+\t\t++$matched;\n+\t}\n+\n+\tif ($matched < 2) {\n+\t\treturn;\n+\t}\n+\n+\twhile (!defined($vine->[$#$vine])) {\n+\t\tpop(@$vine);\n+\t}\n+\n+\tprint &vis_post(&vis_branch($ret)), \"\\n\";\n+}\n+\n+sub vine_commit ($$$)\n+{\n+\tmy($vine, $rev, $parents) = @_;\n+\tmy $ret;\n+\n+\tfor (my $i = 0; $i <= $#$vine; ++$i) {\n+\t\tif (!defined($vine->[$i])) {\n+\t\t\t$ret .= \" \";\n+\t\t} elsif ($vine->[$i] eq $rev) {\n+\t\t\t$ret .= \"â\";\n+\t\t} else {\n+\t\t\t$ret .= \"â\";\n+\t\t}\n+\t}\n+\n+\tif ($ret !~ /â/) {\n+\t\t# Not having produced a â before means this is a HEAD\n+\t\t$ret .= \"â\";\n+\t\tpush(@$vine, $rev);\n+\t}\n+\n+\twhile (scalar(@$vine) > 0 && !defined($vine->[$#$vine])) {\n+\t\tpop(@$vine);\n+\t}\n+\n+\tif (scalar(@$parents) == 0) {\n+\t\t# tree root\n+\t\t$ret =~ s/â/â/g;\n+\t}\n+\n+\treturn $ret;\n+}\n+\n+#\n+#\tGenerate vine graphics for a merge\n+#\n+sub vine_merge ($$$)\n+{\n+\tmy($vine, $rev, $parents) = @_;\n+\tmy $orig_vine = -1;\n+\tmy @slot;\n+\tmy($ret, $max);\n+\n+\tfor (my $i = 0; $i <= $#$vine; ++$i) {\n+\t\tif ($vine->[$i] eq $rev) {\n+\t\t\t$orig_vine = $i;\n+\t\t\tlast;\n+\t\t}\n+\t}\n+\n+\tif ($orig_vine == -1) {\n+\t\tdie \"vine_commit() did not add this vine.\";\n+\t}\n+\n+\tif (scalar(@$parents) <= 1) {\n+\t\t#\n+\t\t# A single parent does not need a visual. Update and return.\n+\t\t#\n+\t\t$vine->[$orig_vine] = $parents->[0];\n+\n+\t\twhile (scalar(@$vine) > 0 && !defined($vine->[$#$vine])) {\n+\t\t\tpop(@$vine);\n+\t\t}\n+\t\treturn;\n+\t}\n+\n+\t#\n+\t# Find some good spots to split out into.\n+\t#\n+\tpush(@slot, $orig_vine);\n+\tmy $parent = 0;\n+\n+\tfor (my $seeker = 2; $parent < $#$parents &&\n+\t    $seeker < 2 + 2 * $#$vine; ++$seeker)\n+\t{\n+\t\tmy $idx = ($seeker % 2 == 0) ? -1 : 1;\n+\t\t$idx   *= int($seeker / 2);\n+\t\t$idx   += $orig_vine;\n+\n+\t\tif ($idx >= 0 && $idx <= $#$vine && !defined($vine->[$idx])) {\n+\t\t\tpush(@slot, $idx);\n+\t\t\t++$parent;\n+\t\t}\n+\t}\n+\tfor (my $idx = $orig_vine + 1; $parent < $#$parents; ++$idx) {\n+\t\tif (!defined($vine->[$idx])) {\n+\t\t\tpush(@slot, $idx);\n+\t\t\t++$parent;\n+\t\t}\n+\t}\n+\n+\tif (scalar(@slot) != scalar(@$parents)) {\n+\t\tdie \"Serious internal problem\";\n+\t}\n+\n+\t@slot = sort { $a <=> $b } @slot;\n+\t$max  = scalar(@$vine) + scalar(@slot);\n+\n+\tfor (my $i = 0; $i < $max; ++$i) {\n+\t\tif ($#slot >= 0 && $i == $slot[0]) {\n+\t\t\tshift @slot;\n+\t\t\t$vine->[$i] = shift @$parents;\n+\t\t\t$ret .= ($i == $orig_vine) ? \"S\" : \"s\";\n+\t\t} elsif (defined($vine->[$i])) {\n+\t\t\t$ret .= \"â\";\n+\t\t} else {\n+\t\t\t$ret .= \" \";\n+\t\t}\n+\n+\t}\n+\n+\t$ret =~ s/ +$//gs;\n+\tprint &vis_post(&vis_merge($ret)), \"\\n\";\n+}\n+\n+sub vis_branch ($)\n+{\n+\t# Sample input: â¬ââ â¬â¬â¬â©â¬ââ¬â¬â¬â¬â¬â¬â©â¬â©ââ¬â¬\n+\tmy $ra = shift @_;\n+\tmy $i;\n+\n+\t$ra =~ s{^(.+?)â }{\n+\t\t$_ = $1;\n+\t\t$_ =~ tr/âªâ/â /;\n+\t\t$_ =~ s/(.)/$1 /gs;\n+\t\t$_ .= 'â ';\n+\t}es;\n+\t$ra =~ s{(â .*)â©}{\n+\t\t$_ = $1;\n+\t\t$_ =~ s/(.)/$1â/gs;\n+\t\t$_ .= 'â';\n+\t}es;\n+\t$ra =~ s{â(.*)$}{\n+\t\t$_ = $1;\n+\t\t$_ =~ tr/âªâ/â /;\n+\t\t$_ =~ s/(.)/$1 /gs;\n+\t\t$_ = \"â $_\";\n+\t}es;\n+\treturn $ra;\n+}\n+\n+sub vis_commit ($$)\n+{\n+\tmy($ra, $sep) = @_;\n+\tmy($l, $r) = ($ra =~ /^(.*?)([âââ].*)/);\n+\t$l =~ s/(.)/$1 /gs;\n+\t$r =~ s/(.)/$1 /gs;\n+\t$r =~ s/ /$sep/gs;\n+\treturn $l.$r;\n+}\n+\n+sub vis_merge ($)\n+{\n+\tmy $s = shift @_;\n+\n+\tif ($s =~ s/(s.*)S(.*s)/&vis_merge3($1, $2)/es) {\n+\t\t;\n+\t} elsif ($s =~ /(?:s.*)S/s) {\n+\t\twhile ($s =~ s/(s.*)â(.*S)/$1âª$2/s) {\n+\t\t\t;\n+\t\t}\n+\t\t$s =~ s/(s.*)S/&vis_merge2L($1).\"â£\"/es;\n+\t} elsif ($s =~ /S(?:.*s)/s) {\n+\t\twhile ($s =~ s/(S.*)â(.*s)/$1âª$2/s) {\n+\t\t\t;\n+\t\t}\n+\t\t$s =~ /S(.*s)/;\n+\t\t$s =~ s/S(.*s)/\"â \".&vis_merge2R($1)/es;\n+\t} else {\n+\t\t# $s =~ s/S/â/s;\n+\t\tdie \"Should not come here\";\n+\t}\n+\t$s =~ s{(.)}{&vis_merge1($1)}egs;\n+\treturn $s;\n+}\n+\n+sub vis_merge1 ($)\n+{\n+\tif ($_[0] eq \"â\" || $_[0] eq \"â¦\" || $_[0] eq \"â \" || $_[0] eq \"âª\") {\n+\t\treturn $_[0].\"â\";\n+\t} else {\n+\t\treturn $_[0].\" \";\n+\t}\n+}\n+\n+sub vis_merge2L ($)\n+{\n+\tmy $l = shift @_;\n+\t$l =~ s/^s/â/;\n+\t$l =~ s/s/â¦/g;\n+\treturn $l;\n+}\n+\n+sub vis_merge2R ($)\n+{\n+\tmy $r = shift @_;\n+\t$r =~ s/s$/â/;\n+\t$r =~ s/s/â¦/g;\n+\treturn $r;\n+}\n+\n+sub vis_merge3 ($$)\n+{\n+\tmy($l, $r) = shift @_;\n+\t$l =~ s/^s/â/;\n+\t$l =~ s/s/â¦/g;\n+\t$r =~ s/s$/â/;\n+\t$r =~ s/s/â¦/g;\n+\treturn \"$lâª$r\";\n+}\n+\n+#\n+#\tpost-process vine graphic\n+#\n+sub vis_post ($)\n+{\n+\tmy $s = shift @_;\n+\n+\tif ($Style == 1) {\n+\t\t$s =~ tr/ââ¦ââ â¬â£ââ©âââââââª/ââ¬âââ¼â¤ââ´âââââââ¼/;\n+\t} elsif ($Style == 2) {\n+\t\t$s =~ tr/âª/â¬/;\n+\t} elsif ($Style == 3) {\n+\t\t$s =~ tr/ââ¦ââ â¬â£ââ©âââââ/ââ¤âââªâ¡ââ§âââââ/;\n+\t} elsif ($Style == 4) {\n+\t\t$s =~ tr/ââ¦ââ â¬â£ââ©ââªâ/ââ¥âââ«â¢ââ¨ââ«â/;\n+\t}\n+\n+\tif ($Color{default} ne \"\") {\n+\t\t$s =~ s{\\Q$Color{default}\\E}{$&$Color{tree}}g;\n+\t}\n+\treturn $Color{tree}, $s, $Color{default};\n+}\ndiff --git a/contrib/git-forest/git-forest.txt b/contrib/git-forest/git-forest.txt\nnew file mode 100644\nindex 0000000..5dfd478\n--- /dev/null\n+++ b/contrib/git-forest/git-forest.txt\n@@ -0,0 +1,53 @@\n+\n+Usage: git-forest [OPTIONS...] [REVLISTOPTIONS] [REFSPEC...]\n+\n+--no-rebase\n+\tDo not show rebase/ pseudo-refs\n+--style=1\n+\tUse single-line visuals\n+--style=2\n+\tUse double-line visuals (default)\n+--style=3\n+\tUse single-line visuals in vertical direction,\n+\tand double-line ones in horizontal direction.\n+--style=4\n+\tUse double-line visuals in vertical direction,\n+\tand single-line ones in horizontal direction.\n+--sha\n+\tDisplay SHAs for each commit\n+\n+All other options and arguments are passed down to git-log.\n+Commonly useful options are --all and --topo-order.\n+\n+Example:\n+\tgit-forest --all | less -RS\n+\tgit-forest origin/master | less -RS\n+\n+This tool does not try to minimize the empty space between branches\n+like gitk does. Take it as a feature.\n+\n+Notes on interpretation:\n+\n+Connections with four \"legs\" ('â¬' or variants thereof, like 'âª') are\n+meant to be interpreted as being connected only in the horizontal and\n+vertical direction, NOT around-the-corner.\n+\n+Connections with three or less \"legs\" ('â ', 'â©', 'â¦', etc.) imply\n+a connection to all connected directions.\n+\n+Consider the following example history. The merge at 070 has merged\n+together the branches with commits f21, 886 and 8f8, but NOT d3e.\n+\n+\tââ[HEAD]ââ[master]ââ-ââ(0c6)\n+\tâ ââ \n+\tâ â -ââ(710)\n+\tâ â -ââ(070)\n+\tâ ââ¬ââ¦ââ\n+\tâ â â â -ââ(d3e)\n+\tâ â â â -ââ(886)\n+\tâ â â â -ââ(8f8)\n+\tâ â ââ â\n+\tâ â   â -ââ(199)\n+\tâ â   â -ââ(f21)\n+\tâ ââ©ââââ \n+\tâ -ââ(15f)\n-- \n1.5.4.4\n"},{"id":"73569","messageId":"7vve3053n7.fsf@gitster.siamese.dyndns.org","threadId":"12968","inReplyTo":"9aca54e6e106be3f26ae289606b9a47a91806d54.1207169779.git.jengelh@computergmbh.de","subject":"Re: [PATCH 1/1] Import git-forest","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-04-02T21:49:00Z","receivedAt":"2008-04-02T21:49:00Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Engelhardt <jengelh@computergmbh.de> writes:\n\n\n    Content-Type: TEXT/PLAIN; charset=ISO-8859-1\n\n> +#\tgit-??????\n\nHmmmm...\n\n> +&main();\n> +\n> +sub main ()\n> +{\n> +\t&Getopt::Long::Configure(qw(bundling pass_through));\n> +\n> +\t&GetOptions(\n> +\t\t\"all\"      => \\$Show_all,\n> +\t\t\"no-color\" => sub { %Color = (); },\n> +\t\t\"no-rebase\" => sub { $Show_rebase = 0; },\n> +\t\t\"style=i\"  => \\$Style,\n> +\t\t\"sha\"      => \\$With_sha,\n> +\t);\n> +\tif ($Show_all) {\n> +\t\tunshift(@ARGV, \"--all\", \"HEAD\");\n> +\t}\n> +\t&process();\n> +}\n\nThis is a Perl script with a curious style.  Your subroutines force the\n\"funny\" parameter semantics to their callers by using prototypes, but\navoid the potential surprises and inconveniences prototypes may cause by\nusing the &name(...) form when they themselves make subroutine calls,\ni.e. not eating their own dog food.\n\nIs it fashionable to make text based tree render these days?  How does\nthis compare with the git-graph in the nearby thread?  Can they borrow\nfrom each other?\n"},{"id":"73579","messageId":"alpine.LNX.1.10.0804030231180.26216@fbirervta.pbzchgretzou.qr","threadId":"12968","inReplyTo":"7vve3053n7.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Import git-forest (20080403)","fromName":"Jan Engelhardt","fromEmail":"jengelh@computergmbh.de","sentAt":"2008-04-03T07:27:50Z","receivedAt":"2008-04-03T07:27:50Z","isPatch":true,"sender":{"key":"jengelh@computergmbh.de","avatar":null},"body":"\nOn Wednesday 2008-04-02 23:49, Junio C Hamano wrote:\n> Jan Engelhardt <jengelh@computergmbh.de> writes:\n>\n>    Content-Type: TEXT/PLAIN; charset=ISO-8859-1\n>\n>> +#\tgit-??????\n>\n> Hmmmm...\n\nA git-send-email bug it seems. It does not add any Content-Type header\nthereby effectively trashing UTF-8. How wonderful. Explains a many \ncorrumped patches on LKML (and subsequently, the git history).\n\n> This is a Perl script with a curious style.  Your subroutines force the\n> \"funny\" parameter semantics to their callers by using prototypes, but\n> avoid the potential surprises and inconveniences prototypes may cause by\n> using the &name(...) form when they themselves make subroutine calls,\n> i.e. not eating their own dog food.\n\nRight, I removed that. I would have probably used PHP (perl is touted as \na write-once language), but I could not be sure everyone has _that_ \ninstalled. Perl, most people have it.\n\n> Is it fashionable to make text based tree render these days?\n\n \tSame arguments as last time :>\nDefinitely. Do not assume everyone has an X display ready at any given \ntime. Also, gitk does a Follows/Precedes scan which would not really be \nnecessary if you just wanted to have the commit forest.\n\n> How does this compare with the git-graph in the nearby thread?\n\ngit-forest does have...\n- unicode/line-drawing graphics, colors\n- display of signs like gitk, that is, ref names like  ──[v2.6.25-rc7],\n   ──[remotes/linus/master], ──[original/filtered-branch] etc.\n- display detached HEAD and its parents when --all is given\n- track in-progress rebase\n\ndifferences:\n- graph does space reduction between vines\n- git-forest keeps a vine in its column right now - this way\n   you can point the mouse on it, scroll down until its end and\n   keep track of it. (Diagonal art would require adjusting the\n   mouse position, which is error prone in complex history\n   like linux.)\n\n> Can they borrow from each other?\n\nMh, I have uptaken some suggestions from the git-graph code: support\nfor --pretty and --reverse. Did not take very long (and if you look\nat the git log for hxtools you can see it's criminally small\npatches :-)\n\n-- \nmake boldconfig -- to boldly select what no one has selected before\n"},{"id":"73580","messageId":"7vej9n49jn.fsf@gitster.siamese.dyndns.org","threadId":"12968","inReplyTo":"alpine.LNX.1.10.0804030231180.26216@fbirervta.pbzchgretzou.qr","subject":"Re: [PATCH] Import git-forest (20080403)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-04-03T08:39:08Z","receivedAt":"2008-04-03T08:39:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Engelhardt <jengelh@computergmbh.de> writes:\n\n> On Wednesday 2008-04-02 23:49, Junio C Hamano wrote:\n>> Jan Engelhardt <jengelh@computergmbh.de> writes:\n>>\n>>    Content-Type: TEXT/PLAIN; charset=ISO-8859-1\n>>\n>>> +#\tgit-??????\n>>\n>> Hmmmm...\n>\n> A git-send-email bug it seems.\n\nDo we know if it has been fixed?  I see you used 1.5.4.4.\n\nBy the way, this time you are speaking Russian ;-)\n\n    Content-Type: TEXT/PLAIN; charset=KOI8-R; format=flowed\n\n>> Can they borrow from each other?\n>\n> Mh, I have uptaken some suggestions from the git-graph code: support\n> for --pretty and --reverse.\n\nGood.  Let's see who survives ;-)\n"},{"id":"73583","messageId":"alpine.LNX.1.10.0804031054530.24458@fbirervta.pbzchgretzou.qr","threadId":"12968","inReplyTo":"7vej9n49jn.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Import git-forest (20080403)","fromName":"Jan Engelhardt","fromEmail":"jengelh@computergmbh.de","sentAt":"2008-04-03T09:03:30Z","receivedAt":"2008-04-03T09:03:30Z","isPatch":true,"sender":{"key":"jengelh@computergmbh.de","avatar":null},"body":"\nOn Thursday 2008-04-03 10:39, Junio C Hamano wrote:\n>>>    Content-Type: TEXT/PLAIN; charset=ISO-8859-1\n>>>> +#\tgit-??????\n>>> Hmmmm...\n>> A git-send-email bug it seems.\n> Do we know if it has been fixed? I see you used 1.5.4.4\n\nI hope you know, you are the git maintainer. :)\nYes, 1.5.4.4 from opensuse.\n>\n> By the way, this time you are speaking Russian ;-)\n>\n>    Content-Type: TEXT/PLAIN; charset=KOI8-R; format=flowed\n\ncurses to alpine... but that still does not change the\nfact that send-email/1.5.4.4 completely forget the header.\n\n\n-- \nmake boldconfig -- to boldly select what no one has selected before\n"},{"id":"73591","messageId":"20080403100344.GB6673@coredump.intra.peff.net","threadId":"12968","inReplyTo":"7vej9n49jn.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Import git-forest (20080403)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-04-03T10:03:44Z","receivedAt":"2008-04-03T10:03:44Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Apr 03, 2008 at 01:39:08AM -0700, Junio C Hamano wrote:\n\n> >>    Content-Type: TEXT/PLAIN; charset=ISO-8859-1\n> >>\n> >>> +#\tgit-??????\n> >>\n> >> Hmmmm...\n> >\n> > A git-send-email bug it seems.\n> \n> Do we know if it has been fixed?  I see you used 1.5.4.4.\n\nI think the problem is that the characters are in the _patch_. We do the\nright thing for the commit message, SoB, and all headers, but we have\nalways just assumed the patch was OK, since we have no encoding\ninformation on the files (and worse, if we have a _different_ encoding\nfor the commit message versus the diff content, we will have to\nre-encode something or make it an attachment).\n\n-Peff\n"},{"id":"73592","messageId":"20080403101418.GC6673@coredump.intra.peff.net","threadId":"12968","inReplyTo":"1207169895-25949-1-git-send-email-jengelh@computergmbh.de","subject":"Re: [announce+patch] git-forest 20080402","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-04-03T10:14:18Z","receivedAt":"2008-04-03T10:14:18Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Apr 02, 2008 at 10:58:14PM +0200, Jan Engelhardt wrote:\n\n> N.B.: This was a ridiculous command to get it right...\n> can't this be done easier?\n> `git-format-patch -C -M --stat=72 --summary -p --thread -n HEAD^..HEAD &&\n> git-send-email --suppress-from --no-chain --compose --to git@xxx 00*`\n\nMost of the time you don't need -C -M (unless you are actually renaming\nstuff). If you always want it, try:\n\n  git config --global diff.renames copies\n\nformat-patch already defaults to \"--stat --summary -p\" if you give it no\nformat options. The default stat is 80, I believe; for format-patch it\nshould probably be bumped to 72 anyway. format-patch will also default\nto ..HEAD if just given HEAD^.\n\nSo you should be able to do:\n\n  git format-patch --thread -n HEAD^\n\nFor your send-email invocation, doing:\n\n  git config --global sendemail.suppressfrom true\n  git config --global sendemail.chainreplyto false\n  # the --global makes the others user-wide; this\n  # one should just be specific to your git repo\n  git config sendemail.to git@vger.kernel.org\n\nshould allow:\n\n  git sendemail --compose 00*\n\nthough if you are just sending a single patch, it is common to put the\ncover letter material (if it is short) after the '---' but before the\ndiffstat.\n\nHTH,\n-Peff\n"}]}