Archive for the 'How To' Category

Bash Autocompletion for Git

The default installation of Git on OS X doesn’t include support for autocompletion. I know it’s possible, because whatever package I used to install Git on my Windows work computer has it, but I’ve never taken the time to figure it out. Well, here’s how it works. Note that these instructions were about 10x longer, until I decided to read the contents of the bash-completion.bash script… the installation is a lot easier than I was making it.

First, you need to copy the bash-completion script somewhere appropriate.

cd /usr/local/git/contrib/completion/
cp git-completion.bash ~/.git-completion.sh

Now add the following line to your ~/.bash_profile

source ~/.git-completion.sh

Next time you login, autocompletion in Git should work just fine. If you want to take it one step further, here’s how you add the current branch to your command line. The bash-completion script tells you to change your PS1 to the following.

PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '

Which is cool, but I already had my PS1 set up, complete with colors and shit. Here’s what I ended up doing.

GIT_PS1_SHOWDIRTYSTATE=1
GIT_PS1_SHOWSTASHSTATE=1
GIT_PS1_SHOWUNTRACKEDFILES=1
export GIT_PS1_SHOWDIRTYSTATE
export GIT_PS1_SHOWSTASHSTATE
export GIT_PS1_SHOWUNTRACKEDFILES

PS1='[\e[1;32m]$(__git_ps1 " (%s)")[\e[m]' PS1="[\e[1;36m]\h:\W[\e[m]$PS1[\e[1;36m]> [\e[m]" export PS1

What a mess! I’m never going to be able to remember what I did here unless I write it down here.

First off, the GIT_PS1_ variables add an indicator to your command line letting you know that you’re in a dirty working directory, you have something stashed or there are untracked files. Handy.

Second, anything between [\e[1;32m] and [\e[m] is given a color. You can read more about it here.

Finally, the function $(__git_ps1 " (%s)") will replace %s with the current branch (plus a flag if you’ve set those variables I described earlier) if you are currently in a directory under Git source control.

The final result:

Terminal%20%E2%80%94%20bash%20%E2%80%94%2080%C3%9748

I’ll be updated my recent post on my .bash_profile to reflect these changes.

Do you have way too many flagged items in Google Reader?

Do you use NetNewsWire?

If so, maybe you can use this script. It finds all the items you’ve flagged that are older than 6 months old and unflags them. Seriously dude… you aren’t going to ever go back and read that shit.

set dateLimit to (current date) - (180 * days)
tell application "NetNewsWire"
    set flaggedItemList to item 1 of (subscriptions where display name is "Flagged Items")
    --get date published of headlines of flaggedItemList
    set oldFlaggedArticles to (headlines of flaggedItemList) where date published < dateLimit
    repeat with article in oldFlaggedArticles
        set isFlagged of article to no
    end repeat
    set theMessage to "Marked " & (count of oldFlaggedArticles) & " flagged items as read. They were all from before " & dateLimit & "."
    display alert "Marked as read" message theMessage
end tell

Unflag old Flagged Items.zip

“Error establishing a database connection” when installing Wordpress on OS X

This drove me nuts for a few days. I’ve been trying to set up a test environment on my desktop so that I can work through website iterations without fouling up this site. I walked through all the tutorials out there, but just could not get my Wordpress install to work.

WordPress › Error.png

Username, password, hostname were double and triple checked.

It turns out, that when I was installing MySQL on my computer (following the official instructions, which are just fine), I set up a UNIX socket. When I was setting up phpMyAdmin it explicitly asked for the socket… but Wordpress doesn’t, so it had never occurred to me to enter it.

You should enter it.

wp-config.php - Focus Group Camera Club.png

It’s for my local camera club, btw. Look for a new page some time into the new year.

Focus Group Camera Club.png

Remote Version Control with Subversion and Xcode

I split my development time between my MacBook and iMac, so I’ve been using some form of source control for the last few months (previously to that I was copying the files back and forth manually… ugh).

Up until last month I was using iDisk and Mobile Me to keep things straight. This actually works pretty well, which is why I kept using it for so long. Turn on iDisk sync and you’re given a new web-based drive on your desktop. Store your projects in there and they’ll always be up-to-date, no matter where they’re stored.

I had a few problems with this setup, thought.

  1. iDisk doesn’t handle symlinks well. This didn’t make any difference to my project, but some of the sample code I’d download wouldn’t work when it was running from the mounted iDisk volume.
  2. References to bundle resources are flakey. I never did figure out what caused this. Loading images from files worked fine, but trying to load sample data from an .XML file was completely broken, unless I stored the file somewhere besides the mounted iDisk volume. Since the file was small and never changed I got around this limitation by storing it on the Desktop on every computer I used, but it was still a janky solution.
  3. Xcode snapshots are broken. First, snapshots didn’t move from computer to computer, so if I made a snapshot on my laptop, it wouldn’t show up on my desktop. Second, the snapshots didn’t seem to persist when the project was stored on the iDisk volume.

I probably could have overcome all these issues with some effort, but why not save myself the headache and do proper SCM with subversion? Since it already has built-in Xcode support, I figured it’d be a breeze to set up. And for the most part it was.

The instructions I followed were from Jeff LaMarche and his excellent iPhone Development blog.

The helped me set up the repository, but didn’t go quite far enough. Since I’m working from two machines at the same time1, I need to be able to access my code from whichever machine I’m on. Most tutorials out there seem focused on either setting up local repositories, or setting up shared repositories on OS X Server, neither of which quite give me what I need.

Creating the Shared Repository

Since subversion is installed in OS X by default, setting up the repository is simple. These instructions are ripped from from Jeff’s blog. Open up Terminal and run the following commands.

cd /Users/Shared
mkdir subversion
cd subversion
mkdir HelloWorld
svnadmin create HelloWorld
chmod -R 777 HelloWorld

Setting up Remote Login in OS X

In order to securely access your repository remotely, you’ll need to turn on remote login in OS X. Navigate to the Sharing tab in Preferences and turn Remote Login on.

While you’ve got preferences open, find out what your computer’s local hostname is, you’ll need this later. You can find it in the text towards the top of the Sharing window, mine is Grover-Cleveland.local. By using this name to access your repository, you will be able to access the source even if the IP address of the server changes and you should be able to access it from outside your LAN if you’ve got Back to My Mac enabled with Mobile Me (I haven’t tested this yet).

Accessing the Shared Repository in Xcode

Open up Xcode. Hit Command-, to open Preferences. Navigating all the way to the right, you should see an SCM window. Click the “plus” sign at the bottom window to create a new repository. Give it a name, the name doesn’t have to be the same as what you set up earlier. Hit OK and create the new repository. In the URL box type the path to your subversion repository like so:

svn+ssh://username@your-computer.local/Users/Shared/subversion/HelloWorld

where username is your current login and your-computer.local is the address of your computer that we located earlier. For your first connection you’ll be prompted to add the SSH key and Xcode will ask to use your confidential information. Go ahead and let it, and you’ll be set!

Read through the rest of Jeff’s post to get some more details on using Subversion and Xcode, or read Apple’s documentation if you’d really like to go in-depth.

After a few weeks of using this system, there is no doubt that it makes the process of working on code from two different machines much more seamless. The one problem I’ve been having, and I’d be grateful if anyone knew a solution to this, is that the Commit All Changes… command will not work for me. I’ve got to go through, select all the modified files and commit them in batches. In order to commit the .xcodeproj file I need to use the SCM Results command to browse inside the .xcodeproj package and manually commit the files it contains. Vexing…

Anyway, I hope this helps some people!

Edit: I’ve had some problems with the following error, Error: 155005 (Working copy not locked; this is probably a bug, please report). After ignoring it for a few months and finally trying to figure out what’s wrong, I realized that you need to delete the “Build” directory from your repository after you delete it. After this you should have no problem doing full project commits from the menu bar.

Footnotes:

  • Now you know what I’d do if I had a million dollars
  • NSPersistentStoreIncompatibleVersionHashError

    Man. This error has been driving me nuts for a few days now. I’ve got my iPhone app up and running, everything works great until I try and run a

    [managedObjectContext save:&error]

    Without saving everything works just fine (though it doesn’t restore data when I restart, obviously). Whenever I try and save, though, I get the following error.

    This NSPersistentStoreCoordinator has no persistent stores.  It cannot perform a save operation.

    After finally looking in what turned out to be a pretty obvious place, the declaration of the Persistent Store Coordinator in the App Delegate, the default code generated by XCode doesn’t do any error handling. Here’s what I replace it with:

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
            if ([error code] == NSPersistentStoreIncompatibleVersionHashError)
                NSLog(@"Persistent Store Incompatible Version error. Please check %@", storeUrl);
            else {
                NSLog([error description]);
            }
        }
    Check it. Turns out that changing your data model after you’ve already run the code once will render your database inoperable. Of course, there are techniques to upgrade your database to the new model, but at this point I don’t care. Delete the old database and next time you run the code, everything will move through smoothly, and your new database will be saved.

    Create HTML link from Safari Tab

    My second script has been completed, this one actually works.

    tell application "Safari"
        set currentTab to current tab of window 1
        set tabName to name of currentTab
        set tabURL to URL of currentTab
        set the clipboard to ("<a href=" & tabURL as text) & ">" & tabName & ""
    end tell
    

    There are message boards that I post on that don’t autoformat URLs as links, so I’ve always had to manually add the “<a href=” tags. This scrip just pulls in the title and URL of the current tab and copies the HTML link to the clipboard. I set the badboy up as a hotkey in Quicksilver and BOOM, I have done it.

    My first successful script has been written

    In case you hadn’t noticed from my last post, I have created a script that automagically generates a blog post using all my kubi.tumblr posts from the last week.

    If you’re interested in taking a look at it, it’s an Automator script with a bunch of AppleScript modules thrown in. The Automator portions handle downloading the RSS feeds, the AppleScript sections do some text editing and deal with MarsEdit.

    Automator Script

    Next step is to get it set up on a timer and have it run automatically each week.

    tubmlr%20post

    Edit: I’m getting a weird

    *** -[PSEntry entryEnumeratorSortedBy:]: unrecognized selector sent to instance 0x13dd440
    error, but it only happens part of the time. Please hold off on using this script for anything business critical until this issue can be rectified.

    Edit 2: I fixed the issue and updated the script. The original script pulled in the last week’s worth of entries from Tumblr and saves it as an Automator variable. For some reason this variable doesn’t work correctly when I attempt to access it later in the script. What I ended up doing was just pulling in entries from my blog twice, once to get the permanent link, once again to get the title.