Programblings

Rambling about programming and life as a programmer - by Mathieu Martin

Archive for the 'programming' Category


GiraffeSoft.push( Karabunga.pop( self ))

7th July 2008

A wise man once suggested that one of the steps in teaching yourself programming involved working with people better than you. (See Teach Yourself Programming in Ten Years)

Even though I feel I’m a pretty competent software developer, I’m very excited to join another developer for which I have a truly profound respect. I’ve only recently made the career move of working on the web full time, and this is a great opportunity for me to kickstart this phase of my career by working with a Rails / REST / jQuery guru.

Starting today, I’m working for GiraffeSoft, with James Golick. We’ve wanted to work together for a while, and the stars have finally aligned to make this possible.

Posted in programming, ruby | No Comments »

Git remote branches

23rd June 2008

I’m ready to bet that setting up and deleting remote branches is something you do rarely enough that you always find yourself looking up the documentation. Or maybe it’s just me.

Due to its roots, Git supports a wide array of usage scenarios for interacting with remote repositories, and we love it that way. It’s a big factor in the flexibility and power of the tool.

However in simple scenarios, there’s still a bunch of commands you must run to accomplish simple tasks. I believe the commands for the simple scenario can be simpler.

Last January, Carl Mercier created git-remote-branch. I’ve found this script very useful and, with his permission, I’ve decided to keep moving it forward and add a few features to it.

git_remote_branch

The first purpose of git_remote_branch is to encapsulate all the commands that need to be run to interact with remote branches in simple scenarios.

Its second purpose is to be a learning tool. git_remote_branch does two things to help you learn these commands:

  •   It clearly displays the commands it runs on your behalf, in a beautiful shade of red;
  •   It has an ‘explain’ meta-command that will simply display the list of commands instead of running them for you.

Examples

Help

Let’s start with the simplest of all:

$ grb

or

$ grb help
git_remote_branch version 0.2.2

  Usage:

  grb create branch_name [origin_server]

  grb delete branch_name [origin_server]

  grb track branch_name [origin_server]

  If origin_server is not specified, the name ‘origin’ is assumed (git’s default)

  The explain meta-command: you can also prepend any command with the keyword ‘explain’.
  Instead of executing the command, git_remote_branch will simply output the list of commands
  you need to run to accomplish that goal.
  Example:
    grb explain create
    grb explain create my_branch github

  All commands also have aliases:
  create: create, new
  delete: delete, destroy, kill, remove
  track: track, follow, grab, fetch

As you can see, the syntax for all commands is very regular: action, branch_name and optionally, origin_server.

To facilitate learning even more, aliases are also provided. So to take an example,

$ grb track his_branch

and

$ grb fetch his_branch

are perfectly equivalent.

create

Create lets you create a new branch both remotely and locally. Note that it’s not made to share an existing branch (that feature’s coming).

So what it does is to push your current branch as a new remote branch, then create it locally and track it, for easier pulling afterwards.

$ grb create some_branch
git_remote_branch version 0.2.2

git push origin master:refs/heads/some_branch
Total 0 (delta 0), reused 0 (delta 0)
To /path/to/repo/
* [new branch]      master -> some_branch

git fetch origin

git branch −−track some_branch origin/some_branch

git checkout some_branch
Switched to branch “some_branch”

delete

Presenting features with names that are too self-evident is boring. Let’s get to the point, already.

$ grb delete some_branch
git_remote_branch version 0.2.2

git push origin :refs/heads/some_branch
To /path/to/repo/
- [deleted]         some_branch

git checkout master
Switched to branch “master”

git branch -d some_branch

track

Track lets you easily track the changes that are made to an existing remote branch you’re not tracking already. Each time you pull from the remote repository, the local branch will be automatically merged with the remote branch.

$ grb track his_branch
git_remote_branch version 0.2.2

git fetch origin
From /path/to/repo/
* [new branch]      his_branch -> origin/his_branch

git branch −−track his_branch origin/his_branch

explain

Explain will spew out all commands necessary to accomplish one of the previous actions. There are two ways of using it. The simplest will give you dummy commands:

$ grb explain create
git_remote_branch version 0.2.2

List of operations to do to create a new remote branch and track it locally:

git push origin master:refs/heads/branch_to_create
git fetch origin
git branch −−track branch_to_create origin/branch_to_create
git checkout branch_to_create

Or you can have steps that are tailor-made for what you want to accomplish.

$ grb explain create my_branch github_origin
git_remote_branch version 0.2.2

List of operations to do to create a new remote branch and track it locally:

git push github_origin master:refs/heads/my_branch
git fetch github_origin
git branch −−track my_branch github_origin/my_branch
git checkout my_branch

get git_remote_branch

(Hey, this title has a nice ring to it)

sudo gem install webmat-git_remote_branch −−source=http://gems.github.com

Now with rubygems 1.2.0 out (don’t do it with a prior version), you can also add GitHub as a permanent source for your gems:

sudo gem sources -a http://gems.github.com

Now and ever after, you will be able to get anything from GitHub with a simple

sudo gem install webmat-git_remote_branch

If in your eagerness you’ve added github as a source before running

sudo gem update −−system

Please refer to What to do when gems.github.com breaks gems FOREVAR

Look ma, no tests!

Uhhhh, yeah, I know…

This tool is still extremely early in its life and - dare I say it - it’s only hand-tested for now. I’ve been using it personally for a while and it’s working very well for me, if that means anything :-)

So this is still a quick script, only now it has lipstick.

Works on my machine logo

This software should be considered an early version of a pre-alpha. You’ve been warned!

If this makes you queasy, there’s always the ‘explain’ command that can act as your cheat sheet without actually having grb run the commands on your behalf.

For the extra queasy, well you can find the commands very easily without running grb. Just point your favorite editor to lib/git_remote_branch.rb. All commands are there, at the beginning of the file.

For the brave, try it out and tell me what you think. Improvements, bug reports and contributions are all welcome.

And remember, in case of an emergency, you can always refer to my illustrated guide to recovering lost commits with Git ;-)

Here’s what’s to come:

  • lots of tests
  • a ‘remotize’ functionality (for existing local branches)
  • a much better resilience to use in faulty situations (e.g. deleting something that’s not present locally or remotely)
  • the possibility to specify different branch names locally vs remotely
  • slap an open source licence on it all
  • and so much more!

Posted in programming | 8 Comments »

Git is a dangerous tool to use

14th May 2008

Quote from the Git documentation:

<branch>

When this parameter names a non-branch (but still a valid commit object), your HEAD becomes detached.
Junio C. Hamano — the checkout documentation

Git — the only SCM that beheads its users.

Posted in garbage out, git, programming | 2 Comments »

Rubinius for the Layman, Part 2: How Rubinius is Friendly

15th April 2008

This is part two of an ongoing series about Rubinius:

In this shorter second installment, I’ll present the ways in which Rubinius will be friendly to your multiple personalities:

  • you, the programmer;
  • you, the (potential) contributor.

Rubinius is programmer-friendly

Backtraces

The first reason why I consider Rubinius more programmer-friendly is the better backtraces. I’ll show some examples run from each interpreter’s interactive console.

Take the following piece of buggy code. Notice the nil at the end of the array.

ary=['bob', 'mom', nil].inject([]) {|result, element| result << element.to_sym}

With MRI you get the following:

NoMethodError: undefined method `to_sym' for nil:NilClass
        from (irb):5
        from (irb):5:in `inject'
        from (irb):5:in `each'
        from (irb):5:in `inject'
        from (irb):5

Ok, we have basic information on all the method calls that led to the NoMethodError.

Rubinius goes a step further, however:

NoMethodError: No method 'to_sym' on an instance of NilClass.
   from Kernel(NilClass)#to_sym (method_missing_cv) at kernel/core/kernel.rb:606
   from Object#irb_binding {} at (irb):4
   from Enumerable(Array)#inject {} at kernel/core/enumerable.rb:375
   from Array#each at kernel/core/array.rb:573
   from Enumerable(Array)#inject at kernel/core/enumerable.rb:371
   from Object#irb_binding {} at (irb):4

The backtrace tells me in which module each method on the stack was defined!

Q: How awesome is that?

A: Very!

I’m almost looking forward to debugging buggy mixins or method chains. Aren’t you?

These backtraces will definitely come in handy when debugging in situations where a lot of magic is happening behind the scenes.

Bring back the horse!

There’s another interesting detail about the backtraces. Remember what language Rubinius is written in? Heh. The backtraces Rubinius generates go deeper.

Say we have another piece of buggy code:

s = 'ahh'
s[1] = nil

MRI:

TypeError: can't convert nil into String
 from (irb):5:in `[]='
 from (irb):5

Rubinius:

TypeError: Coercion error: nil.to_str => String failed:
(undefined local variable or method `to_str' for nil)
   from Type.coerce_to at kernel/core/kernel.rb:19
   from Kernel(String)#StringValue at kernel/core/kernel.rb:80
   from String#splice! at kernel/core/string.rb:2192
   from String#[]= at kernel/core/string.rb:360
   from Object#irb_binding {} at (irb):8

