<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>Copious Free Time</title>
  <subtitle>Jeremy Hinegardner</subtitle>
  <link href="http://copiousfreetime.org/feed/atom.xml" rel="self" />
  <link href="http://copiousfreetime.org/" />
  <updated>2008-11-20T02:03:39-07:00</updated>
  <author>
    <name>Jeremy Hinegardner</name>
    <email>jeremy@copiousfreetime.org</email>
  </author>
  <id>http://copiousfreetime.org/</id>
  
  <entry>
    <title>Building Binary Ruby Gems for Windows</title>
    <link href="/articles/2008/10/12/building-gems-for-windows.html" />
    <id>tag:copiousfreetime.org,2008-10-12:1223853965</id>
    <updated>2008-10-12T17:26:05-06:00</updated>
    <content type="html">&lt;h3 class=&quot;post-title&quot;&gt;&lt;a href=&quot;/articles/2008/10/12/building-gems-for-windows.html&quot;&gt;Building Binary Ruby Gems for Windows&lt;/a&gt; &lt;span class=&quot;post-date&quot;&gt;(2008-10-12)&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;I have two C extension based gems&amp;#8212;&lt;a href=&quot;http://copiousfreetime.rubyforge.org/hitimes/&quot;&gt;Hitimes&lt;/a&gt; and
&lt;a href=&quot;http://copiousfreetime.rubyforge.org/amalgalite/&quot;&gt;Amalgalite&lt;/a&gt;&amp;#8212;that I think
would be useful to Windows users.   This weekend I sat down, did the research
and figured out a way to integrate building binary gems for Windows into my
current setup.&lt;/p&gt;


	&lt;p&gt;Probably the biggest issue for developing binary gems for Windows is that the
&lt;a href=&quot;ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.8.7-i386-mswin32.zip&quot;&gt;official Windows on Ruby builds&lt;/a&gt;
are built built using &lt;abbr title=&quot;Visual C++ 6.0&quot;&gt;VC6&lt;/abbr&gt;.  This compiler is
basically impossible to track down, and &lt;a href=&quot;http://blog.mmediasys.com/2008/01/17/ruby-for-windows-part-1/&quot;&gt;Luis has a great explanation of the
issues developing Ruby for
Windows&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;I could have used the new &lt;a href=&quot;http://www.akitaonrails.com/files/ruby_devkit-186-p279.msi&quot;&gt;One Click
Dev-Kit&lt;/a&gt;, and it does
look tempting.  I already have rake scripts setup for all my building, testing,
and distributing and I want to be able to say &lt;code&gt;rake dist:rubyforge&lt;/code&gt; and all
versions of the gem in question are pushed up to rubyforge in one fell swoop.&lt;/p&gt;


	&lt;p&gt;Fortunately Mauricio Fernandez had a great blog post about 2 years ago on 
&lt;a href=&quot;http://eigenclass.org/hiki.rb?cross+compiling+rcovrt&quot;&gt;Cross-compiling Ruby extensions for win32:
rcovrt&lt;/a&gt;.  His approach
integrates better with my current setup and I was able to learn about
cross-compilers in the process, which are something I&amp;#8217;ve been meaning to
experiment with for a while. Although the rcovrt blog post is 2 years old, it is
still relevant and was able to point me in the right direction.&lt;/p&gt;


	&lt;h4&gt;Install a Cross-Compiler&lt;/h4&gt;


	&lt;p&gt;The first item we need is a cross compiler.&lt;/p&gt;


	&lt;p&gt;Right now I&amp;#8217;m developing on a Mac so I need the mingw32 cross compiler so I can
build binaries that will be compatible with the official &lt;abbr title=&quot;Visual C++ 6.0&quot;&gt;VC6&lt;/abbr&gt; 
built Ruby.  Luckily the i386-mingw cross compiler is available
in &lt;a href=&quot;http://www.macports.org/&quot;&gt;MacPorts&lt;/a&gt;.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
sudo port install i386-mingw32-gcc
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;Unfortunately there is &lt;a href=&quot;http://trac.macports.org/ticket/15730&quot;&gt;a problem with the i386-mingw32-binutils
port&lt;/a&gt;.  If you see an error relating to
&lt;code&gt;makeinfo&lt;/code&gt; in your build, use &lt;a href=&quot;http://trac.macports.org/raw-attachment/ticket/15730/0001-fix-for-makeinfo-error-when-building.patch&quot;&gt;the patch I submitted to the
ticket&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Once binutils is all happy and you&amp;#8217;ve had a cup of coffee or two while the mingw32
tool-chain builds installs we can build our gem for Windows.&lt;/p&gt;


	&lt;h4&gt;Building Ruby Using the MinGW Cross-Compiler&lt;/h4&gt;


	&lt;p&gt;This piece was straight from &lt;a href=&quot;http://eigenclass.org/hiki.rb?cross+compiling+rcovrt&quot;&gt;Cross-compiling Ruby extensions for win32:
rcovrt&lt;/a&gt;.  I used Mauricio&amp;#8217;s
&lt;code&gt;cross-compile.sh&lt;/code&gt; as a base and altered it to work on OS X.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
% cat cross-compile.sh
#!/bin/sh
env ac_cv_func_getpgrp_void=no \
    ac_cv_func_setpgrp_void=yes \
    rb_cv_negative_time_t=no \
    ac_cv_func_memcmp_working=yes \
    rb_cv_binary_elf=no \
    ./configure \
    --host=i386-mingw32 \
    --target=i386-mingw32 \
    --build=i686-darwin9.2.2 \
    --prefix=${HOME}/ruby-mingw32
make ruby
make rubyw.exe
make install
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;Stick this in a freshly extracted &lt;a href=&quot;http://www.ruby-lang.org/en/downloads/&quot;&gt;ruby source
distribution&lt;/a&gt; and run it.
This builds an &lt;code&gt;i386-mingw32&lt;/code&gt; version of ruby and installs it in
&lt;code&gt;${HOME}/ruby-mingw32&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;The whole purpose of this little exercise is a side effect.  I don&amp;#8217;t really need
to run this build of ruby, I only need it to exist so I may build against it.&lt;/p&gt;


	&lt;h4&gt;Building a Windows Gem&lt;/h4&gt;


	&lt;p&gt;Now that I have a mingw32 build of ruby I can build my extensions against it.
Normally when building an extensions I do &lt;code&gt;rake ext:build&lt;/code&gt;.  Which under the
covers does:&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
cd ext/
ruby extconf.rb
make
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;For a Windows build, we need to have the &lt;code&gt;extconf.rb&lt;/code&gt; produced &lt;code&gt;Makefile&lt;/code&gt; build
against the i386-mingw32 ruby.  This is done by taking the &lt;code&gt;rbconfig.rb&lt;/code&gt; file
from the ruby-mingw32 installation and putting it in the &lt;code&gt;ext/&lt;/code&gt; directory.  I
keep a copy of this as &lt;code&gt;ext/rbconfig-mingw.rb&lt;/code&gt;.  The build process then becomes:&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
cd ext
cp rbconfig-mingw.rb rbconfig.rb
ruby -I. extconf.rb
make
rm -f rbconfig.rb
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;Using &lt;code&gt;-I.&lt;/code&gt; forces the current working directory to the front of the
&lt;code&gt;$LOAD_PATH&lt;/code&gt; and &lt;code&gt;mkmf&lt;/code&gt; will therefore load the &lt;code&gt;rbconfig.rb&lt;/code&gt; in the &lt;code&gt;ext/&lt;/code&gt;
directory instead of the one from the global ruby installation.  This forces all
the &lt;code&gt;Config::CONFIG&lt;/code&gt; accesses in &lt;code&gt;mkmf&lt;/code&gt; to use the environment of the mingw
build and make a i386-mingw Makefile.&lt;/p&gt;


	&lt;p&gt;The &lt;code&gt;make&lt;/code&gt; command will then build against the i386-mingw32 ruby installation
and the final loadable library can be shipped in a platform dependent gem.&lt;/p&gt;


	&lt;h4&gt;Packaging the Gem&lt;/h4&gt;


	&lt;p&gt;I have a top level &lt;code&gt;gemspec.rb&lt;/code&gt; file in all of my projects which holds the
global Gem Specification for the project.  For the Windows binary gem I need an
additional spec that is almost the same as the default spec, without the
extensions.  Here is the snippet I added for
&lt;a href=&quot;http://copiousfreetime.rubyforge.org/amalgalite/&quot;&gt;Amalgalite&lt;/a&gt;.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# create a new spec based upon the normal spec&lt;/span&gt;
&lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC_WIN&lt;/span&gt; = &lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC&lt;/span&gt;.clone

&lt;span class=&quot;c&quot;&gt;# set the platform to be compatible with the official &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Windows release of Ruby&lt;/span&gt;
win_platform = ::&lt;span class=&quot;co&quot;&gt;Gem&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Platform&lt;/span&gt;.new( &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;i386-mswin32_60&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; )
&lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC_WIN&lt;/span&gt;.platform = win_platform

