<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUcERn48eSp7ImA9Wx5TFEs.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755</id><updated>2010-07-30T16:10:07.071+12:00</updated><title>Coding Amusement.</title><subtitle type="html">Intellectual Emissions of a Crazy Guy.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.fox.geek.nz/" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/kentnl" /><feedburner:info uri="kentnl" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" /><entry gd:etag="W/&quot;CE4ESXk8eyp7ImA9Wx5TFE8.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-328107414735722485</id><published>2010-07-30T05:01:00.000+12:00</published><updated>2010-07-30T05:01:48.773+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-30T05:01:48.773+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="summary" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>Git Internals: An Executive Summary in 30 Lines of Perl, for smart newbies.</title><content type="html">&lt;strong&gt;Update: Modified code a bit to handle the 'pack' specials. They're not so straight forward, will blog more on that later. &lt;/strong&gt;

&lt;p&gt;This blog post is not intended as a replacement for a real in-depth understanding of Gits command line interface, but it does aim to maximise the exposure of how it works internally, as really, its internal logic is astoundingly simple, and anyone with a good background in graph theory and databases will pretty much be able to quickly see the elegance in it. For more details, check out the excellent book, &lt;a href="http://progit.org/book/"&gt;Pro Git&lt;/a&gt;, especially the &lt;a href="http://progit.org/book/ch9-0.html"&gt;internals chapter&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;The code&lt;/h3&gt;
&lt;p&gt;
Gits core essentials, are almost nothing more than a bunch of deflated(zlib)
text files. I'm going to assume you've got enough intelligence to RTFM and
get a  copy of something gitty and text based checked out. Perl Modules are
good examples of this. I'm using my &lt;a href="http://github.com/kentfredric/Dist-Zilla-PluginBundle-KENTNL-Lite"&gt;Dist::Zilla::PluginBundle::KENTNL::Lite&lt;/a&gt;
tree. 
&lt;/p&gt;
&lt;pre class="bash"&gt;
git clone git://github.com/kentfredric/Dist-Zilla-PluginBundle-KENTNL-Lite.git /tmp/SomeDirName
&lt;/pre&gt;
&lt;p&gt;I'm going to show you the core of git's system, which is just the "object"
store.&lt;/p&gt;
&lt;pre class="bash"&gt;
cd /tmp/SomeDirName/.git
find objects/
&lt;/pre&gt;
&lt;p&gt;Woot, there is all your files and stuff in git. How does it work? Thats
where the perl script comes in.
&lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl
use strict;
use warnings;

use Compress::Zlib;
use Carp qw( croak );

sub inflate_file {
    my ( $filename , $OFH ) = @_;
    my ( $inflator, $status ) = Compress::Zlib::inflateInit or croak("Cannot create inflator: $@");
    my $input = '';
    open my $fh, '&lt;', $filename or croak("Can't open $filename, $@ $! $?");
    binmode $fh;
    binmode $OFH;

    my ( $output );
    while ( read( $fh, $input, 4096 )) {
        ( $output , $status ) = $inflator-&gt;inflate( \$input );
        print { $OFH } $output if $status == Compress::Zlib::Z_OK or $status == Compress::Zlib::Z_STREAM_END;
        last if $status != Compress::Zlib::Z_OK;
    }
    croak( "Inflation failed of $filename , $@" ) unless $status == Compress::Zlib::Z_STREAM_END;
}

for ( @ARGV ) {
    next if $_ =~ /\.(idx|pack)|packs/;
    print qq{&lt;--------BEGIN $_ ---------&gt;\n};
    inflate_file( $_ , *STDOUT );
    print qq{&lt;--------END $_ ---------&gt;\n};

}
&lt;/pre&gt;
&lt;p&gt;Pretend you cargo-cult dump that code to &lt;code&gt;/tmp/deflate.pl&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now check this out:&lt;/p&gt;
&lt;pre class="bash"&gt;
perl /tmp/deflate.pl $( find objects/ -type f ) | cat -v | less
&lt;/pre&gt;
&lt;p&gt;Awesome, you're now seeing the guts of how your repository works. For real.
All we did was deflate each and every object. You'll see 3 types of object, (
each object says at the front what type they are before the ^@ ), tree's,
blobs, and commits ( with trees being the most complicated of all ).
&lt;/p&gt;
&lt;p&gt;Blobs, they're just a files contents&lt;/p&gt;
&lt;p&gt;Commits, all they are is a blob of text, with commit messages and stuff,
  timestamps, etc, and with text references (pretend its like an a-href in a
  web page or something ) to preceding ( parent ) commits, and a commit
  tree.&lt;/p&gt;
&lt;p&gt;Trees are probably the hardest to work out just by looking at it. Its more
or less just another text file, with another list of text references, except
text references are pointing at either blobs, or other trees. So, you can
pretend a "tree" is like a "dir" in some ways. There's data besides this, like
file/dir names, and permissions, but thats the gist of it. &lt;/p&gt;
&lt;p&gt;This has been your executive summary =)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-328107414735722485?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Oa7TbBW9uSMuyy6w-XSHLo9K6GA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Oa7TbBW9uSMuyy6w-XSHLo9K6GA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Oa7TbBW9uSMuyy6w-XSHLo9K6GA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Oa7TbBW9uSMuyy6w-XSHLo9K6GA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/9Z3tEwAKHdk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/328107414735722485/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/07/git-internals-executive-summary-in-30.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/328107414735722485?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/328107414735722485?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/9Z3tEwAKHdk/git-internals-executive-summary-in-30.html" title="Git Internals: An Executive Summary in 30 Lines of Perl, for smart newbies." /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/07/git-internals-executive-summary-in-30.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04MQn05fip7ImA9WxFaFEQ.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-8094350727641886790</id><published>2010-07-19T01:34:00.001+12:00</published><updated>2010-07-19T11:33:03.326+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-19T11:33:03.326+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="limitations" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="exceptions" /><title>Current Limitations In Exception Driven Perl: Stringy Core Exceptions</title><content type="html">&lt;p&gt;Lets just assume for one moment that we have a proper &lt;a href="/2010/07/current-limitations-in-exception-driven.html"&gt;Exception Hierarchy&lt;/a&gt;, and that this wasn't a huge gaping hole in the current Exception landscape.
&lt;/p&gt;&lt;p&gt;
There's still the other problem of so much Perl code being not designed in Exception friendly ways.
&lt;/p&gt;
&lt;p&gt;
&lt;code&gt;die "$string"&lt;/code&gt;and &lt;code&gt;croak "$string"&lt;/code&gt; is about as detailed as you get from most things.
&lt;/p&gt;
&lt;p&gt;And I'm sure everyone agrees that only passes for the bare minimum of exception handling techniques. No benefits of runtime stack introspection ( &lt;B&gt;Edit:&lt;/B&gt; Ok, not without mangling sigdie, yuck ), re-throwing exceptions without losing the source failure point ( &lt;b&gt;Edit&lt;/b&gt;: to clarify, not all 'die' calls are represented in the error ), let alone problem classification without resorting to regexing' the failure string. ( and that's far from reliable, considering those strings are targeted at humans, not machines, so are prone to being modified at a time later in life in a way your regex won't recognise, breaking your code ).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://p3rl.org/autodie"&gt;autodie&lt;/a&gt; is a good &lt;em&gt;start&lt;/em&gt; to solving this problem, it doesn't have all the  bells and whistles I'd hoped for, it has an &lt;a href="http://search.cpan.org/~pjf/autodie-2.10/lib/autodie.pm#CATEGORIES"&gt;error hierarchy&lt;/a&gt;, but it doesn't appear very flexible to extensible into other projects ( the whole thing is defined in a 'my' variable in Fatal.pm it seems ), and additionally, it doesn't supplement any of the things in Perl that already just die by throwing their own stringy exception, because as far as autodie appears concerned, if its already throwing an exception, why replace it?
&lt;/p&gt;
&lt;p&gt;One such builtin that is in this type of problem is &lt;code&gt;require&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are at least 3 unique separate failure conditions that I know 'require' can spit out.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;File not Found in @INC&lt;/li&gt;
    &lt;li&gt;require returned false value&lt;/li&gt;
    &lt;li&gt;compilation failed in require&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the above being reported merely as strings leaves much to be desired. Sure, its great when things fail in obvious ways, but handling it in code is far too pesky.&lt;/p&gt;
&lt;p&gt;Not everyone will have experienced this problem of course, but let me demonstrate a scenario.&lt;/p&gt;
&lt;pre class="perl"&gt;
sub findFirst { 
  my $plugin = shift;
  my $parent = "SomeApp";
  my @guessOrder = ( $plugin . "::" . $parent , $plugin );
  my @fails;
  for( @guessOrder ){
     local $@;
     eval "require $_; 1";
     if ( $@ ) {
        die $@ if $@ !~ /not found/ ; 
        push @fails, $@;
     } else { 
        return $_ ; 
     }
  }
  die "Couldn't load any of @guessOrder : @fails ";
}

my $plug = findFirst("Foo::Bar");

&lt;/pre&gt;
&lt;p&gt;This is about as semantically clean as I can get it. The goal here is to permit "Not Found" family of require failures, but upon encountering something that exists but is merely broken, then push that failure up to userland, and, in the event none are found, dump all the errors out showing all the attempted paths that were searched and what was searched for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt; there are several problems with this code, the most obvious is that stringy eval is a really bad idea, I had hoped that at least &lt;strong&gt;one&lt;/strong&gt; of the workarounds for this sillyness on CPAN came with something that threw an Exception object instead of a string.... but no, all I can find is ones that rely on the stock Perl system, and ones that go contrary to all logic and require you to check a return value for failure.&lt;/p&gt;
&lt;p&gt;Another problem is the check for a string in the error. This is not as big a problem, but somebody malicious I guess could break something by explicitly crafting a death message that matched that line.&lt;/p&gt;
&lt;p&gt;Another lovely problem is that death-rethrowing thing. Finding everywhere that the problem occurred in a non-insane way is hard. Ideally, not only should you have a trace depth from top level down to the point of the failure, but also a trace of everywhere the error was re-thrown, because the failure is really a domino effect, and not being able to see how it propagates without dropping into a debugger is hell.You tend to need more complex cases to see why this is happening though.
&lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl

use strict;
use warnings;

sub fail {
  die "Hurp Durp!";
}

sub maybfail {
  unless ( eval { fail; 1; } ) {
    die "maybfail: $@";
  }
}

sub moarfail {
  unless ( eval { maybfail; 1; } ) {
    die "Moarfail: $@";
  }
}