Not only is the message more descriptive, but as you can see, we can see deeper into the interpreter’s inner workings.

The argument could be made that this could lead to noisier backtraces. On one hand it’s true that adding 5 lines to a 30+ lines backtrace generated in a Rails unit test will rarely help. On the other hand, all this additional information may sometimes help finding subtle bugs (in user code or in Rubinius) or figure out that our use of a feature is not quite correct.

I say the additional information is very welcome. And to help keep the information overload in check, let’s get off our asses and use the quiet_backtrace gem by James Golick and Dan Croak.

The real Rubinius backtraces

It gets even better. The previous examples were only run in irb. So the additionnal information was getting squeezed in IRB’s exception formatting. Say I save both pieces of buggy code to 1.rb and 2.rb. You’ll notice too that I split program 2 in 2.rb and /lib/2.rb (I plan on making it a gem).

Here’s in full colored glory the insults Rubinius will throw back at me:

mat@laptop rubinius $ rbx 1.rb
An exception has occurred:
    No method 'to_sym' on an instance of NilClass. (NoMethodError)Backtrace:
    Kernel(NilClass)#to_sym (method_missing_cv) at kernel/core/kernel.rb:612
                        Object#__script__ {} at 1.rb:1
                 Enumerable(Array)#inject {} at kernel/core/enumerable.rb:375
                                  Array#each at kernel/core/array.rb:573
                    Enumerable(Array)#inject at kernel/core/enumerable.rb:371
                           Object#__script__ at 1.rb:1
                    CompiledMethod#as_script at kernel/core/compiled_method.rb:326
                         Compile.single_load at kernel/core/compile.rb:238
                 Compile.load_from_extension at kernel/core/compile.rb:310
                           Object#__script__ at kernel/loader.rb:190

mat@laptop rubinius $ rbx 2.rb
An exception has occurred:
    Coercion error: nil.to_str => String failed:
(undefined local variable or method `to_str’ for nil) (TypeError)
Backtrace:
                 Type.coerce_to at kernel/core/kernel.rb:19
     Kernel(String)#StringValue at kernel/core/kernel.rb:80
                 String#splice! at kernel/core/string.rb:2192
                     String#[]= at kernel/core/string.rb:360
              Object#__script__ at ./lib/2.rb:2
       CompiledMethod#as_script at kernel/core/compiled_method.rb:326
            Compile.single_load at kernel/core/compile.rb:238
        Compile.unified_load {} at kernel/core/compile.rb:149
                     Array#each at kernel/core/array.rb:573
           Compile.unified_load at kernel/core/compile.rb:120
         Kernel(Object)#require at kernel/core/compile.rb:450
              Object#__script__ at 2.rb:1
       CompiledMethod#as_script at kernel/core/compiled_method.rb:326
            Compile.single_load at kernel/core/compile.rb:233
    Compile.load_from_extension at kernel/core/compile.rb:310
              Object#__script__ at kernel/loader.rb:190

Holy f****** sh** Batman! How centering the lines makes a difference!

To the left is the logical location: the class/module and the method name. To the right is just the necessary information about the physical location. Notice the paths. They only contain what you need i.e. the relative path to execution — relative to the VM for Rubinius code, and relative to the execution root of my glorious code.

Don’t tell anyone, but I think I’ll intentionally put in bugs at work. Just to see these in the logs! Too bad our logs don’t support coloring.

Rubinius is contributor-friendly

Commit access

The Rubinius project is friendly for the programmer who uses it. But the project itself is also friendly to potential contributors. They currently have a policy called the free-flowing commit bit. This policy says the following:

Anyone who submits a patch which is accepted is granted commit access.

In case you missed it, here it is again:

Anyone who submits a patch which is accepted is granted commit access.

This is not crazy talk. The patch can be as simple as you want. A correction to documentation or a spec for the behavior of a Ruby class not behaving properly under Rubinius. Any form of submission is admissible: a pastie, a ticket prepended with [PATCH] on lighthouse, or any other traditional way (emails, ransom notes etc.) Of course these methods are only temporary, since you’re going to get commit access afterwards.

The idea in being so liberal with commit access is to put the barrier to contribution as low as possible. This way, when your commit bit is set, you’re going to be tempted to help more. And your next contribution is going to be so much easier to submit.

A masterful adaptation of the timeless ‘gateway drug’ style of recruiting, really. Get them hooked with as little friction as possible. Then let them, uhhh, flourish in the wonderful world they just discovered.

How’s that for being contributor-friendly? This may not last forever, I guess. So hurry up and submit a patch! ;-)

The naysayers might once again intervene to remind us that this isn’t going to scale. Well it’s every open source project’s dream to have too many contributors. The community and the team will adapt in time. The fact that Rubinius is hosted with Git also gives the team much more flexibility to try different committing strategies, or simply gives more power to recover from mistakes from newcomers.

To really have a better understanding of Evan’s vision of the Rubinius community, I highly recommend watching the video of his presentation at MountainWest RubyConf. The presentation’s content is really not the same as the other presentation mentioned in my first article. Both are really worth it.

Conclusion

That’s it for now, folks. This is how much Rubinius will be friendly to you. Delicious stacktraces and a very welcoming project. A project ready to give you commit access if you submit anything good: a spec, some doc, or just a plain ol’ bug fix.

Stay tuned for the next installment, in which I’ll start covering a few mildly technical bits of Rubinius. Unless I change my mind and decide to tackle another aspect of Rubinius.

A few references:

  • The links for the videos are 3 paragraphs up, you lazy reader. No wait, I’m the one being lazy here.
  • How to write a ticket for the Rubinius project.
  • Let’s bug James Golick and Dan Croak so they make sure quiet_backtrace is ready for these deep Rubinius stack traces. Ha! Sorry James :-)

Posted in programming, ruby | 9 Comments »

irbrc for the runtime tramp

11th April 2008

I’m taking a break from the Rubinius for the Layman series. I don’t know why my posts always spiral into multi-thousand words essays :-) Even worse, when I try to write about Rubinius it’s so easy to get into ratholes and start fiddling, poking at and exploring this wonderful beast. All of that instead of writing, of course.

Tonight’s fiddling led me to playing around with my .irbrc file. I guess we’ve all searched for examples of config files for IRB at one time or another. When you spend a lot of time into your interactive console, you naturally end up wanting to tweak it to your liking.

However you’ll start having problems as soon as you start fooling around with the different runtimes. Or when you share your irbrc between different machines. Maybe even on different OSes. Either some gems are unsupported or you haven’t installed them yet (and don’t necessarily care).

So tonight I tried to fix that problem. My solution is only a small method that I define in my irbrc, so I’m not sure it’s worth putting it on github yet :-) Let me know what you think.

Presenting tramp_require

Usage

When my irbrc requires something just so I don’t need to do it manually:

tramp_require 'pp' #=> true/false (same return value as a normal require)

Outcome if the gem is not installed:

** Unable to require 'wirble'
--> LoadError: Did not find file to load: wirble

And you IRB loads without a problem (just without the gem pre-loaded).

When I require something I actually use in my .irbrc:

tramp_require('wirble') do
  Wirble.init(:skip_prompt=>true)
  Wirble.colorize
end

If the gem is loaded successfully, the block is executed.

If the gem isn’t loaded successfully, the block’s not executed and the same warning message is shown.

Note that the user code passed in the block is not being rescued: if it your code fails, it’s your problem :-)

Implementation

Here I’ll paste 2 equivalent implementations. The first one is a clean and understandable version ( also on pastie):

def tramp_require(what, &block)
  loaded, require_result = false, nil 

  begin
    require_result = require what
    loaded = true 

  rescue Exception => ex
    puts "** Unable to require '#{what}'"
    puts "--> #{ex.class}: #{ex.message}"
  end 

  yield if loaded and block_given? 

  require_result
end

This second version is the one I actually use, if I set the debug variable to false the result is the same as the previous implementation. If I set it to true, I get much more information, including the full backtrace of the exception (also on pastie):

$debug_irbrc=false 

def tramp_require(what, &block)
  loaded, require_result = false, nil 

  begin
    puts('', "requiring #{what}") if $debug_irbrc
    require_result = require what
    loaded = true
    puts "successfully required #{what}" if $debug_irbrc 

  rescue Exception => ex
    puts "** Unable to require '#{what}'"
    exception_details = "#{ex.class}: #{ex.message}"
    if $debug_irbrc
      ex.backtrace.reverse.each{|l| exception_details < < "\n   #{l}"}
    else
      exception_details.insert(0, "--> ")
    end
    puts exception_details
  end 

  if loaded and block_given?
    puts "executing block for #{what}" if $debug_irbrc
    yield
  end 

  require_result
end

Feel free to use these snippets as you see fit :-)

The obligatory full paste of my irbrc is available on pastie, for the curious.

One word of warning, however. I’m guessing some of you will rename tramp_require to something more boring. Just don’t rename it to irb_require. IRB already defines a method named this way.

Posted in garbage out, programming, ruby | 2 Comments »