&lt;span class=&quot;c&quot;&gt;# turn off the extensions, since this is a binary release&lt;/span&gt;
&lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC_WIN&lt;/span&gt;.extensions = []

&lt;span class=&quot;c&quot;&gt;# add the binary extension to the normal file list&lt;/span&gt;
&lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC_WIN&lt;/span&gt;.files +=  [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lib/amalgalite3.so&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;The gem is then packaged using an additional rake gem packaging task.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
desc &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;package the windows gem&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
task &lt;span class=&quot;sy&quot;&gt;:package_win&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ext:build_win&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
  cp &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ext/amalgalite3.so&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:verbose&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;co&quot;&gt;Gem&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Builder&lt;/span&gt;.new( &lt;span class=&quot;co&quot;&gt;Amalgalite&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;GEM_SPEC_WIN&lt;/span&gt; ).build
  mv &lt;span class=&quot;co&quot;&gt;Dir&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*.gem&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;].first, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pkg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt; 
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;This all culminates in the ability to publish a new version of a gem for my
supported platforms to rubyforge with a simple &lt;code&gt;rake dist:rubyforge&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Clone the &lt;a href=&quot;http://github.com/copiousfreetime/amalgalite&quot;&gt;Amalgalite repo&lt;/a&gt; 
or &lt;a href=&quot;http://github.com/copiousfreetime/hitimes&quot;&gt;Hitimes repo&lt;/a&gt; and look around.  
Let me know if you have any questions or comments.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;/articles/2008/10/12/building-gems-for-windows.html#disqus_thread&quot; title=&quot;View&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Managing a Gem Repository with Stickler</title>
    <link href="/articles/2008/10/09/managing-a-gem-repository-with-stickler.html" />
    <id>tag:copiousfreetime.org,2008-10-09:1223612346</id>
    <updated>2008-10-09T22:19:06-06:00</updated>
    <content type="html">&lt;h3 class=&quot;post-title&quot;&gt;&lt;a href=&quot;/articles/2008/10/09/managing-a-gem-repository-with-stickler.html&quot;&gt;Managing a Gem Repository with Stickler&lt;/a&gt; &lt;span class=&quot;post-date&quot;&gt;(2008-10-09)&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;One of the items Fernand and I mentioned in our Lone Star talk was
&lt;a href=&quot;http://copiousfreetime.rubyforge.org/stickler/&quot;&gt;Stickler&lt;/a&gt;.  This was a project I
had originally started on back in June and it lay dormant for a little while.&lt;/p&gt;


	&lt;h5&gt;The first public version (0.1.0) is now released.&lt;/h5&gt;


	&lt;h4&gt;Why should I use Stickler?&lt;/h4&gt;


	&lt;p&gt;One of the problems that we have had at work is inadvertently upgrading a gem on
a production system.  For example, you are adding a gem to a system that
depends on &lt;code&gt;activerecord,  &amp;gt;= 2.0.2&lt;/code&gt;.  This is great, until active_record 2.1.1
comes out and on your production system you type &lt;code&gt;gem install somegem&lt;/code&gt; and it
updates your active record installation, as a side effect.  Yes, you can just
quickly uninstall it, but it is annoying.&lt;/p&gt;


	&lt;p&gt;Another issue that some installations have, is production boxes are unable to
talk directly to the Internet.  This is a problem when doing a gem installation
using rubygems.  You either have to run your own gem server, or install the gems
locally.&lt;/p&gt;


	&lt;h4&gt;Installation and Setup&lt;/h4&gt;


	&lt;p&gt;Stickler currently has a basic workflow.  First, install and setup your Stickler
repository.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:~ % sudo gem install stickler
  ============================================================

  Thank you for installing Stickler!

  * Create a new stickler repository:
      stickler setup /path/to/repo

  * Look at the help:
      stickler help

  ============================================================
Successfully installed stickler-0.1.0
1 gem installed
Installing ri documentation for stickler-0.1.0...
Installing RDoc documentation for stickler-0.1.0...

jeremy@aramis:~ % stickler setup /tmp/stickler
created repository root /tmp/stickler
created directory /tmp/stickler/gems
created directory /tmp/stickler/log
created directory /tmp/stickler/specifications
created directory /tmp/stickler/dist
created directory /tmp/stickler/cache
copied in default configuration to /tmp/stickler/stickler.yml
Setting up sources
 * loading http://gems.rubyforge.org/
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;A Stickler repository is a specific directory that holds all the gem files that
are managed by Stickler for your personal distribution.  In this case, Stickler
is now installed as a gem and we have setup a repository in &lt;code&gt;/tmp/stickler&lt;/code&gt;.&lt;/p&gt;


	&lt;h4&gt;Populating the Repository&lt;/h4&gt;


	&lt;p&gt;A repository is great, and completely useless unless it is populated with gems
