Tuesday, July 31, 2007

How To Convert Bazaar Repo to Git

This was way more difficult that I thought it would be, but I have conquered. I may be the only person in the world who even cares about doing this, but I'm writing it here so I don't forget.

I think it's hard because both the revision control tools, and the conversion tool are all still pretty new and in a state of flux. I finally got it to work using bzr version 0.15.0, git version 1.5.2.3, and tailor version 0.9.29. Both bzr and git are just what I had on my Ubuntu Feisty Fawn box that I keep up to date with backports and everything. Tailor version 0.9.26 is in the feisty repositories, but it most definitely didn't work for this. I grabbed the tarball for the latest source from here. You can just untar it and run it right from there.

OK, now, once you have tailor, to make this work, you need a tailor configuration file. Just put it anywhere and name it whatever you like. Mine looked a little like this:

[DEFAULT]
verbose = True
patch-name-format = ""

[project]
source = bzr:source
target = git:target
start-revision = INITIAL
root-directory = /homes/brmu/testing/fw_tests
state-file = tailor.state

[bzr:source]
repository = /homes/brmu/lnx/fw_tests
subdir = fw_tests-bzr


[git:target]
subdir = fw_tests-git

The paths for root-directory and the subdirs are just what I needed for my particular project. This tells tailor to grab the bzr repo from /homes/brmu/lnx/fw_tests, and then (I'm not sure exactly why it makes a copy) copy it to /homes/brmu/testing/fw_tests/fw_tests-bzr. Then it creates a git repository in /homes/brmu/testing/fw_tests-git and does the migration/conversion from bzr to git using these two new directories. I already had the /homes/brmu/testing/fw_tests directory created. Once you have this configuration file set up you can run tailor like this:

/path/to/latest/tailor -D -c tailor.conf

tailor.conf is the configuration file, of course. I found the best documentation for tailor in the README file with the source code. There is a wiki and a manpage, but those were both not as helpful.

Monday, July 30, 2007

Yegge on Branding (Marketing, eww)

Yegge gave a keynote at OSCON (which I didn't attend even though it's in my own back yard). You can watch it online (scroll down a ways and click on his picture). It's always weird to see and hear someone who's words you've only been reading for a while. He's pretty entertaining in person, but I still like his blog rants better. It was interesting what he said though. I've seen a few blog entries mention branding recently, you know, criticizing names like Haskell and Erlang, and this talk kind of solidified my understanding of how important brand is, even for geeky stuff like programming languages that are meant to be consumed by geeks, who, you would guess would think logically and choose on merits other than name. But they don't. I totally agree that Javascript needs a new name.

Wednesday, July 18, 2007

Haskell Considered Wacky

Just to show how randomly my thoughts wander at times, I was thinking of a problem in our code at work, and how some particular stuff really needed to be encapsulated into some functions, and I got to thinking about these fancy functional languages that the bloggers have been talking about these days, and I went and found a tutorial on Haskell and started reading it for a bit.

At first the purity and cleanliness that it described was quite alluring to me. No side effects. No destructive updates. Beautiful mathematical recursive definitions of functions. This stuff is cool. But wait, how do you do some simple IO? I wondered. The tutorial read my mind and replied:

If you are familiar with books on other (imperative) languages, you might be wondering why you haven’t seen many of the standard programs written in tutorials of other languages (like ones that ask the user for his name and then says “Hi” to him by name).

The language is smart, and so is the tutorial! Yes! Let's read on:

The reason for this is simple: Being a pure functional language, it is not entirely clear how one should handle operations like user input.

Okaaay... I can see what you are saying. Once you break out of the nice idealized world that is Functional Programming, you have to deal with the Real World, which might not give you the same deterministic output for the same input every time. But ultimately all programs have to do something useful for us here in the real world, don't they? There must be a solution to this, even in Haskell. Reading on:

The solution to this was found in the depths of category theory, a branch of formal mathematics: monads. We’re not yet ready monads to talk about monads formally, but for now, think of them simply as a convenient way to express operations like input/output.

I nearly laughed out loud when I read this. It was a shocked laughter. Shocked and delighted in some ways. Delighted that the evil mathematical geniuses behind this thing had stayed so true to themselves, yet still shocked at the pure dogmatism. "We can't express input and output in our perfectly functional language unless there is some math behind it. Let us delve deeper into Mathematics to find our answer!" In the end, that's just awesome that something was found, even in the depths of category theory. Amazing. Insane. Maybe I'm just reading too much out of one tutorial author's understanding of things...

Anyway, at this point I was sharply reminded of what I had just posted this morning about the software philosophers not being directly helpful to my firmware endeavors. Haskell was most definitely a far cry from the direct control over the real world that firmware has to have. But there is something to be learned in the theory. And I love learning this stuff, why else would I have picked up the tutorial? Maybe just so I could laugh. No seriously, I think it's good to be exposed to this stuff. I think our code could very much benefit from fewer side effects from our functions. The real world is tricky enough to deal with on its own without non-deterministic code trying to control it. Let's all pretend our firmware only allows Haskell-like "pure" functions a little more and see what happens. Just don't let it get too out of hand ;-)

Embedded Systems Blogs

I confess, not for the first time, that I'm a sucker for the great software philosophers of our time, Paul, Stevie, and Joel, to name a few. Their blog entries and essays are entertaining and thought provoking. However I'm often left unsatisfied because too much of what they advocate just doesn't apply to firmware and embedded systems programming. Sure, high-level languages like lisp and ruby are neat-o, but I'm just not seeing how they are going to help me poll sensors, write memory-mapped registers, and manage real-time tasks better. Where are the embedded systems philosophers and gurus?

I stumbled upon a few blogs the other day that might begin to qualify as good embedded systems blogs, and I want to write them down before I lost them. So here's a quick list with some accompanying rough first reactions:

Wow, just in making that list I found a few others. It might be time to add another page to my Netvibes RSS collection and see how these compare to the big three I named at the start.

Sunday, July 15, 2007

'git revert' Is Not Equivalent To 'svn revert'

I just learned that if you have some changes in your working tree that you want to get rid of, you don't type 'git revert' like you might guess. No, that's what cvs, subversion, mercurial, and bazaar (to name a few) use revert to mean, but not git. With git, revert is used to undo actual commits. Thankfully, you can undo your revert with another 'git revert', I just learned. So let me repeat to be clear, if you have changes to your working files that you want to abandon, DO NOT do this:

git revert HEAD

That will undo your last commit. Do this instead:

git reset --hard HEAD

I'm glad I have that straightened out now. I'm wondering if /etc was really a good place for me to start out playing with git.

UPDATE: Nearly two years later and I'm still getting comments on this. I'm glad I've been able to help people out this way. The discussion in the comments is good, and one thing I'd like to point out is that I now always use and recommend:

git checkout filename
(as recommended by Anonymous and others below) instead of git reset. I think the git stash trick from Nicolas is pretty cool too.

Sunday, July 8, 2007

Put /etc Under Revision Control (with git)

UPDATE: There is a much easier way now (though it uses bzr by default on Ubunutu, not git, in case you are really particular, but apparently it can be made to use git instead):

sudo aptitude install etckeeper

There, now etc is under revision control and changes are automatically committed with a helpful message after you install new packages. Thanks for the tip, Marcelo! Read on for the original blog entry.

I put my /etc directory under revision control. I used git. It's awesome. Not that I think I'm going to wholesale copy my /etc from one machine to another, nor because I'm going to branch my /etc directory and spend weeks developing some cool new feature (whatever that would look like...) and then merge it back into the main branch. No, it's mostly because I like the idea of having the big "undo" option that having things under revision control provides. Having to commit changes and write check-in comments when I make changes helps me stay more organized too. It's never good when I go in willy-nilly to make a "quick change" to some configuration file.

I relied heavily on this blog entry for using git, and this blog entry for using mercurial (hg). I decided to go with git because mercurial quietly ignores symbolic links, and it seems like there are just a few important symbolic links in /etc. It also seems that git handles these just fine. Oh, and I didn't choose bzr or darcs mainly because they are slow, and because I want to get to know git better.

Here's how I did it (on Ubuntu Feisty Fawn, do all this as root):

First, initialize the repository:

cd /etc
git init-db
chmod og-rwx .git

The chmod is so non-root users can't go poking around in your repository. Next, ignore a few files:

cat > .gitignore << EOF
*~
*.dpkg-new
*.dpkg-old
blkid.tab(|.old)
mtab
# add other files if necessary, depends on your setup...
EOF

Do the initial commit:

git add .
git commit -a -m "initial import"

Set up a script to check in any change made when installing new packages. Put this in /etc/apt and call it something like, git-snapshot-script. Here is the script I use (UPDATED: Jul 11, 2007):

#!/bin/bash
set -e
caller=$(ps axww | mawk '/aptitude|apt-get/ {for (i=5; i<=NF ; i++) printf ("%s ",$i); printf ("\n") }' | head -1)
git-add .

# the || true is to make sure we don't error out because of the set -e
# above
STATUS="$(git status)" || true

if echo $STATUS | grep '\(Changed\|Update\)' > /dev/null ; then
   echo "git-snapshot-script: found changed files"
   echo $STATUS
   git-commit -a -m "snapshot after: $caller"
else
   echo "git-snapshot-script: no changes"
fi
echo "git-snapshot-script: done"

Then tell apt to run this script after it's invoked:

cat >> /etc/apt/apt.conf << EOF
DPkg {
          Post-Invoke {"cd /etc ; ./apt/git-snapshot-script";};
}
EOF

chmod +x /etc/apt/git-snapshot-script

Now, check in the script and the change to apt.conf:

git add .
git commit -a -m "set up apt to track changes with git automatically"

And that should do it.

Tuesday, July 3, 2007

Django Does Gmail

I love it when I ponder something quietly to myself, not even uttering my question aloud, and then bump into an answer that same day by seemingly random bouncing around the internet (and let us not speak of the countless hours utterly wasted by bouncing around the internet at other times!).

I don't check my feed reader enough to notice comments posted to my family website in a timely manner. I need more than just an RSS feed of recent comments. I need a higher priority interrupt. Email seems about right, but I don't think setting up sendmail (or something like unto it) is what I want. Emails from my home machine would probably be rejected as spam most places anyway. If only my Django powered website could send mail through gmail. And lo, the answer was there before me.