moarfail;
&lt;/pre&gt;
To me, I'd like to be able to see that 
&lt;ul&gt;&lt;li&gt;the root error occurred as main:22 { moarfail:17 { maybfail:11 { fail:7 { die } } } &lt;/li&gt;
&lt;li&gt;The error was rethrown at  main:22{ moarfail:17 { maybfail:12 } }&lt;/li&gt;
&lt;li&gt;The error was rethrown at  main:22{ moarfail:18 }&lt;/li&gt;
&lt;/ul&gt;

At present, here's the best I can get out of that simple structure: 

&lt;pre class="bash"&gt;
$ perl -MCarp::Always /tmp/die.pl 
Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 18
 main::moarfail() called at /tmp/die.pl line 22
&lt;/pre&gt;
&lt;pre class="bash"&gt;
$ perl /tmp/die.pl 
Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 7.
&lt;/pre&gt;
&lt;pre class="bash"&gt;
$ perl -MCarp::Always /tmp/die.pl 
Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 18
 main::moarfail() called at /tmp/die.pl line 22
&lt;/pre&gt;
&lt;pre class="bash"&gt;
$ perl -MDevel::SimpleTrace /tmp/die.pl 
Moarfail: maybfail: Hurp Durp!
 at main::fail(/tmp/die.pl:7)
 at &lt;eval&gt;(/tmp/die.pl:11)
 at main::maybfail(/tmp/die.pl:11)
 at &lt;eval&gt;(/tmp/die.pl:17)
 at main::moarfail(/tmp/die.pl:17)
 at main::(/tmp/die.pl:22)
&lt;/pre&gt;
&lt;p&gt;
Note how none of those traces reflect the fact I call "die" on line 12? Be glad the die isn't like 30 lines away in a different method where it might go completely unnoticed.
&lt;/p&gt;
&lt;p&gt;In fact, each and every one of these backtraces confuse me, because I can't work out why some know about the failure origin, and others don't ... ( Carp::Always seems to let you down and being completely unable to see a stack. :/ )&lt;/p&gt;
&lt;p&gt;I would in fact, much rather prefer something like this that actually worked: &lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl

use strict;
use warnings;

sub fail {
    BasicException-&gt;throw( error =&gt; 'HurpDurp' );
}

sub maybfail {
  try { 
      fail;
  } catch ( BasicException $e ) { 
     MoreComplexException-&gt;adopt( $e )-&gt;throw( error =&gt; 'Maybfail');
  }
}

sub moarfail {
  try { 
      maybfail;
  } catch ( MoreComplexException $e ) { 
     EvenMoreComplexExcetpion-&gt;adopt( $e )-&gt;throw( error =&gt; 'Moarfail');
 }
}

moarfail;
&lt;/pre&gt;
&lt;p&gt;
Nothing I've seen handles that "adopt" thing, but its my little way of saying "We are in fact creating a new exception, because we want to provide more information about the problem, and increase the meaning of the problem relative to this context, but we also want to recognise that this problem is likely caused by another problem(s) that we identify here." 
&lt;/p&gt;
&lt;p&gt;In case you TL;DR'd here, ( and because my train of thought was just snapped -_- ), the summary of this is: Its really challenging doing proper exception-oriented Perl when so many code features still throw those nasty stringy exceptions. :( &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-8094350727641886790?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ks272YXKuANzTdRztAcpGViNbsI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ks272YXKuANzTdRztAcpGViNbsI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ks272YXKuANzTdRztAcpGViNbsI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ks272YXKuANzTdRztAcpGViNbsI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/cMUGi1Pik-0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/8094350727641886790/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven_19.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/8094350727641886790?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/8094350727641886790?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/cMUGi1Pik-0/current-limitations-in-exception-driven_19.html" title="Current Limitations In Exception Driven Perl: Stringy Core Exceptions" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven_19.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAAQnk6cCp7ImA9WxFaFE4.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-4796444038747943755</id><published>2010-07-18T18:15:00.000+12:00</published><updated>2010-07-18T18:15:43.718+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-18T18:15:43.718+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="limitations" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="exceptions" /><title>Current Limitations In Exception Driven Perl: Exception Base Classes.</title><content type="html">&lt;p&gt;I've started re-attempting to do Exception Oriented Perl Programming recently, and quickly discovered a whole raft of things that got in my way.&lt;/p&gt;
&lt;p&gt;
This is the first of such things.
&lt;/p&gt;
&lt;p&gt;
I was very much appreciative of &lt;a href="http://p3rl.org/Exception::Class"&gt;Exception::Class&lt;/a&gt;, it looks Mostly to Do The Right thing, its mostly simple and straight forward, it itself has some apparent limitations with regard to exception driven code, but I'll cover those later.
&lt;/p&gt;&lt;p&gt;
The biggest annoyance I have at present is there is no apparent de-facto base set of Exception classes to derive everything else from. I was expecting some sort of Exception Hierarchy much like Moose's Type Hierarchy, but none is to be found anywhere, and this stinks.
&lt;/p&gt;&lt;p&gt;
Is everyone to have their own base hierarchy for everything? The idea of every project having its own FileException class ship with it to me feels like Fail, and this problem I feel will be needed to addressed before more people start taking exception driven Perl seriously. 
&lt;/p&gt;
&lt;p&gt;Additional to this fun, is presently, all the exception classes share the same name-space as everything else in Perl, because they're just Perl packages. I accept this limitation is mostly Perl's fault, but I still dislike it. The 'Type' name-space suffers a similar problem,  but its not quite so bad.&lt;/p&gt;
&lt;p&gt;The challenge here is having adequate classes to represent accurately all the  classes of exception one wishes to provide, but have them still sanely organised, but without people needing to type out 100character incantations just to throw an exception. &lt;/p&gt;
&lt;p&gt;Something akin to &lt;a href="http://p3rl.org/MooseX::Types"&gt;MooseX::Types&lt;/a&gt; which injects subs into the context would be nice-ish, the only problem there is when you do something stupid like create/import an exception with a name identical to a child namespace, ie:
&lt;/p&gt;
&lt;pre class="perl"&gt;
   package Bar;
   use SomeTypePackage qw( Foo );
   use Bar::Foo; # Hurp durp. Bar::Foo-&gt;import() ==&gt; Bar::Foo()-&gt;import() 
   Bar::Foo-&gt;new(); # moar hurp durp. Bar::Foo()-&gt;import() 
&lt;/pre&gt;
&lt;p&gt;
Its reasonably easy to work around, but discovering you've failed in this way is slightly less than obvious.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-4796444038747943755?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BDbF0Z9-um-tgodxwFZZXD-aA2Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BDbF0Z9-um-tgodxwFZZXD-aA2Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BDbF0Z9-um-tgodxwFZZXD-aA2Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BDbF0Z9-um-tgodxwFZZXD-aA2Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/rXWzCCX-iG8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/4796444038747943755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4796444038747943755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4796444038747943755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/rXWzCCX-iG8/current-limitations-in-exception-driven.html" title="Current Limitations In Exception Driven Perl: Exception Base Classes." /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04CQ3gzeyp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-985197264977503623</id><published>2010-06-27T07:02:00.001+12:00</published><updated>2010-06-27T07:52:42.683+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T07:52:42.683+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="parser" /><category scheme="http://www.blogger.com/atom/ns#" term="error" /><category scheme="http://www.blogger.com/atom/ns#" term="bug" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="syntax" /><title>Todays amusing Perl parser confusion</title><content type="html">&lt;p&gt;
Have a look at this very simple code and see what you expect it will do:
&lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl
use strict;
use warnings;


print "hello";

1

=pod

=cut
__END__
&lt;/pre&gt;
&lt;p&gt;
It looks trivial right?
&lt;/p&gt;&lt;p&gt;
Not so. 
&lt;/p&gt;
&lt;pre class="bash"&gt;
$ perl /tmp/pl.pl 
Can't modify constant item in scalar assignment at /tmp/pl.pl line 13, at EOF
Bareword "cut" not allowed while "strict subs" in use at /tmp/pl.pl line 8.
Bareword "pod" not allowed while "strict subs" in use at /tmp/pl.pl line 8.
Execution of /tmp/pl.pl aborted due to compilation errors.
&lt;/pre&gt;
&lt;p&gt;
Wait. 
&lt;/p&gt;&lt;p&gt;
Wut?
&lt;/p&gt;&lt;p&gt;
Running it through Deparse reveals the culprit:
&lt;/p&gt;
&lt;pre class="bash"&gt;
$ perl -MO=Deparse /tmp/pl.pl 
Can't modify constant item in scalar assignment at /tmp/pl.pl line 13, at EOF
Bareword "cut" not allowed while "strict subs" in use at /tmp/pl.pl line 8.
Bareword "pod" not allowed while "strict subs" in use at /tmp/pl.pl line 8.
/tmp/pl.pl had compilation errors.
&lt;/pre&gt;
&lt;pre class="perl"&gt;
use warnings;
use strict 'refs';
print 'hello';
1 = 'pod' = 'cut';
__DATA__
&lt;/pre&gt;
&lt;p&gt;
Pesky indeed!.
&lt;/p&gt;&lt;p&gt;
The solution? Insert the humble &lt;strong&gt;&lt;q&gt;&lt;code&gt;;&lt;/code&gt;&lt;/q&gt;&lt;/strong&gt; like your mother taught you to.
&lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl
use strict;
use warnings;


print "hello";

1;

=pod

=cut
__END__
&lt;/pre&gt;

&lt;pre class="bash"&gt;
$ perl /tmp/pl.pl 
hello

&lt;/pre&gt;
&lt;p&gt;
Perhaps this is worthy of applying a bugfix. Perl version = 5.12.1 =).
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-985197264977503623?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mBWc5gcsaAgWm9sbO7-xezB38_E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mBWc5gcsaAgWm9sbO7-xezB38_E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mBWc5gcsaAgWm9sbO7-xezB38_E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mBWc5gcsaAgWm9sbO7-xezB38_E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/jK-zKTRXm5A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/985197264977503623/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/06/todays-amusing-perl-parser-confusion.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/985197264977503623?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/985197264977503623?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/jK-zKTRXm5A/todays-amusing-perl-parser-confusion.html" title="Todays amusing Perl parser confusion" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/06/todays-amusing-perl-parser-confusion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMGRX48eip7ImA9WxFUFEg.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-6695001641995791168</id><published>2010-06-25T21:17:00.000+12:00</published><updated>2010-06-25T21:17:04.072+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-25T21:17:04.072+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="discipline" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>Any good advice on focusing on the one scope in this massively metarecursive language?</title><content type="html">&lt;div style="text-align: justify;"&gt;
&lt;p&gt;The recursivity of the meta-programming these days in Perl is astounding.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; necessarily a &lt;em&gt;bad&lt;/em&gt; thing, but it has its drawbacks in various fields&lt;/p&gt;

&lt;p&gt;While I &lt;em&gt;love&lt;/em&gt; authoring modules, and I &lt;em&gt;love&lt;/em&gt; contributing to various projects, 
  I often find this is a need, when I would rather be focusing on something that &lt;em&gt;I&lt;/em&gt; need.&lt;/p&gt;

&lt;h3 id="AnExample"&gt;&lt;a href="#AnExample"&gt;An Example&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;
  Let me give you and example: one of my family members requested them work on a
  website for them, for one of their businesses, and I as a result want to
  produce the best product I possibly can for this.
&lt;/p&gt;
&lt;p&gt;
  The first concern I encountered was shipping it. I need to be able to
  develop this website in a way that I can ship it somewhere ( target unknown )
  and have a relatively quick, relatively hassle-free installation that Just
  Works, so in the event I have to hand the code over to somebody else to work
  with, or ship it to a different server where I may have less control over
  the environment or distribution it runs, it will still mostly just work
&lt;/p&gt;
&lt;p&gt;This lead me to my 

&lt;a href="http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html"
   title="Search for the perfect project setup"&gt;state-of-packaging post&lt;/a&gt;, 
where
I started wasting various time trying to work out what best way to
bundle/package and otherwise get the software to just work.
&lt;/p&gt;
&lt;p&gt;
This need sort-of emerged out of the want to use the latest and greatest
tools, such as Plack, the latest editions of Moose, etc. 
&lt;/p&gt;

&lt;p&gt;However, as discovered  &lt;a
href="http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html"
title="Search for the perfect project setup"&gt;in the aforementioned article&lt;/a&gt;,
the state of linux distributions with regard to Perl in the larger scale
largely sucks, and pretty much the "best" option tends to result in "using
&lt;a href="http://www.perl.org/cpan.html" 
  title="CPAN - Comprehensive Perl Archive Network"&gt;CPAN&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt; &lt;a href="http://www.perl.org/cpan.html" title="CPAN - Comprehensive Perl