to distribute.  So that is what we will do.  The best way to operate on a
Stickler repository is to be in it.  You can also use the &lt;code&gt;--directory&lt;/code&gt;
commandline option on every command, but that can get old.  Therefore, we&amp;#8217;ll
operate from the root of the repository.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
cd /tmp/stickler
&lt;/pre&gt;&lt;/div&gt;

First lets look at the state of the repository using the &lt;code&gt;info&lt;/code&gt; command.


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler info
Setting up sources
 * loading http://gems.rubyforge.org/

Upstream Sources
----------------

  http://gems.rubyforge.org/ : 16651 gems available
                             : 0 gems existing

Configured gems (in stickler.yml)
---------------------------------

Existing gems
-------------
&lt;/pre&gt;&lt;/div&gt;

Yes, that definitely is empty.  We do a fair number of merb apps, so lets add
merb to our repository.  It is a 2 step process to add a gem to the repository
via the commandline.  We first pick the requirement operator, and then the
version.  In our case, we want to stick with a specific version of merb so we&amp;#8217;ll
add &lt;code&gt;merb, = 0.9.8&lt;/code&gt; to our repository


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler add gem merb
Setting up sources
 * loading http://gems.rubyforge.org/

You need to pick the merb Requirement to configure Stickler.
This involves picking one of the following Requirement operators
See http://docs.rubygems.org/read/chapter/16#page74 for operator info.

You need to (1) pick an operator and (2) pick a requirement.
The most common operators are &amp;gt;=, &amp;gt; and ~&amp;gt;
1. =  Equals version
2. != Not equal to version
3. &amp;gt;  Greater than version
4. &amp;lt;  Less than version
5. &amp;gt;= Greater than or equal to
6. &amp;lt;= Less than or equal to
7. ~&amp;gt; Approximately greater than
(1) Pick an operator ? 1

Now to pick a requirement.  Based upon your chosen operator '=',
These are the available version of the merb gem.
1. = 0.9.8   7. = 0.9.2   13. = 0.4.1  19. = 0.3.0  25. = 0.0.6
2. = 0.9.7   8. = 0.5.3   14. = 0.4.0  20. = 0.2.0  26. = 0.0.5
3. = 0.9.6   9. = 0.5.2   15. = 0.3.7  21. = 0.1.0  27. = 0.0.4
4. = 0.9.5   10. = 0.5.1  16. = 0.3.4  22. = 0.0.9  28. = 0.0.3
5. = 0.9.4   11. = 0.5.0  17. = 0.3.3  23. = 0.0.8  29. = 0.0.2
6. = 0.9.3   12. = 0.4.2  18. = 0.3.1  24. = 0.0.7  30. = 0.0.1
(2) Pick a requirement ? 1

Resolving gem dependencies for merb (= 0.9.8, runtime) ...
Adding ParseTree-2.1.1-x86-mswin32
Adding ruby2ruby-1.1.9
Adding RubyInline-3.7.0
Adding ParseTree-2.2.0
Adding merb-action-args-0.9.8
Adding merb-assets-0.9.8
Adding highline-1.4.0
Adding diff-lcs-1.1.2
Adding templater-0.3.2
Adding merb-gen-0.9.8
Adding haml-2.0.3
Adding merb-haml-0.9.8
Adding builder-2.1.2
Adding merb-builder-0.9.8
Adding mailfactory-1.4.0
Adding merb-mailer-0.9.8
Adding merb-parts-0.9.8
Adding merb-cache-0.9.8
Adding merb-slices-0.9.8
Adding merb-jquery-0.9.8
Adding extlib-0.9.7
Adding abstract-1.0.0
Adding erubis-2.6.2
Adding json_pure-1.1.3
Adding rubyforge-1.0.0
Adding rake-0.8.3
Adding hoe-1.8.0
Adding rspec-1.1.8
Adding rack-0.4.0
Adding mime-types-1.15
Adding hpricot-0.6.161-java
Adding hpricot-0.6.161
Adding hpricot-0.6-x86-mswin32
Adding thor-0.9.6
Adding merb-core-0.9.8
Adding merb-helpers-0.9.8
Adding merb-more-0.9.8
Adding mongrel-1.1.5-java
Adding mongrel-1.1.1-java
Adding daemons-1.0.10
Adding fastthread-1.0.1
Adding fastthread-1.0.1-x86-mswin32
Adding mongrel-1.1.5
Adding mongrel-1.1.3-x86-mswin32
Adding mongrel-1.1.5-x86-mswin32-60
Adding mongrel-1.1.2-x86-mswin32
Adding gem_plugin-0.2.3
Adding cgi_multipart_eof_fix-2.5.0
Adding mongrel-1.1.5-x86-mingw32
Adding merb-0.9.8
&lt;/pre&gt;&lt;/div&gt;

