5 Must-Have Aliases for bzr-pipeline

August 26, 2009

Recently, my workflow with Bazaar has adapted to use bzr-pipeline, because much of the work I'm doing is based upon prerequisite branches. This means I find myself doing a lot of switching between pipes, sending pipes to Launchpad for review, etc. I have added the following aliases to ~/.bazaar/bazaar.conf in order to make my life easier.

next = switch-pipe :next
prev = switch-pipe :prev
send-pipe = send -r branch::prev..
diff-pipe = diff -r branch::prev
pipes = show-pipeline

Also, if you haven't used bzr-pipeline yet, try it out next time you're trying to break your work up into many smaller branches.


Examples in bzrlib

January 18, 2009

So while I've spent my fair share of time hacking with Bazaar, I'm ashamed to say I hadn't done a lot of hacking on Bazaar. I've fixed small issues in Bazaar plugins, and even written a few of my own (although Jono Lange actually released his implementation before I could get mine done). However, during Christmastime, I had the opportunity to hack on some Bazaar plugins that I will be releasing shortly. In this process, I learned a bunch about the bzrlib API, and its great ease of use. I thought I'd compile a bit of what I've found into a blog post or two.

I'd like to start the examples off with some relatively easy exercises. In order to do some of these examples, it's best to have a local bzr branch of any kind. I'll start by demonstrating how to do some of the tasks you do from the command line (or GUI of your choice) programmatically.

Getting a Branch object

In order to operate on your branch, you'll need to create a Branch object. This will be a programmatic handle to your bzr branch itself. So let's start by getting the branch itself.

from bzrlib.branch import Branch

my_branch = Branch.open('/path/to/branch')