Archive Network"&gt;CPAN&lt;/a&gt; is great and all, don't get me wrong, but compared to
existing linux distribution package management techniques, Perl dependency and
file management leaves much to be desired. Sure, its miles ahead of Ruby and
Python, (&amp;nbsp;not to mention evolutions of species better than PHP, Java and
C/C++'s native package management&amp;nbsp;) but since when do we use the &lt;em&gt;lesser
tools&lt;/em&gt; as our measure of standard?&lt;/p&gt;

&lt;p&gt;So anyhow, after musing for several days on this dilemma, researching
various options, talking to various people, and blogging about it, 
and not getting very far, I decide I'm just wasting my time
again and I should just hack something up on my box, and worry about this
package management crap later&lt;/p&gt;

&lt;h3 id="Distraction2Point0"&gt;&lt;a href="#Distraction2Point0"&gt;Distraction
2.0&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
So, I decide to get it working on my machine first, worry about everywhere
else later, you know, when it matters. This is of course a potentially
dangerous decision from a reliability standpoint, because you may discover
whatever technique you decided to use on your system is completely non-viable on
another.
&lt;/p&gt;
&lt;p&gt;On my machine, the first thing I do is go through my toolkit and update all
the various packages I'll need using my Distributions Package Management
tools. (&amp;nbsp;This surprisingly in my experience sucks less than it does than on
the other distributions I've tried&amp;nbsp;).&lt;/p&gt;
&lt;p&gt;Then I discover a discrepancy in how another developer has mapped Perl
dependencies to Package Manager dependencies, that is different to how I've been doing
them, and I then have to work out if its merely an error, or its intent. ( The
specifics of this I won't bore you with here ). As part of diagnosis, while
I'm waiting for a response on IRC from the developer who wrote that mapping, I
of course write a Perl script to work out where else this style of mapping is
being used in attempt to gauge how often it is used. &lt;/p&gt;

&lt;p&gt;This eventually diverges until I'm parsing individual build scripts with
Perl and am trying to extract balanced bracket sets from these files with
context. (&amp;nbsp;Bad me, I should have just used &lt;a
    href="http://search.cpan.org/dist/Text-Balanced/" 
    title="Text::Balanced on Search.CPAN.org"&gt;Text::Balanced&lt;/a&gt;&amp;nbsp;)
&lt;/p&gt;
&lt;p&gt;Fortunately, I disregarded that script eventually, because I realised how
much of the day I'd wasted on this problem already. Argh. Still no closer to
even starting the actual code :|&lt;/p&gt;

&lt;p&gt;Other times, when doing the update phase, I discover a package
incompatibility with Perl, for whatever reason. A recent example is some
bizarre failure with &lt;a href="http://search.cpan.org/dist/Eval-Context/"
  title="Eval::Context on Search.CPAN.org"&gt;Eval::Context&lt;/a&gt;. This failure is
  being a bit hard to trace down, because the failure occurs, as far as I can
  make out, in &lt;a href="http://search.cpan.org/dist/perl/lib/Carp.pm" 
    title="Carp on Search.CPAN.org"&gt;Carp&lt;/a&gt;. The usual techniques such as
    &lt;code&gt;-M&lt;a href="http://search.cpan.org/dist/Carp-Always/" 
      title="Carp::Always on Search.CPAN.org"&gt;Carp::Always&lt;/a&gt;&lt;/code&gt; or 
    &lt;code&gt;-M&lt;a href="http://search.cpan.org/dist/Devel-SimpleTrace/"
    title="Devel::SimpleTrace on Search.CPAN.org"&gt;Devel::SimpleTrace&lt;/a&gt;&lt;/code&gt; do not
    want to work, as for some reason, their presence cause the wonderful
    Heisenbug scenario, the bug vanishes! (&amp;nbsp;well, and a new one appears in its
        place&amp;nbsp;). And to make matters worse (&amp;nbsp;much much worse&amp;nbsp;), when I
    run the build + test by hand instead of under the packager sandbox
    installation system, the bug also vanishes. Pesky indeed. (&amp;nbsp;I haven't
        filed a bug for the above yet, in case you're asking, there's simply
        no point filing one until I can reliably recreate the scenario in a
        sterile way. And as a general rule I've found with Perl, most of the
        time, If I figure out what the problem is, I figure out a solution
        at the same time&amp;nbsp;)
&lt;/p&gt;
&lt;p&gt;Lets assume for a moment I was able to actually work out what was going on,
  after dicking around for a few hours, I'd probably have found a patch that
  worked too, and possibly submitted a bug-request and patch to upstream, and
  then applied the workaround to the Perl overlay, I'd be able to get on my
  way to the &lt;em&gt;next&lt;/em&gt; package.&lt;/p&gt;
&lt;p&gt;Granted, at the moment, the number of failing packages I'm encountering is
much much higher as I'm helping test the Perl 5.12.1 release precluding the
integration into the main tree, and I'm voluntarily fixing these things
because somebody has to test this stuff before it hits &lt;sub&gt;L&lt;/sub&gt;user
land&lt;/p&gt;
&lt;h3 id="MoreRecursion"&gt;&lt;a href="#MoreRecursion"&gt;More Recursion&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;
Its not the case this time, I mean, &lt;em&gt;yet&lt;/em&gt; with this project
(&amp;nbsp;mostly because its yet to have any code!&amp;nbsp;), but I often find
myself swimming deeper and deeper into the metaprogrammy sea. &lt;/p&gt;&lt;p&gt;In the
beginning, it was just writing modules that made my life easier.&lt;/p&gt;&lt;p&gt;Then
comes the fun of distribution of those modules to make others life
easier&lt;/p&gt;&lt;p&gt;Then comes the want to make distribution of Modules
easier&lt;/p&gt;&lt;p&gt;Then comes the awesome madness that is &lt;a
href="http://search.cpan.org/dist/Dist-Zilla/" 
title="Dist::Zilla on Search.CPAN.org"&gt;Dist::Zilla&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Then comes you writing plugins for &lt;a
href="http://search.cpan.org/dist/Dist-Zilla" 
title="The Awesomeest Distribution Packaging Tool"&gt;
Dist::Zilla&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then you're writing plugin bundles for the above&lt;/p&gt;
&lt;p&gt;Then you're working on Dist::Zilla itself(&amp;nbsp;Patches&amp;nbsp;!&amp;nbsp;:D&amp;nbsp;)&lt;/p&gt;
&lt;p&gt;Then you're contributing code to other peoples Dist::Zilla plugins&lt;/p&gt;
&lt;p&gt;Then you're contributing code to fix various packages that other peoples
Dist::Zilla's plugins use.&lt;/p&gt;
&lt;p&gt;All this is great stuff, really, community++, but something in the back of
my mind says "Hey, you're lost in the meta, you're so far removed from what
you were actually trying to achieve you can no longer see the woods for the
trees, in fact, you can't even see trees, all you're seeing is carbon
atoms and you're trying to compute the spin on their electrons!"&lt;/p&gt;
&lt;h3 id="MyProblemReally"&gt;&lt;a href="#MyProblemReally"&gt;My Problem Really&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I think my problem is really I don't see a viable way of staying strictly a
"high-level abstraction" consumer, and just using the abstractions that exist
to achieve my goal, and I'm always drilling down into the guts of things,
   patching their core, getting all low-level into the implementation of
   things and forgetting my original goal for weeks. &lt;/p&gt;&lt;p&gt;The best I can
   come up with is "hey, perhaps you'll have to be anti-contributive a bit, an
   er, yuck, but write code that is probably redundant somewhere in a way
   that's not really optimally reusable, because the long-term maintenance
   requirements of publican shared code are a bit high"?
   &lt;/p&gt;
   &lt;p&gt;I think I just sicked up in my mouth at the idea of that :/&lt;/p&gt;
   &lt;p&gt;But I have to find some way to focus on the project level, food doesn't
   put itself on the table!&lt;/p&gt;
   &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-6695001641995791168?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/wbSyHHhZcKfBKOrnv1t9cHZ_fig/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wbSyHHhZcKfBKOrnv1t9cHZ_fig/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/wbSyHHhZcKfBKOrnv1t9cHZ_fig/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/wbSyHHhZcKfBKOrnv1t9cHZ_fig/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/HnDOAa6Hkr4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/6695001641995791168/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/06/any-good-advice-on-focusing-on-one.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/6695001641995791168?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/6695001641995791168?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/HnDOAa6Hkr4/any-good-advice-on-focusing-on-one.html" title="Any good advice on focusing on the one scope in this massively metarecursive language?" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/06/any-good-advice-on-focusing-on-one.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUHR3c6eCp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-9155519522417070477</id><published>2010-06-25T08:35:00.002+12:00</published><updated>2010-06-27T07:57:16.910+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T07:57:16.910+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>Some basic statistics on "Line Noise"</title><content type="html">&lt;p&gt;I was reading another blog about somebody intending to analyse what amount of perl code constitutes as "Line Noise", but they didn't appear to have Actually Done It.&lt;/p&gt;
&lt;p&gt;
I took a naïve approach and didn't make any assumptions about what "line noise" constitutes, and just did basic statistics on the prevalence of various characters for the sake of interest.&lt;/p&gt;

&lt;div style="background-color: #FFDDDD; white-space: pre;"&gt;  Partial Dump
&lt;pre class="plaintext" style="background-color: #FFF;"&gt;  0.2 % :   511319 x char   64 : "\@"
  0.2 % :   564540 x char   55 : 7
  0.2 % :   593117 x char   79 : "O"
  0.2 % :   601710 x char   77 : "M"
  0.3 % :   675072 x char   92 : "\\"
  0.3 % :   684986 x char   68 : "D"
  0.3 % :   698665 x char   78 : "N"
  0.3 % :   709768 x char   76 : "L"
  0.3 % :   712074 x char   80 : "P"
  0.3 % :   763426 x char   56 : 8
  0.3 % :   784577 x char  107 : "k"
  0.3 % :   797560 x char   82 : "R"
  0.3 % :   833723 x char   54 : 6
  0.4 % :   912737 x char   52 : 4
  0.4 % :   920716 x char   93 : "]"
  0.4 % :   921001 x char   91 : "["
  0.4 % :   924075 x char   73 : "I"
  0.4 % :   947539 x char  118 : "v"
  0.4 % :   956653 x char   67 : "C"
  0.4 % :   996323 x char   65 : "A"
  0.4 % :  1000637 x char   83 : "S"
  0.5 % :  1125435 x char  119 : "w"
  0.5 % :  1151874 x char   46 : "."
  0.5 % :  1220735 x char   34 : "\""
  0.5 % :  1222341 x char    9 : "\t"
  0.5 % :  1222927 x char   51 : 3
  0.5 % :  1241600 x char   69 : "E"
  0.5 % :  1243448 x char   53 : 5
  0.5 % :  1332828 x char   84 : "T"
  0.6 % :  1443662 x char   57 : 9
  0.6 % :  1491434 x char  120 : "x"
  0.6 % :  1499376 x char  125 : "}"
  0.6 % :  1500792 x char  123 : "{"
  0.7 % :  1718028 x char  103 : "g"
  0.7 % :  1739054 x char   40 : "("
  0.7 % :  1739695 x char   41 : ")"
  0.7 % :  1792258 x char   59 : ";"
  0.7 % :  1825133 x char  121 : "y"
  0.8 % :  1837291 x char   98 : "b"
  0.8 % :  1842316 x char   35 : "#"
  0.8 % :  1960600 x char   50 : 2
  0.9 % :  2149806 x char   62 : "&gt;"
  1.0 % :  2410416 x char   49 : 1
  1.1 % :  2594921 x char   61 : "="
  1.1 % :  2684166 x char   95 : "_"
  1.1 % :  2709633 x char  112 : "p"
  1.2 % :  2818643 x char   58 : ":"
  1.2 % :  2952175 x char  104 : "h"
  1.2 % :  2995621 x char   45 : "-"
  1.3 % :  3151943 x char  109 : "m"
  1.3 % :  3283418 x char   36 : "\$"
  1.3 % :  3291138 x char  102 : "f"
  1.4 % :  3339529 x char   39 : "'"
  1.4 % :  3355931 x char  117 : "u"
  1.5 % :  3638254 x char   99 : "c"
  1.6 % :  4016055 x char  100 : "d"
  1.9 % :  4598003 x char   44 : ","
  2.0 % :  4786703 x char  108 : "l"
  2.2 % :  5472272 x char   48 : 0
  2.6 % :  6279579 x char  110 : "n"
  2.6 % :  6306811 x char  111 : "o"
  2.7 % :  6625715 x char  105 : "i"
  2.8 % :  6872608 x char  114 : "r"
  3.0 % :  7315145 x char  115 : "s"
  3.1 % :  7522087 x char   97 : "a"
  3.6 % :  8711403 x char   10 : "\n"
  3.7 % :  8972142 x char  116 : "t"
  5.4 % : 13289205 x char  101 : "e"
 24.2 % : 59186425 x char   32 : " "
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
I find it quite intriguing how the various bracketings are unbalanced. &lt;span style="text-decoration: line-through;"&gt;Also the significantly greater use of "&amp;gt;" vs "&amp;lt;" indicates people write more than they read.&lt;/span&gt;&lt;strong&gt;Edit:&lt;/strong&gt; probably more &lt;code&gt;=&amp;gt;&lt;/code&gt;
&lt;/p&gt;
&lt;p&gt;
Also, what is extremely amusing, is in this sort order, ignoring "r" "a" and "t" and all whitespace going down, a word is formed. That word.... is "noise". Weird.
&lt;/p&gt;
&lt;p&gt;For a full dump of my diagnositcs, see &lt;a href="http://gist.github.com/451919"&gt; my github gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
The code I used to generate these stats is pretty straight forward, and would be interested in seeing what sort of results other people get, and possibly the result of adapting the code to work for C and other non-perl languages to work out how much "line noise" they are.
&lt;/p&gt;
&lt;pre class="perl"&gt;
#!/usr/bin/perl
use strict;
use warnings;

use 5.12.1;
use File::Find::Rule            ();
use File::Find::Rule::Perl      ();
use Data::Dumper                qw( Dumper );

say $_ for ( @INC );

my @pmfiles = File::Find::Rule-&gt;perl_file-&gt;in( @INC );

my %stats;

for my $file ( @pmfiles ){
    say "scanning $file";
    open my $fh, '&lt;', $file or next;
    my $char;
    while( read $fh, $char, 1 ){
        $stats{$char}++;
    }
#    last;
}

my @data = sort { $a-&gt;[0] &lt;=&gt; $b-&gt;[0] } map { [ $stats{$_} , $_ ] } keys %stats;

$Data::Dumper::Terse = 1;
$Data::Dumper::Useqq = 1;

my $numchars;
$numchars += $_ for values %stats;

for( @data ){
    printf "%5.1f %% : %8d x char %4d : %s" ,
       ( $_-&gt;[0] / $numchars * 100 ) , 
       $_-&gt;[0] , 
       ord( $_-&gt;[1] ),
       Dumper( $_-&gt;[1] );
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-9155519522417070477?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/T8cFGxwo2A-zFs97wZzesXGoyA0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T8cFGxwo2A-zFs97wZzesXGoyA0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/T8cFGxwo2A-zFs97wZzesXGoyA0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T8cFGxwo2A-zFs97wZzesXGoyA0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/H-r3AjD8H1U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/9155519522417070477/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/06/some-basic-statistics-on-line-noise.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/9155519522417070477?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/9155519522417070477?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/H-r3AjD8H1U/some-basic-statistics-on-line-noise.html" title="Some basic statistics on &quot;Line Noise&quot;" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>1</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/06/some-basic-statistics-on-line-noise.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQDSXs8cSp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-8204349057187573431</id><published>2010-06-17T04:17:00.001+12:00</published><updated>2010-06-27T07:59:38.579+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T07:59:38.579+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="suggestions" /><category scheme="http://www.blogger.com/atom/ns#" term="lazyweb" /><category scheme="http://www.blogger.com/atom/ns#" term="halps" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="module" /><title>The Search for the Perfect Project Setup</title><content type="html">&lt;p&gt;
I feel a bit like a retard today.
&lt;/p&gt;
&lt;p&gt;
Perhaps, a spectacular one. I don't even
know what to search for with regard to my problem as follows, and I guess I
don't have the best Idea of what I want, so I'm blogging about it in the hope
I can linearise my thought process a bit and work out what to do, and perhaps,
somebody can point me in the right direction.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;
NB. There's a fair bit of "TL;DR" content here, but it stands in case people
try to suggest I use these solutions instead, Its primarily a demonstration of
what I've tried, and the logic I've obtained therein which I used to reach my
current conclusion, and thus, my actual request.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;Firstly, My current situation&lt;/h3&gt;
&lt;p&gt;
At the moment, I install all my modules, not via any of the CPAN clients, but
through my distribution. This yields a much &lt;q&gt;cleaner&lt;/q&gt; system, and dependency
tracking is more reversible, which files were installed by which distribution
is more reliable, and distribution collisions are explicitly barred. 
&lt;/p&gt;
&lt;p&gt;
This is moderately straight forward, in Gentoo, we have these ebuilds which
automate most of the hard work, and the technical debt of building a CPAN
module and installing it is pretty much 0. A single 30 line text file, most of
which is boiler-plate, ( and generated ), and its essentially bash code,
almost freebsd in nature. 
&lt;/p&gt;
&lt;p&gt;
I'm not a fan-boy for Gentoo for any of the traditional reasons people ascribe
to it ( i.e. as funrolloops portrays ). I actually like how the package management works,
 I like having access to all the source, I like being able to break stuff and
report reasonable bug reports to get actual bugs fixed, and I like being able
to Just Fix It myself when I want to. I'm not going to go and rubbish anybody
else for their distribution choices or why they choose them, just for me,
Gentoo is the &lt;q&gt;sweet spot&lt;/q&gt; in my taste system. ( I just expect people to return
the favour and not treat me like the retard because I'm not using $THEIR_SYSTEM )
&lt;/p&gt;
&lt;p&gt;
As a general rule, other distributions have given me various headaches for
various reasons, I haven't tried Arch yet, so I can't write that off as &lt;q&gt;unfit
for my way of working&lt;/q&gt; yet, but from what I see its mostly nice.
&lt;/p&gt;
&lt;h3&gt;Perceived Obstacles: In walks Deb/Buntu&lt;/h3&gt;
&lt;p&gt;
For various reasons, my way of working with Perl on Gentoo is not very
friendly on some other Distros. At present, I have box running Ubuntu, which I initially set up to
JustWork and be pretty simple for flatmates to use as an Internet terminal. It
has since lost this role, and its really too much effort for me to wipe it off
and install $OtherDistro from scratch on it. And fundementally, needing to do
that just to work in Perl on that distro in a satisfactory nature is either a
failure in that distro ( Snarky comments about Ubuntu here ), a failure of
Perl ( I hope not, ) , or a failure of myself ( Pretty likely ).
&lt;/p&gt;
&lt;p&gt;
I've seen and tried using &lt;code&gt;dh-make-perl&lt;/code&gt; and its behaviour is very
dis-satisfactory. Unfortunately, the most recent Perl I can get on Ubuntu is
5.10.1 , and the most recent version of &lt;code&gt;dh-make-perl&lt;/code&gt; I can get
on Ubuntu is the geriatric 0.62, which is goodness knows versions behind
Debians equivalent.
&lt;/p&gt;
&lt;h4&gt;dh-make-perl problems&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;h5&gt;Non Recursive nature&lt;/h5&gt;&lt;p&gt;I can handle this, that's OK, I'm used to
  walking deps by myself on Gentoo where needed and satisfying them, its not
  challenging. But that said, these files are generated build scripts which
  are just text files, which are essentially generated from a naive template,
  and this is &lt;em&gt;*really fast*&lt;/em&gt;. The dh-make-perl script by comparison takes as
  long to generate and build the .deb file as I could generate and edit the
  text file myself by hand!. &lt;/p&gt;&lt;p&gt;Additionally, at present I only generate
  my files by hand &lt;em&gt;by choice&lt;/em&gt;. I only do it by hand to guarantee quality
  in the generation, so that I can redistribute it.&lt;/p&gt;&lt;p&gt;I &lt;em&gt;could&lt;/em&gt;
  just use &lt;a href="http://search.cpan.org/~vpit/"&gt;Vincent Pit(VPIT)++&lt;/a&gt;'s
  marvellous &lt;a href="http://search.cpan.org/dist/CPANPLUS-Dist-Gentoo/"&gt;CPANPLUS::Dist::Gentoo&lt;/a&gt;
  which for the most part JustWorks&amp;trade;. It does all the cool recursive
  traversal, generation of ebuilds where needed, and its hands free, and
  fast.&lt;/p&gt;&lt;p&gt;I attempted to use CPANPLUS::Dist::Deb, and that kinda just
  failed, which I'll go into later&lt;/p&gt;
  &lt;/li&gt;

  &lt;li&gt;&lt;h5&gt;On half the things I've tried to build with it so far, its
  failed&lt;/h5&gt;&lt;p&gt;Again, possibly I'm a retard, or possibly Ubuntu is failing
  again, but it keeps dying with weird problems trying to find dependencies,
  or computing dependencies, and sometimes even can't detect things that have
  been built earlier and installed. ( For the record, I've been banging my
  head against the wall trying to get Plack to build )&lt;/p&gt;&lt;p&gt;Sure, due to the
  nature of perl stuff its a bit hellish to extract dependencies reliably in
  all cases, but even then, this is Plack man, its pretty straight forward.
  &lt;/p&gt;&lt;p&gt;
  Gentoo dependencies are reasonably simple to sort out when automation gets
  it wrong, the Debian format? I don't even know where to start.&lt;/p&gt;&lt;p&gt; Granted I
  haven't spent much time reading the Debian Developer Guides to learn how to
  fix this sort of problem, and what sort of incantations to call to get
  something to build once I've manually fixed the problem, but its really
  overkill to even need to do that, I didn't need to read &lt;em&gt;anything&lt;/em&gt; to
  start hacking on ebuilds. Its all self-contained and its bash, a language I
  already know, and extremely straight forward. Sure, I needed to learn a bit
  for supremely advanced edge cases, but I don't see demand for those on a
  regular basis. &lt;/p&gt;
&lt;/ol&gt;
&lt;p&gt;
I guess the obvious solution to the above would be learning more about Debian?
But I've already exercised more than my share of WTF quota in this avenue.
&lt;/p&gt;
&lt;h4&gt;CPANPLUS::Dist::Deb&lt;/h4&gt;&lt;p&gt;
Either this module sucks, or its just terribly broken, or its sucking due to
ubuntuisims. My impression is its starting to be a little under-maintained, but
not sure. The first time I tried to use it ( well, install it that is ), the
majority of its tests just failed hard. So, I upgraded from Karmic to Lucid,
and as a result, tests just &lt;em&gt;Hang&lt;/em&gt; instead for about 5 minutes, before
running the tests again, and failing most of them. Brilliant.&lt;/p&gt;
&lt;pre class="bash"&gt;
make[1]: Entering directory `/home/anyone/pl/CPANPLUS-Dist-Deb-0.12'
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/00_constants.t .. ok     
t/01_load.t ....... ok    
t/02_debs.t ....... 1/? # Taking care of Build / xs  # massive hang here.
&lt;/pre&gt;&lt;p&gt;
And then the rest of the &lt;a href="http://gist.github.com/440557"&gt;Massive
Failure is too big to include even in this inordinately large blog&lt;/a&gt;
I eventually managed to get it to build and install, but I had to use
&lt;code&gt;--notest&lt;/code&gt; to get it to work.&lt;/p&gt;&lt;p&gt; Actually, I had to use
define &lt;code&gt;DEB_BUILD_OPTIONS="nocheck"&lt;/code&gt; .. because for some lovely
reason, &lt;code&gt;--notest&lt;/code&gt;, despite being very helpful, is deprecated!
&lt;/p&gt;
&lt;p&gt;Then the real fun started&lt;/p&gt;
&lt;p&gt;using &lt;code&gt;cpan2dist --format CPANPLUS::Dist::Deb Plack&lt;/code&gt; went off
and decided to build packages with stupid names ( 'cpan-libplack-perl' anyone?
), that then fubared for some reason &lt;a href="http://gist.github.com/440616"&gt;I
still don't even want to understand&lt;/a&gt;. Hell, it makes Java back-traces look
simple.&lt;/p&gt;


&lt;h3&gt;Conclusion: Perhaps relying on distro-packaged CPAN packages on most distros still sucks
too hard&lt;/h3&gt;
&lt;p&gt;I've come to understanding at long last why people JustUseCpan&amp;trade; instead
of relying on their distros. Just look at the massive hell-hole of problems I
encountered on &lt;em&gt;just one distribution&lt;/em&gt; of Linux. Woe be unto him to
wants to develop a Perl Project and then ship it and hope its easy to install
using the tools provided by the recipients distribution of choice. I've been
lulled into a false sense of security by my lovely system which is so simple
to use.&lt;/p&gt;

&lt;h3&gt;So, You're doing a Project and relying on CPAN.pm and friends&lt;/h3&gt;&lt;p&gt;
There's a variety of goals a person like myself wants to achieve with this
scenario.&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;h4&gt;Low Pollution&lt;/h4&gt;
  &lt;p&gt;Pooping over /usr and friends is unacceptable. &lt;em&gt;Especially&lt;/em&gt; if its
  not 100% Guaranteed reversible. No 2 Modules should be able to modify each
  others files, either by intent or accident. In some distributions, this is
  guaranteed by building and installing into a clean directory-tree with a
  "sandbox" mechanism that prohibits writing outside the build environment,
  and then collision-testing all the files in the clean-install directory
  prior to unpacking them into the file-system, and then bailing if a collision
  occurs. I like to have this degree of certainty with modules, and in fact,
  all software, which is the primary reason I rely on my Distros' package
  manager because it can give me these guarantees.&lt;/p&gt;&lt;p&gt;You should
  &lt;strong&gt;NOT&lt;/strong&gt; need elevated permissions to ever perform
  configure/build/test &lt;em&gt;or&lt;/em&gt; install. Final application to the
  file-system should be performed by an externality &lt;em&gt;with&lt;/em&gt; the needed
  permissions, that has no way of being "scripted" during the install phase by
  the package that is being installed.&lt;/p&gt; &lt;p&gt;If another mechanism
  can exist within a context ( think perhaps something like
  &lt;code&gt;local::lib&lt;/code&gt; ) that give me this same certainty without resorting
  t say, putting the whole bastard in git and relying on the ability to revert
  commits, ( its not that I'm averse to gitifying an install tree, its just
  when you install lots of modules, you don't want to have to halt things
  between installations just to maintain a 1:1 commit:distribution ratio -_-.
  I tried something like this once, and it was masochism ) then
  ThatConcept++, I want it!&lt;/p&gt;
&lt;/li&gt;
    &lt;li&gt;&lt;h4&gt;Ease of Roll-Out/Distribution&lt;/h4&gt;&lt;p&gt;
    Ideally, you want Some Way to minimise the amount of work one needs to do
    on any given target to make sure the installed modules are the very same
    ones that were on the platform it was developed in. Having to do the above
    dicking around on various distributions with their rubbishy package
    management crap, is a real nightmare. Especially if you don't have the
    luxury of knowing in advance what the target machine will be running.
    Sure, you try to know, but sometimes requirements change, and sometimes
    you don't get much choice about the machine you're working with, so its
    great to have it &lt;strong&gt;completely not matter&lt;/strong&gt; where you're
    taking it. &lt;/p&gt;&lt;p&gt;If you can assume its going to have a &lt;strong&gt;working&lt;/strong&gt;
    version of &lt;strong&gt;some&lt;/strong&gt; recent version of Perl, and that its not
a &lt;em&gt;completely&lt;/em&gt; different platform to the original ( ie: transitioning
    from Linux to Win32( or worse, Win64 ) is a nightmare, it would be nice to be unilaterally
    transformable, but that's too much "dream" at the moment ), then you can
dump your code tree on it and have it more-or-less JustWork without having to
waste &lt;em&gt;more&lt;/em&gt; time working out how to get the bastard up and running.
    &lt;/p&gt;&lt;p&gt;For me, this means I'd want a way to have a mostly-perl-version
    agnostic local::lib-ish installation, which essentially requires
    &lt;ol&gt;&lt;li&gt;Checkout&lt;/li&gt;&lt;li&gt;Some way to rebuild .XS stuff for $arch_target
    without needing to reinstall &lt;em&gt;everything&lt;/em&gt; from
    scratch&lt;/li&gt;&lt;li&gt;Optionally run t/* tests for everything that's
    installed&lt;/li&gt;&lt;li&gt;Run/Serve up the code&lt;/li&gt;
    &lt;/ol&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;h4&gt;Somehow avoid the need to build a second instance of Perl on the
  target machine&lt;/h4&gt;&lt;p&gt;Having to do this is both very annoying, and very time
  consuming. Having a system, a methodology that avoids this need and Just
  Works for everyone who uses this methodology would be &lt;em&gt;great&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Kicking around the idea&lt;/h3&gt;
&lt;pre class="plaintext"&gt;
/
 build/
      tars/
         Source tar.gz's 
      tmp/
         "Scratch" directory where things are configured/built/fake-installed
      installed-t/
        dist-name-version/
          Some attempt at extracting t/ from each dist
 cpan/
      main/
        primary @INC Path
      profile_a/
        supplementary @INC for experiments
 project/
      project_code*
&lt;/pre&gt;
&lt;p&gt;
There's some theoretical layout ideas. Some borrowed from how CPAN currently
works.
&lt;/p&gt;
&lt;p&gt;To facilitate this layout however, some theoretical tools are needed&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Firstly, some way to create an @INC path that includes &lt;em&gt;only&lt;/em&gt;
the modules shipped with Perl itself, if that. This would be like local::lib,
except we &lt;em&gt;explicitly&lt;/em&gt; do &lt;strong&gt;not&lt;/strong&gt; want modules that are
provided by the system to be visible. This is to ensure that when new modules
are added to the projects dependencies, they have to be installed in the
projects custom inc path in order to work, to avoid the issue of going later
on to a different machine, and then and only then discovering you need
it.&lt;br/&gt; If there is no practical way to modify @INC that satisfies this
criteria, then a combination of &lt;code&gt;Module::CoreList&lt;/code&gt; and require
hijacking would be needed to prohibit loading non-core modules from the
system.&lt;/li&gt;&lt;li&gt;Secondly, some way to "bootstrap" an environment for anything
that might be using the project, be it hacking up $ENV vars like
&lt;code&gt;local::lib&lt;/code&gt; does, or something that loads itself via &lt;code&gt;perl
-M&lt;/code&gt; to mess with stuff before the rest of the code runs.&lt;/li&gt;&lt;li&gt;A
variation on the above to be able to run a cpan client without vision of
"system" Perl libraries, in order to install things as if they were nowhere on
the system already.&lt;/li&gt;&lt;li&gt;Optionally, some tool that hooks into the cpan
client to extract information to facilitate rebuilding XS files and running
tests at a later install&lt;/li&gt;
&lt;li&gt;Some method to bundle an entire project tree for network-redistribution (
Git is the most logical option to me, but Rsync or tar.gz + scp would be
suffice here too )&lt;/li&gt;
&lt;li&gt;A recipient tool on the receiving end that can re-inflate the code
directory back in place ( git checkout for example ) &lt;/li&gt;
&lt;li&gt;An ability to, like on the design machine, "bootstrap" into the controlled
environment scenario.&lt;/li&gt;
&lt;li&gt;Optional/Nice to have: Automated XS Rebuild for all applicable items if
needed &lt;/li&gt;
&lt;li&gt;Optional/Nice to have: Automated re-test of everything installed (
preferably without having to &lt;em&gt;re&lt;/em&gt;-unpack &lt;em&gt;re&lt;/em&gt;-configure
&lt;em&gt;re&lt;/em&gt;-rebuild and &lt;em&gt;re&lt;/em&gt;-install every single package.( The idea
is, to have the system be able to make itself useful, in the shortest possible
time, without having to connect to the internet to download more data at any stage )&lt;/li&gt;
&lt;li&gt;Run the "bootstrapped" services.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
This is about as far as I've gotten in my fleshing out of my desirables, let
alone building a solution that works. I am sort-of hoping there is something
simple and straight-forward that already exists and I can just go use and then
recommend to everyone else I see because its just so damn awesome. But as I
stated half-an-hour of reading ago, I don't have a good idea how to look :/
&lt;/p&gt;
&lt;p&gt;
In the famous words of one too many lazy coder: "Plz Halps"
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;In case something in the above has made you want to mock me, please
remember, I already said I feel like a retard. &lt;/em&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-8204349057187573431?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PAPumhXFeFv2L6nbSdfY626g4ms/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PAPumhXFeFv2L6nbSdfY626g4ms/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PAPumhXFeFv2L6nbSdfY626g4ms/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PAPumhXFeFv2L6nbSdfY626g4ms/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/QaDQBBChAIw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/8204349057187573431/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/8204349057187573431?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/8204349057187573431?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/QaDQBBChAIw/search-for-perfect-project-setup.html" title="The Search for the Perfect Project Setup" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMDQ3g4eyp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-4280307060690983173</id><published>2010-01-06T14:45:00.001+13:00</published><updated>2010-06-27T08:01:12.633+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T08:01:12.633+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="moose" /><category scheme="http://www.blogger.com/atom/ns#" term="PerlTidy" /><category scheme="http://www.blogger.com/atom/ns#" term="lazyweb" /><category scheme="http://www.blogger.com/atom/ns#" term="MooseX::Declare" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>LazyWeb? Solutions for using MX::Declare and PerlTidy?</title><content type="html">Dear Lazyweb. &lt;br /&gt;
&lt;br /&gt;
I've been fighting for a while with this minor headache. &lt;br /&gt;
&lt;br /&gt;
Using PerlTidy and MooseX::Declare in conjunction results in pain. &lt;br /&gt;
&lt;br /&gt;
Here is a sample of the sort of indentation that results:&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use MooseX::Declare;&lt;br /&gt;
&lt;br /&gt;
class Foo  {&lt;br /&gt;
&lt;br /&gt;
  method Simple { &lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
    $foo = $foo + 1;&lt;br /&gt;
    if( $foo ) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  method SimpleArgs ( $arg, $arg ) { &lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
    $foo = $foo + 1;&lt;br /&gt;
    if( $foo ) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  method NamedArgs ( :$argname , :$otherarg ) { &lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
    $foo = $foo + 1;&lt;br /&gt;
    if( $foo ) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
And the indentation after going through PerlTidy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="perl"&gt;use MooseX::Declare;&lt;br /&gt;
&lt;br /&gt;
class Foo {&lt;br /&gt;
&lt;br /&gt;
  method Simple {&lt;br /&gt;
&lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
    $foo = $foo + 1;&lt;br /&gt;
    if ($foo) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  method SimpleArgs( $arg, $arg ) {&lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
      $foo = $foo + 1;&lt;br /&gt;
      if ($foo) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    method NamedArgs( : $argname, : $otherarg ) {&lt;br /&gt;
    my $foo = 1;&lt;br /&gt;
      $foo = $foo + 1;&lt;br /&gt;
      if ($foo) {&lt;br /&gt;
      $foo++;&lt;br /&gt;
    }&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
You might notice the second example is both ugly, and refuses to function.&lt;br /&gt;
&lt;br /&gt;
I gripe about it every now and then to various peoples, and the results tend towards 2 options:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Don't use PerlTidy&lt;/li&gt;&lt;li&gt;Don't use MooseX::Declare&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
Neither of those are much of an option to me. I really like keeping formatting and indentation consistent right across a project, but hand adjusting everything is just too much pain. &lt;br /&gt;
&lt;br /&gt;
Some people tell me that I should just tweak my editor to do this for me, but that hardly works, I am yet to see an editor that handles Perl indentation intelligently enough for my liking. Additionally, some editors don't even really have features that tidy indentation and clean up end-of-line whitespace yet, while supporting heaps of other features I want. &lt;br /&gt;
&lt;br /&gt;
Lately, I've been swayed towards using Padre, and its a handy interface for Perl coding, but there's still a massive void in the domain of keeping code tidy. The very best I can find is the Padre PerlTidy plugin, but that has all the same caveats PerlTidy has, so in this case, "just using my editors features" results in PerlTidy being the weak point yet again. &lt;br /&gt;
&lt;br /&gt;
As far as I can make out, there's nothing even slightly comparable to PerlTidy, I cannot seem to see anything else that does anything remotely like it, not even on a more simplistic scale. &lt;br /&gt;
&lt;br /&gt;
So, Dear Lazyweb, please scratch my itch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-4280307060690983173?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JIO-QCrg6QOMXzJteV1il2_KhXI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JIO-QCrg6QOMXzJteV1il2_KhXI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JIO-QCrg6QOMXzJteV1il2_KhXI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JIO-QCrg6QOMXzJteV1il2_KhXI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/TvT2rJlZsTs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/4280307060690983173/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2010/01/lazyweb-solutions-for-using-mxdeclare.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4280307060690983173?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4280307060690983173?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/TvT2rJlZsTs/lazyweb-solutions-for-using-mxdeclare.html" title="LazyWeb? Solutions for using MX::Declare and PerlTidy?" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2010/01/lazyweb-solutions-for-using-mxdeclare.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEINRH4yeSp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-4972164886983108904</id><published>2009-12-09T04:23:00.001+13:00</published><updated>2010-06-27T08:03:15.091+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T08:03:15.091+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="moose" /><category scheme="http://www.blogger.com/atom/ns#" term="Git::PurePerl::CommitBuilder" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="design" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="Git::PurePerl" /><title>PreAnnouncing the in-progress Git::PurePerl::CommitBuilder</title><content type="html">When I blogged about &lt;a href="http://blog.fox.geek.nz/2009/12/building-commits-from-scratch-using.html"&gt;how to create commits raw with git&lt;/a&gt;, it was really a prelude to show why I'm in progress of writing a simple API to do all the hard repetitive stuff, as well as clarify in my mind what was really necessary, so as to write a logical front-end for it. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The basic synopis example I propose will work like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use Git::PurePerl::CommitBuilder;&lt;br /&gt;
&lt;br /&gt;
my $commitBuilder = Git::PurePerl::CommitBuilder-&gt;new(&lt;br /&gt;
  repository   =&gt; '/some/path/to/repository',  # will use /some/path/to/repository/.git&lt;br /&gt;
  auto_init    =&gt; 1 # init the repository if it does not exist, without this, it will die. &lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
my $commit = $commitBuilder-&gt;new_commit( &lt;br /&gt;
  author =&gt; 'Bob Smooth',&lt;br /&gt;
  email  =&gt; 'bob@smooth.example.org',&lt;br /&gt;
  parent =&gt; $commitBuilder-&gt;branch('SomeBranchName'),&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
$commit-&gt;add_file( name =&gt; "Foo.txt" , content =&gt; "This is the content of Foo.txt");&lt;br /&gt;
&lt;br /&gt;
$commit-&gt;write( &lt;br /&gt;
  timestamp   =&gt; DateTime-&gt;now(),  &lt;br /&gt;
  branch      =&gt; 'SomeBranchName', # write the commit to the top of this branch &lt;br /&gt;
  update_head =&gt; 0 , # default.&lt;br /&gt;
  message     =&gt; "This is my first commit, I R a noob",&lt;br /&gt;
);&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
This would produce a file layout as such ( after checking it out ):&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;/some/path/to/repository/Foo.txt
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
This would be your average usecase. This enables you to add/update files and commit them to the branch, but leaving everything else intact. &lt;br /&gt;
&lt;br /&gt;
Initially, supporting 'parent =&gt;' will be limited to the commit-hash lookup so as not to discard history, and won't actually preserve any files from the previous commit in the new one. ( it will be as if the tip was rm ./*  and then added files to for every commit, yeilding huge diffs ). &lt;br /&gt;
&lt;br /&gt;
Although this is ideal for my use, its probably less practical for everyone else. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
my $commit = $commitBuilder-&gt;new_commit( &lt;br /&gt;
  author =&gt; 'Bob Smooth',&lt;br /&gt;
  email  =&gt; 'bob@smooth.example.org',&lt;br /&gt;
  parent =&gt; $commitBuilder-&gt;branch('SomeBranchName'),&lt;br /&gt;
  empty  =&gt; 1&lt;br /&gt;
);&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Will later be required to form empty-tree based commits. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
$commit-&gt;delete_file( name =&gt; "Foo.txt" ); &lt;br /&gt;
$commit-&gt;delete_dir( name =&gt; "Bar" ); &lt;br /&gt;
$commit-&gt;get_content( file =&gt; "Foo.txt");&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
I'm still ambivalent how we'll support directories, they're a complicated issue. &lt;br /&gt;
&lt;br /&gt;
This is how it might look:&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
# String name == split on delimiters&lt;br /&gt;
$code-&gt;add_file( name =&gt; 'path/relative/to/base/here', content =&gt; "Hello" ); &lt;br /&gt;
# ArrayRef name = rightmost token = file. &lt;br /&gt;
$code-&gt;add_file( name =&gt; [qw( path relative to base here )], content =&gt; "Hello" ); &lt;br /&gt;
# Support scalar refs too for people who want them.&lt;br /&gt;
$code-&gt;add_file( name =&gt; [qw( path relative to base here )], content =&gt; \"Hello" ); &lt;br /&gt;
# Read the content from a filehandle.&lt;br /&gt;
open my $fh, '&lt;', 'TheFile.txt';
$code-&gt;add_file( name =&gt; [qw( path relative to base here )], read =&gt; $fh ); &lt;br /&gt;
# Read the content from a file by name&lt;br /&gt;
$code-&gt;add_file( name =&gt; [qw( path relative to base here )], read =&gt; 'TheFile.txt' ); &lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
But I worry about path/file disambiguation qualms. I can't just cheat here and offload it on the filesystem. I feel like being worried about this means I'm doing something wrong, but I can't place why. &lt;br /&gt;
&lt;br /&gt;
This is a notion I'm toying with for clarity:&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
$code-&gt;add_file( name =&gt; 'Foo', in =&gt; 'some/path/here' ... );&lt;br /&gt;
$code-&gt;add_file( name =&gt; 'Foo', in =&gt; [qw( some path here )] ); &lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
That very last one would make implementation of certain things easier.&lt;br /&gt;
&lt;br /&gt;
I guess people can speak up and tell me what they like, and what sucks =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-4972164886983108904?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nz-sa8Xo7IQ53lUyara0Mpl-SLQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nz-sa8Xo7IQ53lUyara0Mpl-SLQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nz-sa8Xo7IQ53lUyara0Mpl-SLQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nz-sa8Xo7IQ53lUyara0Mpl-SLQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/xsqBm9MHkbA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/4972164886983108904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2009/12/preannouncing-in-progress.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4972164886983108904?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/4972164886983108904?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/xsqBm9MHkbA/preannouncing-in-progress.html" title="PreAnnouncing the in-progress Git::PurePerl::CommitBuilder" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2009/12/preannouncing-in-progress.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEFRn0-eCp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-2213191591206270857</id><published>2009-12-07T00:58:00.002+13:00</published><updated>2010-06-27T08:20:17.350+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T08:20:17.350+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="howto" /><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="guide" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="Git::PurePerl" /><title>Building Commits from scratch using Git::PurePerl</title><content type="html">&lt;div style="text-align: justify;"&gt;Anyone who's tried modifying a git repository with code is likely to have discovered a few problems with the experience. &lt;br /&gt;
&lt;br /&gt;
The most common one I encounter is the result of changes having to be done in the git working directory.&lt;br /&gt;
&lt;br /&gt;
This occurs mostly when there are files in a state of non-commit, or files are present in the directory, in an unrevisioned state, and the same file exists on another branch, in a revisioned state.&lt;br /&gt;
&lt;br /&gt;
Here you have a blocking scenario when you try check out that branch.&lt;br /&gt;
&lt;br /&gt;
You can't checkout the other branch, because of the file system collision. &lt;br /&gt;
&lt;br /&gt;
Also, you have a problem  that occurs when 2 processes simultaneously try working with the same code check out, ie: You have a cron job that copies files into the master branch, or a cron job that copies files out of some other branch, etc, etc.., etc, or for some reason, programs which rely on a given file from a given branch being the one it sees all the time.&lt;br /&gt;
&lt;br /&gt;
Generally, the easy way to get around the file system collision fun is with &lt;code&gt;git stash&lt;/code&gt;, then &lt;code&gt;git checkout $otherbranch&lt;/code&gt; , do what you need to do , &lt;code&gt;git checkout $original &lt;/code&gt;, and &lt;code&gt;git stash apply&lt;/code&gt; to get it back.  That however, is too much of a dance for a human to do when they know everything, let alone a bit of naïve code with a stack load of broken conditional checks. Let alone the code do it right with all the other fun stuff that can occur. &lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;Do it in the Rams&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;The great thing about git, is you don't *need* to do everything in the working directory. If you know the internals well enough, you can perform the whole commit on the other directory, without ever needing to check it out.  &lt;a href="http://blog.fox.geek.nz/2009/12/dist-zilla-plugin-git-commitbuild.html"&gt;This is especially handy when one branch is purely automated generation based on another&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
With a helping hand from &lt;a href="http://search.cpan.org/perldoc?Git::PurePerl"&gt; &lt;code&gt;Git::PurePerl&lt;/code&gt;&lt;/a&gt; its possible to build everything from scratch without needing to modify files  in the working directory.  Unfortunately, the documentation is a bit sparse, the whole dist could be a bit enhanced documentation wise, but the good news is, for the most part, it works great, and its structured well enough you can work it out by reading the code.&lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;The Phases of commit generation&lt;/h3&gt;&lt;div style="text-align: justify"&gt;A commit is composed of 3 main pieces of data:&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;Commit Metadata&lt;/dt&gt;
&lt;dd&gt;Comprised of authors ( the author, and the committer), timestamps ( Commit timestamps, Author timestamps ), commit message, and an optional commit parent&lt;/dd&gt;
&lt;dt&gt;A tree object&lt;/dt&gt;
&lt;dd&gt;Every commit refers to a tree object. A tree object essentially is a list of files, and metadata about files. Tree objects can also refer to tree objects, and this forms a sort of directory structure.&lt;/dd&gt;
&lt;dt&gt;A File object&lt;/dt&gt;
&lt;dd&gt;Essentially a blob of data.&lt;/dd&gt; &lt;/dl&gt;You can read how theses objects interact, the conceptual details, their implementation, and how to create them directly in the filesystem via the &lt;code&gt;git&lt;/code&gt; command line in the ProGit book, &lt;a href="http://progit.org/book/ch9-0.html"&gt;Pro Git, Chapter 9: Git Internals&lt;/a&gt;, but this guide will focus more on how to do it with &lt;code&gt;Git::PurePerl&lt;/code&gt;, and entirely in-memory.&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;h3&gt;Injecting the files objects&lt;/h3&gt;&lt;div style="text-align: justify"&gt;DIY Commits have to be composed in reverse order, you need to create the files, then create the trees, then create the commits.&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Git::PurePerl;&lt;br /&gt;
use Git::PurePerl::NewObject::Blob;&lt;br /&gt;
&lt;br /&gt;
my $git  = Git::PurePerl-&gt;new(&lt;br /&gt;
  gitdir =&gt; '/some/dir/foo/.git' # Or use the less direct 'directory' form.&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
my $blob = Git::PurePerl::NewObject::Blob-&gt;new(&lt;br /&gt;
  content =&gt; 'String Of File Content',&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
$git-&gt;put_object( $blob );&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
Congratulations. You just stored a file blob in your git database. Although nothing refers to it at present, its not unlike a detached node in a graph, and the next time somebody calls &lt;code&gt;git prune&lt;/code&gt; in the repository, that file blob will vanish again.&lt;br /&gt;
&lt;br /&gt;
Now, lets try that again with a scattering of objects:&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Git::PurePerl;&lt;br /&gt;
use Git::PurePerl::NewObject::Blob;&lt;br /&gt;
&lt;br /&gt;
my $git  = Git::PurePerl-&gt;new(&lt;br /&gt;
  gitdir =&gt; '/some/dir/foo/.git' # Or use the less direct 'directory' form.&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
# 10 Blobs please.&lt;br /&gt;
my @blobs = map {&lt;br /&gt;
  my $blob = Git::PurePerl::NewObject::Blob-&gt;new(&lt;br /&gt;
    content =&gt; 'String Of File Content, no' . $_ ,&lt;br /&gt;
  );&lt;br /&gt;
} 1 .. 10;&lt;br /&gt;
&lt;br /&gt;
$git-&gt;put_object( $_ ) for @blobs;&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
You'll now note if you execute &lt;code&gt;git prune -n&lt;/code&gt; in your working directory, that there are 10 objects that are not attached to anything pending prune. This number should &lt;strong&gt;NOT&lt;/strong&gt; change if you re-run the above code multiple times, as content with identical SHA1's are only added to the data store once.&lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;Building Tree Objects&lt;/h3&gt;&lt;div style="text-align: justify"&gt;You now have a scattering of files. Well, more data that represents files. there's no file name or permissions metadata yet. Tree objects connect these files with their names and attributes. A tree is basically a blob with a specific content and format. The content of this blob is a series of entries.&lt;br /&gt;
&lt;br /&gt;
Every entry has 3 parts, &lt;ul&gt;&lt;li&gt;mode&lt;/li&gt;
&lt;li&gt;filename&lt;/li&gt;
&lt;li&gt;object sha1&lt;/li&gt;
&lt;/ul&gt;.&lt;br /&gt;
The sha1 is the sha1 of a thing, either a Blob, or another Tree object. The filename is a given name for that commit. The 'mode' I don't fully understand yet, all I know is &lt;q&gt;Files&lt;/q&gt; work with &lt;code&gt;100644&lt;/code&gt;, and &lt;q&gt;Trees&lt;/q&gt; work with &lt;code&gt;040000&lt;/code&gt;.&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Git::PurePerl;&lt;br /&gt;
use Git::PurePerl::NewObject::Blob;&lt;br /&gt;
use Git::PurePerl::NewObject::Tree;&lt;br /&gt;
use Git::PurePerl::NewDirectoryEntry;&lt;br /&gt;
&lt;br /&gt;
my $git  = Git::PurePerl-&gt;new(&lt;br /&gt;
  gitdir =&gt; '/some/dir/foo/.git' # Or use the less direct 'directory' form.&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
# 10 Blobs please.&lt;br /&gt;
my @blobs = map {&lt;br /&gt;
  my $blob = Git::PurePerl::NewObject::Blob-&gt;new(&lt;br /&gt;
    content =&gt; 'String Of File Content, no' . $_ ,&lt;br /&gt;
  );&lt;br /&gt;
} 1 .. 10;&lt;br /&gt;
&lt;br /&gt;
# only put the first blob on the tree.&lt;br /&gt;
my $tree = Git::PurePerl::NewObject::Tree-&gt;new(&lt;br /&gt;
  directory_entries =&gt; [&lt;br /&gt;
    Git::PurePerl::NewDirectoyEntry-&gt;new(&lt;br /&gt;
      mode =&gt; 100644,&lt;br /&gt;
      filename =&gt; "FooFile",&lt;br /&gt;
      sha1 =&gt; $blobs[0]-&gt;sha1,&lt;br /&gt;
    )&lt;br /&gt;
  ],&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
# stash blobs&lt;br /&gt;
$git-&gt;put_object( $_ ) for @blobs;&lt;br /&gt;
# stash tree&lt;br /&gt;
$git-&gt;put_object( $tree );&lt;br /&gt;
&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
Now, as with above, there's still no commit these are bound to. They're just floating bits of data.&lt;br /&gt;
Also, we probably want a dir or 2.&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Git::PurePerl;&lt;br /&gt;
use Git::PurePerl::NewObject::Blob;&lt;br /&gt;
use Git::PurePerl::NewObject::Tree;&lt;br /&gt;
use Git::PurePerl::NewDirectoryEntry;&lt;br /&gt;
&lt;br /&gt;
my $git  = Git::PurePerl-&gt;new(&lt;br /&gt;
  gitdir =&gt; '/some/dir/foo/.git' # Or use the less direct 'directory' form.&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
# 10 Blobs please.&lt;br /&gt;
my @blobs = map {&lt;br /&gt;
  my $blob = Git::PurePerl::NewObject::Blob-&gt;new(&lt;br /&gt;
    content =&gt; 'String Of File Content, no' . $_ ,&lt;br /&gt;
  );&lt;br /&gt;
} 1 .. 10;&lt;br /&gt;
&lt;br /&gt;
my $i = 0;&lt;br /&gt;
my @direntries = map {&lt;br /&gt;
  $i++;&lt;br /&gt;
  Git::PurePerl::NewDirectoyEntry-&gt;new(&lt;br /&gt;
    mode =&gt; 100644,&lt;br /&gt;
    filename =&gt; "FooFile_$i",&lt;br /&gt;
    sha1 =&gt; $_-&gt;sha1,&lt;br /&gt;
  )&lt;br /&gt;
} @blobs;&lt;br /&gt;
&lt;br /&gt;
my ( @treeblobs );&lt;br /&gt;
&lt;br /&gt;
my (@dira, @dirb);&lt;br /&gt;
@dira = splice @direntries, 0, 5, ();&lt;br /&gt;
@dirb = splice @direntries, 0, 3, ();&lt;br /&gt;
&lt;br /&gt;
my $tree_dira = Git::PurePerl::NewObject::Tree-&gt;new(&lt;br /&gt;
  directory_entries =&gt; \@dira,&lt;br /&gt;
);&lt;br /&gt;
push @treeblobs, $tree_dira;&lt;br /&gt;
&lt;br /&gt;
my $tree_dirb = Git::PurePerl::NewObject::Tree-&gt;new(&lt;br /&gt;
  directory_entries =&gt; \@dirb,&lt;br /&gt;
);&lt;br /&gt;
push @treeblobs, $tree_dirb;&lt;br /&gt;
&lt;br /&gt;
my $root_tree = Git::PurePerl::NewObject::Tree-&gt;new(&lt;br /&gt;
  directory_entries =&gt; [&lt;br /&gt;
    @direntries,&lt;br /&gt;
    Git::PurePerl::NewDirectoryEntry-&gt;new(&lt;br /&gt;
      mode =&gt; 040000,&lt;br /&gt;
      filename =&gt; 'SubDir_A',&lt;br /&gt;
      sha1 =&gt; $tree_dira-&gt;sha1,&lt;br /&gt;
    ),&lt;br /&gt;
    Git::PurePerl::NewDirectoryEntry-&gt;new(&lt;br /&gt;
      mode =&gt; 040000,&lt;br /&gt;
      filename =&gt; 'SubDir_B',&lt;br /&gt;
      sha1 =&gt; $tree_dirb-&gt;sha1,&lt;br /&gt;
    ),&lt;br /&gt;
  ]&lt;br /&gt;
);&lt;br /&gt;
push @treeblobs, $root_tree;&lt;br /&gt;
&lt;br /&gt;
# stash blobs&lt;br /&gt;
$git-&gt;put_object( $_ ) for @blobs;&lt;br /&gt;
$git-&gt;put_object( $_ ) for @treeblobs;&lt;br /&gt;
&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Horray, all going to plan, you now have a simple digraph of data in git!.&lt;br /&gt;
There is still no root node, so &lt;code&gt;git prune&lt;/code&gt; will still delete them all, but we're almost there.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Commit it!&lt;/h3&gt;This is the finishing touch. Once you do this, the object will hold its own in the datastore, and all be written in the metadata.&lt;br /&gt;
&lt;br /&gt;
We need: &lt;ol&gt;&lt;li&gt;Authors&lt;/li&gt;
&lt;li&gt;Timestamps&lt;/li&gt;
&lt;li&gt;Commit messages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional:&lt;/strong&gt; parent commit&lt;/li&gt;
&lt;li&gt;Target branch&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;h4&gt;Important Note about parent&lt;/h4&gt;. Although parent is optional, you shouldn't treat it as such unless you know what you're doing, or there is in fact no parent ( ie: its a brand spanking new branch, aka, a new symbolic ref). As git is represented as a chain:&lt;br /&gt;
&lt;pre&gt;[branch]-&gt;{commit}
             -V
            {commit}
             -V
            {commit}
&lt;/pre&gt;and a "branch" is pretty-much a pointer to the head commit of a series, creating a singular commit at the end of a branch with no parent behaves the same as if you had &lt;strong&gt;DELETED THE WHOLE BRANCH, created a new, history-less symbolic-ref with the same name, and committed the commit to it, leaving a branch history of 1 item&lt;/strong&gt;&lt;br /&gt;
We &lt;strong&gt;strongly&lt;/strong&gt; recommend you use this field.&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Git::PurePerl;&lt;br /&gt;
use Git::PurePerl::NewObject::Blob;&lt;br /&gt;
use Git::PurePerl::NewObject::Tree;&lt;br /&gt;
use Git::PurePerl::NewDirectoryEntry;&lt;br /&gt;
use Git::PurePerl::NewObject::Commit;&lt;br /&gt;
use Git::PurePerl::Actor;&lt;br /&gt;
use DateTime;&lt;br /&gt;
&lt;br /&gt;
my $git  = Git::PurePerl-&gt;new(&lt;br /&gt;
  gitdir =&gt; '/some/dir/foo/.git' # Or use the less direct 'directory' form.&lt;br /&gt;
);&lt;br /&gt;
# Snip&lt;br /&gt;
# ....&lt;br /&gt;
# Snip&lt;br /&gt;
&lt;br /&gt;
my $root_tree = something();&lt;br /&gt;
&lt;br /&gt;
# Create the commit author.&lt;br /&gt;
my $author = Git::PurePerl::Actor-&gt;new(&lt;br /&gt;
  name =&gt; "Bob Smith",&lt;br /&gt;
  email =&gt; "BobSmith@example.com",&lt;br /&gt;
);&lt;br /&gt;
my $timestamp = DateTime-&gt;now();&lt;br /&gt;
&lt;br /&gt;
my @parent;&lt;br /&gt;
if ( 0 ){&lt;br /&gt;
# Optional code block to determine parent commit id.&lt;br /&gt;
  my $p = $git-&gt;ref_sha1('refs/heads/thebranchname');&lt;br /&gt;
  @parent = ( parent =&gt; $p );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
my $commit = Git::PurePerl::NewObject::Commit-&gt;new(&lt;br /&gt;
  tree =&gt; $root_tree-&gt;sha1,&lt;br /&gt;
  author =&gt; $author,&lt;br /&gt;
  authored_time =&gt; $timestamp,&lt;br /&gt;
  committer =&gt; $author,&lt;br /&gt;
  committed_time =&gt; $timestamp,&lt;br /&gt;
  comment =&gt; &lt;&lt;'EOF';

This is a commit message!11!!.

EOF
  
);
  
  
# stash blobs
$git-&gt;put_object( $_ ) for @blobs;&lt;br /&gt;
$git-&gt;put_object( $_ ) for @treeblobs;&lt;br /&gt;
$git-&gt;put_object( $_, 'thebranchname') for ( $commit );&lt;br /&gt;
&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt; and that's it!&lt;/strong&gt;. There is a new commit in the repository with the data you ascribed =)&lt;br /&gt;
&lt;br /&gt;
There has been only one visible change as far as the filesystem is concerned, and that's the current checked out branch has been changed from whatever it was on, to 'thebranchname'. For our intents, this is not what we want, as this drops the whole thing we were trying to achieve of "nothing outside of this code should have any substantial visible effect".&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;Disabling the branch switch&lt;/h3&gt;&lt;div style="text-align: justify;"&gt;The comments in the code indicate there may be a future time at which we don't have to work around this behaviour, but until now, here is a good WorksForMe™ way to do it.&lt;br /&gt;
&lt;pre class="perl"&gt;&lt;br /&gt;
sub Git::PurePerl::put_object_noswitch {&lt;br /&gt;
  my ( $self, $object, $ref ) = @_;&lt;br /&gt;
  $self-&gt;loose-&gt;put_object($object);&lt;br /&gt;
&lt;br /&gt;
  return unless ( $object-&gt;kind eq 'commit' );&lt;br /&gt;
&lt;br /&gt;
  $refname = 'master' unless $refname;&lt;br /&gt;
  $self-&gt;update_ref_sane( $ref, $object-&gt;sha1 );&lt;br /&gt;
  my $ref = Path::Class::file( $self-&gt;gitdir, 'refs', 'heads', $refname );&lt;br /&gt;
  $ref-&gt;parent-&gt;mkpath;&lt;br /&gt;
  my $ref_fh = $ref-&gt;openw;&lt;br /&gt;
  $ref_fh-&gt;print($object-&gt;sha1) || die "Error writing to $ref";&lt;br /&gt;
}&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;/div&gt;&lt;h3&gt;Thanks for reading/Inspiration/Rationale&lt;/h3&gt;This document is presently serving as a convenient ways to get my mind state onto print, a brain dump, so I can get the logic of things I'm doing nice and clear. As a result of the above code, which I think is  bit too complicated for somebody who wishes to use it for commit purposes, I've started on &lt;strong&gt;&lt;a href="http://blog.fox.geek.nz/2009/12/preannouncing-in-progress.html"&gt;Git::PurePerl::CommitBuilder&lt;/a&gt;&lt;/strong&gt; that will hopefully provide a much more friendly UI for that purpose than the one above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-2213191591206270857?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-OxHez1BQcdeK8oh6GexCTmYQWI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-OxHez1BQcdeK8oh6GexCTmYQWI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-OxHez1BQcdeK8oh6GexCTmYQWI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-OxHez1BQcdeK8oh6GexCTmYQWI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/tN31AV_S7Kk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/2213191591206270857/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2009/12/building-commits-from-scratch-using.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/2213191591206270857?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/2213191591206270857?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/tN31AV_S7Kk/building-commits-from-scratch-using.html" title="Building Commits from scratch using Git::PurePerl" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2009/12/building-commits-from-scratch-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8BRXk5fCp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-3335046042683351737</id><published>2009-12-03T03:06:00.002+13:00</published><updated>2010-06-27T08:24:14.724+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T08:24:14.724+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="git" /><category scheme="http://www.blogger.com/atom/ns#" term="feature-request" /><category scheme="http://www.blogger.com/atom/ns#" term="Dist::Zilla" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><category scheme="http://www.blogger.com/atom/ns#" term="module" /><title>Dist-Zilla-Plugin-Git-CommitBuild</title><content type="html">&lt;div style="text-align: justify;"&gt;I've contemplated this for a while. I might get a round tuit, and do this myself, so this blog entry is here to jog my brain, jot down ideas, possibly collect info.&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;If you look at the repositories behind any of my CPAN dists ( well, most of them ), you'll see I maintain both release and source branches for the entire history ( &lt;a href="http://github.com/kentfredric/ELF-Extract-Sections/network"&gt;http://github.com/kentfredric/ELF-Extract-Sections/network&lt;/a&gt; ), and more recently, maintaining a sort of "pre-release/release" sub-system, where stuff I build just for testing/preview purposes may have a life on their own branch, sort of like release candidates.&amp;nbsp; &lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This is essentially to provide a branch that is containing a full copy of all the generated code, as posted on CPAN, as opposed to the source that it is generated from, for posterity reasons mostly, and so I can deprecate versions on CPAN for incompatibility reasons one day , and people won't be left in the lurch to get an identical copy of it somewhere, as it will always be in the git history, just grab the right tag and you're set. &lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;They could always use the backpan, but that has 2 caveats in my experience.&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;ol style="text-align: justify;"&gt;&lt;li&gt;&amp;nbsp;No diff mechanism. This feature is very important to people who do release maintenance for distributions, as&amp;nbsp; its the only good way to conclusively see what exactly changed between 2 consecutive versions, in order to update their internal dependency data that controls the shipping of the built copies. &lt;br /&gt;
&lt;br /&gt;
For this reason also, I loathe every time somebody deletes an older copy of their dist when its not been outdated for &amp;lt; 3 months, because it can take that long to notice that the shipped copy is outdated and for somebody to request a version bump. Not being able to use CPAN's &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;diff&lt;/span&gt; &lt;span style="font-family: inherit;"&gt;feature makes this task much more challenging. ( At least for me, for that is how I do my work-flow, and I kind-of help out lots with &lt;a href="http://git.overlays.gentoo.org/gitweb/?p=proj/perl-overlay.git;a=summary"&gt;gentoo's perl-experimental overlay&lt;/a&gt; ).&lt;br /&gt;
&lt;br /&gt;
&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Sometimes, versions live too short a time to be backed up on backpan. This is very problematic, for the above reason, and for the reason is you have no historical record of what happened outside the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt;, and the original commit history.&amp;nbsp; You could probably argue there's no reason to ever want these version that never made it to backpan, and you'd probably be right.&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;div style="text-align: justify;"&gt;So to remedy this problem, here is what I do.&lt;br /&gt;
&lt;/div&gt;&lt;ol&gt;&lt;li style="text-align: justify;"&gt; Commit, and tag the exact source tree that was used to generate the released code in the notation &lt;span style="font-size: xx-small;"&gt;%v-source&lt;/span&gt;. This theoretically guarantees that anyone can check out that exact same release, run "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dzil release&lt;/span&gt;", and produce more or less the exact same output, with the only difference possibly being the version numbers emitted if you're using an &lt;a href="http://search.cpan.org/dist/Dist-Zilla/lib/Dist/Zilla/Plugin/AutoVersion.pm"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[AutoVersion]&lt;/span&gt;&lt;/a&gt; or &lt;a href="http://search.cpan.org/dist/Dist-Zilla-Plugin-AutoVersion-Relative/lib/Dist/Zilla/Plugin/AutoVersion/Relative.pm"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[AutoVersion::Relative]&lt;/span&gt;&lt;/a&gt; plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
Here is the code snippet I use to do this that uses &lt;a href="http://jquelin.blogspot.com/"&gt;Jerome Quelin's&lt;/a&gt; &lt;a href="http://search.cpan.org/dist/Dist-Zilla-Plugin-Git/"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[Git]&lt;/span&gt;&lt;/a&gt; plugin suite.&lt;br /&gt;
&lt;/div&gt;&lt;blockquote&gt;&lt;pre class="ini"&gt;[Git::Check]&lt;br /&gt;
filename = Changes&lt;br /&gt;
&lt;br /&gt;
[NextRelease]&lt;br /&gt;
&lt;br /&gt;
[Git::Tag]&lt;br /&gt;
filename = Changes&lt;br /&gt;
tag_format = %v-source&lt;br /&gt;
&lt;br /&gt;
[Git::Commit]&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;This Order is important. In the Build phase, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[NextRelease]&lt;/span&gt; formats the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt; template into an exportable form, and puts the datestamp in it.&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;In the pre-release phase, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[Git::Check]&lt;/span&gt; makes sure theres nothing in the tree that isn't committed.&lt;br /&gt;
&lt;/div&gt;&lt;div style="font-family: inherit; text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[UploadToCpan]&lt;/span&gt;uploads the dist to CPAN, and the post-release phase kicks in.&lt;br style="font-family: inherit;" /&gt; &lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[NextRelease]&lt;span style="font-family: inherit;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;&amp;nbsp; then kicks in again, and reformats the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt; so it resembles the previously released &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt; except with that &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;{{$NEXT}} &lt;/span&gt;stuff in it ready for hacking on.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[Git::Tag]&amp;nbsp;&lt;/span&gt; tags the last commit ( that is, not the current tree with the modified &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt;, that's not committed yet, but the commit that it was at still when we released ) with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;%v-source&lt;/span&gt;, and then &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[Git::Commit]&lt;/span&gt; commits the updated &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt; as a new commit ( with a copy of the first segment of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Changes&lt;/span&gt; file as its commit message )&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Have a separate commit history just for releases to be copied into. &lt;br /&gt;
&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;git symbolic-ref HEAD refs/heads/releases&lt;/span&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;The first commit of this is built, generally from the first releases files. At present, I do this first release as so:&lt;br /&gt;
&lt;/div&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;rsync -avp Some-Dist-Name-0.010101/ ./&lt;br /&gt;
&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;then weed out all the files I'm pretty sure weren't in the generated tree by hand. ( I had a some code that did it all with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;rsync&lt;/span&gt;, and had an ignore list so that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;--delete-after &lt;/span&gt;argument didn't accidentally erase all of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;.git&lt;/span&gt;, which would be very sad, but I accidentally deleted it :[&amp;nbsp; )&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This tree now represents an exact copy of the generated code, and it is committed as follows:&lt;br /&gt;
&lt;/div&gt;&lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;git commit -m "Build of 0deadbeef0, version 0.010101 on cpan" &lt;/span&gt;&lt;br /&gt;
&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;or similar, to assure that every commit on the release branch, is a direct derivative of another commit on the source branch, and there's an intrinsic link between them.&amp;nbsp; ( I avoided having a direct link, because that gives cleaner histories ).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;That commit is tagged as the released version, ( ie: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;0.010101&lt;/span&gt; )&lt;/li&gt;
&lt;/ol&gt;Now all this is wonderfully Tedious. At present, the best I have &lt;a href="http://gist.github.com/247201"&gt;a script&lt;/a&gt; that makes the "commit and tag" phase on the release branch reasonably painless, but what I want to do, is have a nice way, to automate all of the above, every single bit of it, with a plugin.&lt;br /&gt;
&lt;br /&gt;
Here is some proposed syntax.&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&lt;pre class="ini" style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[Git::CommitBuild / prerelease ]&lt;br /&gt;
branch = prereleases&lt;br /&gt;
autocreate = 1&lt;br /&gt;
phase = build&lt;br /&gt;
&lt;br /&gt;
[Git::CommitBuild / release]&lt;br /&gt;
branch = releases&lt;br /&gt;
autocreate = 1&lt;br /&gt;
phase = after_release&lt;br /&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;/blockquote&gt;&amp;nbsp;Why this notation? well, I guess it just seems the right amount of flexible to me.&lt;br /&gt;
the text after the&amp;nbsp; / is totally optional, and its just a way to let dzil differentiate between copies of the same plugin. &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;branch&lt;/span&gt; is to tell it what git branch to work with. I figgured I could just use the name part after the&amp;nbsp; /, but it seemed nasty to me ( spaces for instance ). At very best, it could default to that value if &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;branch =&lt;/span&gt; is not specified.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;autocreate = 1&lt;/span&gt; would magick the branch out of fat air the first time you tried to commit to it and it wasn't there. This would be off by default, as it could be annoying to you if you'd already created another branch with a different name for that purpose, and typoed and it created another branch. This way it fails instead of annoying you.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;phase =&lt;/span&gt; build is sadly the most scary bit I'm trying to eliminate the stink of. Essentially, I have one plugin that does only one thing, but there are 2 different times I may want to run it at. ( And there are possibly more places people might want to say "stop the build, store this somewhere, then continue" ).&amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
In the above scenario, 'prerelease' I envisage as only getting run when I call "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dzil build&lt;/span&gt;" explicitly. &lt;b&gt;NOT&lt;/b&gt; '&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dzil test&lt;/span&gt;' and &lt;b&gt;NOT&lt;/b&gt; '&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dzil release&lt;/span&gt;', only '&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;dzil build&lt;/span&gt;'.&lt;br /&gt;
&lt;br /&gt;
Also, Ideally, the whole commit phase should be done, magically, entirely in memory, with some magical git magic, to eliminate the whole "write it out to the filesystem before creating the actual commit data" part of the equation, so that nowhere anywhere does there transpire something like &lt;blockquote&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;git checkout releases&lt;br /&gt;
git commit stuff&lt;br /&gt;
git checkout master&lt;/span&gt;&lt;/blockquote&gt;which causes anarchy in the event anything else happened to be using the file-system. &lt;br /&gt;
&lt;br /&gt;
Thoughts/Suggestions anyone?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-3335046042683351737?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mE0EEVjvSgTvAt5TflJF_aQnHTw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mE0EEVjvSgTvAt5TflJF_aQnHTw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mE0EEVjvSgTvAt5TflJF_aQnHTw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mE0EEVjvSgTvAt5TflJF_aQnHTw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/97vGgnA3nqE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/3335046042683351737/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2009/12/dist-zilla-plugin-git-commitbuild.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/3335046042683351737?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/3335046042683351737?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/97vGgnA3nqE/dist-zilla-plugin-git-commitbuild.html" title="Dist-Zilla-Plugin-Git-CommitBuild" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2009/12/dist-zilla-plugin-git-commitbuild.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIBQ3c-cSp7ImA9WxFUFUU.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-2021105091938171067</id><published>2009-12-02T02:18:00.007+13:00</published><updated>2010-06-27T08:35:52.959+12:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T08:35:52.959+12:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ideas" /><category scheme="http://www.blogger.com/atom/ns#" term="metaprogramming" /><category scheme="http://www.blogger.com/atom/ns#" term="ast" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>Code Wanted: Abstract Syntax Tree to Perl Code compiler</title><content type="html">WANTED:&lt;pre class="perl"&gt;

use AST::Assembler qw( :all );

# Code Generation Via AST.

my $code = context( 
  package_def('Foo', context(
        use_declaration('Moose'),
        call_sub('with', package =&gt; CURRENTCONTEXT, args =&gt; list( 'Some::Role' )),
        def_sub('bar', context( 
           def_var(['x','y','z], 'context' =&gt; CURRENTCONTEXT),
           assign(['x','y','z',], STACK ),
           assign('z', add('x','y')),
           return('z'),
        ))
  ))
);

# AST Augmentation.
$code-&gt;find('def_sub')-&gt;grep(sub{ $_[0] eq 'bar' })-&gt;find('assign')-&gt;grep(sub{ $_[0] eq 'z' })-&gt;before(assign('x',sub(0,'x')));

my $codestr = $code-&gt;to_perl; 

# --&gt;&lt;/pre&gt;
&lt;pre class="darkperl" style="background-color: #EEE; padding: 5px;"&gt;
package Foo;
use Moose;
with "Some::Role";
sub bar { 
  my ( $x,$y, $z);
  ($x,$y,$z) = (@_);
  $x = 0 - $x;  # inserted by augmentation.
  $z = ( $x + $y )
  return $z;
}   
&lt;/pre&gt;
&lt;pre class="perl"&gt;
$code-&gt;optimise-&gt;to_perl
&lt;/pre&gt;
&lt;pre class="darkperl" style="background-color: #EEE; padding: 5px;"&gt;
package Foo;
use Moose;
with "Some::Role";
sub bar { 
  return ( ( 0 - $_[0] ) + $_[1] )
}
&lt;/pre&gt;
&lt;pre class="perl"&gt;
$code-&gt;find('package_def', [ 0 , 'eq' , 'Foo' ])-&gt;child('context')-&gt;append(callsub('bar',args=&gt;list('1','2','3')));

$code-&gt;optimise-&gt;to_perl
&lt;/pre&gt;
&lt;pre class="darkperl" style="background-color: #EEE; padding: 5px;"&gt;
package Foo;
use Moose;
with "Some::Role";
sub bar { 
  return ( ( 0 - $_[0] ) + $_[1] )
}

( ( 0 - '1' ) + '2' )
&lt;/pre&gt;
&lt;br /&gt;
Its just an insane starting point for code generation. Somebody run with it and make it not suck :)&lt;br /&gt;
&lt;br /&gt;
Once we get a working AST to Perl code thing, maybe somebody can consider doing the inverse ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-2021105091938171067?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CNksKw_aAlmMIJbCAXVAg3HjSMc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CNksKw_aAlmMIJbCAXVAg3HjSMc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CNksKw_aAlmMIJbCAXVAg3HjSMc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CNksKw_aAlmMIJbCAXVAg3HjSMc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/-jnrlReMtow" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/2021105091938171067/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2009/12/code-wanted-abstract-syntax-tree-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/2021105091938171067?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/2021105091938171067?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/-jnrlReMtow/code-wanted-abstract-syntax-tree-to.html" title="Code Wanted: Abstract Syntax Tree to Perl Code compiler" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2009/12/code-wanted-abstract-syntax-tree-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QHRnY9fip7ImA9WxNaFkg.&quot;"><id>tag:blogger.com,1999:blog-6533723486908610755.post-834879884523899500</id><published>2009-12-01T22:11:00.001+13:00</published><updated>2009-12-01T22:22:17.866+13:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-01T22:22:17.866+13:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="software" /><category scheme="http://www.blogger.com/atom/ns#" term="blogging" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><category scheme="http://www.blogger.com/atom/ns#" term="meta" /><title>Initial Metablog/The State of the blogsphere</title><content type="html">&lt;div style="background-color: rgba( 240,240,240, 0.9 ); border: 1px solid #BBB; font-size: 70%; text-align: center; padding: 20px;"&gt;I heavily encourage people to contradict me, tell me where I am frankly wrong, if you're not even sure I'm wrong and think I might be, and have some reasons, go ahead, point them out, I actively encourage criticism, because I actively wish to correct my own failings&lt;/div&gt;&lt;div style="text-align: justify"&gt;Well, this is a new blog. One of the standard initiation rites is to write a blog about blogging&lt;sup id="fromfoot1"&gt;&lt;a href="#foot1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;br /&gt;
&lt;br /&gt;
Instead of going on a fork about blogging techniques and whatnot, I'm just going to lament about the sad state of blogging platforms that don't suck and JustWork, and why I eventually chose Blogger.&lt;ul&gt;&lt;li&gt;&lt;a href="#DoItYourself"&gt;Do It Yourself&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#SelfHosted"&gt;{{ $InsertProjectNameHere }} Hosted On Your Own Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#Services"&gt;3rd Party Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;h3 id="DoItYourself"&gt;Do It Yourself.&lt;/h3&gt;&lt;div style="text-align: justify"&gt;People I've seen have this penchant to hard-code and rewrite their own blogs from scratch. &lt;br /&gt;
&lt;br /&gt;
This concept to me is Made With Fail™.&lt;br /&gt;
&lt;br /&gt;
Sure, you get exactly what you want, but you also have the blissfully joyful task of maintaining &lt;em&gt;everything&lt;/em&gt; yourself, and making all the fun calls about how to handle commenting, aggregation, and all that sort of stuff, and its just too much work. &lt;br /&gt;
&lt;br /&gt;
Doing that sort of stuff for a living is challenging enough, let alone having to do it for a living &lt;strong&gt;and&lt;/strong&gt; yourself at the same time, which is just too much work.&lt;/div&gt;&lt;h3 id="SelfHosted"&gt;{{ $InsertProjectNameHere }} Hosted On Your Own Server&lt;/h3&gt;&lt;div style="text-align: justify"&gt;This is a substantially better option verses &lt;a href="#DoItYourself"&gt; Do It Yourself &lt;/a&gt;, you don't have to worry so much about code maintenance.&lt;br /&gt;
&lt;br /&gt;
However, you still have to worry about host security, and how safe the code really is. After all, you're paying for that server, and have pissy entry-level grade database support&lt;sup id="fromfoot2"&gt;&lt;a href="#foot2"&gt;2&lt;/a&gt;&lt;/sup&gt;, and you sort of have the worry much of the time of keeping your host platform up-to-date and secure, and keeping your blogging software up to date and secure.&lt;br /&gt;
&lt;br /&gt;
Additionally, the average designed-for-self-hosting project appears to have lots of associated stupidity, and the arbitrary hoop jumping install phase and arbitrary hoop jumping configuration, and the bizarre do-it-all-by-hand database setup stuff, which I'm really sick of, combined with the fact they often don't even have documentation or support for non-apache web-servers&lt;sup id="fromfoot3"&gt;&lt;a href="#foot3"&gt;3&lt;/a&gt;&lt;/sup&gt;, or require some magically odd setup for apache which has since been deprecated by the distribution you're trying to install it on.&lt;/div&gt;&lt;h3 id="Services"&gt;3rd Party Service&lt;/h3&gt;&lt;div style="text-align: justify"&gt;Eliminating the above 2 choices leaves me with only the logical conclusion of utilising some 3rd party service.  This absolves me of the need to worry about the hosting and software requirements of the platform, and let their team of dedicated staff handle those problems. &lt;br /&gt;
&lt;br /&gt;
Sure, there's the caveat of "if something doesn't work, you can't fix it yourself", but they know more about their software than I do. You get about as much benefit here as with {{$ProjectName}} built from code you don't grok, and don't have time to grok.&lt;br /&gt;
&lt;br /&gt;
Then we go down to the list of features that matter to you:&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;1. DNS Support&lt;/dt&gt;
&lt;dd&gt; Being able to map the Blog under your own site of choosing is a must have feature. Some services charge for the luxury of doing this, others, its standard issue.&lt;/dd&gt;
&lt;dt&gt;2. Free&lt;/dt&gt;
&lt;dd&gt;This, is also important for me, if you can't get the most out of  a service for free, its not worth it. Pay-for blogging services are a huge turnoff&lt;/dd&gt;
&lt;dt&gt;3. All The Mundane things worked out for you&lt;/dt&gt;
&lt;dd&gt;It should be easy by default, and you can just Start Using It, and have capacity for power later.&lt;/dd&gt;
&lt;dt&gt;4. Feed Production&lt;/dt&gt;
&lt;dd&gt;A must have: not everybody wants to be forced to browse your site via a web-browser, and feeds are much more convenient for them&lt;/dd&gt;
&lt;dt&gt;5. Simple Advertisement Integration&lt;/dt&gt;
&lt;dd&gt;I know ads are a bit nasty, but sometimes a guy isn't making enough money to get by on, and throwing up some much needed adverts can help contribute to some much needed denero. Simplicity is also important, because one day if I decide I want to change them, or rip them out all together, I want minimal migration pain.&lt;/dd&gt;
&lt;dt&gt;6. Simple themes by default that look great&lt;/dt&gt;
&lt;dd&gt;There's nothing worse than a site with a theme that screams "I was born in the geocities era." , and as a coder, not a graphic designer, my eye for style tends towards looking pretty brutal. As I'm not a designer, I want something that looks good, and requires none of my time to maintain it. &lt;/dd&gt;
&lt;dt&gt;7. No HTML Restrictions&lt;/dt&gt;
&lt;dd&gt;Ideally, you should be able to avoid manually hacking html for the most part, but should you feel the need to extend it, there should be no limitations on how you can lay out stuff, theme it, and format it. Anything that puts restrictions on what I can put in the code or tries to "magic" my insertions into something else get epic beatings from me.&lt;/dd&gt;&lt;/dl&gt;&lt;br /&gt;
And now for the blogging services.&lt;br /&gt;
&lt;dl&gt;&lt;dt&gt;1. LiveJournal&lt;/dt&gt;
&lt;dd&gt;I've been using this off and on for mundane stuff, but its hopeless for a blog of technical merit. Pointing somebody to your LJ blog invokes the whole "hurr" mental result. Its too arcane, too old, and over the top restrictive with decade old use models. It contravenes goals 1,2, 5, 6 and 7 in my experiences, it has this nasty "skin" oriented theme thing which sucks epically hard. And you have to be a premium member ( $$$ ) to get the maximum use out of it. The best you can do is get a semi-premium account by proliferating it with adverts that work for LiveJournal, not for you. You can't get a dns association without being a premium member. &lt;/dd&gt;
&lt;dt&gt;2. WordPress&lt;/dt&gt;
&lt;dd&gt;I don't want to go into this one, but eww. Whats not to hate about Wordpress?. Its far too noisy. Like LJ, it plunders you with adverts, and you have to pay to get rid of them. And it appears to me there's not much in the way of goal 1,5 and 7. The whole plugin architecture they have is just an abuse farm festering under the hood.&lt;/dd&gt;
&lt;dt&gt;3. blogs.perl.org&lt;/dt&gt;
&lt;dd&gt;Too new, and hideously broken for me all the time. Apparently no support for proper per-domain blogs, and you're all like different bloggers using the same site. Sorry, signal to noise far too high for me. &lt;/dd&gt;
&lt;dt&gt;4. use.perl.org blogs&lt;/dt&gt;
&lt;dd&gt;Ugly as sin, user interface like a leather bag over the head. Hopeless RSS. No DNS. No themes. Overcomplicated. &lt;/dd&gt;
&lt;dt&gt;5. TypePad&lt;/dt&gt;
&lt;dd&gt;Pay for only. Won't even attempt to use it. Teired pricing for different features is a bigger turnoff still. I don't own a VISA, and don't want one, which makes it simply &lt;em&gt;impossible&lt;/em&gt; to do anything that incurrs international payments ( I might cover this at  a latter time ).&lt;/dd&gt;
&lt;dt&gt;6. Vox&lt;/dt&gt;
&lt;dd&gt;This seems the best of breed with regard to the Perl options I've seen so far,  but the interface is too heavy, too much chrome that can't be turned off, the site is so dizzying in complexity, that its not "Just a frickn blog" like I want, its a whole damned social blogging network thing, and that's awful. Its looking too much like its trying to be live journal. As for the desired features, I can't tell what it does, what features I really want, it doesn't appear to mention them , anywhere, and I'd only be able to work it out if I signed up. I highly doubt DNS control though. &lt;/dd&gt; &lt;/dl&gt;So I've settled for Blogger. It just seems to suck less for the things I want to do.&lt;br /&gt;
&lt;/div&gt;&lt;div style="background-color: rgba( 240,240,240, 0.9 ); border: 1px solid #BBB; font-size: 70%; text-align: center; padding: 20px; "&gt;I heavily encourage people to contradict me, tell me where I am frankly wrong, if you're not even sure I'm wrong and think I might be, and have some reasons, go ahead, point them out, I actively encourage criticism, because I actively wish to correct my own failings&lt;/div&gt;&lt;div style="text-align: justify" name="footnote"&gt;&lt;sub id="foot1"&gt;&lt;a href="#fromfoot1"&gt;1.&lt;/a&gt; I'm now blogging about blogging about blogging, so meta-level just keeps growing.&lt;/sub&gt;&lt;br /&gt;
&lt;sub id="foot2"&gt;&lt;a href="#fromfoot2"&gt;2.&lt;/a&gt;That is, I'm betting you don't have replication and backups to high-heaven  for your average self-hosted project.&lt;/sub&gt;&lt;br /&gt;
&lt;sub id="foot3"&gt;&lt;a href="#fromfoot3"&gt;3.&lt;/a&gt;Which is especially problematic if you cant even run apache because the bloated thing consumes &lt;strong&gt;all&lt;/strong&gt; the available memory on your cheap XEN VPS, and then starts hardcore swapping to disk, and the site becomes inaccessible as soon as a crawler hits it.&lt;/sub&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6533723486908610755-834879884523899500?l=blog.fox.geek.nz' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JY8nMV1lDMFSu1MKyfWDfpS7R7M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JY8nMV1lDMFSu1MKyfWDfpS7R7M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JY8nMV1lDMFSu1MKyfWDfpS7R7M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JY8nMV1lDMFSu1MKyfWDfpS7R7M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/kentnl/~4/Jk4rhX86V_4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.fox.geek.nz/feeds/834879884523899500/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.fox.geek.nz/2009/12/initial-metablogthe-state-of-blogsphere.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/834879884523899500?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6533723486908610755/posts/default/834879884523899500?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/kentnl/~3/Jk4rhX86V_4/initial-metablogthe-state-of-blogsphere.html" title="Initial Metablog/The State of the blogsphere" /><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="13851482182989892275" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.fox.geek.nz/2009/12/initial-metablogthe-state-of-blogsphere.html</feedburner:origLink></entry></feed>