Wow, that&amp;#8217;s a lot of gems added with for merb.  And this is more than would be
normally installed if you did a &lt;code&gt;gem install merb&lt;/code&gt;.  Stickler assumes you are
redistributing gems, and as such gets every available platform for a gem when
you add it to the repository.  And then it recurses through all runtime and
development dependencies.  And now when we look at the repository state we see:


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
Setting up sources
 * loading http://gems.rubyforge.org/

Upstream Sources
----------------

  http://gems.rubyforge.org/ : 16652 gems available
                             : 50 gems existing

Configured gems (in stickler.yml)
---------------------------------

merb : = 0.9.8

Existing gems
-------------

ParseTree-2.1.1-x86-mswin32
ParseTree-2.2.0
RubyInline-3.7.0
abstract-1.0.0
builder-2.1.2
cgi_multipart_eof_fix-2.5.0
daemons-1.0.10
diff-lcs-1.1.2
erubis-2.6.2
extlib-0.9.7
fastthread-1.0.1
fastthread-1.0.1-x86-mswin32
gem_plugin-0.2.3
haml-2.0.3
highline-1.4.0
hoe-1.8.0
hpricot-0.6-x86-mswin32
hpricot-0.6.161
hpricot-0.6.161-java
json_pure-1.1.3
mailfactory-1.4.0
merb-0.9.8
merb-action-args-0.9.8
merb-assets-0.9.8
merb-builder-0.9.8
merb-cache-0.9.8
merb-core-0.9.8
merb-gen-0.9.8
merb-haml-0.9.8
merb-helpers-0.9.8
merb-jquery-0.9.8
merb-mailer-0.9.8
merb-more-0.9.8
merb-parts-0.9.8
merb-slices-0.9.8
mime-types-1.15
mongrel-1.1.1-java
mongrel-1.1.2-x86-mswin32
mongrel-1.1.3-x86-mswin32
mongrel-1.1.5
mongrel-1.1.5-java
mongrel-1.1.5-x86-mingw32
mongrel-1.1.5-x86-mswin32-60
rack-0.4.0
rake-0.8.3
rspec-1.1.8
ruby2ruby-1.1.9
rubyforge-1.0.0
templater-0.3.2
thor-0.9.6
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;There is a difference between &lt;em&gt;configured&lt;/em&gt; gems and &lt;em&gt;existing&lt;/em&gt;
gems.  Configured gems are those you have specifically requested to be in the
repository.  Existing gems are those that are added to support the configured
gems and the configured gems themselves.&lt;/p&gt;


	&lt;h4&gt;Adding Additional Sources&lt;/h4&gt;


	&lt;p&gt;Part of the reason for Stickler is to merge upstream gem repositories into your
own internal repository.  Say you use the github repository and want to add a
gem or two from it to your internal system.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler add source http://gems.github.com
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/
http://gems.github.com added to sources
&lt;/pre&gt;&lt;/div&gt;

That was easy enough.  Now lets add a gem from github and watch the dependencies
roll in.


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler add gem aniero-tire_swing
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/

You need to pick the aniero-tire_swing Requirement to configure Stickler.
This involves picking one of the following Requirement operators
See http://docs.rubygems.org/read/chapter/16#page74 for operator info.

You need to (1) pick an operator and (2) pick a requirement.
The most common operators are &amp;gt;=, &amp;gt; and ~&amp;gt;
1. =  Equals version
2. != Not equal to version
3. &amp;gt;  Greater than version
4. &amp;lt;  Less than version
5. &amp;gt;= Greater than or equal to
6. &amp;lt;= Less than or equal to
7. ~&amp;gt; Approximately greater than
(1) Pick an operator ? =

Now to pick a requirement.  Based upon your chosen operator '=',
These are the available version of the aniero-tire_swing gem.
1. = 0.0.3  2. = 0.0.2
(2) Pick a requirement ? 1