Now we can operate on the branch with python. Let's say we want to see what config variables are set on this branch. We'll want to get the configuration of the branch, and then examine its contents. In this example, we'll check the username you'll be committing to bzr with (because you hopefully ran bzr whoami.

my_branch_config = my_branch.get_config()
print my_branch_config.username()

Simple local branching

Let's say you want to programatically create a local copy of a remote branch.

from bzrlib.branch import Branch

remote_branch_url = 'bzr+ssh://bzr.eventuallyanyway.com/code/foo-bar-baz'

remote_branch = Branch.open(remote_branch_url)
local_branch = remote_branch.bzrdir.sprout(
    '/code/foo-bar-baz').open_branch()

Getting a diff

Programmatically, I think the best use for understanding the Bazaar API is to diff the changes in your current working tree. You'll do this by creating a WorkingTree object and operating on it.

from bzrlib.workingtree import WorkingTree

tree = WorkingTree.open('/code/foo-bar-baz')

Now you've got a working tree. Let's get a diff between it's current state and its last committed state. If it's changed, commit the changes with a commit message of "Committed changes"

delta = tree.changes_from(tree.basis_tree())
if delta.has_changes:
    tree.commit('Committed changes')

All in all, I think the greatest strength of Bazaar is its easy extensibility, and easy entry into working with its API is proof.


Launchpad Code Reviews Without A Browser

January 15, 2009

I do a lot of code review in Launchpad, use a lot of the code features, and have worked out some pretty good methods of making this simple and easy to work with. I thought, in lieu of my last post, and the ones I'm planning for the near future, it'd be good to detail some of the things that I do to make my workflow.

Launchpad's web UI is slow. I'll admit it. We're working on doing some really great things to speed it up, but frankly, all web applications are. You've got to load pages, parse javascript, etc. In fact, most things you shouldn't even have to wait around for. They are things that should require minimal attention for much of the time, and often things that are "fire and forget."

So let's build off the config settings I've already blogged about. If you haven't read that article yet, I highly suggest you go back and read it, or you're gonna get really confused really quick.

Creating a merge proposal with email

Looking back on the general Launchpad branch configs we used, we need to add one more line so that Bazaar knows the email address that Bazaar's "bundles" should go to. So, let's edit our ~/.bazaar/locations.conf to show the following:

[/home/rockstar/Projects/repos]
push_location = lp:~rockstar/
push_location:policy = appendpath
public_branch = lp:~rockstar/
public_branch:policy = appendpath
submit_to = merge@code.launchpad.net

The line added is the submit_to line. This means that Bazaar is going to send its bundles to merge@code.launchpad.net. This is the email address that parses the bundle, and derives the the source branch (the branch to be merged) and the target branch (the branch to merge into).

Now we need to specify the submit branch. This requires some specific configs for each project, so we'll need to add a new section. For this example, we're going to use Entertainer since Bazaar's development doesn't use Launchpad for it's review process. I'm going to add another section specific to Entertainer.

# Entertainer
[/home/rockstar/Projects/repos/entertainer]
submit_branch = lp:entertainer

This sets all branches in ~/Projects/entertainer to submit to the branch lp:entertainer which happens to be the current development focus of Entertainer. Note: The target branch MUST be a Launchpad branch. The source branch doesn't really need to be, and Launchpad is smart enought to create a Remote branch (a branch that Launchpad only keeps a reference of).

Finally, we need to tell Bazaar what your preferred email client is. So crack open ~/.bazaar/bazaar.conf and let's add one more line to the [DEFAULT] section.

mail_client = evolution

Wait. You don't want to use evolution to send your email? Well, you can choose between thunderbird, evolution, kmail, thunderbird, mutt, emacsclient (although I don't know how that emacsclient works), or editor. I use editor, but that requires some more config set up (and it's beyond the scope of this post). Also, if you want to use Gmail, see BzrSendWithGmail or use James Henstridge's bzr-imapclient plugin to use GMail to send the merge-directive (see https://lists.ubuntu.com/archives/bazaar/2009q1/051602.html. As of Bazaar 1.11, bzr also now supports claws as a mail_client as well.

Now, hacka hack on your branch, and when it's all ready, make sure it's pushed to Launchpad, and then do bzr send --no-bundle. This will create a bundle and open up your mail client for you to detail what your branch does. Fill that out, and send the email. It'll be processed, and the merge proposal will be created, using the Default Reviewer for the target branch as the reviewer.

Reviewing a branch through email

This is where things get more interesting. Those subscribed to the branch (as branch code reviewers should be) will get an email with the creation of the merge proposal, and an email with the patch (these two emails will be consolidated shortly).

So a reviewer cracks open the email and looks through the patch. They merge the branch into their local mirror of trunk and run the tests (because you have tests for code, right?). The reviewer makes their inline comments to the patch in the email reply. The To: in their reply should be something like mp+1234@code.launchpad.net.

If you (as reviewer) were to send this email now, it'll be parsed as a comment to the merge proposal. What if you want to give an official review vote? What if you want to set the merge proposal status to Approved? This is the clever part. For example, I review a branch and I think it needs to be set to Needs Fixing. Within the email, I would type:

vote needs_fixing

Note the leading space there. It's important. Now, GPG sign your email, and send it off. You've just given your vote. After someone decides to fix the issues that arose from your review, you can reply to the response email with:

vote approve
status approved

Send this with a GPG signed email, and you've updated the merge proposal to Approved as well as "voted" approve. Now, if you can merge the branch, merge it, otherwise, nudge someone who can.

Hooray! You've successfully navigated the hairy process of code review without having to hassle with the web UI at all. Now THAT'S a service worth working with. There are similar commands to work with bugs as well, and by learning to use these commands, you can create a workflow with Launchpad that works best for you.

Update: Thanks to some great comments, I've noted some of extras.

Comments | Tagged as: bzr launchpad

Using Bazaar with Launchpad : Making Pushing Easy

January 13, 2009

Many of Bazaar's dirty little secrets are hidden away in options you can set in ~/.bazaar/bazaar.conf and ~/.bazaar/locations.conf. Here are some fun things to configure to streamline your hacking with Launchpad and with other projects.

First, some background. I have a rather detailed and involved setup and workflow (which I'll detail later), so I'm going to do my best to make this as simple as possible. For the sake of this example, I'm going to lay out my folders this way:

~/
~/Projects
~/Projects/bzr
~/Projects/bzr/bzr.dev
~/Projects/bzr/foo
~/Projects/bzr/bar
~/Projects/bzr/baz
~/Projects/entertainer
~/Projects/entertainer/entertainer
~/Projects/+junk
~/Projects/private
~/Projects/private/ironlion

So I have put all my branches into a ~/Projects directory, inside a dir each for various projects I work on that are hosted on Launchpad(bzr and Entertainer for the sake of this example). I also have two other folders, one called +junk (for junk branches), a folder called private which, as you may have guessed, will be for things I don't push to Launchpad (like, say, for instance, the source for this blog, which contains db passwords all sorts of fun info... :)

To start out, let's look at my ~/.bazaar/bazaar.conf:

[DEFAULT]
email = Paul Hummer <paul@myemaildomain.com>
create_signatures = always
gpg_signing_command = /usr/bin/gpg
launchpad_username = rockstar

This where you put all the things about your general use of bzr. The email line will usually get set by doing bzr whoami which you should generally run the first time you run bzr, so that bzr knows your name and your email address. If you've ever seen your revisions on Launchpad saying something like rockstar <rockstar@megatron> it's probably because you haven't set your email config line, and so it's taking your user name and host name of the system you're working on (in this case, my system's name is megatron). I've also set my launchpad username. This is also important, and would get set when doing bzr launchpad-login rockstar Confused yet? If so, just skip down to the next block. create_signatures and gpg_signing_command are both to allow me to sign my revisions.

[ALIASES]
cbranch = cbranch --lightweight
ci = commit --strict
diff = diff --diff-options -p
diff-thread = cdiff -r thread:
ll = log --line -r-10..-1
lpsend = send --no-bundle
recentlog = log -r-20..-1 --short
sdiff = cdiff -r submit:
st = status --short
unpushed = missing --mine-only :push

These are my aliases. Think of them like shell aliases. The details you don't have to worry about too much, but when find yourself running the same commands over and over, add them to your aliases.

locations.conf is where all the fun happens. It's what tells bzr, based on the location of the branch, where to push, where to submit, etc. So let's start with a generic blanket statement that'll be used for all projects pushed to Launchpad. So let's start with:

[/home/rockstar/Projects]
push_location = lp:~rockstar/
push_location:policy = appendpath
public_branch = lp:~rockstar/
public_branch:policy = appendpath

The secret here is in the appendpath. Basically, bzr looks at the relationship of the current branch, say ~/Projects/entertainer/entertainer to this config section, and, using the appendpath policy, decides it needs to be pushed to lp:/~rockstar/entertainer/entertainer Hooray! Now, if I create a new branch at ~/Projects/entertainer/fix-bug-123465 and just call bzr push, bzr is smart enough to push it to lp:~rockstar/entertainer/fix-bug-123456 This even works with junk branches (branches that aren't attached to a project), provided you just put your branch in the +junk folder.

But wait! What if I don't want to push to Launchpad? I first ask "Why don't you? It's so great!" :) As locations.conf stands now, if you put something in your private area, Launchpad is going to tell you there is no project named private when yo utry to push. Well, let's fix that.

[/home/rockstar/Projects/private]
push_location = bzr+ssh://bzr.eventuallyanyway.com/code/
push_location:policy = appendpath
public_branch = bzr+ssh://bzr.eventuallyanyway.com/code/
public_branch:policy = appendpath

As you can see, I push my private branches to bzr.eventuallyanyway.com/code. It uses the same tricks as I showed before, so the same idea can be assumed.

It's important that I point out that there's no order required in how these config sections get put into locations.conf because bzr is smart enough to find the most specific config and use it.

This concludes this session of bzr-lp hackery. Comments welcome.

Comments | Tagged as: bzr launchpad

Also, some similarly tagged posts from the archives...