Monday, November 23, 2009

Ripping CDs in Linux with Rhythmbox

I'm a little particular about my LAME MP3 encoder settings. I really like the size/quality tradeoff of '--preset standard'. I used to install and configure Grip but since I use Rhythmbox for everything else, I figured it was time to get the GStreamer backend to do what I want.

My first step was finding the preset code for gstreamer. Run 'gst-inspect lame'. The last section specifies the codes for the preset keyword, In this case, 1001 equates to standard.

Now I just needed to edit the gstreamer pipeline in rhythmbox. Here's the pipeline I'm using: audio/x-raw-int,rate=44100,channels=2 ! lame name=enc preset=1001 ! xingmux ! id3v2mux

Note that you need gstreamer-plugins-ugly installed (rpmfusion has it) for lame and xingmux to be available.

Thursday, October 29, 2009

iPhone Calendar Colors + sqlite

I have a jailbroken iphone and I use google calendar and google sync to take it mobile. The iphone doesn't have a GUI to select the calendar color. If you happen to be using MobileMe then you don't have a problem but if you're using ActiveSync then you have to resort to using sqlite from the command line. You can find instructions here: http://chriscarey.com/wordpress/?p=353

For my own reference here are the sanitized sqlite update commands:
update Calendar set color_r=15, color_g=77, color_b=140 where title = "Blue";
update Calendar set color_r=76, color_g=176, color_b=82 where title = "Green";
update Calendar set color_r=229, color_g=98, color_b=0 where title = "Orange";
update Calendar set color_r=242, color_g=166, color_b=64 where title = "Light Orange";
update Calendar set color_r=212, color_g=95, color_b=134 where title = "Pink";
update Calendar set color_r=181, color_g=0, color_b=13 where title = "Red";
update Calendar set color_r=153, color_g=68, color_b=153 where title = "Purple";

Thursday, October 15, 2009

Git With Svn - Update

During the course of working with git-svn we've discovered a slight kink in our previous workflow. We've been using git-wtf to stay on top of the relationships between our feature and integration branches and that's alerted us to the following problem.

Broken workflow:
1. git checkout -b feature
2. Hack, hack, hack.
3. git checkout master
4. git svn rebase
5. git checkout feature
6. git merge master
7. git checkout master
8. git merge --squash feature
9. git svn dcommit

Simply put, that workflow is meant to merge changes from upstream svn into master and then into our feature branch. Then we merge our feature into master (squashed into a single commit) and push that commit up to svn. The problem comes when examining the relationship between the feature branch and master branch at this point. Running a diff between the two branches show that they hold the exact same content and yet git will insist that they are not the same. The solution here is to use the following workflow:

1. git checkout -b feature
2. Hack, hack, hack.
3. git checkout master
4. git svn rebase
5. git checkout feature
6. git merge master (You can also use rebase here depending on personal preference.)
7. git checkout master
8. git merge --squash feature
9. git svn dcommit
10. git checkout feature
11. git rebase master