Resolving gem dependencies for aniero-tire_swing (= 0.0.3, runtime) ...
Adding polyglot-0.2.3
Adding treetop-1.2.4
Adding attributes-5.0.1
Adding activesupport-2.1.1
Adding aniero-tire_swing-0.0.3
&lt;/pre&gt;&lt;/div&gt;

You can see that &lt;code&gt;aneiro-tire_swing&lt;/code&gt; was added from github, and it also
resolved the dependencies to gems that reside on rubyforge.  Looking at &lt;code&gt;info&lt;/code&gt;
shows us:


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler info
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/

Upstream Sources
----------------

  http://gems.rubyforge.org/ : 16652 gems available
                             : 54 gems existing
     http://gems.github.com/ : 2463 gems available
                             : 1 gems existing

Configured gems (in stickler.yml)
---------------------------------

aniero-tire_swing : = 0.0.3
merb : = 0.9.8
...
&lt;/pre&gt;&lt;/div&gt;


	&lt;h4&gt;Batch Addition&lt;/h4&gt;


	&lt;p&gt;It can get repetitive to manually add gem after gem from the commandline.  When
you know exactly what you need, crack open the &lt;code&gt;stickler.yml&lt;/code&gt; file and add a few
gems.  For instance, lets say that we are in the process of updating all our
rails apps to 2.1.  In the meantime we want to make sure we do not inadvertently
update our production systems to 2.1.  They are still at 2.0.2.  So we add all
the rails gems at the 2.0.2 level to the &lt;code&gt;stickler.yml&lt;/code&gt; file in the repository.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
---
downstream_source: http://gems.example.com/
sources:
- http://gems.rubyforge.org/
- http://gems.github.com/
gems:
  aniero-tire_swing:
  - = 0.0.3
  merb:
  - = 0.9.8
  activerecord: = 2.0.2
  activesupport: = 2.0.2
  actionmailer: = 2.0.2
  actionpack: = 2.0.2
  activeresource: = 2.0.2
  rails: = 2.0.2
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;We can now use the &lt;code&gt;sync&lt;/code&gt; command to add all of them in at once.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler sync
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/

Making sure that all gems listed in configuration are available

Resolving gem dependencies for rails (= 2.0.2, runtime) ...
Adding activerecord-2.0.2
Adding actionpack-2.0.2
Adding actionmailer-2.0.2
Adding activesupport-2.0.2
Adding activeresource-2.0.2
Adding rails-2.0.2
Resolving gem dependencies for activerecord (= 2.0.2, runtime) ...
Resolving gem dependencies for activeresource (= 2.0.2, runtime) ...
Resolving gem dependencies for aniero-tire_swing (= 0.0.3, runtime) ...
Resolving gem dependencies for actionpack (= 2.0.2, runtime) ...
Resolving gem dependencies for actionmailer (= 2.0.2, runtime) ...
Resolving gem dependencies for merb (= 0.9.8, runtime) ...
Resolving gem dependencies for activesupport (= 2.0.2, runtime) ...
&lt;/pre&gt;&lt;/div&gt;


	&lt;p&gt;You can see that it added in all the gems in and then it also made sure that
&lt;code&gt;aneiro-tire_swing&lt;/code&gt; and &lt;code&gt;merb&lt;/code&gt; were also synced up.  If you need to rebuild the
entire repository from scratch, use &lt;code&gt;stickler sync --rebuild&lt;/code&gt; and it will wipe
out the current gems and specifications in the repo and download them again.&lt;/p&gt;


	&lt;h4&gt;Distribution of Gems&lt;/h4&gt;


	&lt;p&gt;Populating the repository is only good if you can get your internal systems to
