Monthly Archives: April 2011

Git and git-flow command line completion

I switch between the command line and a GUI tool called SourceTree to manage my Git repositories.  When I first installed git-flow, I noticed that the readme talked about command line completion.  It took me a while to get around to installing it, but I have to say that it is really impressive.

Git and git-flow command line completion works like the rest of bash against the file system.  It reminds me a little of PowerShell on Windows (that should tell you how much I know about bash).

To install command line completion on a Mac, you need to find a copy of the git-completion.bash script.  Some of the posts I read on the net seem to indicate that it should be installed with Git in a contrib folder, but I couldn’t find it (showing how new I am on a Mac), so I decided to just clone Git from Git-Hub. Once I had that, I created a link to the script in my ~/bin directory:

cd ~/src/external
git clone https://github.com/git/git.git git
cd ~
mkdir bin
ln -s ~/src/external/git/contrib/completion/git-completion.bash ./git-completion.sh

I did a similar thing for git-flow-completion:

cd ~/src/external
git clone https://github.com/bobthecow/git-flow-completion.git git-flow-completion
cd ~/bin
ln -s ~/src/external/git-flow-completion/git-flow-completion.bash ./git-flow-completion.sh

The next thing to do is to modify your .bash_profile to call those scripts.

source ~/bin/git-completion.sh
source ~/bin/git-flow-completion.sh

Now when you execute git commands from the command line, you can use tab to complete commands, branches, remotes, and features. On top of that, it works for both local and remote elements. Very cool!

Resources

Defensive Programming in Cocoa (from VTM_iPhone)

I’ve been attending the iPhone Developers Conference in Seattle hosted by Voices That Matter (check out VTM_iPhone for the Twitter stream), which has been really informative.  Easily the most informative session at the iPhone Developers Conference for me was Defensive Programming in Cocoa by Mike Ash.  On Mike’s blog he has a series called Friday Q&A and it appears that most of the material for his talk was taken from an article he posted in December with the same name.  Two sections really stand out for me.

Memory Management – Put all your memory management for member variables in the setter for that member variable rather than scattering it around the code.  So instead of doing this:

[_myMemberVar release];

do this:

self.myMemberVar = nil;

after implementing this:

@property (retain) MyClass * myMemberVar;
@synthesize myMemberVar = _myMemberVar;

or this:

- (void) setMyMemberVar: (MyClass *) myMemberVar
{
    if (_myMemberVar != myMemberVar)
    {
        [_myMemberVar release];
        _myMemberVar = [myMemberVar retain];
    }
}

Categories – Since someone could override a method in your category with their own method making your method impossible to call, name your methods in a way to reduce that possibility.  The converse is also true.  For example, if you define a method in a category for an Apple-provided class, Apple could later come along and define that method in a class category and then all their calls will go to your method instead of theirs.

Key-Value Observers – The only thing not covered in that article that he covered in his talk was something that I started applying immediately:  When implementing key-value observers, make sure your observer only handles the notification if it knows that it is for your class.  This is a problem because your observer could be overriding the superclass’s observer and your observer must call the superclass’s observer if the notification isn’t for you.

To solve this, always pass specific to your class as the context parameter to the addObserver: method.

static void * s_kClassContext = &s_kClassContext;
...
[obj addObserver: self
      forKeyPath: "foo"
         options: NSKeyValueObservingOptionNew
         context: s_kClassContext];
...
- (void) observeValueForKeyPath: (NSString *) keyPath
                       ofObject: (id) object
                         change: (NSDictionary *) change
                        context: (void *) context
{
    if (context == s_kClassContext)
    {
        if ([keyPath isEqual: @"location"])
        {
            ...
        }
    }
    else
    {
        // Notification is not for us.
        [super observeValueForKeyPath: keyPath
                             ofObject: object
                               change: change
                              context: context];
    }
}