<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6533723486908610755</id><updated>2022-01-23T21:50:07.671+13:00</updated><category term="perl"/><category term="git"/><category term="Gentoo"/><category term="lazyweb"/><category term="module"/><category term="Dist::Zilla"/><category term="Git::PurePerl"/><category term="cpanm"/><category term="cpanminus"/><category term="exceptions"/><category term="file"/><category term="limitations"/><category term="moose"/><category term="perlbrew"/><category term="portage"/><category term="require"/><category term=".la"/><category term="0x0273"/><category term="1510"/><category term="A10"/><category term="Git::PurePerl::CommitBuilder"/><category term="MooseX::Declare"/><category term="OpenBSD"/><category term="PerlTidy"/><category term="X"/><category term="X11"/><category term="Xauthority"/><category term="Xorg"/><category term="adoption"/><category term="ast"/><category term="bios"/><category term="blogging"/><category term="bug"/><category term="class::load"/><category term="community"/><category term="create"/><category term="data"/><category term="dell"/><category term="design"/><category term="directory"/><category term="discipline"/><category term="dotfile"/><category term="dzil"/><category term="error"/><category term="explorer"/><category term="feature-request"/><category term="file::sharedir"/><category term="firefox"/><category term="flash"/><category term="guide"/><category term="halps"/><category term="handle"/><category term="howto"/><category term="ideas"/><category term="lafilefixer"/><category term="libpng12"/><category term="linux"/><category term="lol"/><category term="maintenance"/><category term="mathnotation"/><category term="meta"/><category term="metaprogramming"/><category term="microsoft"/><category term="minting"/><category term="mozilla"/><category term="optional"/><category term="paludis"/><category term="parser"/><category term="perl6"/><category term="pesky"/><category term="phishing"/><category term="profile"/><category term="rebase"/><category term="research"/><category term="root"/><category term="scam"/><category term="security"/><category term="sharedir"/><category term="software"/><category term="statistics"/><category term="suggestions"/><category term="summary"/><category term="syntax"/><category term="theory"/><category term="tutorial"/><category term="vostro"/><category term="web"/><category term="wikipedia"/><category term="windows"/><category term="workflow"/><category term="xauth"/><title type='text'>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='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-539762643872405016</id><published>2012-10-25T16:21:00.000+13:00</published><updated>2012-10-25T16:21:09.347+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="root"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><category scheme="http://www.blogger.com/atom/ns#" term="X"/><category scheme="http://www.blogger.com/atom/ns#" term="X11"/><category scheme="http://www.blogger.com/atom/ns#" term="xauth"/><category scheme="http://www.blogger.com/atom/ns#" term="Xauthority"/><category scheme="http://www.blogger.com/atom/ns#" term="Xorg"/><title type='text'>Granting Root access to all XOrg / X11 Displays on a machine.</title><content type='html'>&lt;a href=&quot;#tldr&quot;&gt;Jump &lt;strong&gt;&lt;u&gt;here&lt;/u&gt;&lt;/strong&gt; if you just want the code&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;code&gt;xauth&lt;/code&gt; is hard&lt;/h3&gt;&lt;p&gt;There are many techniques for allowing root ( or any other user ) to open programs on your display.&lt;/p&gt;&lt;p&gt;When not configured to do so, simple things don&#39;t work, and there are 2 general results you get:&lt;/p&gt;&lt;h4&gt;No previous attempt at getting &lt;code&gt;xauth&lt;/code&gt; based auth to work&lt;/h4&gt;&lt;code&gt;&lt;pre&gt;&gt; sudo gvim &lt;br /&gt;No protocol specified&lt;br /&gt;E233: cannot open display&lt;br /&gt;E852: The child process failed to start the GUI&lt;br /&gt;No protocol specified&lt;br /&gt;                                                                                             &lt;br /&gt;Press ENTER or type command to continue&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;h4&gt;With Previous attempts at using &lt;code&gt;xauth&lt;/code&gt; based auth&lt;/h4&gt;&lt;code&gt;&lt;pre&gt;Invalid MIT-MAGIC-COOKIE-1 key&lt;br /&gt;E233: cannot open display&lt;br /&gt;E852: The child process failed to start the GUI&lt;br /&gt;Invalid MIT-MAGIC-COOKIE-1 key&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This case occurs I believe due to your X display having a unique authentication key per session.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;But your display likely stores an Xauthority database somewhere on disk&lt;/h3&gt;I discovered this little gem when looking at some of the code VirtualGL/Bumblebee uses ( because it has to run a secret display as a different user, and that different user has to be able to write to your screen )&lt;br /&gt;&lt;code class=&quot;bash&quot;&gt;&lt;pre&gt;set_xauth() {&lt;br /&gt;&lt;br /&gt;# common case (works in almost all tested environments (except of lightdm)):&lt;br /&gt;XAUTHORITY=&quot;$(ps wwax -C X,Xorg -o args= --sort=-stime | grep -m 1 -o &#39;\B[-]auth\s*/var\S*auth\S*&#39; | cut -d &#39; &#39; -f 2)&quot;&lt;br /&gt;&lt;br /&gt;# kdm and some others:&lt;br /&gt;# XAUTHORITY=&quot;$(find /var/run/xauth/A${DISPLAY}-*|tail -n1)&quot;&lt;br /&gt;&lt;br /&gt;# gdm:&lt;br /&gt;# XAUTHORITY=&quot;/var/gdm/${DISPLAY}.Xauth&quot;&lt;br /&gt;&lt;br /&gt;# slim:&lt;br /&gt;# XAUTHORITY=&quot;/var/run/slim.auth&quot;&lt;br /&gt;&lt;br /&gt;# lightdm:&lt;br /&gt;# XAUTHORITY=&quot;/var/run/lightdm/root/${DISPLAY}&quot;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And as I&#39;m running &lt;code&gt;kdm&lt;/code&gt; I took a look at the relevant command.&lt;br /&gt;&lt;code class=&quot;bash&quot;&gt;&lt;br /&gt;$ find /var/run/xauth/A${DISPLAY}-*|tail -n1&lt;br /&gt;/var/run/xauth/A:0-xNjOfc&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Aha. Useful. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;sudo xauth -f /var/run/xauth/A\:0-xNjOfc  list&lt;br /&gt;#ffff##:  MIT-MAGIC-COOKIE-1  711f067eae4ec73599dc38dbfaa164f0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Oh handy. That hex code is the key you need to access the relevant display :D.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;$ xterm&lt;br /&gt;Invalid MIT-MAGIC-COOKIE-1 key&lt;br /&gt;xterm: Xt error: Can&#39;t open display: %s&lt;br /&gt;$ xauth add :0 MIT-MAGIC-COOKIE-1 700f067eae4ec73599dc38dbe7a164f1&lt;br /&gt;$ xterm &lt;br /&gt;$ # success!&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3 id=&quot;tldr&quot;&gt;Putting it all together&lt;/h3&gt;Here&#39;s a blob of shell script I have in &lt;code&gt;/root/.bash_profile&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;setup_xauth() {&lt;br /&gt; authfile=$( echo /var/run/xauth/A${DISPLAY}-* );&lt;br /&gt; if [ -z &quot;${DISPLAY}&quot; ]; then&lt;br /&gt;  return&lt;br /&gt; fi&lt;br /&gt; if [ ! -f $authfile ]; then&lt;br /&gt;  return;&lt;br /&gt; fi&lt;br /&gt; if [ ! -s $authfile ]; then&lt;br /&gt;  return;&lt;br /&gt; fi&lt;br /&gt; authtoken=$( xauth -f &quot;$authfile&quot;  nlist | cut -d&quot; &quot; -f 9 );&lt;br /&gt; xauth add $DISPLAY MIT-MAGIC-COOKIE-1 $authtoken&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;setup_xauth;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Note, its &lt;strong&gt;essential&lt;/strong&gt; that you check for read access to the file, especially if you plan on using this in a non-root users profile code.&lt;br /&gt;&lt;br /&gt;If &lt;code&gt;xauth&lt;/code&gt; can&#39;t read the authfile, it will just block and do nothing, and this is &lt;em&gt;very bad&lt;/em&gt; to have in your profile.&lt;br /&gt;&lt;br /&gt;Additionally, due to this being defined as a function, all roots shells will have a convenience function &#39;setup_xauth&#39; that you can call at any time in the event you&#39;ve had to change &lt;code&gt;$DISPLAY&lt;/code&gt;, or in the event you want to access a local X display from a &lt;code&gt;VT&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;export DISPLAY=:0&lt;br /&gt;setup_xauth&lt;br /&gt;gvim # gvim launches on :0 &lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/539762643872405016/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2012/10/granting-root-access-to-all-xorg-x11.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/539762643872405016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/539762643872405016'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2012/10/granting-root-access-to-all-xorg-x11.html' title='Granting Root access to all XOrg / X11 Displays on a machine.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>3</thr:total><georss:featurename>Christchurch</georss:featurename><georss:point>-44.339565248097124 171.9140625</georss:point><georss:box>-69.297775248097125 131.484375 -19.381355248097123 -147.65625</georss:box></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-7412950392813535648</id><published>2012-10-11T05:29:00.000+13:00</published><updated>2012-10-25T16:21:40.175+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="create"/><category scheme="http://www.blogger.com/atom/ns#" term="dotfile"/><category scheme="http://www.blogger.com/atom/ns#" term="explorer"/><category scheme="http://www.blogger.com/atom/ns#" term="file"/><category scheme="http://www.blogger.com/atom/ns#" term="microsoft"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>How to create files with a leading period in the filename with Microsoft Explorer</title><content type='html'>I have to post this, because this seems a very frequently asked question on the internet, and while there is a straight-forward solution, most people propose bizarre solutions that circumvent the problem by using some other tool.&lt;br /&gt;&lt;br /&gt;If you dig deeper, you&#39;ll find working solutions in comments, but they&#39;re incomplete and its not obvious at first that it even works.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Problem&lt;/h3&gt;&lt;br /&gt;The problem is simple: You wish to create a unix-style hidden file, such as &quot;&lt;code&gt;.htaccess&lt;/code&gt;&quot; , &quot;&lt;code&gt;.gitignore&lt;/code&gt;&quot;, or &quot;&lt;code&gt;.netrc&lt;/code&gt;&quot;, or a unix-style hidden folder, for whatever reason.&lt;br /&gt;&lt;br /&gt;While this is not a problem for literally &lt;i&gt;any&lt;/i&gt; tool other than Windows Explorer, attempting to do this in Explorer yields the following error:&lt;br /&gt;&lt;br /&gt;&lt;blockquote class=&quot;tr_bq&quot;&gt;You must type a file name.&lt;/blockquote&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://i.imgur.com/lPQTf.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;The Windows Explorer &amp;quot;Rename&amp;quot; Dialog showing the error &amp;quot;You must type a file name.&amp;quot;&quot; border=&quot;0&quot; exify_intitialized=&quot;true&quot; src=&quot;http://i.imgur.com/lPQTf.png&quot; title=&quot;Rename Dialog&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;The Solution&lt;/h3&gt;Most proponents suggest strange solutions such as using &lt;code&gt;cmd.exe&lt;/code&gt; or &lt;code&gt;notepad&lt;/code&gt; to do your dirty work,&amp;nbsp; and &lt;a href=&quot;http://blogs.msdn.com/b/oldnewthing/archive/2008/04/14/8389268.aspx&quot;&gt;even Microsoft Developers seem to think that letting Explorer do this is crazy and suggest using some other tool &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;However, all that is unnecessary. &lt;br /&gt;&lt;br /&gt;All that is required is writing an additional dot ( period ) at the tailing end.&lt;br /&gt;&lt;br /&gt;If you wanted &#39;&lt;code&gt;.htaccess&lt;/code&gt;&#39;, instead, write &#39;&lt;code&gt;.htaccess.&lt;/code&gt;&#39;&lt;br /&gt;If you wanted &#39;&lt;code&gt;.gitignore&lt;/code&gt;&#39; , instead, write &#39;&lt;code&gt;.gitignore.&lt;/code&gt;&#39;&lt;br /&gt;&lt;br /&gt;Explorer will silently strip the last dot and give you the file name you wanted, with no fuss.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://1.bp.blogspot.com/-LzGSgIfXQGI/UHWf3gT6-wI/AAAAAAAAA6o/b8TTyO-bEoE/s1600/rename_0.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;The Windows Explorer Rename Dialog showing the error &amp;quot;You must type a file name.&amp;quot; as a result of the user specifying &amp;quot;.gitignore&amp;quot; as the file name&quot; border=&quot;0&quot; exify_intitialized=&quot;true&quot; src=&quot;http://1.bp.blogspot.com/-LzGSgIfXQGI/UHWf3gT6-wI/AAAAAAAAA6o/b8TTyO-bEoE/s1600/rename_0.png&quot; title=&quot;Rename Dialog&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://1.bp.blogspot.com/-vbpJY90iX3M/UHWf3078hII/AAAAAAAAA6w/BdUx3OSlm00/s1600/rename_1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Windows Explorer prompting the user to confirm they want to change a file name extension, as a result of specifying the filename as &amp;quot;.gitignore.&amp;quot;&quot; border=&quot;0&quot; exify_intitialized=&quot;true&quot; src=&quot;http://1.bp.blogspot.com/-vbpJY90iX3M/UHWf3078hII/AAAAAAAAA6w/BdUx3OSlm00/s1600/rename_1.png&quot; title=&quot;Rename Dialog - But better&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://3.bp.blogspot.com/-TQQ0YdvV7tg/UHWf4udc3eI/AAAAAAAAA64/XUBz-6kE5gU/s1600/rename_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;Windows Explorer showing the successfully renamed file as &amp;quot;.gitignore&amp;quot; after confirming the file extension change, showing how the trailing period has been removed&quot; border=&quot;0&quot; exify_intitialized=&quot;true&quot; src=&quot;http://3.bp.blogspot.com/-TQQ0YdvV7tg/UHWf4udc3eI/AAAAAAAAA64/XUBz-6kE5gU/s1600/rename_2.png&quot; title=&quot;Windows Explorer&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/7412950392813535648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2012/10/how-to-create-files-with-leading-period.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7412950392813535648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7412950392813535648'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2012/10/how-to-create-files-with-leading-period.html' title='How to create files with a leading period in the filename with Microsoft Explorer'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-LzGSgIfXQGI/UHWf3gT6-wI/AAAAAAAAA6o/b8TTyO-bEoE/s72-c/rename_0.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-1813213222544040221</id><published>2011-02-22T02:00:00.003+13:00</published><updated>2011-02-22T02:30:39.862+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="file"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="sharedir"/><title type='text'>Testing your File::ShareDir based dist now possible.</title><content type='html'>For the last few months, every time I&#39;ve had a dist that needed File::ShareDir to do its dirty work, I&#39;ve used various tricks to make it work.  &lt;ul&gt;&lt;li&gt;&lt;b&gt;Simply not test it:&lt;/b&gt;&lt;br/&gt; Sad as this may seem, this is pretty much the primary approach because it was too confusing&lt;/li&gt;&lt;li&gt;&lt;b&gt;Invest a bit of code into overriding sharedir behaviour&lt;/b&gt;&lt;br/&gt;This usually involved having some coderef or lazy-loaded attribute that was normally populated by File::ShareDir, instead provided during test via hard-coding it.  &lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Enter Test::File::ShareDir&lt;/h3&gt; &lt;a href=&quot;http://frepan.org/~kentnl/Test-File-ShareDir-0.1.0/&quot;&gt;I uploaded Test::File::ShareDir this morning to CPAN&lt;/a&gt;, which lets you do this:  &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use Test::More;&lt;br /&gt;&lt;br /&gt;use FindBin;&lt;br /&gt;&lt;br /&gt;use Test::File::ShareDir&lt;br /&gt;  -root =&gt; &quot;$FindBin::Bin/../&quot;,&lt;br /&gt;  -share =&gt; {&lt;br /&gt;    -module =&gt; { &#39;My::Module&#39; =&gt; &#39;share/MyModule&#39; }&lt;br /&gt;  };&lt;br /&gt;&lt;/pre&gt; This configuration would be sufficient to use in a test in &lt;em&gt;&lt;code&gt;t/&lt;/code&gt;&lt;/em&gt; for a distribution shipping &lt;em&gt;&lt;code&gt;My::Module&lt;/code&gt;&lt;/em&gt; along with its corresponding shared directory &lt;em&gt;&lt;code&gt;share/MyModule&lt;/code&gt;&lt;/em&gt;.  If you were shipping this dist with Dist::Zilla, you&#39;d have something like this in dist.ini &lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;[ModuleShareDirs]&lt;br /&gt;My::Module = share/MyModule&lt;br /&gt;&lt;/pre&gt; I plan to add support for &#39;package&#39; style ShareDir support, but for now, module share dirs are sufficient.  Enjoy =).</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/1813213222544040221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2011/02/testing-your-filesharedir-based-dist.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1813213222544040221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1813213222544040221'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2011/02/testing-your-filesharedir-based-dist.html' title='Testing your File::ShareDir based dist now possible.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-1902687111022304687</id><published>2011-01-08T01:19:00.000+13:00</published><updated>2011-01-08T01:19:10.711+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dist::Zilla"/><category scheme="http://www.blogger.com/atom/ns#" term="dzil"/><category scheme="http://www.blogger.com/atom/ns#" term="file::sharedir"/><category scheme="http://www.blogger.com/atom/ns#" term="minting"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>Making a Minting Profile as a CPANized Dist.</title><content type='html'>&lt;h2&gt;... or one more reason why &lt;a href=&quot;http://search.cpan.org/dist/Dist-Zilla/&quot;&gt;Dist::Zilla&lt;/a&gt; is awesome.&lt;/h2&gt;&lt;h3&gt;Minting With Dzil&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Minting&lt;/em&gt; is a term we use for &quot;Creating a new distribution from a template of sorts&quot;. Since Dist::Zilla 2.101230 ( 2010-05-03 23:42:27 America/New_York ), there has been a command for Dist::Zilla to facilitate setting up a new distribution. &lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ dzil new Acme-An-Example&lt;br /&gt;# [DZ] making target dir /tmp/Acme-An-Example&lt;br /&gt;# [DZ] writing files to /tmp/Acme-An-Example&lt;br /&gt;# [DZ] dist minted in ./Acme-An-Example&lt;br /&gt;$ find Acme-An-Example/&lt;br /&gt;# Acme-An-Example/&lt;br /&gt;# Acme-An-Example/dist.ini&lt;br /&gt;# Acme-An-Example/lib&lt;br /&gt;# Acme-An-Example/lib/Acme&lt;br /&gt;# Acme-An-Example/lib/Acme/An&lt;br /&gt;# Acme-An-Example/lib/Acme/An/Example.pm&lt;br /&gt;$ cat Acme-An-Example/dist.ini&lt;br /&gt;# name    = Acme-An-Example&lt;br /&gt;# author  = Kent Fredric &lt;kentnl@cpan.org&gt;&lt;br /&gt;# license = Perl_5&lt;br /&gt;# copyright_holder = Kent Fredric &lt;kentnl@cpan.org&gt;&lt;br /&gt;# copyright_year   = 2011&lt;br /&gt;# &lt;br /&gt;# version = 0.001&lt;br /&gt;# &lt;br /&gt;# [@Basic]&lt;br /&gt;$ cat Acme-An-Example/lib/Acme/An/Example.pm&lt;br /&gt;# use strict;&lt;br /&gt;# use warnings;&lt;br /&gt;# package Acme::An::Example;&lt;br /&gt;# &lt;br /&gt;# 1;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And while this is a good starting point, once you&#39;ve gotten into Dist::Zilla, you&#39;ll probably find it somewhat lacking and find yourself doing things over and over again. &lt;/p&gt;&lt;p&gt;For this, we have &quot;&lt;em&gt;Minting Profiles&lt;/em&gt;&quot;.  &lt;/p&gt;&lt;h3&gt;Basic Minting Profiles&lt;/h3&gt;. &lt;p&gt;Minting Profiles have been in Dist::Zilla since 4.101780 ( 2010-06-27 14:30:55 America/New_York ).  &lt;/p&gt;&lt;p&gt;The first thing you&#39;ll tend to do, is make a minting profile in &lt;code&gt;~/.dzil&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://dzil.org/tutorial/minting-profile.html&quot;&gt;dzil.org&#39;s minting-profile tutorial&lt;/a&gt; adequately covers the innards of how this works, but summarised, its lots like &lt;code&gt;dist.ini&lt;/code&gt;. You have a &lt;code&gt;profile.ini&lt;/code&gt; in a directory in &lt;code&gt;~/.dzil/profiles/$profilename/&lt;/code&gt; and it will control how your dist is created, and you can then throw together new dists as simply as:&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ dzil new -p $profilename Acme-An-Example&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In the absence of &lt;code&gt;-p $profilename&lt;/code&gt;, if there is a &lt;code&gt;~/.dzil/profiles/default/&lt;/code&gt;, that will be used instead. &lt;/p&gt;&lt;p&gt;This is pretty convenient. &lt;/p&gt;&lt;p&gt;Me, I had a very simple default profile for a while that did most of what I needed to do:&lt;/p&gt;&lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;; ~/.dzil/profiles/default/profile.ini&lt;br /&gt;[Author::KENTNL::DistINI]&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That behaves more-or-less identical to how normal &lt;code&gt;dzil new&lt;/code&gt; operates, but it generates a custom &lt;code&gt;dist.ini&lt;/code&gt; from my custom &lt;a href=&quot;http://search.cpan.org/~kentnl/Dist-Zilla-PluginBundle-KENTNL-0.01023312/lib/Dist/Zilla/Plugin/Author/KENTNL/DistINI.pm&quot;&gt;&lt;code&gt;Author::KENTNL::DistINI&lt;/code&gt; plugin&lt;/a&gt;. This is based on &lt;a href=&quot;http://search.cpan.org/~rjbs/Dist-Zilla-4.200000/lib/Dist/Zilla/Plugin/DistINI.pm&quot;&gt;DistINI&lt;/a&gt; just tuned for how I like it. Its more or less a template ;). &lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;; Generated by Dist::Zilla::Plugin::Author::KENTNL::DistINI version 0.01023312 at Fri Jan  7 20:05:56 2011&lt;br /&gt;name             = Acme-An-Example&lt;br /&gt;author           = Kent Fredric &lt;kentnl@cpan.org&gt;&lt;br /&gt;license          = Perl_5&lt;br /&gt;copyright_holder = Kent Fredric &lt;kentnl@cpan.org&gt;&lt;br /&gt;&lt;br /&gt;; Uncomment this to bootstrap via self &lt;br /&gt;; [Bootstrap::lib]&lt;br /&gt;&lt;br /&gt;[@KENTNL]&lt;br /&gt;version_major     = 0&lt;br /&gt;version_minor     = 1&lt;br /&gt;; the following data denotes when this minor was minted&lt;br /&gt;version_rel_year  = 2011&lt;br /&gt;version_rel_month = 1&lt;br /&gt;version_rel_day   = 7&lt;br /&gt;version_rel_hour  = 20&lt;br /&gt;version_rel_time_zone = Pacific/Auckland&lt;br /&gt;twitter_hash_tags = #perl #cpan&lt;br /&gt;&lt;br /&gt;[Prereqs]&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt; &lt;/p&gt;&lt;h3&gt;CPAN Centralization&lt;/h3&gt;&lt;p&gt;However, many people like to use CPAN as their file storage mechanism, and centralise all their perly bits they might need in different locations so they can just get their current favourite configuration with a handy : &lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;cpanm --interactive --verbose Dist::Zilla::MintingProfile::Author::KENTNL &lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;A Word on Name-spaces&lt;/h3&gt;&lt;p&gt;Before we go further, I think it important to plead my rationale behind the &quot;Author::&quot; prefix I&#39;m using now, as I feel its an important concern.&lt;/p&gt;&lt;p&gt;As we have seen with Dist::Zilla there have been a &lt;a href=&quot;http://search.cpan.org/search?query=Dist%3A%3AZilla%3A%3APluginBundle&amp;mode=module&quot;&gt;slew of PluginBundles with CPANID&#39;s in their name&lt;/a&gt;, to the point that there is a copious amount of name-space pollution in the PluginBundle name-space, and more Author bundles than task-bundles, which was really what the name-space was designed for, and I&#39;ll freely admit, I am guilty of this crime as well, but I&#39;m petitioning you to help reduce this annoyance in future modules.&lt;/p&gt;&lt;p&gt;From a CPAN testers perspective, the annoyance of lots of CPANID-dists is similar to the annoyance of the whole DPCHRIST:: subspace, and that if this pattern continues, it will mean for the testers who do not wish to test everyones personal modules, that they will have to work hard to avoid this. If DPCHRIST:: had used something like Author::DPCHRIST:: instead, I doubt so many people would be horrified by it, because you can just have a policy/rule that excludes  ^Author::, and everyone else who goes that way can be quietly ignored.&lt;/p&gt;&lt;p&gt;Then we could probably rationally add that same restriction to the irc announce bots, the &quot;recent modules&quot; list and soforth, and possibly even apply special indexing restrictions or something so people wouldn&#39;t even have to know those modules exist on cpan!&lt;/p&gt;&lt;p&gt;So, for the sake of cleanliness, semantics, and general global sanity, I ask you to join me with my Author:: naming policy to voluntarily segregate modules that are most likely of only personal use from those that have more general application.&lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;Dist::Zilla::Plugin::Foo                 # [Foo]                 dist-zilla plugins for general use&lt;br /&gt;Dist::Zilla::Plugin::Author::KENTNL::Foo # [Author::KENTNL::Foo] foo that only KENTNL will probably have use for&lt;br /&gt;Dist::Zilla::PluginBundle::Classic       # [@Classic]            A bundle that can have practical use by many&lt;br /&gt;Dist::Zilla::PluginBundle::Author::KENTNL #[@Author::KENTNL]     KENTNL&#39;s primary plugin bundle&lt;br /&gt;Dist::Zilla::MintingProfile::Default     # A minting profile that is used by all&lt;br /&gt;Dist::Zilla::MintingProfile::Author::KENTNL # A minting profile that only KENTNL will find of use.&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Making Dist::Zilla::MintingProfile::Author::YOURID&lt;/h3&gt;&lt;p&gt;First, we&#39;ll start with the above default empty profile with a basic &lt;code&gt;dist.ini&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ dzil new Dist-Zilla-MintingProfile-Author-YOURID&lt;br /&gt;&lt;/pre&gt;And then the guts of that Minting Profile is pretty basic. &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;package Dist::Zilla::MintingProfile::Author::YOURID;&lt;br /&gt;&lt;br /&gt;# ABSTRACT: YOURID&#39;s Minting Profile&lt;br /&gt;&lt;br /&gt;use Moose;&lt;br /&gt;use namespace::autoclean;&lt;br /&gt;with &#39;Dist::Zilla::Role::MintingProfile::ShareDir&#39;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;__PACKAGE__-&gt;meta-&gt;make_immutable;&lt;br /&gt;no Moose;&lt;br /&gt;1;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is a deceptively simple piece of magic that took me a little while to fully grok.&lt;/p&gt;&lt;p&gt;Next, we make a &#39;profile&#39; directory in our dist.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ mkdir -p Dist-Zilla-MintingProfile-Author-YOURID/share/profiles/&lt;br /&gt;&lt;/pre&gt;And in that, we can put one or many profiles. For simplicity, we&#39;ll just start off with a &#39;default&#39; profile. &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ mkdir -p Dist-Zilla-MintingProfile-Author-YOURID/share/profiles/default/&lt;br /&gt;$ pushd Dist-Zilla-MintingProfile-Author-YOURID/share/profiles/default/&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now, you could just stick the same profile.ini you had above in ~/.dzil there, and you&#39;re mostly done with the hard part. However, I&#39;ll go a little more into detail so you get an idea of what use it is.&lt;/p&gt;&lt;h4&gt;Make a &#39;skel&#39; dir&lt;/h4&gt;&lt;p&gt;Make a &#39;skel&#39; dir holding a selection of templated-files you want in all new dists&lt;/p&gt;&lt;p&gt;Here is the most notable ones in mine&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ mkdir skel&lt;br /&gt;# stuff directory with files&lt;br /&gt;$ find skel/&lt;br /&gt;# skel/&lt;br /&gt;# skel/.gitignore&lt;br /&gt;# skel/.perltidyrc&lt;br /&gt;# skel/Changes&lt;br /&gt;# skel/perlcritic.rc&lt;br /&gt;# skel/weaver.ini&lt;br /&gt;$ cat skel/Changes&lt;br /&gt;# Release history for {{ $dist-&gt;name }}&lt;br /&gt;# &lt;br /&gt;# {{ &#39;{{$NEXT}}&#39; }}&lt;br /&gt;#&lt;br /&gt;#        First version, released on an unsuspecting world.&lt;br /&gt;#&lt;br /&gt;$ cat skel/.gitignore&lt;br /&gt;# .build&lt;br /&gt;# {{ $dist-&gt;name }}-*&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;{{ $dist-&gt;name }}&lt;/code&gt; is expanded during &#39;new&#39; to the name of the intended dist, and &lt;code&gt;{{ &#39;{{$NEXT}}&#39; }}&lt;/code&gt; is just a nasty hack so that the literal string &lt;code&gt;{{$NEXT}}&lt;/code&gt; turns up in the changelog file so the Changelog plugin keeps working.&lt;/p&gt;&lt;p&gt;For more in-depth understanding, please read &lt;a href=&quot;http://dzil.org/tutorial/minting-profile.html&quot;&gt;The dzil minting profile tutorial&lt;/a&gt;&lt;/p&gt;&lt;h4&gt;Adding support for the skel directory&lt;/h4&gt;You now need to tell your profile.ini about that skel directory if you want it to mean anything.&lt;/p&gt;&lt;p&gt;&lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;[GatherDir::Template]&lt;br /&gt;root = skel&lt;br /&gt;include_dotfiles = 1 ; I want the dot files! &lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;./profile.ini    # this file ---&gt; indicates inclusion of&lt;br /&gt;./skel                           #      /&lt;br /&gt;./skel/.gitignore          &lt;-----------/&lt;br /&gt;./skel/.perltidyrc         &lt;----------/&lt;br /&gt;./skel/Changes             &lt;---------/&lt;br /&gt;./skel/perlcritic.rc       &lt;--------/&lt;br /&gt;./skel/weaver.ini          &lt;-------/&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Other misc profile additions&lt;/h4&gt;Now most people will probably just put in  &lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;./skel/dist.ini&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;With some template variables expanded, but I myself prefer the dedicated module approach for dist.ini, so I add that to profile.ini&lt;/p&gt;&lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;[GatherDir::Template]&lt;br /&gt;root = skel&lt;br /&gt;include_dotfiles = 1 ; I want the dot files! &lt;br /&gt;&lt;br /&gt;[Author::KENTNL::DistINI]&lt;br /&gt;&lt;/pre&gt;And for good measure, I want every new dist to automatically have git set up with it, so I add that plugin too. &lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;[GatherDir::Template]&lt;br /&gt;root = skel&lt;br /&gt;include_dotfiles = 1 ; I want the dot files! &lt;br /&gt;&lt;br /&gt;[Author::KENTNL::DistINI]&lt;br /&gt;[Git::Init]&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Gluing it together&lt;/h3&gt;Now if you&#39;ve been following me, you&#39;ll have a directory that looks a lot like this: &lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;dist.ini&lt;br /&gt;lib/&lt;br /&gt;lib/Dist&lt;br /&gt;lib/Dist/Zilla&lt;br /&gt;lib/Dist/Zilla/MintingProfile&lt;br /&gt;lib/Dist/Zilla/MintingProfile/Author&lt;br /&gt;lib/Dist/Zilla/MintingProfile/Author/YOURID.pm&lt;br /&gt;share/&lt;br /&gt;share/profiles&lt;br /&gt;share/profiles/default&lt;br /&gt;share/profiles/default/profile.ini&lt;br /&gt;share/profiles/default/skel&lt;br /&gt;share/profiles/default/skel/.gitignore&lt;br /&gt;share/profiles/default/skel/.perltidyrc&lt;br /&gt;share/profiles/default/skel/Changes&lt;br /&gt;share/profiles/default/skel/perlcritic.rc&lt;br /&gt;share/profiles/default/skel/weaver.ini&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And you&#39;re probably wondering how the &#39;share&#39; directory and its contents will be seen by &#39;YOURID.pm&#39; after installation.&lt;/p&gt;&lt;p&gt;The magic is this stanza in your &lt;code&gt;dist.ini&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;ini&quot;&gt;&lt;br /&gt;[ModuleShareDirs]&lt;br /&gt;Dist::Zilla::MintingProfile::Author::YOURID = share/profiles &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Yeah, at first that baffled me too.&lt;/p&gt; &lt;h3&gt;Into the guts of File::ShareDir&lt;/h3&gt;Dist::Zilla utilizes sharedir in 2 places, 1. In the module that does the minting, and 2. Using some instructions injected in your install tool. &lt;h4&gt;During Install&lt;/h4&gt;&lt;p&gt;Lets pretend there is a directory, we&#39;ll call it &lt;code&gt;&lt;strong&gt;$x&lt;/strong&gt;&lt;/code&gt;, which is known as the &quot;base directory&quot; for all Things File::ShareDir::Install installs, which is also known to to File::ShareDir.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;/usr/lib64/perl5/vendor_perl/5.12.2/auto/share/    # $x &lt;br /&gt;/usr/lib64/perl5/vendor_perl/5.12.2/               # module install dir.&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;The ModuleShareDirs plugin tells File::ShareDir::Install  that the directory &#39;share/profiles&#39; should be installed in a path associated with the module, i.e.: &lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;$x/module/Dist-Zilla-MintingProfile-Author-YOURID/ &lt;= share/profiles/ &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;So, during install, the files in share/profiles/* will be copied to that directory.&lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/skel/perlcritic.rc&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/skel/weaver.ini&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/skel/.perltidyrc&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/skel/.gitignore&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/skel/Changes&lt;br /&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/profile.ini&lt;br /&gt;.../Dist/Zilla/MintingProfile/Author/YOURID.pm&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And that is not all that scary =)&lt;/p&gt;&lt;h4&gt;How your profile uses that&lt;/h4&gt;&lt;p&gt;Having seen how it installs to the file-system, how the plug-in works should be a bit of a no brainer. &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;pre class=&quot;bash&quot;&gt;dzil new -P Author::YOURID -p default Some-Module-Name&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Dist::Zilla, sees -P, and loads the respective profile from &lt;strong&gt;&lt;code&gt;@INC&lt;/code&gt;&lt;/strong&gt;, &lt;code&gt;Dist::Zilla::MintingProfile::Author::YOURID&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Your minting profile uses that sharedir role, and asks File::ShareDir for the directory associated with &#39;Dist-Zilla-MintingProfile-Author-YOURID&#39;, which of course returns that &#39;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/&#39; we installed above.&lt;/li&gt;&lt;li&gt;The Role then determines which sub-profile to use ( default, as specified by &lt;code&gt;-p&lt;/code&gt; ) and then returns that path ( now &lt;code&gt; .../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/&lt;/code&gt; )&lt;/li&gt;&lt;li&gt;&lt;code&gt;.../auto/share/module/Dist-Zilla-MintingProfile-Author-YOURID/default/profile.ini&lt;/code&gt; is then read and a new distribution is constructed using the instructions therein &lt;/li&gt;&lt;li&gt;And presto, you have a newly minted dist =): &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ cd Some-Module-Name;&lt;br /&gt;$ find&lt;br /&gt;# ./.git &lt;br /&gt;# ... a bunch of .git files ...&lt;br /&gt;# ./dist.ini&lt;br /&gt;# ./weaver.ini&lt;br /&gt;# ./perlcritic.rc&lt;br /&gt;# ./Changes&lt;br /&gt;# ./.perltidyrc&lt;br /&gt;# ./.gitignore&lt;br /&gt;# ./lib&lt;br /&gt;# ./lib/Some&lt;br /&gt;# ./lib/Some/Module&lt;br /&gt;# ./lib/Some/Module/Name.pm&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Hopefully thats enough to get you started, but...&lt;/h3&gt;&lt;p&gt;There is one warning you must uptake with the use of file sharedir. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;ONCE YOU INSTALL A FILE IN A SHAREDIR FROM A CPAN DIST, IT IS THERE FOR GOOD&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;At least, it will be there till somebody manually deletes it, at least in the current implementation of CPAN.&lt;/p&gt;&lt;p&gt;This means if you decide to put a file in &lt;code&gt;skel/&lt;/code&gt;, and then later decide you don&#39;t want that file in &lt;code&gt;skel/&lt;/code&gt;, you&#39;re going to have a problem when something decides to &quot;add all of skel/ to your new dist&quot;.&lt;/p&gt;&lt;p&gt;For vendor-wrapped/packaged stuff ( ie: Redhat, Debian, Gentoo ) you&#39;re fine, those systems have package management that guarantee atomicity somewhat, but the CPAN toolchain ( at least, in my experience ) provides very little guarantee in this regard. This may change in the future, but that&#39;s how it seems to be now. But now I&#39;ve warned you, you&#39;ll hopefully not bump into that =).&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/1902687111022304687/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2011/01/making-minting-profile-as-cpanized-dist.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1902687111022304687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1902687111022304687'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2011/01/making-minting-profile-as-cpanized-dist.html' title='Making a Minting Profile as a CPANized Dist.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-1045396180022342506</id><published>2010-12-29T02:12:00.000+13:00</published><updated>2010-12-29T02:12:29.677+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="directory"/><category scheme="http://www.blogger.com/atom/ns#" term="firefox"/><category scheme="http://www.blogger.com/atom/ns#" term="mozilla"/><category scheme="http://www.blogger.com/atom/ns#" term="profile"/><title type='text'>Discover Where your Firefox Profile Directory is.</title><content type='html'>I&#39;ve often had the challenge of knowing &quot;Which profile am I running? Where is it loaded from ? &quot; with firebox.  Especially on Windows, where there is a dizzying maze of inconsistency, which only seems to be getting worse.  Thankfully, Firefox 4.0 ( and possibly earlier ) has a solution of sorts.   &lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;about:support&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This helpful dialogue summarises a whole bunch of useful things that are probably cause for your woes.  &lt;/p&gt;&lt;p&gt;However, they&#39;ve done one thing, well meaning, but completely stupid in my estimation.  &lt;/p&gt;&lt;div style=&quot;width: 100%;&quot;&gt;&lt;div style=&quot;margin: 0px auto;&quot;&gt;&lt;img src=&quot;http://i.imgur.com/eOptk.png&quot; alt=&quot;&quot; title=&quot;Hosted by imgur.com&quot; style=&quot;width: 1154px; height:225px&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Now to me, this is a big problem, because mostly, I&#39;ve had a common issue with anything &quot;open a directory&quot; related simply not work, and for me, it would be much much more practical if it just told me where it is ( this also really gets on my goat with the download manager, because open pretty almost never works as expected , especially as directories, and I just wish it would tell me where the damned file is instead of making me do a dance ).&lt;/p&gt;&lt;p&gt;So, I got busy and poked around in the guts of &lt;code&gt;about:support&lt;/code&gt; with firebug, and found the source code for that button in &lt;code&gt;chrome://&lt;/code&gt;. As a result, here is a nice little scriptlet that will tell you where that location is without needing to open some external application!&lt;/p&gt;&lt;pre class=&quot;javascript&quot;&gt;&lt;br /&gt;javascript:alert(Services.dirsvc.get(&quot;ProfD&quot;, Ci.nsIFile).path);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;When you are on the about:support page, copy and paste that string as-is into your address bar and press enter, if you are lucky, you&#39;ll get an alert box telling you where to look&lt;/p&gt;&lt;div style=&quot;width: 100%;&quot;&gt;&lt;div style=&quot;margin: 0px auto;&quot;&gt;&lt;img src=&quot;http://i.imgur.com/t9PiM.png&quot; alt=&quot;Hosted by imgur.com&quot;  style=&quot;width: 926px; height:281px&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Hopefully, this technique will help out where others fail ( Such as the one odd incident I saw on IRC today  where the user has &lt;code&gt; rm -r ~/.mozilla&lt;/code&gt; but they still somehow have Firefox remembering what their profile looks like. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/1045396180022342506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/12/discover-where-your-firefox-profile.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1045396180022342506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1045396180022342506'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/12/discover-where-your-firefox-profile.html' title='Discover Where your Firefox Profile Directory is.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-5790767898899272961</id><published>2010-12-24T21:48:00.000+13:00</published><updated>2010-12-24T21:48:13.268+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mathnotation"/><category scheme="http://www.blogger.com/atom/ns#" term="pesky"/><category scheme="http://www.blogger.com/atom/ns#" term="wikipedia"/><title type='text'>Pet Peeve: People who use Math Notation to explain Programming.</title><content type='html'>&lt;p&gt;Sure, I get that many programming things have a mathematical backing underlying their working. But do we have to have Math notation that only MathGeeks understand? Especially on Wikipedia?  &lt;/p&gt;&lt;p&gt;I mean, there&#39;s a mathematical equation ( or equations ) backing you walking to the shop, but to explain walking to the shop I really really do &lt;em&gt;not&lt;/em&gt; want to have to take several university papers to get there. &lt;/p&gt;&lt;p&gt;What practical purpose could there be to using it on Wikipedia?&lt;/p&gt;&lt;p&gt;Its not at all immediately accessible to anyone who is a programmer trying to understand the programming concept explained&lt;/p&gt;&lt;p&gt;Its even less accessible to anyone who is neither a programmer or a math-geek, and face it, they&#39;re the majority of the people out there.&lt;/p&gt;&lt;p&gt;I&#39;d love to understand &lt;a href=&quot;https://secure.wikimedia.org/wikipedia/en/wiki/Canonical_LR_parser&quot;&gt;Canonincal LR Parsers&lt;/a&gt;, but the whole concept flys right out the window within 3 lines of that page at that lovely asinine: &lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt; [ A → B • C, a ]&lt;/pre&gt;&lt;p&gt;Sure, I probably learnt that syntax at some stage aeons ago, but gosh, I don&#39;t have a clue what it means now, nor is there any way for me to know what that is even talking about in order to search for it&lt;/p&gt;&lt;p&gt;Ironically, theres another little problem which makes using math notation completely pointless, is there&#39;s many operations that are simply impractical to use math-notation for, and people resort to using programming notation: &lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;action[k, b] = &quot;shift m&quot;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt; and that, just makes matters worse, because that notation seems completely incoherent with the rest of it.&lt;/p&gt;&lt;h3&gt;So is it stupid?&lt;/h3&gt; &lt;p&gt; ... or is it just me &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/5790767898899272961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/12/pet-peeve-people-who-use-math-notation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5790767898899272961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5790767898899272961'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/12/pet-peeve-people-who-use-math-notation.html' title='Pet Peeve: People who use Math Notation to explain Programming.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-7372005422932742614</id><published>2010-12-19T03:46:00.000+13:00</published><updated>2010-12-19T03:46:13.434+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="lol"/><category scheme="http://www.blogger.com/atom/ns#" term="phishing"/><category scheme="http://www.blogger.com/atom/ns#" term="scam"/><title type='text'>Funniest Phishing Scam Ever.</title><content type='html'>&lt;p&gt;Today I just received the funniest phishing scam I think I&#39;ve ever seen. They&#39;re claiming to be paying out to victims of scams!. Awesome!. &lt;/p&gt;&lt;p&gt;Excerpt:  &lt;/p&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;2010 SCAM VICTIMS COMPENSATIONS PAYMENTS.&lt;br /&gt;YOUR REF/PAYMENTS CODE: ECB/06654 FOR $500,000 USD ONLY.&lt;br /&gt;&lt;br /&gt;This is to bring to your notice that our bank (ECOBANK INTL. PLC) is&lt;br /&gt;delegated by the ECOWAS/UNITED NATIONS in Central Bank to pay victims&lt;br /&gt;of scam $500,000 (Five Hundred Thousand Dollars Only).&lt;br /&gt;&lt;br /&gt;You are to send the following informations for remittance.&lt;br /&gt;&lt;br /&gt;Your Name.___________________________&lt;br /&gt;Address.___________________________&lt;br /&gt;Phone .___________________________&lt;br /&gt;Amount Defrauded.___________________________&lt;br /&gt;Country.________________________&lt;br /&gt;&lt;br /&gt;Send a copy of your response with the PAYMENT CODE&lt;br /&gt;NUMBER(ECB/06654).&lt;br /&gt;&lt;br /&gt;NAME: MR.KEN OSAZUWA&lt;br /&gt;     SCAMMED VICTIM/REF/PAYMENTS CODE:&lt;br /&gt;     ECB/06654 $500,000 USD.&lt;br /&gt;     TEL: +234 7025669085&lt;br /&gt;&lt;br /&gt;Email: scamvictimstransfer_2010@yahoo.co.jp&lt;br /&gt;&lt;br /&gt;Yours Faithfully,&lt;br /&gt;Mrs. Rosemary Peter&lt;br /&gt;PUBLIC RELATIONS OFFICER&lt;br /&gt;Copyright 2010&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I bet you &lt;a href=&quot;http://www.countrycallingcodes.com/Reverse-Lookup.php?calling-code=234&quot;&gt;Won&#39;t Guess&lt;/a&gt; what the country that phone number is for. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/7372005422932742614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/12/funniest-phishing-scam-ever.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7372005422932742614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7372005422932742614'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/12/funniest-phishing-scam-ever.html' title='Funniest Phishing Scam Ever.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-5506728252473685314</id><published>2010-12-19T00:13:00.001+13:00</published><updated>2010-12-19T00:26:22.711+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="data"/><category scheme="http://www.blogger.com/atom/ns#" term="handle"/><category scheme="http://www.blogger.com/atom/ns#" term="module"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>Introducing Data::Handle</title><content type='html'>Comming to a mirror near you, soon, is &lt;b&gt;Data::Handle&lt;/b&gt;.  &lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://frepan.64p.org/~kentnl/Data-Handle-0.01011322/lib/Data/Handle.pm&quot;&gt;Frepan documentation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://search.cpan.org/dist/Data-Handle&quot;&gt;search.cpan.org documentation&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;What does Data::Handle do?&lt;/h3&gt;&lt;p&gt;Data::Handle solves 2 very simple problems that occur with the __DATA__ section and the associated *DATA Glob, and both of them are to do with &quot;multiple modules trying to access the section&quot;. &lt;/p&gt;&lt;h4&gt;1. Provide a reliable way to get a file-handle with the position at the start of the __DATA__ segment&lt;/h4&gt;&lt;ol&gt;   &lt;li&gt;&lt;code&gt;*DATA&lt;/code&gt; is really a pointer to the entire file, and not &lt;em&gt;just&lt;/em&gt; the data segment&lt;/li&gt;   &lt;li&gt;The Perl interpreter sets the current position in the file to be after the __DATA__ line&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The first time you read from &lt;code&gt;*DATA&lt;/code&gt; this of course works fine, but the issue is once you read it, it moves the internal file cursor, and if you read the whole section, after the first complete read, the cursor now points to EOF. For a second block of code to re-read this data without communicating with the first block of code, it has to then rewind the file cursor back to the start prior to reading, and there is no way naturally to know  where that point to rewind back to is.  &lt;/p&gt;&lt;p&gt;Other modules so far have remedied this by trying to rewind to the start of the file, and manually emulate various parts of the Perl Parser to re-find the start of the __DATA__ section before re-reading its contents.&lt;/p&gt;&lt;p&gt;This module however takes a different approach, and assumes that hopefully, the first person to read that file handle will know what they&#39;re doing, and use this module to do it. This module will then record the file offset the __DATA__ section began at, so from that point onwards, rewinding to the start is a trivial exercise.&lt;/p&gt;&lt;p&gt; And all this happens for you simply by you doing :&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;my $handle = Data::Handle-&gt;new( __PACKAGE__ ); &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;instead of doing&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;my $handle = do { no strict &#39;refs&#39;; \*{ __PACKAGE__ . &quot;::DATA&quot;} };&lt;br /&gt;&lt;/pre&gt;. ( &lt;strong&gt;Note:&lt;/strong&gt; Side perk, the new syntax is simpler, more straight forward, easier to remember, and no dicking around with strict! ;D )   &lt;h4&gt;2. Provide a reliable way for 2 separate logical code units to access the same __DATA__ segment without interfering with each other&lt;/h4&gt;&lt;p&gt;Because &lt;code&gt;*DATA&lt;/code&gt; is  a filehandle, and there is only one of them, seeking around in it can be problematic. &lt;/p&gt;&lt;p&gt;Especially if you have 2 code units that are trying to read it from different places.  For a contrived example, prior to this module if you wanted to go back and re-read the start of the section, or skip forwards and read something later in the section, without forgetting where you are now, you&#39;d need a contrived dance of seek/tell. Instead, now, you can just create another worker that will read that stuff for you, and the original handle will retain its position. &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;my $handle = Data::Handle-&gt;new( &#39;Foo&#39; );&lt;br /&gt;while( &lt;$handle&gt; ){ &lt;br /&gt;&lt;br /&gt;   if ( $_ =~ /something/ ){ &lt;br /&gt;       # get line 1. &lt;br /&gt;       my $slave = Data::Handle-&gt;new(&#39;Foo&#39;);&lt;br /&gt;       my $firstline = &lt;$slave&gt;;&lt;br /&gt;       do_stuff_with_first_line($firstline);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   # continue as normal.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Internally, there is a lovely dance of Seek() going on there, but from an interface perspective, you don&#39;t need to know its seeking, all you need to know is &quot;Get  reference to DATA, get data from it&quot;.&lt;/p&gt;&lt;p&gt;Sure, you can probably argue you could do it easily with lots of seek() in a nice way, but that logic falls apart when you have code in 2 separate places reading the same &lt;code&gt;*DATA&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Its much smarter to be defensive about it, and have &lt;em&gt;some&lt;/em&gt; assurance that you can read a file descriptor in a safe way without something evil like this tampering with it.&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;&lt;br /&gt;my $handle = do { no strict &#39;refs&#39;; \*{ __PACKAGE__ . &quot;::DATA&quot;} };&lt;br /&gt;while(&lt;*DATA&gt;){ &lt;br /&gt;   do_something_with_($_);&lt;br /&gt;   evil_function();   &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;sub evil_function { &lt;br /&gt;  my $handle = do { no strict &#39;refs&#39;; \*{ __PACKAGE__ . &quot;::DATA&quot;} };&lt;br /&gt;  seek $handle, 0, 3; # seek to EOF.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That is spooky action at a distance!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Data::Handle&lt;/strong&gt; solves this by meticulously tracking position in each instance, and re-seeking the file handle to the place it was at the end of the last tracked read, so regardless of how much seeking around some other module did, as long as you got on the scene first, you should be unstoppable ;) &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/5506728252473685314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/12/introducing-datahandle.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5506728252473685314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5506728252473685314'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/12/introducing-datahandle.html' title='Introducing Data::Handle'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-6184525900909592510</id><published>2010-12-04T00:54:00.000+13:00</published><updated>2010-12-04T00:54:05.916+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Gentoo"/><category scheme="http://www.blogger.com/atom/ns#" term="maintenance"/><category scheme="http://www.blogger.com/atom/ns#" term="portage"/><category scheme="http://www.blogger.com/atom/ns#" term="statistics"/><title type='text'>Find stale packages in Gentoo</title><content type='html'>&lt;p&gt;I often get in days of clean-up mentality, and like to go through and see how old my oldest packages are, see if I can either clean them out, or recompile them to make sure they&#39;re using the latest tool-chain enhancements. &lt;/p&gt;&lt;p&gt;The easiest way to do this is really just scrape the file-system MTimes, its fast, it works, and nobody cares if its not 100% accurate. &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;find -O3 /var/db/pkg -depth -type f -name &quot;*.ebuild&quot; -printf &quot;%T@ %T+ %p/%f\n&quot; | \&lt;br /&gt;    sort -r -k 1 &gt; /tmp/mtimes;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;You now have a lovely list of files in /tmp/mtimes showing when the most recent incarnation of each currently installed package appeared to have been installed. &lt;/p&gt;&lt;p&gt;I tend to walk over the tail end of this and manually re-emerge them if I feel like it.&lt;/p&gt;&lt;p&gt;Alternatively, if you think you don&#39;t need the package any-more, you can give the reverse dependencies a quick scan.&lt;/p&gt;&lt;p&gt;Sometimes the portage tools are fast enough, but I find just running a grep does the trick:&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;grep &quot;silgraphite&quot; /var/db/pkg/*/*/*DEPEND* &lt;br /&gt;# /var/db/pkg/app-text/texlive-core-2010/DEPEND:... xetex? ( ...media-libs/silgraphite )&lt;br /&gt;# /var/db/pkg/app-text/texlive-core-2010/RDEPEND:... xetex? ( ...media-libs/silgraphite )&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Oh right, seems I do need that, so I can either tell texlive-core I don&#39;t want xetex support and then clean it out, or I can just re-merge it and then think about this problem later&lt;/p&gt;&lt;h3&gt;For the curious people&lt;/h3&gt;I&#39;m also curious somewhat as to how old my system is as a whole, and have this script I threw together. &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;find -O3 /var/db/pkg -depth -type f -name &quot;*.ebuild&quot; -printf &quot;%T@ %T+ %p/%f\n&quot; | \&lt;br /&gt;    sort -r -k 1 &gt; /tmp/mtimes;&lt;br /&gt;&lt;br /&gt;for j in $(seq 2008 2010 );&lt;br /&gt;do&lt;br /&gt;  for i in $(seq 01 12 | sed &quot;s/^\([0-9]\)$/0\1/&quot; );&lt;br /&gt;  do&lt;br /&gt;     echo -n &quot;$j-$i:&quot; ;&lt;br /&gt;     grep $j-$i /tmp/mtimes | wc -l ;&lt;br /&gt;  done ;&lt;br /&gt;done ;&lt;br /&gt;&lt;/pre&gt;And my findings tell me that most of my system is around 3-months old, and this is a good thing in my mind.  &lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;2009-10:0&lt;br /&gt;2009-11:0&lt;br /&gt;2009-12:1&lt;br /&gt;2010-01:2&lt;br /&gt;2010-02:0&lt;br /&gt;2010-03:6&lt;br /&gt;2010-04:27&lt;br /&gt;2010-05:1&lt;br /&gt;2010-06:44&lt;br /&gt;2010-07:54&lt;br /&gt;2010-08:88&lt;br /&gt;2010-09:1094&lt;br /&gt;2010-10:139&lt;br /&gt;2010-11:381&lt;br /&gt;2010-12:35&lt;br /&gt;&lt;/pre&gt;There&#39;s a couple things that are stuck in the past, but that&#39;s due to GCC incompatibilities/test failures, and I&#39;ll come back to these later and probably file a bug report if I can find something worth-while reporting.</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/6184525900909592510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/12/find-stale-packages-in-gentoo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/6184525900909592510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/6184525900909592510'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/12/find-stale-packages-in-gentoo.html' title='Find stale packages in Gentoo'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-8000486412400530344</id><published>2010-11-14T08:04:00.002+13:00</published><updated>2010-11-16T12:15:17.003+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="class::load"/><category scheme="http://www.blogger.com/atom/ns#" term="optional"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="require"/><title type='text'>Handling optional requirements with Class::Load</title><content type='html'>&lt;p&gt;In &lt;a href=&quot;http://blog.fox.geek.nz/2010/11/searching-design-spec-for-ultimate.html&quot;&gt;a previous blog&lt;/a&gt; I discovered &lt;a href=&quot;http://search.cpan.org/dist/Class-Load/&quot;&gt;Class::Load&lt;/a&gt; and its awesomeness.  &lt;/p&gt;&lt;p&gt;Here is one practical application of it: &lt;/p&gt;&lt;h4&gt; &lt;a href=&quot;#UPDATES&quot;&gt; --&gt; UPDATES&lt;/a&gt; &lt;/h4&gt;&lt;h4&gt; &lt;a href=&quot;#UPDATES2&quot;&gt; --&gt; UPDATES2&lt;/a&gt; &lt;/h4&gt;&lt;h3&gt;Automatic Optional Requisites&lt;/h3&gt;&lt;p&gt;Say you have a library which provides some form of extensibility to consuming modules, and you want a way to &quot;magically&quot; discover a class to use, but use a fallback if its not there. &lt;/p&gt;&lt;p&gt;Here is how to do it with &lt;em&gt;Class::Load&lt;/em&gt;&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package Some::Module;&lt;br /&gt;use Class::Load qw( :all );&lt;br /&gt;&lt;br /&gt;sub do_setup { &lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;sub import {&lt;br /&gt;    my $caller = caller(); &lt;br /&gt;    my $maybemodule = &quot;$caller::Controller&quot;;&lt;br /&gt;    if( try_load_class( $maybemodule ) ){ &lt;br /&gt;        do_setup( $maybemodule ); # its there, and it works.&lt;br /&gt;    } else { &lt;br /&gt;        if ( $Class::Load::ERROR =~ qr/Can&#39;t locate \Q$maybemodule\E in \@INC/ ){ &lt;br /&gt;           do_setup(&quot;Some::Module::Default&quot;);&lt;br /&gt;        } else { &lt;br /&gt;           die $Class::Load::ERROR;&lt;br /&gt;        } &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; To do it the right way without Class::Load is extraordinarily complicated.   &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package Some::Module;&lt;br /&gt;&lt;br /&gt;sub do_setup { &lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;sub import {&lt;br /&gt;    my $caller = caller(); &lt;br /&gt;    my $maybemodule = &quot;$caller::Controller&quot;;&lt;br /&gt;&lt;br /&gt;    # see rt.perl.org #19213&lt;br /&gt;    my @parts = split &#39;::&#39;, $class;&lt;br /&gt;    my $file = $^O eq &#39;MSWin32&#39;&lt;br /&gt;             ? join &#39;/&#39;, @parts&lt;br /&gt;             : File::Spec-&gt;catfile(@parts);&lt;br /&gt;    $file .= &#39;.pm&#39;;&lt;br /&gt;      &lt;br /&gt;    my $error;&lt;br /&gt;    my $success;&lt;br /&gt;    { &lt;br /&gt;       local $@;     &lt;br /&gt;       $success = eval { &lt;br /&gt;          local $SIG{__DIE__} = &#39;DEFAULT&#39;;&lt;br /&gt;          require $file;&lt;br /&gt;          &#39;success&#39;;&lt;br /&gt;       };&lt;br /&gt;       $error = $@;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;     if( $success eq &#39;success&#39; ) ){ &lt;br /&gt;        do_setup( $maybemodule ); # its there, and it works.&lt;br /&gt;    } else { &lt;br /&gt;        if ( $error =~ qr/Can&#39;t locate \Q$maybemodule\E in \@INC/ ){ &lt;br /&gt;           do_setup(&quot;Some::Module::Default&quot;);&lt;br /&gt;        } else { &lt;br /&gt;           die $error;&lt;br /&gt;        } &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And even then, you still have a handful of sneaky bugs lurking in there :/ &lt;/p&gt;&lt;p&gt;&lt;ol&gt;  &lt;li&gt;With the second code, if somebody dynamically created the ::Controller class and didn&#39;t create a file for it, it will not work properly, and they&#39;ll have to tweak $INC somewhere for it to work &lt;/li&gt;  &lt;li&gt;If somebody loaded the ::Controller class manually before hand, but it failed, and they didn&#39;t report the error, on 5.8, the above code will behave as if the code &lt;em&gt;Did&lt;/em&gt; load successfully. ( Truely nasty )&lt;/li&gt;&lt;/ol&gt;&lt;/p&gt;&lt;p&gt;Class::Load has a lot of heuristics in it to try avoid both these situations ( well, the latter one will be soon once a 1-line patch goes in )&lt;/p&gt;&lt;p&gt;There are a few things still that I don&#39;t like doing that way, but for now, that&#39;s the best I can get&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Using a regular expression to determine what type of load failure occurred is nasty, but the only alternative approaches are either &lt;ol&gt;&lt;li&gt;more complicated&lt;/li&gt;&lt;li&gt;prone to be wrong on 5.8&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;What I&#39;d like to be able to do&lt;/h3&gt;&lt;h4&gt;and may write a patch for&lt;/h4&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package Some::Module;&lt;br /&gt;use Class::Load qw( :all );&lt;br /&gt;&lt;br /&gt;sub do_setup { &lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;sub import {&lt;br /&gt;    my $caller = caller(); &lt;br /&gt;    my $maybemodule = &quot;$caller::Controller&quot;;&lt;br /&gt;    if( try_load_working_class( $maybemodule ) ){ &lt;br /&gt;        do_setup( $maybemodule ); # its there, and it works.&lt;br /&gt;    } else {&lt;br /&gt;        do_setup(&quot;Some::Module::Default&quot;); #its not there.&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The idea being &quot;Syntax errors are syntax errors, there&#39;s no good reason to suppress them , at all&quot;, so in the above code, if Whatever::Controller existed, but was broken, it would die, instead of treating it as if it were absent. &lt;/p&gt; &lt;h3 id=&quot;UPDATES&quot;&gt;UPDATE&lt;/h3&gt;  &lt;p&gt;&lt;a href=&quot;https://github.com/bestpractical/class-load/pull/3&quot;&gt;Module Patched and on github!&lt;/a&gt; =). Waiting on an authoritative update =)  &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;package App;&lt;br /&gt;use Class::Load qw( :all );&lt;br /&gt;&lt;br /&gt;sub import { &lt;br /&gt;   my $caller = caller();&lt;br /&gt;   my $baseclass = load_optional_class(&quot;${caller}::Controller&quot;) ? &quot;${caller}::Controller&quot; : &quot;App::Controller&quot;;&lt;br /&gt;   push @{$caller}::ISA, $base_class; # this line is pseudocode.&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; &lt;h3 id=&quot;UPDATES2&quot;&gt;UPDATE #2&lt;/h3&gt;&lt;p&gt;   On CPAN: &lt;a href=&quot;http://search.cpan.org/~sartak/Class-Load-0.06/lib/Class/Load.pm&quot;&gt;http://search.cpan.org/~sartak/Class-Load-0.06/lib/Class/Load.pm&lt;/a&gt;. &lt;br/&gt;Thanks Sartak =) &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/8000486412400530344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/11/handling-optional-requirements-with.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/8000486412400530344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/8000486412400530344'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/11/handling-optional-requirements-with.html' title='Handling optional requirements with Class::Load'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-3742862707329903617</id><published>2010-11-13T16:01:00.000+13:00</published><updated>2010-11-13T16:01:38.178+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="require"/><category scheme="http://www.blogger.com/atom/ns#" term="research"/><title type='text'>Searching / Design spec for the Ultimate &#39;require&#39; tool.</title><content type='html'>&lt;p&gt;Perl&#39;s de-facto require method is something of confusing amounts of complexity, complexity that is often overlooked in the edge cases. It looks straight forward: &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;require Class::Name;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;And you think you&#39;re done right? &lt;/p&gt;&lt;p&gt;Not so. &lt;/p&gt;&lt;p&gt;Most of the problems come from one of 2 avenues. &lt;/p&gt;&lt;p&gt;&lt;ol&gt;&lt;li&gt;Things that happen when the module specified cannot, for whatever reason, be sourced&lt;/li&gt;&lt;li&gt;Things that happen when you want to require a module by string name&lt;/li&gt;&lt;/ol&gt;&lt;/p&gt;&lt;p&gt;Point 2 is probably the most commonly covered one, and it seems to be the primary objective of practically every require module I can find on CPAN. &lt;/p&gt;&lt;p&gt;However, many of the existing modules, in attempting to solve the string-name issue, result in the handling of &#39;this module cannot be sourced&#39; becoming WORSE!.&lt;/p&gt; &lt;h3&gt;Module Sourcing Headaches&lt;/h3&gt;&lt;h4&gt;The mysterious Perl 5.8 double-require hell&lt;/h4&gt;&lt;p&gt;The following code, in my testing, works without issue:&lt;/p&gt;&lt;p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;     eval &quot;require Foo;1&quot;; &lt;br /&gt;     require Foo;&lt;br /&gt;&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;Now, if &lt;code class=&quot;perl&quot;&gt;Foo&lt;/code&gt; happens to be broken, and cannot be sourced, on Perl &lt; 5.10, then nothing will happen in the above code!. Scary, but true. Its even scarier if those 2 lines of code are worlds apart.  &lt;/p&gt;&lt;p&gt;A quirk of how Perl 5.8 functions ( which is now solved in 5.10 ) is that once a module is &lt;code class=&quot;perl&quot;&gt;require&lt;/code&gt;&#39;d, as long as that file existed on disk, &lt;code class=&quot;perl&quot;&gt;$INC{ }&lt;/code&gt; will be updated to map the module name to the found file name. This doesn&#39;t seem to bad, until you see how it behaves with regard to that being called again somewhere else.  Take a look at this sample code from perlfunc:&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;sub require {&lt;br /&gt;    my ( $filename ) = @_;&lt;br /&gt;    if ( exists $INC{$filename} ){&lt;br /&gt;       return 1 if $INC{$filename};&lt;br /&gt;       die &quot;Compilation failed in require&quot;;&lt;br /&gt;    }&lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now on 5.10 this is fine, because &lt;code class=&quot;perl&quot;&gt;$INC{$filename}&lt;/code&gt; is set to &#39;undef&#39; if an error was encountered. But on everything prior to 5.10, the value of &lt;code class=&quot;perl&quot;&gt;$INC{$file}&lt;/code&gt; is in every way &lt;em&gt;identical&lt;/em&gt; to the value it would have if the module loaded successfully. And as you do &lt;em&gt;not&lt;/em&gt; want to require the module again once it has loaded, this behaviour falsely thinks &quot;Oh, that&#39;s already loaded&quot; and doesn&#39;t tell anyone anywhere that there is a problem.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;If that&#39;s too much reading for you, here&#39;s the executive summary of the problem:&lt;/strong&gt;You need &lt;em&gt;everyone&lt;/em&gt;, &lt;em&gt;everywhere&lt;/em&gt;, who either directly, or indirectly calls require inside an eval, to make sure any compilation/parsing errors with require is handled &lt;em&gt;immediately&lt;/em&gt;. Because failing this, everything else that requires that same broken file will treat the file as successfully loaded, will &lt;strong&gt;not&lt;/strong&gt; error, and you&#39;ll just get some confusing problem where the modules contents will not be anywhere you can see them. &lt;/p&gt;&lt;p&gt;From a debugging perspective, this behaviour frankly scares me, and I&#39;m very glad its fixed in 5.10, and glad I can use 5.10, but for you poor suckers stuck working with 5.8, or trying to make 5.8 backwards compatible modules, this problem will crop up eventually, if not for you, for somebody who uses your modules.&lt;/p&gt; &lt;h4&gt; Awful exceptions are awful &lt;/h4&gt;&lt;p&gt;This following code looks fine at a first approach, but there are many things wrong with it:&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;     if( eval &quot;require Foo; 1&quot; ){ &lt;br /&gt;         # behaviour to perform if there is a Foo&lt;br /&gt;     } else {&lt;br /&gt;         # behaviour to perform if there is no Foo&lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;A nice and elegant way of saying &quot;Try use this module, and if its not there, resort to some default behaviour&quot;&lt;/p&gt;&lt;p&gt;But what about the magical middle condition, where its there, but its broken?. In this code, it will silently fall back to the default behaviour, and nothing anywhere will tell you that Foo is broken, and you&#39;ll spend several hours with a dumb look on your face while you prod completely unrelated code.&lt;/p&gt;&lt;p&gt;What we really need is a way to disambiguate between &quot;its there&quot; and &quot;its broken&quot;, because ideally, if its there, and broken, we want a small nuclear explosion.&lt;/p&gt;&lt;p&gt;On Perl 5.10 and higher, this isn&#39;t so hard, we can just prod $INC{} to see what happened. &lt;/p&gt;&lt;table&gt;  &lt;thead&gt;&lt;tr&gt;    &lt;td&gt;Test&lt;/td&gt;&lt;td&gt;Value&lt;/td&gt;&lt;td&gt;Implication&lt;/td&gt;   &lt;/tr&gt;  &lt;/thead&gt; &lt;tr&gt;  &lt;td&gt;exists $INC{&#39;Foo.pm&#39;}&lt;/td&gt;&lt;td&gt; a false value&lt;/td&gt;&lt;td&gt;The module couldn&#39;t be found on disk, or nobody required it yet&lt;/td&gt;  &lt;/tr&gt;  &lt;tr&gt;  &lt;td&gt;exists $INC{&#39;Foo.pm&#39;}&lt;/td&gt;&lt;td&gt; a true value&lt;/td&gt;&lt;td&gt;The module exists on disk, and somebody has required it&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;  &lt;td&gt;defined $INC{&#39;Foo.pm&#39;}&lt;/td&gt;&lt;td&gt;a false value&lt;/td&gt;&lt;td&gt;The module exists, somebody required it, but it failed ( &gt;5.10 only )&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;defined $INC{&#39;Foo.pm&#39;}&lt;/td&gt;&lt;td&gt; a true  value&lt;/td&gt;&lt;td&gt;&lt;ul&gt;&lt;li&gt;The module loaded successfully ( &gt;=5.10 )&lt;/li&gt;&lt;li&gt; Absolutely nothing useful( &lt; 5.10 )&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt;So that approach is not exactly very nice, or very portable. &lt;/p&gt;&lt;p&gt;The next option you have, is, if you&#39;re fortunate enough to actually get require to die for you when it should, is regexing the exception it throws. But that is just horrible. Regexing messages from die is stupid, its limited, and prone to breaking. &lt;a href=&quot;http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven_19.html&quot;&gt;Proper&lt;/a&gt; &lt;a href=&quot;http://blog.fox.geek.nz/2010/07/current-limitations-in-exception-driven.html&quot;&gt;object&lt;/a&gt; &lt;a href=&quot;http://blog.woobling.org/2010/07/are-we-ready-to-ditch-string-errors.html&quot;&gt;exceptions&lt;/a&gt; are our salvation. What we really need for this situation is different exceptions that indicate the type of problem encountered, so we&#39;re not left guessing with cludgy code.&lt;/p&gt; &lt;h3&gt;Stringy require headaches&lt;/h3&gt;&lt;p&gt;This is the lesser evil, but not without its perils. &lt;/p&gt;&lt;p&gt;At some stage, if you write anything moderately interesting, you&#39;ll find the need to programmatically divine the name of a module to require. This is where require tends to bite you in the ass. &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;sub load_plugin { &lt;br /&gt;    my $plugin = shift;&lt;br /&gt;    my $fullname = &#39;MyPackage::&#39; . $plugin;&lt;br /&gt;    require $fullname;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is simply prohibited by the Perl Gods of Yore. You have to find some other way, and there are many modules targeted at this. There are some simple approaches, but they&#39;re also somewhat dangerous approaches too sometimes.  &lt;/p&gt;&lt;h4&gt;Bad Approach&lt;/h4&gt;&lt;p&gt;Here is something you should &lt;strong&gt;really&lt;/strong&gt; avoid if you&#39;re expecting the code to be used anywhere worth having any security. &lt;strong&gt;DO NOT DO THIS&lt;/strong&gt;: &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;sub load_plugin { &lt;br /&gt;    my $plugin = shift;&lt;br /&gt;    my $fullname = &#39;MyPackage::&#39; . $plugin;&lt;br /&gt;    eval &quot;require $fullname;1&quot; or die $@;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Firstly,&lt;/strong&gt; you just pretty much wrote a wide open security hole. Somebody just needs to call: &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;   load_plugin( &#39;Bobby; unlink &quot;/etc/some/important/document&quot;;&#39; ); &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;and the show is pretty much over. That&#39;s not necessarily so tragic if its your own code, and you&#39;re the only person who ever invokes it, but if its public facing, ( and especially if the code is published somewhere ), then avoid that style like cancer, because in my opinion, its not &quot;if&quot; its exploitable, but &quot;when&quot; its exploitable. Taint mode may help you a little bit, but don&#39;t bet on it. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Secondly&lt;/strong&gt;, if you were foolish enough to have accidentally left out that &#39;or die $@&#39; part, then you will have just created an invisible bug to be discovered later for everyone using Perl 5.8. Congratulations.&lt;/p&gt;&lt;h4&gt;Less insane approach&lt;/h4&gt;&lt;p&gt;The less insane approach is to emulate how perl maps Package names to file names internally, and pass that value to require. ( Because when you pass something as a string to require, its expecting a path of sorts, not a module name ). &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;sub load_plugin { &lt;br /&gt;    my $plugin = shift;&lt;br /&gt;    my $fullname = &#39;MyPackage::&#39; . $plugin;&lt;br /&gt;    $fullname =~ s{::}{/}g;&lt;br /&gt;    $fullname .= &#39;.pm&#39;;&lt;br /&gt;    require $fullname;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is good, because there&#39;s no room for accidentally forgetting to call die $@, and the worst somebody can do is specify an arbitrary file on disk to read, which is what you were doing to begin with anyway. This is way way less dangerous than allowing execution of arbitrary code. Both these code samples are still plagued by the 5.8 double-require situation, if somebody manages to require() the broken code before you do and hide the error, but that&#39;s substantially less likely to happen. &lt;/p&gt;&lt;h3&gt;Existing Modules, and what is wrong with them&lt;/h3&gt;I&#39;ve seriously looked at many many modules on CPAN for this task. And sadly, none fit the bill perfectly. &lt;h4&gt;UNIVERSAL::require&lt;/h4&gt;This seems to be the most popular one. But it only solves the stringy-require issue, and in reality, adds  MORE potential for failure. &lt;ul&gt;&lt;li&gt;Victim to the double-load on 5.8 issue.     &lt;p&gt;this one line of code is sufficient enough to make this weak to the double require issue.&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;return eval { 1 } if $INC{$file};&lt;br /&gt;&lt;/pre&gt;As discussed above, on 5.8, if the file has already been &#39;required&#39; but failed, $INC{$file} will be set to the path to that file. And as a result , UNIVERSAL::require will just respond with &quot;Oh right&quot;. &lt;/p&gt;&lt;/li&gt;&lt;li&gt;No Exceptions &lt;p&gt;This module doesn&#39;t help us at all with regard to exception objects. It relies entirely on Perl&#39;s native ( virtually non-existent ) exception system&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Actually exacerbates the 5.8 issue &lt;p&gt;In my opinion, this module actually makes us take a step &lt;b&gt;backwards&lt;/b&gt; in progressive coding. It replaces useful informative exception throwing, with silence, and requires you to check a return value.  The result is, everyone who does &lt;code class=&quot;perl&quot;&gt;  Foo-&gt;require() &lt;/code&gt; without checking the return value, will result in the very next thing that tries to require Foo, and expect an exception when its broken, silently succeed, but there will be no &quot;Foo&quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;2005 called and want their Perl style back &lt;p&gt;Seriously, we&#39;ve been trying to encourage people to use stuff like &#39;Autodie&#39; because checking the return value of every open, every close, and every print ( yes, print can fail! ) is tedium, lazy people often forget to, adding &#39;die &quot;$@ $? $!&quot; &#39; at the end of everything SUCKS, let alone throwing actual exceptions that explain /what/ the problem was. &lt;br/&gt;Try working out whether the reason open failed was the file just wasn&#39;t there, or there was a permissions issue, or one of the other dozens of possible reasons, via code, and you&#39;re stuck using regular expressions. Yuck.&lt;/p&gt;&lt;li&gt;Monkey patching &lt;p&gt;A lot of people really dislike the monkey-patch style that bolts into UNIVERSAL. Magically turning up everywhere on every object is really nasty, and really magical, and far too much magic for something that could be achieved by using an exported method instead. Seriously,  &lt;code&gt;string_require(&quot;Foo::Bar&quot;)&lt;/code&gt; vs &lt;code&gt;&quot;Foo::Bar&quot;-&gt;require()&lt;/code&gt;; the difference is not big enough to warrant the nastiness of the latter. &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Module::Load&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;5.8 Double-Load Weak&lt;p&gt;Still relies entirely on require to die if it cant load something.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;No Exceptions&lt;p&gt;Relies on $@ being a useful enough value to the user&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Implicitly treats Exceptions like scalars &lt;p&gt; Even if in the future fantasty land Perl &#39;s require started throwing useful Exceptions ( backtrace, attributes that explained the problem type, introspection, soforth ), the code concatentates it into another scalar, so any exceptions that may exist will get squashed&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Module::Locate&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Holy hell, what?&lt;p&gt; the code is from 2005 and has 2005 written all over it, if it was less chatoic, I might be able to see how it works&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Doesn&#39;t invoke require&lt;p&gt;It doesn&#39;t use require anywhere, so it doesn&#39;t even populate $@&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Recommended use is to pass discovered variables to require&lt;p&gt;Doesn&#39;t sound like much of a win to me. probably prone to the 5.8 issue&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Doesn&#39;t throw exception objects&lt;p&gt;Seems in 2005, nobody had discovered exceptions yet really.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Module::Require&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Module is not really designed for one-off module requires&lt;/li&gt;&lt;li&gt;Code is weak vs 5.8 issues. &lt;/li&gt;&lt;li&gt;Code is pretty high on the wtfometer&lt;/li&gt;&lt;li&gt;Code aggravates 5.8 issues with suppressed failures by ignoring $@ after failures &lt;/li&gt;&lt;li&gt;No exception objects&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Mrequire&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Mangles $@ with chomp&lt;/li&gt;&lt;li&gt;No exception objects&lt;/li&gt;&lt;li&gt;5.8 double-require weak&lt;/li&gt;&lt;li&gt;Oh dear, please , not AUTOLOAD :( &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;File::Where&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Mostly an over the top file finding library, doesn&#39;t handle any of the require stuff&lt;/li&gt;&lt;li&gt;the usual, no exceptions, 5.8 double-require-weak &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Module::Use&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Not for requiring modules at all. &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;autorequire&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Not really for this job, but...&lt;/li&gt;&lt;li&gt;Has a method for detecting package loading, however....&lt;/li&gt;&lt;li&gt;That method is subject to the 5.8 double-require weakness and its friends&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Acme::RequireModule&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;pro&lt;/strong&gt;Despite being Acme::, it sucks less than everything else so far!&lt;/li&gt;&lt;li&gt;Still depends on native require for exceptions&lt;/li&gt;&lt;li&gt;XS&lt;/li&gt;&lt;li&gt;Still defers to the internal require() op, so probably still suffers the 5.8 problems.&lt;/li&gt;&lt;li&gt;Depends on &gt;= 5.10 anyway&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;ClassLoader&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Just as bad interface wise as UNIVERSAL::require&lt;/li&gt;&lt;li&gt;But worse, AUTOLOAD magics&lt;/li&gt;&lt;li&gt;Documented in German&lt;/li&gt;&lt;li&gt;&lt;pre class=&quot;perl&quot;&gt;eval &quot;use $string&quot;&lt;/pre&gt;, very bad&lt;/li&gt;&lt;li&gt;Substitutes Perl require-fails string-only exceptions with alternative, german, string-only exceptions. Joy.&lt;/li&gt;&lt;li&gt;Prone to 5.8 issues&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Module::Runtime&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Prone to 5.8 issues&lt;/li&gt;&lt;li&gt;Standard Perl native exceptions only&lt;/li&gt;  &lt;/ul&gt;&lt;h3&gt;THE BEST SO FAR&lt;/h3&gt;&lt;h4&gt;Class::Load&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;pro:Actually appears to have work-arounds in place for heuristically solving the 5.8 problem!&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;pro:Tests for the above claimed fact!&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://matrix.cpantesters.org/?dist=Class-Load%200.05;maxver=1&quot;&gt;pro:Tests pass !&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Still no exception objects ( perl default exceptions )&lt;/li&gt;&lt;li&gt;&lt;strong&gt;pro:&lt;/strong&gt; Reasonably sane API&lt;/li&gt;&lt;li&gt;&lt;strong&gt;pro:&lt;/strong&gt; No need to check silly return values&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;tl;dr summary&lt;/h3&gt;&lt;p&gt;Class::Load is awesome, you should use it everywhere you need require to actually work sanely with possibly-missing or possibly-broken classes  (ie: everywhere that there is a user-part in a require ).&lt;br/&gt;You can probably use it for more, but that might be overkill =).&lt;br/&gt;&lt;/p&gt;&lt;p&gt;The only way I can see something being better than it is if something decides to implement object exceptions with failure metadata in them, instead of needing to re-explore the failure manually  &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/3742862707329903617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/11/searching-design-spec-for-ultimate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/3742862707329903617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/3742862707329903617'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/11/searching-design-spec-for-ultimate.html' title='Searching / Design spec for the Ultimate &#39;require&#39; tool.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-7566087003783952293</id><published>2010-09-27T08:20:00.000+13:00</published><updated>2010-09-27T08:20:22.518+13:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="0x0273"/><category scheme="http://www.blogger.com/atom/ns#" term="1510"/><category scheme="http://www.blogger.com/atom/ns#" term="A10"/><category scheme="http://www.blogger.com/atom/ns#" term="bios"/><category scheme="http://www.blogger.com/atom/ns#" term="dell"/><category scheme="http://www.blogger.com/atom/ns#" term="flash"/><category scheme="http://www.blogger.com/atom/ns#" term="Gentoo"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="vostro"/><title type='text'>Flashing a Dell Vostro 1510 Bios Without Windows.</title><content type='html'>I&#39;ve been trying to get my BIOS updated for several months now, and attempted several times with no success, but tonight, I stumbled into the information that gave me the breakthrough I needed.  &lt;h3&gt;What Doesn&#39;t Work&lt;/h3&gt;Dell have started being nice and releasing more Linux friendly ways of installing bios updates, but sadly, for models like mine, there is no support.  &lt;h4&gt;Using Windows7/Vista 64bit&lt;/h4&gt;It just will never work. Not even with administrator privileges. That WinPhlash thing just Doesn&#39;t Work&amp;trade; &lt;h4&gt;Using The biosdisk technique&lt;/h4&gt;Doesn&#39;t work, because the winphlash executable that you have to use will &lt;em&gt;not&lt;/em&gt; run in the FreeDOS boot environment. It&#39;s a Win32 GUI app. &lt;h4&gt;Using the remote boot update method&lt;/h4&gt;There is no hdr file produced by Dell to work with this bios yet, and there is no way to produce one. &lt;h4&gt;Windows XP Portable Edition( BartPE )&lt;/h4&gt;In my case, the &quot;bootable media&quot; just hung for 8 hours and wouldn&#39;t boot.  &lt;h3&gt;Working Solution: phlash16.exe&lt;/h3&gt;&lt;strong&gt;Legacy dos apps save the day!.&lt;/strong&gt;&lt;p&gt;While this method worked for me, its not official, nor supported, and you are on your own if it breaks, just like I was. However, you have my good intentions and the testimony of others that it works for some of us.&lt;/p&gt;&lt;h3&gt;Checklist&lt;/h3&gt;&lt;p&gt;From here on, I&#39;m going to be using very gentoo-specific terms, but they should be portable to other Linux distributions. &lt;/p&gt;&lt;h4&gt;Install nessecary tools&lt;/h4&gt;&lt;p&gt;You&#39;ll need libsmbios to see what you have, and biosdisk to generate a bootfloppy which we can inject our tools into. Wine will also be required to extract the ROM file from the Winphlash self-extractor.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;$ sudo emerge -uvatDN libsmbios&lt;br /&gt;$ sudo emerge -uvatDN biosdisk&lt;br /&gt;$ sudo emerge -uvatDN wine&lt;br /&gt;$ sudo emerge -uvatDN unzip&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Check your Bios and System&lt;/h4&gt;While this technique may work for other Dells, I have not myself tested it and thus, cannot recommend it.  If you use my pre-generated boot-floppy , you will &lt;strong&gt;WANT&lt;/strong&gt;to have the same BIOS  SystemID and Version as I currently have. &lt;pre class=&quot;bash&quot;&gt;$ sudo smbios-sys-info-lite &lt;br /&gt;Libsmbios:    2.2.19&lt;br /&gt;System ID:    0x0273  # MATCH &lt;br /&gt;Service Tag:  XXXXXXX&lt;br /&gt;Express Service Code: XXXXXXXXXXX&lt;br /&gt;Aset Tag:  X&lt;br /&gt;Product Name: Vostro1510&lt;br /&gt;BIOS Version: A10 # MATCH&lt;br /&gt;Vendor:       Dell Inc.&lt;br /&gt;Is Dell:      1&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Get Dell Bios updates in WinPhlash form&lt;/h4&gt;I must remind you, this solution works &lt;strong&gt;ONLY&lt;/strong&gt; for WinPhlash based bios updates. If your bios update installer tool does &lt;strong&gt;NOT&lt;/strong&gt; use WinPhlash, you should not continue.   &lt;ul&gt;&lt;li&gt;Visit &lt;a href=&quot;http://support.dell.com&quot;&gt;support.dell.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Find your notebook model, &lt;/li&gt;&lt;li&gt;Find the bios driver for that model&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://support.dell.com/support/downloads/download.aspx?c=us&amp;l=en&amp;s=gen&amp;releaseid=R215210&amp;SystemID=VOS_N_1510&amp;servicetag=&amp;os=BIOSA&amp;osl=en&amp;deviceid=17544&amp;devlib=0&amp;typecnt=0&amp;vercnt=7&amp;catid=-1&amp;impid=-1&amp;formatcnt=0&amp;libid=1&amp;typeid=-1&amp;dateid=-1&amp;formatid=-1&amp;source=-1&amp;fileid=305034&quot;&gt;Download the Bios Update&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Get a copy of Phlash16.exe&lt;/h4&gt;I can&#39;t gurantee that this link will always work, so &lt;a href=&quot;http://google.com/search?q=phlash16.exe&quot;&gt;Google for it&lt;/a&gt; if my link dies. But in the mean time, you can get a copy of winphlash16 with one of intels bios flashes. You won&#39;t need everything in the archive, but it has what we need. So, &lt;a href=&quot;http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&amp;ProdId=2475&amp;DwnldID=12625&amp;lang=eng&quot;&gt;download the 3C91.zip bios package for  Quanta* QTW3A945PM1&lt;/a&gt; &lt;h3&gt;Preparation&lt;/h3&gt; &lt;h4&gt;Unpack your Dell BIOS&lt;/h4&gt;Unfortunately, Dell bundle this as a self-extracting achive, a weirdly formatted one at that, which contains the winphlash and the BIOS.ROM file you need. So we need to run this with Wine to get it out. &lt;pre class=&quot;bash&quot;&gt;$ wine ~/Downloads/V151015.exe&lt;/pre&gt;It will do its thing, run and so forth, tell it to start extracting, and then winphlash will run. It will then throw an error, but it doesn&#39;t matter, its done the job we wanted it to.  &lt;h4&gt;Grab the BIOS.ROM from your wine dir&lt;/h4&gt;This will be in a directory such as C:\WINDOWS\TEMP\WINPHLASH, but relative to your wine directory. In my case, its ~/.wine/drive_c/windows/temp/WINPHLASH/BIOS.ROM &lt;pre class=&quot;bash&quot;&gt;$ cp ~/.wine/drive_c/windows/temp/WINPHLASH/BIOS.ROM /tmp/&lt;/pre&gt; &lt;h4&gt;Unzip phlash16.exe from the Zip&lt;/h4&gt;&lt;pre class=&quot;bash&quot;&gt;$ cd /tmp/&lt;br /&gt;$ mkdir phlash&lt;br /&gt;$ cd phlash&lt;br /&gt;$ unzip ~/Downloads/3C91.zip phlash16.exe&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;Build the MemDisk&lt;/h3&gt;We can now build an in-memory FreeDOS boot diskette and stash it into Grub.conf so we can boot into our bios updater on our next boot. &lt;h4&gt;Mount /boot&lt;/h4&gt;&lt;pre class=&quot;bash&quot;&gt;$ sudo mount /boot &lt;/pre&gt;&lt;h4&gt;Generate a BiosDisk&lt;/h4&gt;&lt;p&gt;Note I don&#39;t really &quot;get&quot; how biosdisk works inside, so we&#39;re passing it here an executable thats reasonably large, and known &lt;strong&gt;not&lt;/strong&gt; to work =). &lt;/p&gt;&lt;p&gt;We&#39;re going to fix that later.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;$ sudo biosdisk install ~kent/Downoads/V151015.exe&lt;/pre&gt;That should have built you a nice boot floppy config and setup grub in nice ways. &lt;h4&gt;Manually hack the generated BiosDisk&lt;/h4&gt;Now for the part that does all the sexy good work. That boot floppy image is a mountable filesystem image we can  read and write to. &lt;pre class=&quot;bash&quot;&gt;$ mkdir /tmp/vfat/&lt;br /&gt;$ sudo mount /boot/V151015.img /tmp/vfat/&lt;br /&gt;$ cd /tmp/vfat&lt;br /&gt;$ sudo rm /tmp/vfat/V151015.exe&lt;br /&gt;$ sudo cp /tmp/phlash/phlash16.exe ./&lt;br /&gt;$ sudo cp /tmp/BIOS.ROM ./&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now here, we could make this automatically flash the bios on boot, but I&#39;m going to suggest against that, because I don&#39;t want to run it accidentally at some later stage before I get rid of it again, and interrupt it, bricking my box =).&lt;/p&gt;&lt;p&gt;So instead, I&#39;ve set it up to give me a command shell, and I manually execute the flash command.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;$ sudo vim -c &quot;set fileformat=dos&quot; autoexec.bat&lt;/pre&gt;&lt;pre class=&quot;plaintext&quot;&gt;command.com&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is the flash instruction. You &lt;em&gt;really&lt;/em&gt; want the &lt;code&gt;/S&lt;/code&gt; option, unless you enjoy deafening beeping at 3am.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;/EXIT&lt;/code&gt; option is supposed to &lt;strong&gt;STOP&lt;/strong&gt; exiting and auto-rebooting, but it does this anyway, for reasons that I don&#39;t understand, and quite frankly am slighly afraid of.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;$ sudo vim -c &quot;set fileformat=dos&quot; flash.bat&lt;/pre&gt;&lt;pre class=&quot;plaintext&quot;&gt;phlash16.exe /S /EXIT BIOS.ROM&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Now to check we have DOS line endings.  &lt;pre class=&quot;bash&quot;&gt;$  grep &#39;&#39;  autoexec.bat flash.bat  | cat --show-all&lt;br /&gt;autoexec.bat:command.com^M$&lt;br /&gt;autoexec.bat:^M$&lt;br /&gt;flash.bat:phlash16.exe /S /EXIT BIOS.ROM^M$&lt;br /&gt;flash.bat:^M$&lt;/pre&gt; And now we can unmount it, and be ready to fly. &lt;pre class=&quot;bash&quot;&gt;$ cd /&lt;br /&gt;$ sudo umount /tmp/vfat&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;IMPORTANT PRE-FLIGHT BRIEFING&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;You are about to fly into dangerous territory, where enemy combatants like &quot;power failure&quot; can mean certain death&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Please read all following instructions and be familiar with them &lt;em&gt;BEFORE&lt;/em&gt; attempting to continue&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you reboot, you will see the bios flash option in grub&lt;/li&gt;&lt;li&gt;Select this&lt;/li&gt;&lt;li&gt;A few seconds later, you will be given the A:\ prompt of FreeDOS&lt;/li&gt;&lt;li&gt;You will double check you are on an uninterruptable power supply system, and batteries are working&lt;/li&gt;&lt;li&gt;You will be running mains power&lt;/li&gt;&lt;li&gt;type &lt;code&gt;flash.bat&lt;/code&gt; and press your &lt;code&gt;ENTER&lt;/code&gt; key&lt;/li&gt;&lt;li&gt;A bios flash utility will load, and progress to flash your bios&lt;/li&gt;&lt;li&gt;&lt;strong&gt;YOU WILL BE PATIENT AND NOT INTERRUPT IT&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Upon completion of flashing, the computer may &lt;em&gt;suddenly&lt;/em&gt; and &lt;em&gt;unexpectedly&lt;/em&gt; reboot with &lt;strong&gt;NO&lt;/strong&gt; warning, and this may &lt;em&gt;surprise&lt;/em&gt; you and make you think your computer has crashed! &lt;strong&gt;DONT PANIC&lt;/strong&gt;, &lt;em&gt;wait&lt;/em&gt; it should quickly return to normal booting. &lt;/li&gt;&lt;li&gt;During this boot, you should observe the code &quot;A15&quot; in the bios booting sequence instead of &quot;A10&quot; =). &lt;/li&gt;&lt;li&gt;Boot back into linux,  and proceed to remove the flash installer from the boot menu =)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;SUCCESS!&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Experimenters Advice&lt;/h4&gt;If you have elected to try see what other flags phlash16.exe has, you&#39;re probably not going to find any of them useful. I have noticed something weird, and that is, at least in the biosdisk boot enviroment, the /BU option does not work.  Using it causes phlash16.exe to reboot as soon as it hits the backup phase, making you panic and thinking you killed it.  I have not played with the other flags, but they didn&#39;t appear to be of use to me =). &lt;h4&gt;Proceed! AND GOOD LUCK MY FELLOW COUNTRYMAN!&lt;/h4&gt;&lt;sub&gt;yes, you may now go and try the above.&lt;/sub&gt;&lt;h3&gt;POST-OP cleanup&lt;/h3&gt;Once you have successfully flashed your bios, you may then clean the biosdisk entry out of grub:  &lt;pre class=&quot;bash&quot;&gt;$ biosdisk uninstall ~kent/Downloads/V1510A15.exe&lt;/pre&gt; And then it should be gone from &lt;code&gt;menu.lst&lt;/code&gt;   &lt;h3&gt;PREMADE BIOSDISKS&lt;/h3&gt; &lt;p&gt; For your convenience, I have made a pre-built copy of the biosimage, my grub configuration, and the memdisk kernel:&lt;/p&gt; &lt;blockquote&gt; &lt;a href=&quot; http://www.humyo.com/FXGcBgc/Dell%20Bios%20Phlash/?a=STxMGVD8Yds,RtFnNTvRBsc,Lbj4wxOmN_g&quot;&gt;Dell Bios Phlash Vostro1510 A10 -&gt; A15 on humyo.com &lt;/a&gt;&lt;/blockquote&gt;&lt;p&gt; They worked for me, and might work for you too.&lt;/p&gt;&lt;p&gt; The grub configuration is given for your understanding. The top section is all you need to add, but it probably won&#39;t work like that verbatim.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/7566087003783952293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/09/flashing-dell-vostro-1510-bios-without.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7566087003783952293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/7566087003783952293'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/09/flashing-dell-vostro-1510-bios-without.html' title='Flashing a Dell Vostro 1510 Bios Without Windows.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-1614865495064180964</id><published>2010-09-17T02:27:00.001+12:00</published><updated>2010-09-18T06:16:25.342+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cpanm"/><category scheme="http://www.blogger.com/atom/ns#" term="cpanminus"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="perlbrew"/><title type='text'>Installing Multiple Perls with App::perlbrew and App::cpanminus</title><content type='html'>&lt;p&gt;Having learnt from my &lt;a href=&quot;http://blog.fox.geek.nz/2010/09/openbsd-perl-modern-tools-and.html&quot; title=&quot;OpenBSD + Perl + Modern Tools and Approaches -&amp;gt; Me = Confused :(&quot;&gt;previous mistakes&lt;/a&gt;, this is a simplistic way to set up multiple somewhat isolated installs of Perl in a user profile&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://p3rl.org/App::perlbrew&quot; title=&quot;App::perlbrew&quot;&gt;App::perlbrew&lt;/a&gt; is a very handy tool for managing several user-installs of Perl, and facilitates the easy switching between Perl versions.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://p3rl.org/App::cpanminus&quot; title=&quot;App::cpanminus&quot;&gt;App::cpanminus&lt;/a&gt; is the most straight-forward and lightweight cpan client I&#39;ve ever seen, and it just works,  and works well, and leads to relatively pain-free installation 80% of the time.&lt;/p&gt; &lt;h3&gt;1. Install A Bare copy of Perlbrew&lt;/h3&gt;Getting a copy of Perlbrew should be the very first thing you do. No cpanm, no local::lib, just straight perlbrew. &lt;pre class=&quot;bash&quot;&gt;$ cd ~ &lt;br /&gt;$ curl -LO http://xrl.us/perlbrew&lt;/pre&gt; &lt;h3&gt;2. Setup Perlbrew&lt;/h3&gt;Once we have a copy of perlbrew, we run the install command of it, which completes the bootstrapping of perlbrew.  Then all thats needed is to update your profile with the right magic line so that new shells will have the right environment set up. &lt;pre class=&quot;bash&quot;&gt;$ perl ~/perlbrew install&lt;br /&gt;$ rm ~/perlbrew&lt;br /&gt;$ ~/perl5/perlbrew/bin/perlbrew init&lt;br /&gt;# use the line perlbrew spits out.&lt;br /&gt;$ echo &quot;source /home/test_1/perl5/perlbrew/etc/bashrc&quot; | tee -a ~/.bashrc&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;3. Enter your new perlbrew ENV&lt;/h3&gt;Now we enter our new shell so that we can test the change to our configuration. We run env and grep the PATH value just to double check perlbrew has worked properly.  &lt;pre class=&quot;bash&quot;&gt;$ bash&lt;br /&gt;$ env | grep PATH&lt;br /&gt;PATH=/home/test_1/perl5/perlbrew/bin:/home/test_1/perl5/perlbrew/perls/current/bin:/home/test_1/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:.&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;4. Choose a mirror&lt;/h3&gt;This step is mostly optional, but it lets you choose which mirror perlbrew will download Perl sources from, so a local one is best for speed sakes. &lt;pre class=&quot;bash&quot;&gt;$ perlbrew mirror&lt;/pre&gt; &lt;h3&gt;5. Install your wanted perl versions&lt;/h3&gt;Now we perform the slow installation of our Perls.  In my case, I&#39;m installing a copy of the current stable ( 5.12.2 ) and the current development release ( 5.13.2 ). The -v is optional, but you&#39;ll want it if you do not wish to die of boredom because it generally just sits there doing nothing for 10+ minutes without it. &lt;pre class=&quot;bash&quot;&gt;$ perlbrew -v install perl-5.12.2&lt;br /&gt;$ perlbrew -v install perl-5.13.4&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;6. Setup &#39;cpanm&#39; for each perl&lt;/h3&gt;This step appears to be the most important step. If you previously had cpanm installed with system perl you do &lt;strong&gt;NOT&lt;/strong&gt; want to be using that &lt;em&gt;at all&lt;/em&gt;. When cpanm is installed, the bin/ script hard-codes a path to the perl it was installed with, so using cpanm built with system perl will build installed modules using that system perl instead, and using its install paths and soforth, and you &lt;strong&gt;do not want this&lt;/strong&gt;. So, you must install a cpanm for each perl using this bootstrap technique. &lt;pre class=&quot;bash&quot;&gt;$ perlbrew switch perl-5.12.2&lt;br /&gt;$ curl -L http://cpanmin.us | perl - App::cpanminus&lt;br /&gt;$ perlbrew switch perl-5.13.4&lt;br /&gt;$ curl -L http://cpanmin.us | perl - App::cpanminus&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;7. Configure local cpans&lt;/h3&gt;Strangely, I&#39;ve found a &lt;a href=&quot;https://rt.cpan.org/Public/Bug/Display.html?id=49874&quot;  title=&quot;Bug #49874 for CPAN-Inject: Fails t/02_main.t line 80 &#39;got expected error&#39; on 5.10.1/snow leopard&quot;&gt;few modules&lt;/a&gt; I try install tend to expect a working CPAN install, regardless of what tool I&#39;m actually using. This should be fixed, but there is a practical work-around until then. Simply configure cpan! &lt;pre class=&quot;bash&quot;&gt;$ perlbrew switch perl-5.12.2&lt;br /&gt;$ cpan&lt;br /&gt;# Answer all setup instructions&lt;br /&gt;» o conf commit&lt;br /&gt;» q&lt;br /&gt;$ perlbrew switch perl-5.13.4&lt;br /&gt;$ cpan&lt;br /&gt;# Answer all setup instructions&lt;br /&gt;» o conf commit&lt;br /&gt;» q&lt;br /&gt;&lt;/pre&gt; &lt;h3&gt;8. Test your installs&lt;/h3&gt;This is a list of things I&#39;ve found to trip up various corner cases and indicate you&#39;ve built it wrong. &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perlbrew switch perl-5.12.2&lt;br /&gt;$ cpanm --interactive -v App::cpanoutdated&lt;br /&gt;$ cpan-outdated&lt;br /&gt;$ cpanm --interactive -v App::CPAN::Fresh&lt;br /&gt;&lt;br /&gt;$ perlbrew switch perl-5.13.4&lt;br /&gt;$ cpanm --interactive -v App::cpanoutdated&lt;br /&gt;$ cpan-outdated&lt;br /&gt;$ cpanm --interactive -v App::CPAN::Fresh&lt;br /&gt;&lt;/pre&gt;With all things going to plan, those 2 things at least should build and be runnable. cpan-outdated and cpanf should both be runnable in both perls without complaining it cant find their modules, and CPAN::Inject and Compress::BZip2 should install without strange failures. ( those 2 modules lead me in prior cases to discover broken setups that needed fixing to work, so hopefully, going to plan, following the instructions above will avoid this havoc. )  &lt;h3&gt;9. Profit!&lt;/h3&gt;Thats all there is to it. Note we do &lt;strong&gt;NOT&lt;/strong&gt; use local::lib for this setup. Using each Perls default local module installation directory should be perfectly satisfactory, and as long as you&#39;re in a properly configured ENV and you&#39;re using &#39;perlbrew&#39; to select perl&#39;s that are not system perl, everything should be sweet =).  &lt;br /&gt;Ok, lots of things on my machine fail to build still, but those peskynesses I&#39;m convinced are unrelated to the Perl setup. &lt;h3&gt;10. Credit&lt;/h3&gt;Props to the people who helped me out with &lt;a href=&quot;http://blog.fox.geek.nz/2010/09/openbsd-perl-modern-tools-and.html&quot; title=&quot;OpenBSD + Perl + Modern Tools and Approaches -&amp;gt; Me = Confused :(&quot;&gt;working out this configuration&lt;/a&gt; ( brian d foy, miyagawa, John Napiorkowski ) and to the authors of cpanm ( miyagawa ) and perlbrew ( gugod ). These are awesome tools, and once you learn them, they really can make working with Perl a much more pleasureable experience!. And also &lt;a href=&quot;http://blog.fox.geek.nz/2010/09/i-perl-community.html&quot; title=&quot;I ♥ the Perl Community&quot;&gt;props and ♥ to the Perl Community &lt;/a&gt; for simply existing, and fostering this development path.</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/1614865495064180964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/09/installing-multiple-perls-with.html#comment-form' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1614865495064180964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/1614865495064180964'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/09/installing-multiple-perls-with.html' title='Installing Multiple Perls with App::perlbrew and App::cpanminus'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-2649818805978239658</id><published>2010-09-15T15:05:00.001+12:00</published><updated>2010-09-15T15:06:21.816+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="community"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>I ♥ the Perl Community</title><content type='html'>&lt;div&gt;&lt;p&gt;&lt;a href=&quot;http://bulknews.net/me&quot; title=&quot;Tatsuhiko Miyagawa&quot; alt=&quot;miyagawa&quot;&gt;miyagawa++&lt;/a&gt;,&lt;a href=&quot;http://search.cpan.org/~jjnapiork/&quot; alt=&quot;jjnapiork&quot; title=&quot;John Napiorkowski&quot;&gt;jjnapiork++&lt;/a&gt;,&lt;a href=&quot;http://www.pair.com/~comdog/&quot; alt=&quot;bdfoy&quot; title=&quot;brian d foy&quot;&gt;bdfoy++&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Perl is awesome, but the community is better, with nothing even in competition as I know it. &lt;/p&gt;&lt;p&gt;Where else can you &lt;a title=&quot;OpenBSD + Perl + Modern Tools and Approaches -&amp;gt; Me = Confused :(&quot; href=&quot;http://blog.fox.geek.nz/2010/09/openbsd-perl-modern-tools-and.html&quot;&gt;blog about a confusing corner case you hit in a seemingly rare operating system&lt;/a&gt; and get &lt;em&gt;Excellent&lt;/em&gt; answers from not only great people, but the &lt;a href=&quot;http://bulknews.net/me&quot; title=&quot;Tatsuhiko Miyagawa: The Author of cpanm&quot;&gt;author of the module the problem was in&lt;/a&gt;, &lt;a href=&quot;http://search.cpan.org/~jjnapiork/&quot; title=&quot;John Napiorkowski: Author of MooseX-Types-Parameterizable and MooseX-Types-Structured&quot;&gt; one of the people who wrote or contributed a lot of the other useful tools you use&lt;/a&gt;, and &lt;a href=&quot;http://www.pair.com/~comdog/&quot; title=&quot;brian d foy: Author of Effective Perl Programming 2nd Edition, Learning Perl 4th and 5th Edition, Intermediate Perl, Mastering Perl and many articles for The Perl Review and perl.com&quot;&gt;the author many recognized Perl books&lt;/a&gt;&lt;/p&gt;&lt;p&gt;And then, not only did I get the &lt;em&gt;right&lt;/em&gt; solution for my problem, but &lt;em&gt;many&lt;/em&gt; other alternative good approaches, as well as answering parts of the question &lt;em&gt;I didn&#39;t even ask&lt;/em&gt; with side tips that seem &quot;related enough&quot; that I&#39;d likely encounter in similar ways, and how to make my life easier when that happens.&lt;/p&gt;&lt;p&gt;I ♥ this positive approach to programming, where people are not only caring about solving my specific problem, but suggesting things that can help me become a better programmer as a whole, and I&#39;m frankly &lt;em&gt;proud&lt;/em&gt; simply to be &lt;em&gt;involved&lt;/em&gt; with a community which has such a valuable work-ethic.&lt;/p&gt;&lt;p&gt;Frankly, its a shame its so hard to sell Perl on the community aspect, because it is just awesome in ways I&#39;ve never seen before in a Programming Language, and it by far trumps technical aspects in terms of awesomeness. If brainf**k had a community as awesome as Perl has, it would probably be better than many languages simply because of the community aspect, at least in my opinion. Its just a shame you can&#39;t convey how great such a community being preset is to newbies to the language without first immersing them in the culture and community, because to understand and appreciate, I think you must first &lt;em&gt;experience&lt;/em&gt; it.&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/2649818805978239658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/09/i-perl-community.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/2649818805978239658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/2649818805978239658'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/09/i-perl-community.html' title='I ♥ the Perl Community'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-2668623695387345399</id><published>2010-09-15T05:04:00.000+12:00</published><updated>2010-09-15T05:04:06.649+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cpanm"/><category scheme="http://www.blogger.com/atom/ns#" term="cpanminus"/><category scheme="http://www.blogger.com/atom/ns#" term="lazyweb"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenBSD"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="perlbrew"/><title type='text'>OpenBSD + Perl + Modern Tools and Approaches -&gt; Me = Confused :(</title><content type='html'>&lt;div&gt;&lt;p&gt;So, I&#39;m doing my first attempt at a hand-holding free install of Perl. I&#39;m used to the niceties of Gentoo and being able to do everything through its package manager, so I thought I&#39;d try doing it the way everyone else in the world apparently uses as &quot;The most practical&quot;.&lt;/p&gt;&lt;p&gt;I&#39;m going to walk you through what I did, mostly constructed from memory, so you have an idea of what the problem I have is, or, if you&#39;re in a similar situation, you can get some progress and learn from my mistakes once I&#39;ve worked out what I need.&lt;/p&gt;&lt;p&gt;Normally, I&#39;d ask about this on &lt;span style=&quot;font-family: monospace;&quot;&gt;#perl@irc.freenode.org &lt;/span&gt;or something on &lt;span style=&quot;font-family: monospace;&quot;&gt;irc.perl.org&lt;/span&gt;, or if appropriate, file a bug. However, in this case, I can&#39;t even conceive of which would be the right place to target my question, OpenBSD is in my estimation very &quot;nich&amp;eacute;&quot; market at the moment, as are lots of the modern tools for Perl, and I don&#39;t know where the appropriate place to solicit help for them are. So, I approach the ALL MIGHTY LAZY-WEB.&lt;/div&gt;&lt;h3&gt;The Setup&lt;/h3&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt; Installed OpenBSD 4.7&lt;br /&gt;This shall be left as an exercise to the reader as to how this works.&amp;nbsp; Its too much to cover here, and it really is pretty straight forward =).&lt;/li&gt;&lt;li&gt;Install &lt;code&gt;cpanm&lt;/code&gt;&lt;br /&gt;Everyone I see in Perl these days seems to be ranting about this, so I used the perscribed instructions:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;pre class=&quot;bash&quot;&gt;$ curl -L http://cpanmin.us | perl - --sudo App::cpanminus&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;I don&#39;t want to be stuck using Perl 5.10.1, which is great and all, but I&#39;d rather be doing work with 5.12.2 and 5.13.* . And I keep getting recommendations &lt;strong&gt;NOT&lt;/strong&gt; to use system Perl for &lt;strong&gt;ANYTHING&lt;/strong&gt; other than getting your custom Perl running. ( Using system Perl is fine in Gentoo, at least how I use it, we&#39;ve got 5.12.2 in tree now, and stuffing Perl dists into Package Management JustWorks&amp;trade; ). The new sex for this is allegedly &lt;code&gt;perlbrew&lt;/code&gt;, so I&#39;m firing that baby up next.&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;$ cpanm --sudo App::perlbrew&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;All appears good!. Now from here on, is where I think a few things start to drift south, but not entirely sure &lt;strong&gt;WHERE&lt;/strong&gt;.&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;$ perlbrew init&lt;br /&gt;# add instructed line to bash&lt;br /&gt;$ bash&lt;br /&gt;$ perlbrew install perl-5.13.4 -v&lt;br /&gt;$ perlbrew install perl-5.12.2 -v&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;All this appears to run smoothly.&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;$ perlbrew switch perl-5.13.4&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Here is where I do the stupid things that possibly lead to my downfall. First, you must understand how I want my setup:&lt;ol&gt;&lt;li&gt;I want my primary development user (kent) to have 2 copies of Perl available, 5.13.4 and 5.12.4&lt;/li&gt;&lt;li&gt;I want the modules for each install of Perl to follow their respective installs so I can just switch between Perls and have the modules switch over too&lt;/li&gt;&lt;li&gt;&quot;Production&quot; Will repeat this process, except with less versions of Perl, and probably with less modules installed.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;To achieve this, I insert lines in my .bashrc until it resembles this&lt;br/&gt;&lt;pre class=&quot;bash&quot;&gt;source /home/kent/perl5/perlbrew/etc/bashrc&lt;br /&gt;export PERLDIR=/home/kent/perl5/perlbrew/perls/current&lt;br /&gt;export MODULEBUILDRC=/home/kent/perl5/perlbrew/etc/.modulebuildrc&lt;br /&gt;export PERL_MM_OPT=&quot;INSTALL_BASE=${PERLDIR}&quot;&lt;br /&gt;export PERL5LIB=&quot;${PERLDIR}:${PERLDIR}/i386-openbsd&quot;&lt;br /&gt;export PERL_CPANM_OPT=&quot;--local-lib=${PERLDIR}&quot;&lt;br /&gt;&lt;/pre&gt; and .modulebuildrc of course contains this:  &lt;pre class=&quot;bash&quot;&gt;install  --install_base  /home/kent/perl5/perlbrew/perls/current/&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;For the most part this works perfectly, and I&#39;m off installing modules happy as Larry.&lt;/li&gt;&lt;li&gt;And then a few hours later, something depends on IO::Compress::BZip2. Now is the beginning of sorrows.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;h3&gt;The Problem:&lt;/h3&gt;&lt;h4&gt;Can&#39;t find libbz2!&lt;/h4&gt;&lt;div&gt;I&#39;m sure as eggs I have &lt;code&gt;bzip2&lt;/code&gt; and family installed and working.&lt;br /&gt;However, this worrisome notice appears during build: &lt;pre class=&quot;plaintext&quot;&gt; Entering Compress-Bzip2-2.09&lt;br /&gt;Configuring Compress-Bzip2-2.09 ... Running Makefile.PL&lt;br /&gt;Parsing config.in...&lt;br /&gt;/usr/bin/ld: cannot find -lbz2&lt;br /&gt;collect2: ld returned 1 exit status&lt;br /&gt;compile command &#39;cc -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -Wl,-E  -fstack-protector -o show_bzversion show_bzversion.c -lbz2&#39; failed&lt;br /&gt;system bzip2 not found, building internal libbz2&lt;br /&gt;&lt;/pre&gt;Ah .... ok.&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ bzip2 -h 2❭&amp;1 | head -n 1&lt;br /&gt;bzip2, a block-sorting file compressor.  Version 1.0.5, 10-Dec-2007.&lt;br /&gt;$ /usr/bin/ldd $(which bzip2)&lt;br /&gt;/usr/local/bin/bzip2:&lt;br /&gt;        Start    End      Type Open Ref GrpRef Name&lt;br /&gt;        1c000000 3c006000 exe  1    0   0      /usr/local/bin/bzip2&lt;br /&gt;        065b5000 265b9000 rlib 0    1   0      /usr/local/lib/libbz2.so.10.4&lt;br /&gt;        07295000 272ce000 rlib 0    1   0      /usr/lib/libc.so.53.1&lt;br /&gt;        0643c000 0643c000 rtld 0    1   0      /usr/libexec/ld.so&lt;br /&gt;&lt;/pre&gt;Ok, so maybe it is a bit geriatric&lt;br /&gt;That should be fine though right? &lt;strong&gt;WRONG&lt;/strong&gt;&lt;/div&gt;&lt;h4&gt; Something magical keeps finding Perl 5.10.1 :(&lt;/h4&gt;&lt;div&gt;Surely, this abomination will not end well: &lt;pre class=&quot;plaintext&quot;&gt;Building and testing Compress-Bzip2-2.09 for Compress::Bzip2 ... cp lib/Compress/Bzip2.pm blib/lib/Compress/Bzip2.pm&lt;br /&gt;AutoSplitting blib/lib/Compress/Bzip2.pm (blib/lib/auto/Compress/Bzip2)&lt;br /&gt;cd bzlib-src &amp;&amp; make &lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   blocksort.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   huffman.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   crctable.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   randtable.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   compress.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   decompress.c&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   bzlib.c&lt;br /&gt;ar cr libbz2.a  &amp;&amp; ranlib libbz2.a&lt;br /&gt;cc -c    -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;\&quot;  -DXS_VERSION=\&quot;\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   bzip2.c&lt;br /&gt;/usr/bin/perl /usr/libdata/perl5/ExtUtils/xsubpp  -typemap /usr/libdata/perl5/ExtUtils/typemap -typemap typemap  Bzip2.xs &gt; Bzip2.xsc &amp;&amp; mv Bzip2.xsc Bzip2.c&lt;br /&gt;cc -c  -Ibzlib-src  -fno-strict-aliasing -fno-delete-null-pointer-checks -pipe -fstack-protector -I/usr/local/include -O2     -DVERSION=\&quot;2.09\&quot;  -DXS_VERSION=\&quot;2.09\&quot; -DPIC -fPIC &quot;-I/usr/libdata/perl5/i386-openbsd/5.10.1/CORE&quot;   Bzip2.c&lt;br /&gt;In file included from Bzip2.xs:7:&lt;br /&gt;ppport.h:231:1: warning: &quot;PERL_UNUSED_DECL&quot; redefined&lt;br /&gt;In file included from Bzip2.xs:4:&lt;br /&gt;/usr/libdata/perl5/i386-openbsd/5.10.1/CORE/perl.h:330:1: warning: this is the location of the previous definition&lt;br /&gt;Running Mkbootstrap for Compress::Bzip2 ()&lt;br /&gt;&lt;/pre&gt;Um. Um. Um. &lt;br /&gt;&lt;strong&gt;How about &lt;u&gt;NO&lt;/u&gt;&lt;/strong&gt;&lt;pre class=&quot;bash&quot;&gt;$ perl -v  | grep version &lt;br /&gt;This is perl 5, version 13, subversion 4 (v5.13.4) built for OpenBSD.i386-openbsd&lt;br /&gt;&lt;/pre&gt;That&#39;s going to go down like a houseboat on fire. &lt;/div&gt;&lt;h4&gt;What comes next is only a natural&lt;/h4&gt;&lt;div&gt;&lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;t/010-useability.t ...... 1/3 ol &#39;BZ2_bzDecompressInit&#39;nm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symb&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzDecompress&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzBuffToBuffDecompress&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzDecompressEnd&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzCompress&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzBuffToBuffCompress&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzlibVersion&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzCompressInit&#39;&lt;br /&gt;/usr/bin/perl:/home/kent/.cpanm/work/1284524774.31144/Compress-Bzip2-2.09/blib/arch/auto/Compress/Bzip2/Bzip2.so: undefined symbol &#39;BZ2_bzCompressEnd&#39;&lt;br /&gt;&lt;/pre&gt; And more and more of that explosion until you see:  &lt;pre class=&quot;plaintext&quot;&gt;&lt;br /&gt;Files=25, Tests=33,  7 wallclock secs ( 0.35 usr  0.21 sys +  4.74 cusr  1.44 csys =  6.74 CPU)&lt;br /&gt;Result: FAIL&lt;br /&gt;Failed 25/25 test programs. 30/33 subtests failed.&lt;br /&gt;&lt;/pre&gt;Oh crap. That&#39;s &lt;em&gt;not&lt;/em&gt; good.&lt;br /&gt;Something &lt;em&gt;Seriously&lt;/em&gt; wrong is going on here, but hell knows what it is, and I&#39;m the &lt;em&gt;least&lt;/em&gt; qualified to work it out. &lt;/div&gt;&lt;h3&gt;Call For Halp&lt;/h3&gt;&lt;div&gt;If you know what I&#39;ve done wrong,  and how to correct this fatal flaw, please, point me straight. I can only reward you with Karma Cookies and a blog of response and update. &lt;br /&gt;I acknowledge that CPANTS lists many many passes for this module, so it must be &lt;em&gt;I&lt;/em&gt; who is at fault, right? &lt;/div&gt;&lt;h3&gt;perl -V&lt;/h3&gt;&lt;div&gt;&lt;pre class=&quot;plaintext&quot;&gt;Summary of my perl5 (revision 5 version 13 subversion 4) configuration:&lt;br /&gt;   &lt;br /&gt;  Platform:&lt;br /&gt;    osname=openbsd, osvers=4.7, archname=OpenBSD.i386-openbsd&lt;br /&gt;    uname=&#39;openbsd stridor.lan 4.7 generic#558 i386 &#39;&lt;br /&gt;    config_args=&#39;-de -Dprefix=/home/kent/perl5/perlbrew/perls/perl-5.13.4 -Dusedevel&#39;&lt;br /&gt;    hint=recommended, useposix=true, d_sigaction=define&lt;br /&gt;    useithreads=undef, usemultiplicity=undef&lt;br /&gt;    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef&lt;br /&gt;    use64bitint=undef, use64bitall=undef, uselongdouble=undef&lt;br /&gt;    usemymalloc=y, bincompat5005=undef&lt;br /&gt;  Compiler:&lt;br /&gt;    cc=&#39;cc&#39;, ccflags =&#39;-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include&#39;,&lt;br /&gt;    optimize=&#39;-O2&#39;,&lt;br /&gt;    cppflags=&#39;-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include&#39;&lt;br /&gt;    ccversion=&#39;&#39;, gccversion=&#39;3.3.5 (propolice)&#39;, gccosandvers=&#39;openbsd4.7&#39;&lt;br /&gt;    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234&lt;br /&gt;    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12&lt;br /&gt;    ivtype=&#39;long&#39;, ivsize=4, nvtype=&#39;double&#39;, nvsize=8, Off_t=&#39;off_t&#39;, lseeksize=8&lt;br /&gt;    alignbytes=4, prototype=define&lt;br /&gt;  Linker and Libraries:&lt;br /&gt;    ld=&#39;cc&#39;, ldflags =&#39;-Wl,-E  -fstack-protector -L/usr/local/lib&#39;&lt;br /&gt;    libpth=/usr/local/lib /usr/lib&lt;br /&gt;    libs=-lm -lutil -lc&lt;br /&gt;    perllibs=-lm -lutil -lc&lt;br /&gt;    libc=/usr/lib/libc.so.53.1, so=so, useshrplib=false, libperl=libperl.a&lt;br /&gt;    gnulibc_version=&#39;&#39;&lt;br /&gt;  Dynamic Linking:&lt;br /&gt;    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=&#39; &#39;&lt;br /&gt;    cccdlflags=&#39;-DPIC -fPIC &#39;, lddlflags=&#39;-shared -fPIC  -L/usr/local/lib -fstack-protector&#39;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Characteristics of this binary (from libperl): &lt;br /&gt;  Compile-time options: MYMALLOC PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP&lt;br /&gt;                        PERL_USE_DEVEL USE_LARGE_FILES USE_PERLIO&lt;br /&gt;                        USE_PERL_ATOF&lt;br /&gt;  Built under openbsd&lt;br /&gt;  Compiled at Sep 14 2010 11:31:21&lt;br /&gt;  %ENV:&lt;br /&gt;    PERL5LIB=&quot;/home/kent/perl5/perlbrew/perls/current:/home/kent/perl5/perlbrew/perls/current/i386-openbsd&quot;&lt;br /&gt;    PERLDIR=&quot;/home/kent/perl5/perlbrew/perls/current&quot;&lt;br /&gt;    PERL_CPANM_OPT=&quot;--local-lib=/home/kent/perl5/perlbrew/perls/current&quot;&lt;br /&gt;    PERL_MM_OPT=&quot;INSTALL_BASE=/home/kent/perl5/perlbrew/perls/current&quot;&lt;br /&gt;  @INC:&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/current&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/current/i386-openbsd&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/perl-5.13.4/lib/site_perl/5.13.4/OpenBSD.i386-openbsd&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/perl-5.13.4/lib/site_perl/5.13.4&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/perl-5.13.4/lib/5.13.4/OpenBSD.i386-openbsd&lt;br /&gt;    /home/kent/perl5/perlbrew/perls/perl-5.13.4/lib/5.13.4&lt;br /&gt;    .&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/2668623695387345399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/09/openbsd-perl-modern-tools-and.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/2668623695387345399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/2668623695387345399'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/09/openbsd-perl-modern-tools-and.html' title='OpenBSD + Perl + Modern Tools and Approaches -&amp;gt; Me = Confused :('/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-5550700558009366322</id><published>2010-09-12T02:21:00.000+12:00</published><updated>2010-09-12T02:21:04.339+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".la"/><category scheme="http://www.blogger.com/atom/ns#" term="Gentoo"/><category scheme="http://www.blogger.com/atom/ns#" term="lafilefixer"/><category scheme="http://www.blogger.com/atom/ns#" term="libpng12"/><category scheme="http://www.blogger.com/atom/ns#" term="paludis"/><category scheme="http://www.blogger.com/atom/ns#" term="portage"/><title type='text'>Gentoo Protip: Clean orphaned .la files.</title><content type='html'>If you&#39;ve been using the &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;lafilefixer&lt;/span&gt;&quot;&lt;sup&gt;&lt;a href=&quot;#foot1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; to tweak &quot;broken&quot; &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;.la &lt;/span&gt;files, you may have discovered a negative side effect of its use.&lt;br /&gt;&lt;br /&gt;Primarily, that lafilefixer breaks the MD5/SHA sums of the various .la files, so when somebody removes that package later, or upgrades to a package with a differently named .la file, it leaves behind this .la cruft.&lt;sup&gt;&lt;a href=&quot;#foot2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;The effect of this, is that subsequent builds can die in mysterious ways trying to find stuff, as stupid code tries to use the old and outdated .la files.&lt;br /&gt; &lt;br /&gt;The solution is reasonably simple, all you need is a little help from a few good Unix commands.&lt;br /&gt;&lt;br /&gt;You&#39;ll need 2 basic packages installed:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://www.gnu.org/software/findutils/&quot;&gt;GNU findutils&lt;/a&gt; &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;xargs&lt;/span&gt;&quot; and &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;find&lt;/span&gt;&quot;, provided in &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;sys-apps/findutils&lt;/span&gt;. You should already have these, because they are after all part of the &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;system&lt;/span&gt;&quot; set.&lt;/li&gt;&lt;li&gt;Gentoo&#39;s Portage-Utils&#39;&amp;nbsp; &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;qfile&lt;/span&gt;&quot;, provided in &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;app-portage/portage-utils&lt;/span&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Firstly, we generate a list of all the .la files.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;kent@ember$ find -O3 /usr/lib64&amp;nbsp; -type f&amp;nbsp; -name &quot;*.la&quot;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We then pipe this list null-delimited to &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;xargs&lt;/span&gt; ( for safety ) and ask &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;qfile&lt;/span&gt;&quot; to tell us if they are &lt;u&gt;o&lt;/u&gt;rphans.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;kent@ember$ find -O3 ./&amp;nbsp; -type f -name &quot;*.la&quot;&amp;nbsp; -print0 | xargs -0 qfile -o&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can then review this list, make a few &quot;ahh!, so that explains that problem&quot; statements, and then proceed to remove the listed files using our mechanism of choice. &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;xargs&lt;/span&gt; + &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;rm&lt;/span&gt; is good enough for me.&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;bash&quot;&gt;kent@ember$ find -O3 ./&amp;nbsp; -type f -name &quot;*.la&quot;&amp;nbsp; -print0 | xargs -0 qfile -o | xargs rm&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And as if by magic, things that no longer wanted to compile resume compiling!.&lt;br /&gt;&lt;br /&gt;For me, this cleaned up &lt;i&gt;most&lt;/i&gt; of the residual problems I had after the whole &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;libpng12&lt;/span&gt; debacle.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Important:&lt;/strong&gt; You should read the man pages for &lt;code&gt;xargs&lt;/code&gt; and &lt;code&gt;find&lt;/code&gt; to make sure you&#39;re not just cargoculting bad code. i.e: that -O3 thing can be dangerous. &lt;br /&gt;&lt;span id=&quot;foot1&quot;&gt;1:&amp;nbsp; ( dev-util/lafilefixer )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id=&quot;foot2&quot;&gt;2: Perhaps portage has a workaround for this, but I&#39;m using Paludis, so don&#39;t know, sorry. Complaints to: /dev/null. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/5550700558009366322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/09/gentoo-protip-clean-orphaned-la-files.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5550700558009366322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/5550700558009366322'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/09/gentoo-protip-clean-orphaned-la-files.html' title='Gentoo Protip: Clean orphaned .la files.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-9017337216436921606</id><published>2010-08-13T01:51:00.001+12:00</published><updated>2010-08-13T02:15:02.996+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="rebase"/><category scheme="http://www.blogger.com/atom/ns#" term="theory"/><title type='text'>Git Rebase Part 1: Why you should use it, Theory.</title><content type='html'>&lt;div style=&quot;text-align: justify&quot;&gt;&lt;p&gt;If you have yet to master Gits rebase feature, now is the time to do so. Rebasing, as we call it, provides you with astonishingly awesome powers of manipulating your repository history.  Rebasing is however, not for the faint of heart, and those still green on how Git really works, as there is a lot of concepts you need to have a firm grasp of in order to utilize it. ( I will try cover these concepts here ). &lt;/p&gt;&lt;p&gt;If you have only ever worked on simple no-branching repositories with few committers, in a non-distributed SCM, you probably have not even yet encountered a scenario where rebasing would make much sense to you. The problem is when you get diverging histories greater than a few commits.  &lt;/p&gt;&lt;p&gt;Normally, people wait till merge time to resolve this divergence, but it can be less than simple, and the longer and more complex your history, the harder merging will be, and there is no technological way to make this simply go away ( at least, not yet ).  &lt;/p&gt;&lt;p&gt;Fortunately, most of merges are non-competing commits, and Git does a stellar job of doing the right thing in these scenarios.   &lt;/p&gt;&lt;p&gt;The challenge occurs when two people create competing commits on parallel histories, and the problem is exacerbated when there is a stack load of changes on top of those competing commits. &lt;/p&gt;&lt;p&gt;Classical solutions to this result in a big explosion at merge time, and all you have to go on is what the &lt;em&gt;current&lt;/em&gt; state of either branch is at that time, and you have to know the code very well, and be able to “pick one” of the solutions ( or, if you are especially unlucky, manually find a 3&lt;sup&gt;rd&lt;/sup&gt; solution in your head which is a product of both ). &lt;/p&gt;&lt;p&gt;Unfortunately, in many large open-source projects, not everyone knows everything about everything, and when it comes time to merge, the person doing the merge knows nothing about the specifics of the others changes on a line-by-line basis, and so, there is an unreasonable demand on the merger to be a magician. &lt;/p&gt;&lt;h3&gt;Offloading the merge load to the contributor.&lt;/h3&gt;&lt;p&gt;A good solution in my mind, is to offload the responsibility of resolving issues onto the person performing the contributions. They understand their code the most, they know what needs to go away when and where. One approach to this, involves perpetual merges from upstream to keep your branch “synced”, but this is a nightmare. It also in my experience doesn&#39;t work like you would expect.  I do not want to go into the specifics of the problems I have seen with merges, simply because communicating them simply is difficult. Also, it makes things even more complicated later down the line with reintegration, as comparing the diffs can be misleading as to what really changed, as well as overcomplicating the commit history. &lt;/p&gt;&lt;h3&gt;A logical way to consider how rebasing works.&lt;/h3&gt;&lt;p&gt;Consider you are working on a more old-school SCM such as Subversion, where this rebasing feature does not exist. To emulate a rebase, what you would have to do, is first, find the point where the branch you are to rebase first diverges from trunk. Then, you would produce a patch for each and every commit that had been applied to the branch since it was branched from trunk. Doing this, is of course no simple feat ☺. &lt;/p&gt;&lt;p&gt;You would then create &lt;em&gt;another&lt;/em&gt; branch, starting from the current trunk, and switch to it. Then, you would iterate through every patch in order, and apply it to this new branch, possibly stopping between each patch application, to correct any collisions that caused the patch to fail ( i.e.: edit the patch until it applied cleanly ), before committing it. &lt;/p&gt;&lt;p&gt;The product is a completely unambiguous patch series, relative to the current trunk. Where branches are considered “feature branches”, this new branch becomes a perfect logical sequence of commits that can be unambiguously applied to trunk to add the given feature. &lt;/p&gt;&lt;p&gt;At this new state, assuming no other commits are made to trunk, this new branch logically should be merge-able straight into trunk with no collisions whatsoever. ( I am of course making huge assumptions here with regard to subversion being smart enough to know how to handle it, and not simply going “Hurr, branch and trunk look different, must be a collision!”) &lt;/p&gt;&lt;h3&gt;To Explain this Visually:&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;http://imgur.com/JZqxV.png&quot; alt=&quot;http://gist.github.com/raw/517220/9b885f405d2f9cd3bc1c19b69868db341d6eea75/graph.dot.txt&quot; style=&quot;float:left; margin-right: 10px;&quot;/&gt;This is our initial repository, a nice straight forward commit sequence. “Trunk” is the current state of our directory. Note that although I have used numbers for clarity in explanation, Git internally has no such sequential concept. Hopefully, this structure is apparent to all readers. &lt;div style=&quot;height: 30px;&quot; &gt;&lt;/div&gt;&lt;img src=&quot;http://imgur.com/qJhPo.png&quot; alt=&quot;http://gist.github.com/raw/517220/81a7d918d13cfec92fcc84c6fd39b1fdb68e28cd/graph2.dot.txt&quot; style=&quot;float:right; margin-left: 10px;&quot; /&gt;In diagram 2, more commits have been created. At &lt;strong&gt;04&lt;/strong&gt; a new topic branch was created called “&lt;strong&gt;X&lt;/strong&gt;”. Since the divergence of these branches, 4 commits have been created on &lt;strong&gt;trunk&lt;/strong&gt; and 5 commits on &lt;strong&gt;X&lt;/strong&gt;.  Normally, you would probably want to try merging x05 back into trunk to create a new commit. But this leaves you with multiple paths in your history, which can make things very messy over time. &lt;div style=&quot;height: 1px; clear: both; float: none;&quot; &gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&lt;div style=&quot;width: 100%;&quot;&gt;&lt;img src=&quot;http://imgur.com/sazVr.png&quot; alt=&quot;http://gist.github.com/raw/517220/8e6db008abe76f80575a225734148cfc6f6af05c/graph3.dot.txt&quot; style=&quot;margin: 0 auto; width: 593px; height: 784px; float: left;&quot; /&gt;&lt;div style=&quot;height: 1px; clear: both; float: none;&quot; &gt;&lt;/div&gt;&lt;/div&gt;In the above diagram, each and every commit has been “replayed” on top of the trunk. Note that this creates a &lt;em&gt;new&lt;/em&gt; commit, which is a derivation of the original commit. Aggregatively, when a whole branch is replayed on top of trunk ( or any other branch for that matter ), the effect is you produce a second derived branch, that simply has a different origin.  &lt;/p&gt;&lt;p&gt;In practice, this new branch is much like you had decided “Hey, branches are too hard, we will not do them, so new features must be worked on, and completed 100%, before starting another feature” , and you had instead merely “waited around” for commit 08 to arrive, and then proceeded to develop the same feature. ( Except for of course, in reality, you never had to do any of that silly waiting stuff, and you actually were able to use branches! ) &lt;/p&gt;&lt;p&gt; &lt;img src=&quot;http://imgur.com/LjpJO.png&quot; style=&quot;float: right; margin-left: 10px;&quot; /&gt;After creating the derivative branch, we can then clean up the original branch. It is no longer needed, and having it lying around is just likely to confuse people, not to mention make our history graph very messy. Git will perform this step for you automatically, as soon as the rebase is deemed “Successful” and “Complete”. &lt;div style=&quot;height: 1px; clear: both; float: none;&quot; &gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&lt;div style=&quot;height: 30px;&quot; &gt;&lt;/div&gt;&lt;img src=&quot;http://imgur.com/MZQnE.png&quot; style=&quot;float: left; margin-right: 10px;&quot; /&gt;Now, if you consider the logical application of what a merge does at this point, its quite straight forward now.  In fact, that sentence almost constitutes a bad pun, considering git calls this type of merge scenario a “Fast Forward”. This is simply because it does no real merging at all. Git sees there is a simple straight linear sequence of commits that can exist to update trunk to reflect the integration of the branch, so it simply changes what commit it calls “head”.  &lt;/p&gt;&lt;h3&gt;Now as you can see ... &lt;/h3&gt;&lt;p&gt;The result is a much much cleaner history to work with, and merging branches becomes trivially mindless ☺&lt;/p&gt; &lt;h5&gt;Footnotes:&lt;/h5&gt;&lt;p&gt;All diagrams designed in graphviz. For the source for these diagrams, see &lt;a href=&quot;http://gist.github.com/517220&quot;&gt;This Gist on Github&lt;/a&gt;&lt;div style=&quot;height: 1px; clear: both; float: none;&quot; &gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/9017337216436921606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/08/git-rebase-part-1-why-you-should-use-it.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/9017337216436921606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/9017337216436921606'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/08/git-rebase-part-1-why-you-should-use-it.html' title='Git Rebase Part 1: Why you should use it, Theory.'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-953402823678518377</id><published>2010-08-06T04:23:00.001+12:00</published><updated>2010-08-06T04:28:24.957+12:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="adoption"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="perl6"/><title type='text'>Why Am I not using Perl 6 Yet?</title><content type='html'>&lt;p&gt;I&#39;m not here to deride it, I think its pretty, the syntax is nice, and it lacks some of the annoyances I currently have with Perl 5. Its got great features, and I whole heartedly want them to keep on trucking with that project.&lt;/p&gt;&lt;p&gt;My problem is not a petty squabble over things like &lt;q&gt;Hurr, not perl5 enough&lt;/q&gt; or &lt;q&gt;Derp, uses too much rams!&lt;/q&gt;, or &lt;q&gt;Its too slow!&lt;/q&gt; or qualms about its completedness or its buggyness.&lt;/p&gt;&lt;p&gt;To a pragmatic person, none of those things really matter that much, you have to be doing really heavy work for speed and ram to be a problem on a Modern machine, and for a lot of things, I could not care less if startup time was a &lt;strong&gt;WHOLE SECOND LONGER&lt;/strong&gt;. Hell, the total amount of time spent &lt;em&gt;bitching&lt;/em&gt; about load time and speed now, in the real world, is likely to exceed the net total amount of time spent actually waiting for Perl6 to start. And the volumes of text and debate on this issue is almost certain to be a much larger waste of memory ( considering how much a single bit of information is replicated everywhere, and how it has to be replicated just to be *read*, and all the transport stuff that makes that possible ).&lt;/p&gt;&lt;p&gt;&lt;em&gt;Back on the subject!&lt;/em&gt;&lt;/p&gt;&lt;p&gt;I think my biggest reason for not using Perl6 yet is that I&#39;m not using Perl6 yet. I guess this is somewhat circular reasoning. but the problem is when I think &quot;Oh, I have a task to achieve&quot;, my brain instantly starts forming it with regard to Perl5 and its idioms and methods.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Additionally&lt;/em&gt;, When I use Perl5, I&#39;m not really spending a great deal of time messing around with its syntactical nuances. What I&#39;m spending &lt;em&gt;more&lt;/em&gt; time doing, is importing and using code and modules that already exists. I have a good mental understanding of all those great Perl modules from CPAN, and which ones I can JustUse to do whatever it is I want to be doing.&lt;/p&gt;&lt;p&gt;When I want to be doing something I don&#39;t already know how to do, the first thing I&#39;m hitting up CPAN to see if somebodys done it already in a way I need, or to see if there are a few aggregate parts I can scrape together to make what I want&lt;/p&gt;&lt;p&gt;&lt;em&gt;Also,&lt;/em&gt; most of my coding these days revolves around my various Perl5 modules, enhancing, maintaining, etc, and all this of course &lt;strong&gt;requires&lt;/strong&gt; Perl5 to be employed. Its silly to consider depending on Perl6 to make a Perl5 module. And although I know I probably should be helping to reduce this problem by making Perl6 ports of my modules, its a bit chicken-egg because many of my modules are extensions for other Perl5 modules. &lt;/p&gt;&lt;p&gt;So, essentially, going Perl6 would require me to basically throw out everything I know, and then resort to doing things myself? If this is not the case, I don&#39;t understand/see how else I&#39;m expected to do something in Perl6.&lt;/p&gt;&lt;p&gt;There&#39;s lots of fun examples of people doing raw hacking in Perl6, but I don&#39;t see boatloads of people using modules, and I don&#39;t see boatloads of Perl6 modules on CPAN when I&#39;m searching for things I need to do.&lt;/p&gt;&lt;p&gt;If there&#39;s a secret second c6pan somewhere I&#39;m just not seeing that these magically awesome Perl6 modules are being served on instead, Somebody should post a link to somewhere I&#39;m likely to stumble over it.&lt;/p&gt;&lt;p&gt;Because presently, the gut reaction is barely better than suggesting I move back to PHP, where I have to reinvent every wheel myself in the event my behaviour is not implemented by a core PHP feature.&lt;/p&gt;&lt;p&gt;And the idea of being stuck back in that mindset is less than inspiring to me.&lt;/p&gt;&lt;h3&gt;What would it take me to switch?&lt;/h3&gt;In a nutshell: &lt;ul&gt;&lt;li&gt;A much more obvious path to adoption&lt;ul&gt;&lt;li&gt;Obvious path to learning core syntax&lt;/li&gt;&lt;li&gt;Obvious path to finding extensions/modules&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;A More Comprehensive Archive of Perl6 modules.&lt;/li&gt;&lt;li&gt;Being things I &lt;em&gt;currently&lt;/em&gt; use available on Perl6 in similar ways to how they are now, so I can jump ship, and start using &lt;em&gt;those&lt;/em&gt; versions  instead, and then start hacking on/improving those things with my own modules.&lt;/li&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/953402823678518377/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/08/why-am-i-not-using-perl-6-yet.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/953402823678518377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/953402823678518377'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/08/why-am-i-not-using-perl-6-yet.html' title='Why Am I not using Perl 6 Yet?'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6533723486908610755.post-9138423395883909865</id><published>2010-08-04T11:26:00.000+12:00</published><updated>2010-08-04T11:26:10.784+12:00</updated><title type='text'>Extending Exception::Class in Moose</title><content type='html'>&lt;p&gt;I recently had the joyous experience of &lt;a href=&quot;http://github.com/kentfredric/net-api-rpx/tree/Exceptional&quot;&gt;porting some code &lt;/a&gt; to use proper Object Oriented Exceptions, and found a few niggles in my experience.  &lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://search.cpan.org/dist/Exception-Class/&quot;&gt;Exception::Class&lt;/a&gt; is a great module, and in terms of an &lt;a href=&quot;http://search.cpan.org/dist/Exception-Class/lib/Exception/Class/Base.pm&quot;&gt;Exception base class&lt;/a&gt; does lots of the things I want an exception module to do.&lt;/p&gt;&lt;p&gt;However, it has one and only one really big problem from my perspective, and that is, by default, its extensibility is a bit limited.&lt;/p&gt;&lt;p&gt;It appears to be highly targeted for its in-line declarations at &lt;code&gt;import()&lt;/code&gt;, as follows:&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt; use Exception::Class (&lt;br /&gt;      &#39;MyException&#39;,&lt;br /&gt;&lt;br /&gt;      &#39;AnotherException&#39; =&gt; { isa =&gt; &#39;MyException&#39; },&lt;br /&gt;&lt;br /&gt;      &#39;YetAnotherException&#39; =&gt; {&lt;br /&gt;          isa         =&gt; &#39;AnotherException&#39;,&lt;br /&gt;          description =&gt; &#39;These exceptions are related to IPC&#39;&lt;br /&gt;      },&lt;br /&gt;&lt;br /&gt;      &#39;ExceptionWithFields&#39; =&gt; {&lt;br /&gt;          isa    =&gt; &#39;YetAnotherException&#39;,&lt;br /&gt;          fields =&gt; [ &#39;grandiosity&#39;, &#39;quixotic&#39; ],&lt;br /&gt;          alias  =&gt; &#39;throw_fields&#39;,&lt;br /&gt;      },&lt;br /&gt;  );&lt;/pre&gt;&lt;p&gt;This is handy, For the simple case. But it doesn&#39;t do you a whole bunch of favours. Adding custom methods is a bane, and there&#39;s no field validation/processing support.&lt;/p&gt;&lt;p&gt;The best alternative to getting custom methods is &lt;a href=&quot;http://search.cpan.org/dist/Exception-Class-Nested/&quot;&gt;Exception::Class::Nested&lt;/a&gt; which lets you do this:&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;        use Exception::Class::Nested (&lt;br /&gt;                &#39;MyException&#39; =&gt; {&lt;br /&gt;                        description =&gt; &#39;This is mine!&#39;,&lt;br /&gt;&lt;br /&gt;                        &#39;YetAnotherException&#39; =&gt; {&lt;br /&gt;                                description =&gt; &#39;These exceptions are related to IPC&#39;,&lt;br /&gt;&lt;br /&gt;                                &#39;ExceptionWithFields&#39; =&gt; {&lt;br /&gt;                                        fields =&gt; [ &#39;grandiosity&#39;, &#39;quixotic&#39; ],&lt;br /&gt;                                        alias =&gt; &#39;throw_fields&#39;,&lt;br /&gt;                                        full_message =&gt; sub {&lt;br /&gt;                                                my $self = shift;&lt;br /&gt;                                                my $msg = $self-&gt;message;&lt;br /&gt;                                                $msg .= &quot; and grandiosity was &quot; . $self-&gt;grandiosity;&lt;br /&gt;                                                return $msg;&lt;br /&gt;                                        }&lt;br /&gt;                                }&lt;br /&gt;                        }&lt;br /&gt;                },&lt;br /&gt;        );&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is loads more practical, merely by eliminating the &lt;code&gt;isa =&amp;gt;&lt;/code&gt; stuff and adding of custom methods, but it still lacks many things in extensibility. No Type checking, no parameter processing, and worst of all, no apparently logical path to avoid clobbering parent methods ( I&#39;m entirely assuming the &lt;code&gt;-&amp;gt;SUPER::&lt;/code&gt; stuff works, but I dislike that peskyness with a passion ). And last but not least, that module won&#39;t even install or pass its own tests.&lt;/p&gt;&lt;p&gt;So, you find yourself to this sort of thing:&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package ExceptionWithFields;&lt;br /&gt;use base &#39;YetAnotherException&#39;;&lt;br /&gt;# Every time I have to do this, I forget how to do it&lt;br /&gt;# which is especially annoying as its not documented anywhere&lt;br /&gt;# and Exception::Class bolts it on to its generated exceptions during -&gt;import()&lt;br /&gt;# so the method is nowhere to be found in Exception::Class::Base &#39;s code &lt;br /&gt;# or its inheritance hierarchy.&lt;br /&gt;# the inner guts of it are hidden away in Exception::Class::_make_subclass&lt;br /&gt;sub Fields {&lt;br /&gt;     # return an array of field names or they won&#39;t get populated.&lt;br /&gt;     return (&#39;grandiosity&#39;, &#39;quixotic&#39;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# yes, you have to write your own accessors&lt;br /&gt;# Exception::Class-&gt;import() generates these accessors manually.&lt;br /&gt;&lt;br /&gt;sub grandiosity { &lt;br /&gt;    my ( $self ) = shift;&lt;br /&gt;    return $self-&gt;{grandiosity};&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub quixotic {&lt;br /&gt;    my ( $self ) = shift;&lt;br /&gt;    return $self-&gt;{quixotic};&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub full_message {&lt;br /&gt;    my $self = shift;&lt;br /&gt;    my $msg = $self-&gt;message;&lt;br /&gt;    $msg .= &quot; and grandiosity was &quot; . $self-&gt;grandiosity;&lt;br /&gt;    return $msg;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;1;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;YUCK!. &lt;/strong&gt;. That&#39;s an awfully lot of nasty boilerplate :(.&lt;/p&gt;&lt;p&gt;This is only a simple example, so you can see how it&#39;d get more complicated with more advanced things, I don&#39;t even want to contemplate how to handle parameter coercion/processing.&lt;/p&gt;&lt;h3&gt;So, lets Moose this thing up!&lt;/h3&gt;&lt;p&gt;I&#39;m addicted to this &lt;a href=&quot;http://search.cpan.org/dist/Moose&quot;&gt;Moose&lt;/a&gt; thing.&lt;/p&gt;&lt;p&gt;Moose probably makes Exception classes overweight, but considering how short lived they are, in many cases it doesn&#39;t really matter.&lt;/p&gt;&lt;p&gt;Unfortunately for us, Exception::Class uses &lt;a href=&quot;http://search.cpan.org/dist/Class-Data-Inheritable/&quot;&gt;some other weird thing&lt;/a&gt; which makes bolting stuff on to it a bit harder. &lt;/p&gt;&lt;p&gt;But fortunately, there is &lt;a href=&quot;http://search.cpan.org/dist/MooseX-NonMoose/&quot;&gt;MooseX::NonMoose&lt;/a&gt; which makes this &lt;em&gt;mostly&lt;/em&gt; painless.&lt;/p&gt; &lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package MyException;&lt;br /&gt;use Moose;&lt;br /&gt;use MooseX::NonMoose;&lt;br /&gt;use namespace::autoclean;&lt;br /&gt;extends qw(Exception::Class::Base);&lt;br /&gt;# This method is needed to delete things which are supposed to be handled by Moose &lt;br /&gt;# so they don&#39;t get passed to the parent constructor, because excess args cause it to fail -_-&lt;br /&gt;sub FOREIGNBUILDARGS {&lt;br /&gt;  my ( $class, %args ) = @_;&lt;br /&gt;  for ( $class-&gt;meta-&gt;get_attribute_list ) {&lt;br /&gt;    delete $args{$_};&lt;br /&gt;  }&lt;br /&gt;  return %args;&lt;br /&gt;}&lt;br /&gt;# Handy addition for giving back traces to user-land.&lt;br /&gt;around show_trace =&gt; sub {&lt;br /&gt;  my ( $orig, $class, @rest ) = @_;&lt;br /&gt;  return 1 if exists $ENV{MYEXCEPTION_STACKTRACE} and $ENV{MYEXCEPTION_STACKTRACE};&lt;br /&gt;  return $class-&gt;$orig(@rest);&lt;br /&gt;};&lt;br /&gt;__PACKAGE__-&gt;meta-&gt;make_immutable;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Yay&lt;/em&gt;. Suddenly we have something Moose friendly that JustWorks as we want it to. And we&#39;ve already added functionality by making all our children&#39;s stack-traces forced on by an ENV option, but otherwise behave as usual.&lt;/p&gt;&lt;p&gt;Now for the derivative classes&lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package YetAnotherException;&lt;br /&gt;use Moose;&lt;br /&gt;use namespace::autoclean;&lt;br /&gt;extends &#39;MyException&#39;; &lt;br /&gt;__PACKAGE__-&gt;meta-&gt;make_immutable();&lt;br /&gt;1;&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;package ExceptionWithFields;&lt;br /&gt;use Moose;&lt;br /&gt;extends &#39;YetAnotherException&#39;; &lt;br /&gt;use namespace::autoclean;&lt;br /&gt;&lt;br /&gt;has &#39;grandiosity&#39; =&gt; ( isa =&gt; &#39;Str&#39;, is =&gt; &#39;ro&#39;, required =&gt; 1 );&lt;br /&gt;has &#39;quixotic&#39; =&gt; ( isa =&gt; &#39;Str&#39;, is =&gt; &#39;ro&#39; , required =&gt; 1 );&lt;br /&gt;&lt;br /&gt;# Now with inheritable message code =)&lt;br /&gt;around full_message =&gt; sub {&lt;br /&gt;    my ( $orig, $self , @args ) = @_;&lt;br /&gt;    my $msg = $self-&gt;$orig( @args );&lt;br /&gt;    $msg .= &quot; and grandiosity was &quot; . $self-&gt;grandiosity;&lt;br /&gt;    return $msg;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;# Stick some lines *after* the stacktrace =D &lt;br /&gt;around as_string =&gt; sub { &lt;br /&gt;    my ( $orig, $self , @args ) = @_;&lt;br /&gt;    my $msg = $self-&gt;$orig( @args ); &lt;br /&gt;    $msg .= &quot;\n\n Please refer to the ExceptionWithFields Manual for more information&quot;; &lt;br /&gt;    return $msg;&lt;br /&gt;}&lt;br /&gt;__PACKAGE__-&gt;meta-&gt;make_immutable();&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;WAAAY&lt;/strong&gt; More fun. &lt;em&gt;Waaay&lt;/em&gt; Less headaches. Moose++ &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use ExceptionWithFields;&lt;br /&gt;&lt;br /&gt;ExceptionWithFields-&gt;throw( &lt;br /&gt;    message     =&gt; &quot;This is a test&quot;,&lt;br /&gt;    grandiosity =&gt; &quot;This is grand!&quot;,&lt;br /&gt;    quixotic    =&gt; &quot;Very!&quot;,&lt;br /&gt;);&lt;br /&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.fox.geek.nz/feeds/9138423395883909865/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.fox.geek.nz/2010/08/extending-exceptionclass-in-moose.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/9138423395883909865'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/9138423395883909865'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/08/extending-exceptionclass-in-moose.html' title='Extending Exception::Class in Moose'/><author><name>KENTNL</name><uri>http://www.blogger.com/profile/03928687531294568058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>5</thr:total></entry><entry><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><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="summary"/><title type='text'>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 &#39;pack&#39; specials. They&#39;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=&quot;http://progit.org/book/&quot;&gt;Pro Git&lt;/a&gt;, especially the &lt;a href=&quot;http://progit.org/book/ch9-0.html&quot;&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&#39;m going to assume you&#39;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&#39;m using my &lt;a href=&quot;http://github.com/kentfredric/Dist-Zilla-PluginBundle-KENTNL-Lite&quot;&gt;Dist::Zilla::PluginBundle::KENTNL::Lite&lt;/a&gt;tree.  &lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;git clone git://github.com/kentfredric/Dist-Zilla-PluginBundle-KENTNL-Lite.git /tmp/SomeDirName&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I&#39;m going to show you the core of git&#39;s system, which is just the &quot;object&quot; store.&lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;cd /tmp/SomeDirName/.git&lt;br /&gt;find objects/&lt;br /&gt;&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=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;use Compress::Zlib;&lt;br /&gt;use Carp qw( croak );&lt;br /&gt;&lt;br /&gt;sub inflate_file {&lt;br /&gt;    my ( $filename , $OFH ) = @_;&lt;br /&gt;    my ( $inflator, $status ) = Compress::Zlib::inflateInit or croak(&quot;Cannot create inflator: $@&quot;);&lt;br /&gt;    my $input = &#39;&#39;;&lt;br /&gt;    open my $fh, &#39;&lt;&#39;, $filename or croak(&quot;Can&#39;t open $filename, $@ $! $?&quot;);&lt;br /&gt;    binmode $fh;&lt;br /&gt;    binmode $OFH;&lt;br /&gt;&lt;br /&gt;    my ( $output );&lt;br /&gt;    while ( read( $fh, $input, 4096 )) {&lt;br /&gt;        ( $output , $status ) = $inflator-&gt;inflate( \$input );&lt;br /&gt;        print { $OFH } $output if $status == Compress::Zlib::Z_OK or $status == Compress::Zlib::Z_STREAM_END;&lt;br /&gt;        last if $status != Compress::Zlib::Z_OK;&lt;br /&gt;    }&lt;br /&gt;    croak( &quot;Inflation failed of $filename , $@&quot; ) unless $status == Compress::Zlib::Z_STREAM_END;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;for ( @ARGV ) {&lt;br /&gt;    next if $_ =~ /\.(idx|pack)|packs/;&lt;br /&gt;    print qq{&lt;--------BEGIN $_ ---------&gt;\n};&lt;br /&gt;    inflate_file( $_ , *STDOUT );&lt;br /&gt;    print qq{&lt;--------END $_ ---------&gt;\n};&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&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=&quot;bash&quot;&gt;&lt;br /&gt;perl /tmp/deflate.pl $( find objects/ -type f ) | cat -v | less&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Awesome, you&#39;re now seeing the guts of how your repository works. For real. All we did was deflate each and every object. You&#39;ll see 3 types of object, ( each object says at the front what type they are before the ^@ ), tree&#39;s, blobs, and commits ( with trees being the most complicated of all ). &lt;/p&gt;&lt;p&gt;Blobs, they&#39;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 &quot;tree&quot; is like a &quot;dir&quot; in some ways. There&#39;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;</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='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/328107414735722485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/328107414735722485'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/07/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>3</thr:total></entry><entry><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><category scheme="http://www.blogger.com/atom/ns#" term="exceptions"/><category scheme="http://www.blogger.com/atom/ns#" term="limitations"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>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=&quot;/2010/07/current-limitations-in-exception-driven.html&quot;&gt;Exception Hierarchy&lt;/a&gt;, and that this wasn&#39;t a huge gaping hole in the current Exception landscape. &lt;/p&gt;&lt;p&gt;There&#39;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 &quot;$string&quot;&lt;/code&gt;and &lt;code&gt;croak &quot;$string&quot;&lt;/code&gt; is about as detailed as you get from most things. &lt;/p&gt;&lt;p&gt;And I&#39;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 &#39;die&#39; calls are represented in the error ), let alone problem classification without resorting to regexing&#39; the failure string. ( and that&#39;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&#39;t recognise, breaking your code ).&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://p3rl.org/autodie&quot;&gt;autodie&lt;/a&gt; is a good &lt;em&gt;start&lt;/em&gt; to solving this problem, it doesn&#39;t have all the  bells and whistles I&#39;d hoped for, it has an &lt;a href=&quot;http://search.cpan.org/~pjf/autodie-2.10/lib/autodie.pm#CATEGORIES&quot;&gt;error hierarchy&lt;/a&gt;, but it doesn&#39;t appear very flexible to extensible into other projects ( the whole thing is defined in a &#39;my&#39; variable in Fatal.pm it seems ), and additionally, it doesn&#39;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 &#39;require&#39; 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=&quot;perl&quot;&gt;&lt;br /&gt;sub findFirst { &lt;br /&gt;  my $plugin = shift;&lt;br /&gt;  my $parent = &quot;SomeApp&quot;;&lt;br /&gt;  my @guessOrder = ( $plugin . &quot;::&quot; . $parent , $plugin );&lt;br /&gt;  my @fails;&lt;br /&gt;  for( @guessOrder ){&lt;br /&gt;     local $@;&lt;br /&gt;     eval &quot;require $_; 1&quot;;&lt;br /&gt;     if ( $@ ) {&lt;br /&gt;        die $@ if $@ !~ /not found/ ; &lt;br /&gt;        push @fails, $@;&lt;br /&gt;     } else { &lt;br /&gt;        return $_ ; &lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;  die &quot;Couldn&#39;t load any of @guessOrder : @fails &quot;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;my $plug = findFirst(&quot;Foo::Bar&quot;);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is about as semantically clean as I can get it. The goal here is to permit &quot;Not Found&quot; 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=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;sub fail {&lt;br /&gt;  die &quot;Hurp Durp!&quot;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub maybfail {&lt;br /&gt;  unless ( eval { fail; 1; } ) {&lt;br /&gt;    die &quot;maybfail: $@&quot;;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub moarfail {&lt;br /&gt;  unless ( eval { maybfail; 1; } ) {&lt;br /&gt;    die &quot;Moarfail: $@&quot;;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;moarfail;&lt;br /&gt;&lt;/pre&gt;To me, I&#39;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&#39;s the best I can get out of that simple structure:   &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl -MCarp::Always /tmp/die.pl &lt;br /&gt;Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 18&lt;br /&gt; main::moarfail() called at /tmp/die.pl line 22&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl /tmp/die.pl &lt;br /&gt;Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 7.&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl -MCarp::Always /tmp/die.pl &lt;br /&gt;Moarfail: maybfail: Hurp Durp! at /tmp/die.pl line 18&lt;br /&gt; main::moarfail() called at /tmp/die.pl line 22&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl -MDevel::SimpleTrace /tmp/die.pl &lt;br /&gt;Moarfail: maybfail: Hurp Durp!&lt;br /&gt; at main::fail(/tmp/die.pl:7)&lt;br /&gt; at &lt;eval&gt;(/tmp/die.pl:11)&lt;br /&gt; at main::maybfail(/tmp/die.pl:11)&lt;br /&gt; at &lt;eval&gt;(/tmp/die.pl:17)&lt;br /&gt; at main::moarfail(/tmp/die.pl:17)&lt;br /&gt; at main::(/tmp/die.pl:22)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Note how none of those traces reflect the fact I call &quot;die&quot; on line 12? Be glad the die isn&#39;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&#39;t work out why some know about the failure origin, and others don&#39;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=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;sub fail {&lt;br /&gt;    BasicException-&gt;throw( error =&gt; &#39;HurpDurp&#39; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub maybfail {&lt;br /&gt;  try { &lt;br /&gt;      fail;&lt;br /&gt;  } catch ( BasicException $e ) { &lt;br /&gt;     MoreComplexException-&gt;adopt( $e )-&gt;throw( error =&gt; &#39;Maybfail&#39;);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub moarfail {&lt;br /&gt;  try { &lt;br /&gt;      maybfail;&lt;br /&gt;  } catch ( MoreComplexException $e ) { &lt;br /&gt;     EvenMoreComplexExcetpion-&gt;adopt( $e )-&gt;throw( error =&gt; &#39;Moarfail&#39;);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;moarfail;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Nothing I&#39;ve seen handles that &quot;adopt&quot; thing, but its my little way of saying &quot;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.&quot;  &lt;/p&gt;&lt;p&gt;In case you TL;DR&#39;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;</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'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/8094350727641886790'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/07/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>1</thr:total></entry><entry><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><category scheme="http://www.blogger.com/atom/ns#" term="exceptions"/><category scheme="http://www.blogger.com/atom/ns#" term="limitations"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>Current Limitations In Exception Driven Perl: Exception Base Classes.</title><content type='html'>&lt;p&gt;I&#39;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=&quot;http://p3rl.org/Exception::Class&quot;&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&#39;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&#39;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&#39;re just Perl packages. I accept this limitation is mostly Perl&#39;s fault, but I still dislike it. The &#39;Type&#39; 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=&quot;http://p3rl.org/MooseX::Types&quot;&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=&quot;perl&quot;&gt;&lt;br /&gt;   package Bar;&lt;br /&gt;   use SomeTypePackage qw( Foo );&lt;br /&gt;   use Bar::Foo; # Hurp durp. Bar::Foo-&gt;import() ==&gt; Bar::Foo()-&gt;import() &lt;br /&gt;   Bar::Foo-&gt;new(); # moar hurp durp. Bar::Foo()-&gt;import() &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Its reasonably easy to work around, but discovering you&#39;ve failed in this way is slightly less than obvious. &lt;/p&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'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/4796444038747943755'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/07/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>2</thr:total></entry><entry><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><category scheme="http://www.blogger.com/atom/ns#" term="bug"/><category scheme="http://www.blogger.com/atom/ns#" term="error"/><category scheme="http://www.blogger.com/atom/ns#" term="parser"/><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><category scheme="http://www.blogger.com/atom/ns#" term="syntax"/><title type='text'>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=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;print &quot;hello&quot;;&lt;br /&gt;&lt;br /&gt;1&lt;br /&gt;&lt;br /&gt;=pod&lt;br /&gt;&lt;br /&gt;=cut&lt;br /&gt;__END__&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;It looks trivial right? &lt;/p&gt;&lt;p&gt;Not so.  &lt;/p&gt;&lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl /tmp/pl.pl &lt;br /&gt;Can&#39;t modify constant item in scalar assignment at /tmp/pl.pl line 13, at EOF&lt;br /&gt;Bareword &quot;cut&quot; not allowed while &quot;strict subs&quot; in use at /tmp/pl.pl line 8.&lt;br /&gt;Bareword &quot;pod&quot; not allowed while &quot;strict subs&quot; in use at /tmp/pl.pl line 8.&lt;br /&gt;Execution of /tmp/pl.pl aborted due to compilation errors.&lt;br /&gt;&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=&quot;bash&quot;&gt;&lt;br /&gt;$ perl -MO=Deparse /tmp/pl.pl &lt;br /&gt;Can&#39;t modify constant item in scalar assignment at /tmp/pl.pl line 13, at EOF&lt;br /&gt;Bareword &quot;cut&quot; not allowed while &quot;strict subs&quot; in use at /tmp/pl.pl line 8.&lt;br /&gt;Bareword &quot;pod&quot; not allowed while &quot;strict subs&quot; in use at /tmp/pl.pl line 8.&lt;br /&gt;/tmp/pl.pl had compilation errors.&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;use warnings;&lt;br /&gt;use strict &#39;refs&#39;;&lt;br /&gt;print &#39;hello&#39;;&lt;br /&gt;1 = &#39;pod&#39; = &#39;cut&#39;;&lt;br /&gt;__DATA__&lt;br /&gt;&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=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;print &quot;hello&quot;;&lt;br /&gt;&lt;br /&gt;1;&lt;br /&gt;&lt;br /&gt;=pod&lt;br /&gt;&lt;br /&gt;=cut&lt;br /&gt;__END__&lt;br /&gt;&lt;/pre&gt; &lt;pre class=&quot;bash&quot;&gt;&lt;br /&gt;$ perl /tmp/pl.pl &lt;br /&gt;hello&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Perhaps this is worthy of applying a bugfix. Perl version = 5.12.1 =). &lt;/p&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'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/985197264977503623'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/06/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>1</thr:total></entry><entry><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><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 type='text'>Any good advice on focusing on the one scope in this massively metarecursive language?</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&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=&quot;AnExample&quot;&gt;&lt;a href=&quot;#AnExample&quot;&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=&quot;http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html&quot;    title=&quot;Search for the perfect project setup&quot;&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=&quot;http://blog.fox.geek.nz/2010/06/search-for-perfect-project-setup.html&quot; title=&quot;Search for the perfect project setup&quot;&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 &quot;best&quot; option tends to result in &quot;using &lt;a href=&quot;http://www.perl.org/cpan.html&quot;    title=&quot;CPAN - Comprehensive Perl Archive Network&quot;&gt;CPAN&lt;/a&gt;&quot;.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://www.perl.org/cpan.html&quot; title=&quot;CPAN - Comprehensive Perl Archive Network&quot;&gt;CPAN&lt;/a&gt; is great and all, don&#39;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++&#39;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&#39;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=&quot;Distraction2Point0&quot;&gt;&lt;a href=&quot;#Distraction2Point0&quot;&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&#39;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&#39;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&#39;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&#39;t bore you with here ). As part of diagnosis, while I&#39;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&#39;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=&quot;http://search.cpan.org/dist/Text-Balanced/&quot;      title=&quot;Text::Balanced on Search.CPAN.org&quot;&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&#39;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=&quot;http://search.cpan.org/dist/Eval-Context/&quot;   title=&quot;Eval::Context on Search.CPAN.org&quot;&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=&quot;http://search.cpan.org/dist/perl/lib/Carp.pm&quot;      title=&quot;Carp on Search.CPAN.org&quot;&gt;Carp&lt;/a&gt;. The usual techniques such as     &lt;code&gt;-M&lt;a href=&quot;http://search.cpan.org/dist/Carp-Always/&quot;        title=&quot;Carp::Always on Search.CPAN.org&quot;&gt;Carp::Always&lt;/a&gt;&lt;/code&gt; or      &lt;code&gt;-M&lt;a href=&quot;http://search.cpan.org/dist/Devel-SimpleTrace/&quot;     title=&quot;Devel::SimpleTrace on Search.CPAN.org&quot;&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&#39;t         filed a bug for the above yet, in case you&#39;re asking, there&#39;s simply         no point filing one until I can reliably recreate the scenario in a         sterile way. And as a general rule I&#39;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&#39;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&#39;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&#39;m encountering is much much higher as I&#39;m helping test the Perl 5.12.1 release precluding the integration into the main tree, and I&#39;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=&quot;MoreRecursion&quot;&gt;&lt;a href=&quot;#MoreRecursion&quot;&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=&quot;http://search.cpan.org/dist/Dist-Zilla/&quot;  title=&quot;Dist::Zilla on Search.CPAN.org&quot;&gt;Dist::Zilla&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Then comes you writing plugins for &lt;a href=&quot;http://search.cpan.org/dist/Dist-Zilla&quot;  title=&quot;The Awesomeest Distribution Packaging Tool&quot;&gt;Dist::Zilla&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Then you&#39;re writing plugin bundles for the above&lt;/p&gt;&lt;p&gt;Then you&#39;re working on Dist::Zilla itself(&amp;nbsp;Patches&amp;nbsp;!&amp;nbsp;:D&amp;nbsp;)&lt;/p&gt;&lt;p&gt;Then you&#39;re contributing code to other peoples Dist::Zilla plugins&lt;/p&gt;&lt;p&gt;Then you&#39;re contributing code to fix various packages that other peoples Dist::Zilla&#39;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 &quot;Hey, you&#39;re lost in the meta, you&#39;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&#39;t even see trees, all you&#39;re seeing is carbon atoms and you&#39;re trying to compute the spin on their electrons!&quot;&lt;/p&gt;&lt;h3 id=&quot;MyProblemReally&quot;&gt;&lt;a href=&quot;#MyProblemReally&quot;&gt;My Problem Really&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I think my problem is really I don&#39;t see a viable way of staying strictly a &quot;high-level abstraction&quot; consumer, and just using the abstractions that exist to achieve my goal, and I&#39;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 &quot;hey, perhaps you&#39;ll have to be anti-contributive a bit, an    er, yuck, but write code that is probably redundant somewhere in a way    that&#39;s not really optimally reusable, because the long-term maintenance    requirements of publican shared code are a bit high&quot;?    &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&#39;t    put itself on the table!&lt;/p&gt;   &lt;/div&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'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/6695001641995791168'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/06/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>2</thr:total></entry><entry><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><category scheme="http://www.blogger.com/atom/ns#" term="perl"/><title type='text'>Some basic statistics on &quot;Line Noise&quot;</title><content type='html'>&lt;p&gt;I was reading another blog about somebody intending to analyse what amount of perl code constitutes as &quot;Line Noise&quot;, but they didn&#39;t appear to have Actually Done It.&lt;/p&gt;&lt;p&gt;I took a naïve approach and didn&#39;t make any assumptions about what &quot;line noise&quot; constitutes, and just did basic statistics on the prevalence of various characters for the sake of interest.&lt;/p&gt; &lt;div style=&quot;background-color: #FFDDDD; white-space: pre;&quot;&gt;  Partial Dump &lt;pre class=&quot;plaintext&quot; style=&quot;background-color: #FFF;&quot;&gt;  0.2 % :   511319 x char   64 : &quot;\@&quot;&lt;br /&gt;  0.2 % :   564540 x char   55 : 7&lt;br /&gt;  0.2 % :   593117 x char   79 : &quot;O&quot;&lt;br /&gt;  0.2 % :   601710 x char   77 : &quot;M&quot;&lt;br /&gt;  0.3 % :   675072 x char   92 : &quot;\\&quot;&lt;br /&gt;  0.3 % :   684986 x char   68 : &quot;D&quot;&lt;br /&gt;  0.3 % :   698665 x char   78 : &quot;N&quot;&lt;br /&gt;  0.3 % :   709768 x char   76 : &quot;L&quot;&lt;br /&gt;  0.3 % :   712074 x char   80 : &quot;P&quot;&lt;br /&gt;  0.3 % :   763426 x char   56 : 8&lt;br /&gt;  0.3 % :   784577 x char  107 : &quot;k&quot;&lt;br /&gt;  0.3 % :   797560 x char   82 : &quot;R&quot;&lt;br /&gt;  0.3 % :   833723 x char   54 : 6&lt;br /&gt;  0.4 % :   912737 x char   52 : 4&lt;br /&gt;  0.4 % :   920716 x char   93 : &quot;]&quot;&lt;br /&gt;  0.4 % :   921001 x char   91 : &quot;[&quot;&lt;br /&gt;  0.4 % :   924075 x char   73 : &quot;I&quot;&lt;br /&gt;  0.4 % :   947539 x char  118 : &quot;v&quot;&lt;br /&gt;  0.4 % :   956653 x char   67 : &quot;C&quot;&lt;br /&gt;  0.4 % :   996323 x char   65 : &quot;A&quot;&lt;br /&gt;  0.4 % :  1000637 x char   83 : &quot;S&quot;&lt;br /&gt;  0.5 % :  1125435 x char  119 : &quot;w&quot;&lt;br /&gt;  0.5 % :  1151874 x char   46 : &quot;.&quot;&lt;br /&gt;  0.5 % :  1220735 x char   34 : &quot;\&quot;&quot;&lt;br /&gt;  0.5 % :  1222341 x char    9 : &quot;\t&quot;&lt;br /&gt;  0.5 % :  1222927 x char   51 : 3&lt;br /&gt;  0.5 % :  1241600 x char   69 : &quot;E&quot;&lt;br /&gt;  0.5 % :  1243448 x char   53 : 5&lt;br /&gt;  0.5 % :  1332828 x char   84 : &quot;T&quot;&lt;br /&gt;  0.6 % :  1443662 x char   57 : 9&lt;br /&gt;  0.6 % :  1491434 x char  120 : &quot;x&quot;&lt;br /&gt;  0.6 % :  1499376 x char  125 : &quot;}&quot;&lt;br /&gt;  0.6 % :  1500792 x char  123 : &quot;{&quot;&lt;br /&gt;  0.7 % :  1718028 x char  103 : &quot;g&quot;&lt;br /&gt;  0.7 % :  1739054 x char   40 : &quot;(&quot;&lt;br /&gt;  0.7 % :  1739695 x char   41 : &quot;)&quot;&lt;br /&gt;  0.7 % :  1792258 x char   59 : &quot;;&quot;&lt;br /&gt;  0.7 % :  1825133 x char  121 : &quot;y&quot;&lt;br /&gt;  0.8 % :  1837291 x char   98 : &quot;b&quot;&lt;br /&gt;  0.8 % :  1842316 x char   35 : &quot;#&quot;&lt;br /&gt;  0.8 % :  1960600 x char   50 : 2&lt;br /&gt;  0.9 % :  2149806 x char   62 : &quot;&gt;&quot;&lt;br /&gt;  1.0 % :  2410416 x char   49 : 1&lt;br /&gt;  1.1 % :  2594921 x char   61 : &quot;=&quot;&lt;br /&gt;  1.1 % :  2684166 x char   95 : &quot;_&quot;&lt;br /&gt;  1.1 % :  2709633 x char  112 : &quot;p&quot;&lt;br /&gt;  1.2 % :  2818643 x char   58 : &quot;:&quot;&lt;br /&gt;  1.2 % :  2952175 x char  104 : &quot;h&quot;&lt;br /&gt;  1.2 % :  2995621 x char   45 : &quot;-&quot;&lt;br /&gt;  1.3 % :  3151943 x char  109 : &quot;m&quot;&lt;br /&gt;  1.3 % :  3283418 x char   36 : &quot;\$&quot;&lt;br /&gt;  1.3 % :  3291138 x char  102 : &quot;f&quot;&lt;br /&gt;  1.4 % :  3339529 x char   39 : &quot;&#39;&quot;&lt;br /&gt;  1.4 % :  3355931 x char  117 : &quot;u&quot;&lt;br /&gt;  1.5 % :  3638254 x char   99 : &quot;c&quot;&lt;br /&gt;  1.6 % :  4016055 x char  100 : &quot;d&quot;&lt;br /&gt;  1.9 % :  4598003 x char   44 : &quot;,&quot;&lt;br /&gt;  2.0 % :  4786703 x char  108 : &quot;l&quot;&lt;br /&gt;  2.2 % :  5472272 x char   48 : 0&lt;br /&gt;  2.6 % :  6279579 x char  110 : &quot;n&quot;&lt;br /&gt;  2.6 % :  6306811 x char  111 : &quot;o&quot;&lt;br /&gt;  2.7 % :  6625715 x char  105 : &quot;i&quot;&lt;br /&gt;  2.8 % :  6872608 x char  114 : &quot;r&quot;&lt;br /&gt;  3.0 % :  7315145 x char  115 : &quot;s&quot;&lt;br /&gt;  3.1 % :  7522087 x char   97 : &quot;a&quot;&lt;br /&gt;  3.6 % :  8711403 x char   10 : &quot;\n&quot;&lt;br /&gt;  3.7 % :  8972142 x char  116 : &quot;t&quot;&lt;br /&gt;  5.4 % : 13289205 x char  101 : &quot;e&quot;&lt;br /&gt; 24.2 % : 59186425 x char   32 : &quot; &quot;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I find it quite intriguing how the various bracketings are unbalanced. &lt;span style=&quot;text-decoration: line-through;&quot;&gt;Also the significantly greater use of &quot;&amp;gt;&quot; vs &quot;&amp;lt;&quot; 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 &quot;r&quot; &quot;a&quot; and &quot;t&quot; and all whitespace going down, a word is formed. That word.... is &quot;noise&quot;. Weird. &lt;/p&gt;&lt;p&gt;For a full dump of my diagnositcs, see &lt;a href=&quot;http://gist.github.com/451919&quot;&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 &quot;line noise&quot; they are. &lt;/p&gt;&lt;pre class=&quot;perl&quot;&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;&lt;br /&gt;use 5.12.1;&lt;br /&gt;use File::Find::Rule            ();&lt;br /&gt;use File::Find::Rule::Perl      ();&lt;br /&gt;use Data::Dumper                qw( Dumper );&lt;br /&gt;&lt;br /&gt;say $_ for ( @INC );&lt;br /&gt;&lt;br /&gt;my @pmfiles = File::Find::Rule-&gt;perl_file-&gt;in( @INC );&lt;br /&gt;&lt;br /&gt;my %stats;&lt;br /&gt;&lt;br /&gt;for my $file ( @pmfiles ){&lt;br /&gt;    say &quot;scanning $file&quot;;&lt;br /&gt;    open my $fh, &#39;&lt;&#39;, $file or next;&lt;br /&gt;    my $char;&lt;br /&gt;    while( read $fh, $char, 1 ){&lt;br /&gt;        $stats{$char}++;&lt;br /&gt;    }&lt;br /&gt;#    last;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;my @data = sort { $a-&gt;[0] &lt;=&gt; $b-&gt;[0] } map { [ $stats{$_} , $_ ] } keys %stats;&lt;br /&gt;&lt;br /&gt;$Data::Dumper::Terse = 1;&lt;br /&gt;$Data::Dumper::Useqq = 1;&lt;br /&gt;&lt;br /&gt;my $numchars;&lt;br /&gt;$numchars += $_ for values %stats;&lt;br /&gt;&lt;br /&gt;for( @data ){&lt;br /&gt;    printf &quot;%5.1f %% : %8d x char %4d : %s&quot; ,&lt;br /&gt;       ( $_-&gt;[0] / $numchars * 100 ) , &lt;br /&gt;       $_-&gt;[0] , &lt;br /&gt;       ord( $_-&gt;[1] ),&lt;br /&gt;       Dumper( $_-&gt;[1] );&lt;br /&gt;}&lt;br /&gt;&lt;/pre&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'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6533723486908610755/posts/default/9155519522417070477'/><link rel='alternate' type='text/html' href='http://blog.fox.geek.nz/2010/06/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:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_Q3sWw5V6-CE/TCR1qFCvp5I/AAAAAAAAA14/s1GP7R75Wy8/S220/36774_1312533341140_1464853131_1882298_5955176_n.jpg'/></author><thr:total>1</thr:total></entry></feed>