utilize the repo.  This is where the &lt;code&gt;generate&lt;/code&gt; commands come into play.  The
&lt;code&gt;generate index&lt;/code&gt; command does exactly what a &lt;code&gt;gem generate_index&lt;/code&gt; does, but it
uses your repository as the base.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/
Generating rubygems index in /private/tmp/stickler/dist
Loading 61 gems from /private/tmp/stickler/dist
...............WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/fastthread-1.0.1-x86-mswin32.gem =&amp;gt; fastthread-1.0.1-x86-mswin32 (fastthread-1.0.1-mswin32)
.....WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/hpricot-0.6-x86-mswin32.gem =&amp;gt; hpricot-0.6-x86-mswin32 (hpricot-0.6-mswin32)
WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/hpricot-0.6.161-java.gem =&amp;gt; hpricot-0.6.161-java (hpricot-0.6.161-jruby)
..................WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/mongrel-1.1.1-java.gem =&amp;gt; mongrel-1.1.1-java (mongrel-1.1.1-jruby)
WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/mongrel-1.1.2-x86-mswin32.gem =&amp;gt; mongrel-1.1.2-x86-mswin32 (mongrel-1.1.2-mswin32)
WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/mongrel-1.1.3-x86-mswin32.gem =&amp;gt; mongrel-1.1.3-x86-mswin32 (mongrel-1.1.3-i386-mswin32)
....WARNING:  Skipping misnamed gem: /private/tmp/stickler/dist/gems/ParseTree-2.1.1-x86-mswin32.gem =&amp;gt; ParseTree-2.1.1-x86-mswin32 (ParseTree-2.1.1-i386-mswin32)
............
Loaded all gems
Generating quick index gemspecs for 54 gems
......................................................
Complete
Generating specs index
Generating latest specs index
Generating quick index
Generating latest index
Generating Marshal master index
Generating YAML master index for 54 gems (this may take a while)
......................................................
Complete
Compressing indicies
&lt;/pre&gt;&lt;/div&gt;

The generated, distributable gem repository based upon your stickler repository
is generated in the &lt;code&gt;dist&lt;/code&gt; sub directory in your repository.  This directory can
be rsynced to a web server in your infrastructure, or run a web server on this
machine and point its document root, or a directory alias to the &lt;code&gt;dist&lt;/code&gt;
directory.

	&lt;p&gt;An extra item you may do is globally configure your rubygems installations to
automatically use your internal gem server as the canonical source instead of
http://gems.rubyforge.org/.  Stickler provides a quick command to generate this
top level configuration, and the file contains the information on where to put
it.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
jeremy@aramis:/tmp/stickler % stickler generate sysconfig &amp;gt; gemrc
Setting up sources
 * loading http://gems.rubyforge.org/
 * loading http://gems.github.com/
Generating configuration to stdout

jeremy@aramis:/tmp/stickler % cat gemrc
#
# This is the system wide configuration to be used by
# rubygem clients that install gems from the repository
# located at :
#
#   http://gems.example.com/
#
# On Unix like machines install in
#
#   /etc/gemrc
#
# On Windows machines install in
#
#   C:\Documents and Settings\All Users\Application Data\gemrc
#
---
:sources:
- http://gems.example.com/
&lt;/pre&gt;&lt;/div&gt;


	&lt;h4&gt;Conclusions&lt;/h4&gt;


	&lt;p&gt;Hopefully you can find Stickler useful in your infrastructure.  Please let me
know about &lt;a href=&quot;http://rubyforge.org/tracker/?group_id=3707&quot;&gt;features and bugs.&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;/articles/2008/10/09/managing-a-gem-repository-with-stickler.html#disqus_thread&quot; title=&quot;View&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Hitimes are upon us</title>
    <link href="/articles/2008/09/14/hitimes-0_2_0.html" />
    <id>tag:copiousfreetime.org,2008-09-14:1221449719</id>
    <updated>2008-09-14T21:35:19-06:00</updated>
    <content type="html">&lt;h3 class=&quot;post-title&quot;&gt;&lt;a href=&quot;/articles/2008/09/14/hitimes-0_2_0.html&quot;&gt;Hitimes are upon us&lt;/a&gt; &lt;span class=&quot;post-date&quot;&gt;(2008-09-14)&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;Saturday afternoon at the &lt;a href=&quot;http://www.lonestarrubyconf.com/&quot;&gt;Lone Star Ruby Conf&lt;/a&gt;
I was discussing something, I forget exactly what, with &lt;a href=&quot;http://www.codefluency&quot;&gt;Bruce&lt;/a&gt; 
and he mentioned that he was looking for a really fast way to measure elapsed
time of a piece of code.&lt;/p&gt;


	&lt;p&gt;The naive approach would be call &lt;code&gt;Time.now&lt;/code&gt; before and after the call, or maybe
use the
&lt;a href=&quot;http://facets.rubyforge.org/doc/api/core/classes/Time.html&quot;&gt;Time.elapse&lt;/a&gt; method
from &lt;a href=&quot;http://facets.rubyforge.org/&quot;&gt;Facets&lt;/a&gt;.  Both of those approaches are
perfectly acceptable, and return results down to the &amp;micro;second.  Can we do
better?  Yes.&lt;/p&gt;


	&lt;p&gt;We have a goal of being faster than 2 successive &lt;code&gt;Time.now&lt;/code&gt; calls.  Each