The additional rebase from master onto feature at the end will first merge all the changes from master and then try to replay the commits on top of feature back. This will fail and git will attempt a 3 way merge only to realize that the content is already the same. In the end, the branches will now have exactly the same commits (unless you had additional commits on feature you didn't merge) and git/git wtf will now tell you that the feature has been merged in.

The other alternative would be to always use rebase at step 6 and commit each individual commit on your feature branch to master and then to svn; that part is up to you and your team.

Wednesday, September 30, 2009

Effectively publishing branches with Git / Deleting remote branches

We recently ran into some problems when trying to push branches to a central remote to share changes with each other. We were following this workflow:

1. Create a local branch: git checkout -b feature
2. Make some changes.
3. Decide that a coworker should see this feature branch: git push origin feature
4. Make more changes.
5. Push those changes: git push

At this point git push may return an error or try to do something very wrong. Those of you more experienced with git have already spotted the problem. At no point did we tell git that our local branch is now tracking the new remote branch we published! This prevents us from running git push/pull without arguments.

Some users use the following workflow to get around this problem:
1. Create a remote branch: git push origin master:refs/heads/feature
2. Checkout remote branch: git checkout -b feature origin/feature (--track is default when the start point is a remote branch)

I don't like this workflow though. It assumes that I'm connected to the internet where git is trying to leverage disconnected workflows. It also assumes that I know when I create the branch that I'm going to want/need to share it. This isn't always true.

I feel that the right solution to this problem is to update the git config with the information it needs to start tracking the remote branch. Doing this by hand (either editing .git/config or using the git config command) is error prone at best. I was going to write a script until I realized that I already had the tool installed that I needed.

Let me introduce you to William's miscellaneous git tools.

Once I've installed git-publish-branch, my workflow looks like this:
1. Create a local branch: git checkout -b feature
2. Make some changes.
3. Decide that a coworker should see this feature branch: git publish-branch
(Without arguments publish-branch pushes the current branch to origin.)
4. Make more changes.
5. Push those changes: git push

This works correctly. You can also check to see if you're tracking the right branch and if you're in sync with the humorously named git-wtf from the same website.

Bonus points: Run "git config --global color.ui auto" for fun colors from these commands.



The other thing we discovered is that when we delete remote branches (with "git push origin :branch-to-delete"), the person who did the delete has their remote tracking branch (not the same as the remote branch itself) deleted but others who have run git fetch at some point still have that stale remote tracking branch. This can be cleaned up by running "git remote prune origin" periodically. My desire would be to get a notification of a deleted branch when I run git fetch but that's not how it works.

Monday, September 28, 2009

Git Archive

I've been working with some code on rightscale. A common workflow for me is:

1. Hack, hack, hack.
2. Commit.
3. Export to a compressed tarball.
4. Upload to rightscale as a script attachment.

Today I figured out a better way to do #3. Here is a simple script I wrote to automate the export (names changed).

#!/bin/bash

echo "Reminder: This exports from master."

git archive --prefix=client1/ master | gzip > client1-tools.tar.gz

This saves me a step over copying my working copy and removing .git.

Tuesday, September 15, 2009

Everyday Git Workflow

I use git each day both as an svn client and in git-only environments. Here's my standard workflow for each environment.

Init
If this is a new project, merely create a directory to work in and run git init.

Clone
git clone user@host:repo.git
or
git svn clone -s https://host/path/to/svn/repo (the -s says this uses trunk, branches, and tags directories)

This leaves you with a git repository that is in sync with your upstream.

If you've gone the svn route and need git to understand your svn:ignore props, run this:
git-svn show-ignore > .gitignore (Beware, it takes a while.)

Feature Branches
I generally create a new "feature branch" for each feature I want to work on. This allows me to switch cleanly between features as I see fit.
git checkout -b feature

When moving from branch to branch after I've made changes, I use git stash to save those changes. Git will move your pending changes in your working copy and index with you when you checkout a different branch (handy when you start editing in the wrong branch).
git stash (by itself will create a new stash of your working copy and index)
git stash list (shows all stashes)
git stash pop [] (Removes the named, or first, stash and applies it to your working copy/index)

Beginning of Day
I generally start by checking out the master branch (git checkout master) and updating from upstream.
git pull
or
git svn rebase

If there were changes in there that I need in one of my feature branches, I'll check it out and merge.
git checkout feature
git merge master
If there were any conflicts, fix them as part of the merge.

Working
Once I'm in a feature branch, I typically code there unless an interruption causes me to switch to another. That simply looks like this:
*Code, code, etc*
git add
git commit -m "Here's a short explanation of what I changed. Don't skimp on this part."

git diff can also be useful during the add/commit process to see exactly what you changed. git add --patch can also be used to "stage" (the process of adding changes to the index) individual hunks from each file instead of the entire file.

Sharing Branches
If your sysadmin has given you access to a remote git repository (I recommend using gitosis), you can share your feature branches with other devs without committing to your master/svn repo.

Note that in the following instructions I'm using "origin" as my remote. If you're working with a remote git repo already instead of svn you'll need to use a different name here.

git remote add origin user@host:repo.git
git checkout feature
git push origin feature

Now your coworker can run:
git remote add origin user@host:repo.git
git fetch
git branch -a (lists all branches including remote branches)
git checkout -b feature origin/feature (where "feature" is the local branch name and "origin/feature" is the remote branch name)

After you've done your initial push or checkout, you can just run git push to update the remote branch or git pull to fetch and merge from that remote branch (with the above caveat about already using origin). In this way, you can continue to distribute changes to one another.

Committing Upstream
Once you're done with your feature, it's time to commit to master/svn. Do one last pull or svn rebase on master (as described above). Then it's time to run the process in reverse with one important change.
Assuming your working copy is already on your feature branch.
git merge master (to sync with your upstream in your feature branch)
Fix any conflicts and commit the merge.
git checkout master
git merge --squash feature (The --squash flag will combine all your changes into one complete changeset. This will also leave everything uncommitted in the index so you can have a look.)
git commit -m "Here's a great summary of everything I did in my feature branch that will be visible upstream,"

git push
or
git svn dcommit

Props
I got my start with git-svn after reading a post by the viget guys.

Wednesday, September 02, 2009

git-svn and --squash

When you're using git-svn, it's important to remember to use git merge --squash when you're merging a feature branch back to master in preparation for a git svn dcommit. In case you forget (like I just did) here are some simple steps to repair what you've done without dealing with interactive rebase.

The setup (what you should avoid):
git checkout -b feature
hack, hack, hack, merge with changes on master, etc
git checkout master
git merge feature
git svn dcommit

My experience at this point was that the first changeset from the merge was successfully committed to svn followed by the rebase failing. Dcommit actually will commit each revision independently and rebase between them. I was left in interactive rebase. Instead of trying to clean this up iteratively by running through all the changesets I did the following:

(this is still on the master branch)
git rebase --abort
git reset --merge (the merge option sticks everything in your working copy into the index)
git svn rebase (to get the commit that made it to svn)
git merge --squash feature
git commit -m "Here's my feature for all you svn users!"
git svn dcommit

This will successfully push ONE commit with all your remaining changes up to svn. Hope this helps someone who finds themselves in this situation. I also expect to have to read this again next time I forget --squash. Happy coding!

Friday, August 28, 2009

Thunderbird 3 Beta 3 Icons

I've been using Thunderbird 3 Beta 3 in Fedora 11 today. The icon set has been changed to be more "linuxy" or "gnomey". I've gotten so used to the appearance and location of the previously used icon theme that I'm having trouble using it at times.

Example: I'd like to delete this email.
Find big red X.
There is no big red X....
Oh it's a trash can now.

I'm trying not to have a gut "Hey! This is different!" reaction. I'm not sure that the new icons do as good of a job portraying to me what they are supposed to be used for. I'll see how another few days makes me feel about it.

Tuesday, August 25, 2009

New Direction (and url!)

It's been suggested by several of my friends that I turn this space into random snippets of linux/programming knowledge. I make no commitments as to the frequency of said posts. I'll try to throw things up here as I'm inspired. Also, you get bonus points if you find this at the new url.

So, without further ado:

If you're in a situation where ssh-agent isn't running farther up in your process tree automatically, here's how to get the same functionality out of .bashrc.

export EDITOR=/usr/bin/vim

SSH_ENV="$HOME/.ssh/environment"

function start_agent {
echo "Initialising new SSH agent..."
/usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
echo succeeded
chmod 600 "${SSH_ENV}"
. "${SSH_ENV}" > /dev/null
/usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
#ps ${SSH_AGENT_PID} doesn't work under cywgin
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi