Posted by Rob Kaufman
on Mar 28, 08
It is common to have others code lurking in the vendor directory of your project. Many have switched to using piston on the Subversion side of life, and braids fills the same gap over on the git side, but can be used to freeze either subversion or git repos.
Braids (like much of git) is still a little wet behind the ears in the usability department, so don't expect it to hold your hand through the process just yet. An example from today, I got the this message:
2008-03-28 12:26 $ braid add http://async-observer.rubyforge.org/svn/async_observer --type svn vendor/plugins/async_observer
braid: Creating work branch 'braid/track'
braid: Checking out work branch 'braid/track'.
braid: Adding svn mirror from 'http://async-observer.rubyforge.org/svn/async_observer' into 'vendor/plugins/async_observer' using local branch 'braid/svn/vendor/plugins/async-observer'.
braid: Got remote svn revision: 19.
braid: Setting up remote branch and fetching data.
braid: Error occured:
braid: Resetting braid/track to d38137af1951a32f0d217a2c77f3d553890576ba.
braid: Checking out branch 'async'.
braid: An exception has occured: ()
Its those empty parentheses that are really informative ;-) It turned out that I installed git via Macports, then manually installed a newer version in /usr/local/bin. I then had changed my path to have /opt/local/bin behind /usr/local/bin. That worked just fine until last week when some other (not SCM) thing broke and I switched them back (forgetting why I'd switched in the first place). The bottom line is the error above is caused by not having subversion bindings installed right in git. Macports now has a better version to use, so I blew away the custom compiled one and just updated my Macports to be right. I found the comment about subversion bindings at the bottom of this excellent post
Posted by Rob Kaufman
on Mar 24, 08
I like to tweak my workflow all the time. I often change something for a week, try it out and then either change back or move on to something else. I got used to tabbed terminals in Linux and even had mrxvt working under cygwin, so when I came to the Mac not having tabs in the Terminal bugged me. I tried several solutions and settled on iTerm. Life was good for a while. I got tired of using nohup to run long emerges in the background on the servers, so I learned about gnu screen. That led me to wonder if you could get labels for the various windows, and sure enough the hardstatus line will happily act as a tab bar for you as long as your not fond of clicking to change tabs (in the terminal? You shouldn't be). I had seen Visor and thought it was cool, so I tried it out for a while with Screen to give me tabs. There where some problems with Visor interacting weird with screen, so back to iTerm I went. When I updated to Leopard, I moved to Terminal.app, since it had tabs now. But it turns out I had grown to love the "Do what I'm typing in all tabs" feature. So I went back yet again. But iTerm didn't work as well for me under Leopard as it did under Tiger. So I got over not having the do in all tabs feature and lived with Terminal.app. Recently I realized that I was spending a lot of time 'setting up' my work environment. The steps go like this:
- Go to tab 1
- Stop script server
- Change directory to new project
- Restart script/server
- Go to tab 2
- Stop autotest
- Change directory to new project
- Start autotest
- Go to tab 3
- Change directory to new project
- Run sake gitrdone
- does svn up or git pull (depending on .git file)
- does rake db:migrate
- rake db:test:clone
- rake spec:db:fixtures:load
- rake notes
- svn status | grep ? or git status
- mate .
So yeah, thats a lot. Way to much to do manually (even with the awesome sake script). So I started looking around the web to see what others had done. I found this OnRails article which seems to have met with some serious frustration, and the associated links. The outlook did not look good. So back to iTerm... again. That still wasn't satisfying. Then I stumbled across something (I don't remember what) that mentioned screens -X and its -X stuff command. The way it works is this. -X tells screen to do one of its internal commands from the outside, so screen -X next would change the focused window by one, either form inside the screen session or from outside of it. stuff 'do this' is the screen command that sends 'do this' to the current screen. That got me thinking... what if screen could be used to do all the magic that Apples sucky Applescript in Terminal.app can't? So I started to fiddle and hack and read. Screen's documentation is the suck, though I did find this source This led to the creation of the following script
#!/usr/bin/env ruby
def find_or_create_by_id(window_id)
File.delete('/tmp/current_screen') if File.exists?("/tmp/current_screen")
`screen -p #{window_id} -X hardcopy /tmp/current_screen`
sleep(0.1)
unless File.exists?("/tmp/current_screen") && File.size("/tmp/current_screen") > 0
`screen -X screen`
return find_or_create_by_id(window_id)
end
return window_id
end
i = 0
find_or_create_by_id(i)
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; ruby script/server --debugger'`
i += 1
find_or_create_by_id(i)
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff ''`
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; sake git_r_done; autotest'`
i += 1
find_or_create_by_id(i)
`screen -p #{i} -X stuff 'cd #{ARGV[0]}; mate .'`
I drop that into my bin dir under the title hack and now as long as screen is running I can do
hack ~/work/project/trunk
and off I go. It is worth noting that since it sends a kill to whatever is running in the first and second screen tabs, you have to run it from either outside screen or from some tab other than the first or second.
I also found this article that showed my some other features of scripting screen and allowed me to write a script I call all which takes whatever you type after it and sends it to all open tabs in a screen session.
I've coupled this with my .screenrc file and the new version of Visor lets me have simple drop down terminal with all the power I need.