operating system has a different way accessing a high-resolution timer.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Unixes &amp;#8211; the POSIX calls to &lt;code&gt;clock_gettime()&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;OS X &amp;#8211; &lt;code&gt;UpTime()&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;Windows &amp;#8211; &lt;code&gt;QueryPerformanceCounter()&lt;/code&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Unify the C level interface to all of those, wrap it up in a Ruby extension and
the result is the just-released &lt;a href=&quot;http://copiousfreetime.rubyforge.org/hitimes/&quot;&gt;Hitimes&lt;/a&gt;, a 
high-resolution timer library in Ruby for when you want to do measuring at the
nanosecond level.&lt;/p&gt;



&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;
gem install hitimes
&lt;/pre&gt;&lt;/div&gt;

The simplest and lightest weight way to use the library is via the &lt;code&gt;Interval&lt;/code&gt;
class.  This does one really simple thing.  It measures an interval of time.
You can measure code in a block:


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;hitimes&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;open-uri&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;
duration = &lt;span class=&quot;co&quot;&gt;Hitimes&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Interval&lt;/span&gt;.measure &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;
            bruce = open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://www.codefluency.com/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).read
           &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;
puts duration &lt;span class=&quot;c&quot;&gt;# =&amp;gt; 0.261841618&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

Or measure a particular piece of code for performance:


&lt;div class=&quot;CodeRay&quot;&gt;&lt;pre&gt;interval = &lt;span class=&quot;co&quot;&gt;Hitimes&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Interval&lt;/span&gt;.new
&lt;span class=&quot;c&quot;&gt;# do something&lt;/span&gt;
interval.start
&lt;span class=&quot;c&quot;&gt;# some code to measure&lt;/span&gt;
duration = interval.stop
&lt;/pre&gt;&lt;/div&gt;

There are other approaches using &lt;code&gt;Interval&lt;/code&gt;, and a
&lt;a href=&quot;http://copiousfreetime.rubyforge.org/hitimes/classes/Hitimes/Timer.html&quot;&gt;Timer&lt;/a&gt;
class for measuring series of intervals and reporting statistics.

	&lt;p&gt;&lt;a href=&quot;/articles/2008/09/14/hitimes-0_2_0.html#disqus_thread&quot; title=&quot;View&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Post Lone Star Talk Thoughts</title>
    <link href="/articles/2008/09/08/lonestar-2008-epilogue.html" />
    <id>tag:copiousfreetime.org,2008-09-08:1220907974</id>
    <updated>2008-09-08T15:06:14-06:00</updated>
    <content type="html">&lt;h3 class=&quot;post-title&quot;&gt;&lt;a href=&quot;/articles/2008/09/08/lonestar-2008-epilogue.html&quot;&gt;Post Lone Star Talk Thoughts&lt;/a&gt; &lt;span class=&quot;post-date&quot;&gt;(2008-09-08)&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;&lt;img src=&quot;/images/LSRC_2008_presenter.png&quot; style=&quot;float:left;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://liquidrail.com/&quot;&gt;Fernand&lt;/a&gt;  and I presented a talk at &lt;a href=&quot;http://www.lonestarrubyconf.com/&quot;&gt;Lone Star Ruby
Conf&lt;/a&gt; last Friday entitled &lt;em&gt;Building and
Managing a Ruby Infrastructure&lt;/em&gt;.  It appears we hit upon a subject that people
are starting encounter.  Over the next couple of weeks I&amp;#8217;ll post a few more articles
explaining in more detail a few of the key concepts.  For now, a few links to
things that we mentioned in the talk.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://codeforpeople.rubyforge.org/bones/&quot;&gt;Bones&lt;/a&gt;&amp;#8212;A great project
  templating tool, extendible to use your own proect templates.   &lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.rubygems.org/read/chapter/7&quot;&gt;Rational Versioning Policy&lt;/a&gt;&amp;#8212;in
  which &lt;code&gt;~&amp;gt;&lt;/code&gt; a.k.a &amp;#8220;Twiddle Wakka&amp;#8221; is explained.&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/copiousfreetime/stickler&quot;&gt;Stickler&lt;/a&gt;&amp;#8212;organize and maintain
  an internal gem distribution server.  Still in planning stages.&lt;/li&gt;
		&lt;li&gt;take a look at the &lt;code&gt;gem index&lt;/code&gt; and &lt;code&gt;gem server&lt;/code&gt; commands&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href=&quot;/articles/2008/09/08/lonestar-2008-epilogue.html#disqus_thread&quot; title=&quot;View&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  
</feed>
