Latest Posts

Next 10 posts:

Another Emacs Project Library

I've posted a new project handling library to the Emacs Wiki: mk-project.el. A "project" in this sense is a directory of source files. You define a named project and provide settings for it: base directory, source file patterns, file patterns to ignore, the TAGS file, the compile command, etc.

Features:

  • Quickly switch between projects, optionally closing the files in the old project.
  • Use the new project's TAGS file -- and be able to rebuild the TAGS file based on project settings.
  • Run find-grep from the new project's base directory, ignoring certain files or directories based on project settings.
  • Run compile with the project's preferred compile command.
  • Open any file in the project quickly based on regex matches.
  • Quickly open dired on the project's base directory.
  • Define per-project startup and shutdown hooks -- useful for opening often-used files.

Perhaps the feature I'm happiest with is project-find-file. The library maintains a list of all the files under the project's base directory in a special buffer, *file-list*. Project-find-file ask for a regular expression representing part of a file's path or name and either 1) opens the file if there is only one match in *file-list*, or 2) allows selecting among the matching files with Emacs' built-in completion mechanism. Also, it sometimes comes in handy to search buffer *file-list* directly when you want an overview of the entire project. I often work with projects having thousands of files in deep folder hierarchies so project-find-file is very convenient.

After writing my library, I discovered a similar library, ProjMan by David Shilvock. The project operations we offer are similar - we even recommend similar keybindings! ProjMan is perhaps more complete, but I don't feel my time was wasted writing mk-project.el -- elisp is pleasure to code in.

Technorati tags for this post:

Suspend/Resume on a Lenovo T61 Running Ubuntu 8.04

As I've discussed before, I have a Lenovo T61 laptop with a Nvidia Nv140m video card running Ubuntu 8.04 (Hardy Heron). With the proprietary "nvidia" video driver, suspend/resume works fine. However, I use the open source "nv" driver as it supports xrandr which I need to hotdock my machine. The laptop fails to fully resume when running "nv": the screen is black; the keyboard and mouse are unresponsive.

The T61 thinkwiki pages for Ubuntu 8.04 and 7.10, the hal sleep quirk page and David Goodlad's post helped identify the root problem.

First, gnome-power-manager has taken over suspend/resume duty from acpid in 8.04 -- so the changes I had made to /etc/default/acpi-support are no longer used. Secondly, as David noted, the nv driver requires the s3_bios and vbemode_restore video quirk settings. However, my many attempts to edit /usr/share/hal/fdi/information/10freedesktop/20-video-quirk-pm-lenovo.fdi so that hal would set these particular quirks for my hardware failed. (The thinkwiki page has complaints from people who could not get hal to recognize their edits as well -- does anybody definitively know how to edit these files?) I resorted to adding these lines to my /etc/rc.local file:

hal-set-property --udi /org/freedesktop/Hal/devices/computer --key power_management.quirk.s3_bios --bool true
hal-set-property --udi /org/freedesktop/Hal/devices/computer --key power_management.quirk.s3_mode --bool false
hal-set-property --udi /org/freedesktop/Hal/devices/computer --key power_management.quirk.vbemode_restore --bool true

For the record, hal reports my hardware model as:

# hal-device | grep system.hardware
...
system.hardware.vendor = 'LENOVO'  (string)
system.hardware.product = '6459CTO'  (string)
system.hardware.version = 'ThinkPad T61'  (string)

And finally, now hal reports my quirk settings as:

# lshal | grep quirk
power_management.quirk.s3_bios = true  (bool)
power_management.quirk.s3_mode = false  (bool)
power_management.quirk.save_pci = true  (bool)
power_management.quirk.vbemode_restore = true  (bool)

Suspend/resume functionality has been resumed (ugh) for me.

As an aside, hibernate works now too. It did not work in 7.10. I don't know if these changes fixed it, or if the upgrade to 8.04 did the trick.

Update 2008/09/04: After reading the HAL spec, I discovered that the /etc/hal/fdi/information directory is where an administrator should drop custom device information for the system. Settings in this location will override the /usr/share/hal/fdi/information data. Looking there, I discovered Ubuntu had already created a lenovo.fdi file. Editing the file to look like below fixed suspend:

<?xml version="1.0" encoding="ISO-8859-1"?> <!-- -*- SGML -*- -->
<deviceinfo version="0.2">
  <device>
    <match key="system.hardware.vendor" string="LENOVO">
      <!-- Ubuntu default settings: good for nvidia driver
      <merge key="power_management.quirk.s3_mode" type="bool">true</merge>
      <merge key="power_management.quirk.s3_bios" type="bool">false</merge>
      <merge key="power_management.quirk.save_pci" type="bool">true</merge>
      -->

      <!-- My settings: good for the nv driver -->
      <merge key="power_management.quirk.s3_bios" type="bool">true</merge>
      <merge key="power_management.quirk.save_pci" type="bool">true</merge>
      <merge key="power_management.quirk.vbemode_restore" type="bool">true</merge>
      <merge key="power_management.quirk.s3_mode" type="bool">false</merge>
    </match>
  </device>
</deviceinfo>

Why I Quit Facebook

I joined Facebook out of technical curiosity. My curiosity was satisfied after a week of light use; my patience was finally depleted after 2 1/2 months. I completed deleted my account. Not deactivated it, deleted it.

Sorry friends -- I owe you an explanation. And given my motivation for joining, I was planning a long, technical evaluation of Facebook's failings.

But this is much funnier:

Compiling SBCL with Threads and Unicode

This is one of those note-to-self posts. For whatever reason, I nearly always forget to enable threads and unicode when I build SBCL. Threads are required by hunchentoot; I enable Unicode just for kicks.

Here's my build recipe for SBCL:

  1. > git clone git://sbcl.boinkor.net/sbcl.git sbcl-git ./sbcl.git
  2. > cd sbcl.git
  3. > git checkout sbcl_1_0_18
  4. Edit customize-target-features.lisp to enable the features you want.
     (lambda (features)
       (flet ((enable (x)
                (pushnew x features))
              (disable (x)
                (setf features (remove x features))))
         ;; Threading support, available only on x86/x86-64 Linux, x86 Solaris
         ;; and x86 Mac OS X (experimental).
         (enable :sb-thread)
         (enable :sb-unicode)))
    
  5. > screen
  6. > sh make.sh
  7. detach screen from terminal while compiling -- too much output! Ctrl-a, d
  8. > sudo INSTALL_ROOT=/opt/sbcl sh install.sh

Defining Recursion Algorithmically

This is too much text to twitter, so it finds a home on my blog. From Andrew Plotkin via Wikipedia:

"If you already know what recursion is, just remember the answer. Otherwise, find someone who is standing closer to Douglas Hofstadter than you are; then ask him or her what recursion is."

Lisp Advocacy at its Best

Kenny says, Go Write Something in Lisp!

Technorati tags for this post:

Xrandr solved my linux docking station woes

I had to switch from the proprietary nvidia drivers to the vanilla 'nv' driver, but that enabled xrandr and now I can take my T61 (running Ubuntu Hardy) on and off my docking station -- without restarting X!

Technorati tags for this post:

OSS wifi (finally) on on my T61

From dmesg on my new(ish) Lenovo T61 running Ubuntu Hardy Heron:

iwl4965: Intel(R) Wireless WiFi Link 4965AGN driver for Linux, 1.2.26k
iwl4965: Copyright(c) 2003-2008 Intel Corporation
iwl4965: Detected Intel Wireless WiFi Link 4965AGN
iwl4965: Tunable channels: 11 802.11bg, 13 802.11a channels

I finally got the OSS driver for my wifi card to work - thanks to the Linux Wireless project. Version 1.2.0 of iwl4965, included with Hardy Heron, didn't work for me - neither did its predecessor that shipped with Gutsy. But version 1.2.6k is working fine. Joy! - no more ndiswrapper for me. <grin />

Boston Lisp Meeting

The inaugural Boston Lisp meeting was well attended. Lisp is not dead language - at least not in Cambridge and within sight of the MIT campus. I'm a relatively new lisper (thanks Peter for the excellent introduction) and it was fun to talk with people who code full time in common lisp.

Technorati tags for this post:

Git Backstage, Under the Covers and on the Down Low

Don't tell my employer, but I'm an undercover git user. Officially, my company uses Clearcase UCM - but I do almost all my coding outside Clearcase. I use git behind the official version control system. I'll tell you why I risk a scolding from my boss1 and the IT department for using an unsanctioned tool. But to do that, I'll have to tell you a bit more about both Clearcase2 and git.

Clearcase Basics

Clearcase is a centrally managed, client-server type system -- a big server hosts the repository which tracks all the project's info: individual files, the directory tree, versions, branches, users, permissions, Social Security numbers, DNA sequences, etc. The client (that's you) gets a working copy of the project files and tools to interact with the server. Checking out, checking in and viewing history all require connecting to the server. You can't do a thing without being tethered to the central repository.

In the Clearcase UCM development model, programmers create new "streams" ("branches" in generic terms), each having an "activity" (which is Clearcase talk for "changeset"). When you checkin a file, it's recorded against an activity. Therefore, an activity is a set of checked-in files (and directory changes). Other developers on the project won't see your changes until you "deliver" (merge) your activity (changeset) to the parent stream (the main branch). End of vocabulary lesson.

Where Clearcase Falls Down

My biggest issue with the Clearcase model is that it inhibits both experimental and iterative programming. I assert the following:

  1. Experimental coding requires branching. Let's hope this isn't a controversial statement. The only arguments people make against branching are practical - their VCSs don't support it well. Or they don't support merging well. Clearly, if you had a VCS that could branch and merge well, you'd use it all the time.
  2. Clearcase discourages experimental branching as streams are centralized, limited and public. On my project, creating "unnecessary" experimental streams is discouraged as each stream incurs the maintenance penalty of using more resources on the server.
  3. Merging in Clearcase is also less than perfect. Instead of a patch-based approach, Clearcase restricts merges to streams that have a common baseline. And guess who has to create, maintain and recommend these baselines? You, the user. Want to merge between streams that have diverged - that don't share an exact baseline? Forget it: you have to go outside Clearcase to do it.
  4. Finally, Clearcase activities don't allow logical commits within an activity - a checkin is limited to just one file. You cannot checkin 4 files as a group representing a logical change. This makes it hard to both organize your work and revert multi-file changes if they don't work out.

Let's see if git could help. (Ok, it can - or else why would I continue writing?)

Git Comes (Quietly) to the Rescue

Git is the distributed VCS used by Linus to maintain the Linux kernel. Where Clearcase requires a centralized server, git requires none -- the repository is stored in a single hidden directory at the top of your project's file tree. You can create a git repository from an existing project very easily:

cp -R /my/clearcase/project /my/git/project
cd /my/git/project
git init
git add .
git commit

A git repository is local and under your complete control, you don't need any anybody's permission to create one. And obviously you don't need network connectivity to a centralized server. You won't need to file a single TPS report to setup a git repository. And, if needed, you can keep your repo a secret.

What was I complaining about? Oh yes, branching and logical commits.

Branching is simple and lightweight in git. Let's say you're working in your 'bug_fix' branch, and you decide that the fix could be simplified by moving some methods from class Foo to class Bar. Here's how you'd create a new branch called 'foo_refactoring', make some changes in it, and then merge those changes back to the master branch:

cd /my/git/project
git checkout bug_fix
git checkout -b foo_refactoring
// make some changes to Foo and Bar, compile, and test
git add Foo.java Bar.java
git commit -m 'Refactored Foo'
git checkout bug_fix
git merge foo_refactoring

If you decided the refactoring was unnecessary, you could have skipped the merge -- or even permanently removed the experimental branch. The branch was created quickly -- just to try out some ideas -- and it can be ignored or removed. Branching is up to you, not the sysadmin.

Finally, git lets you build logical changesets. As you can see in the foo_refactoring example, a commit can contain any number of file changes. You can build a new feature piece-by-piece, committing chunks of related work together. This is good for both you and your reviewers!

So, how are you going to use git behind your VCS?

Getting it to Git

Getting your Clearcase (or CVS, Subversion, Perforce, etc) code into git is easy: copy your working dir to some local drive space and do the "git init; git add .; git commit" sequence.

Dealing with rebases is easy too. Other users have probably made changes to the codebase (in Clearcase) and you'll need to merge your work with theirs before merging to the main stream. You can handle this by rsyncing the upstream code into a git branch, then using git rebase to merge that code into your development branch - fixing any conflicts as necessary. Git rebase basically pops your current commits off your branch, merges with the requested branch, then re-applies your commits. It helps keep the history of your changes simple. I recommending doing all development work in a sub-branch off master (master is git's default branch) and keeping master for rebases. For example:

cd /my/clearcase/project
cleartool rebase -recommended // or 'cvs up' or whatever
cd /my/git/project
git checkout master
rsync -r /my/clearcase/project /my/git/project
git commit -a -m 'rebased from clearcase'
git checkout dev_branch
git rebase master

Getting it back to Clearcase

Git has made my daily coding much nicer - but if I want my code built into my product, I still have to get it back to Clearcase.

I find the simplest and safest way to do this is by applying a series of patches to the Clearcase controlled working dir. You can ask git to generate a patch for a single commit using git diff:

git diff 345983 > my-change.patch

But if you give git-diff a branch name instead of a commit, it will generate patch files for each diverging commit between the two branches. Assuming your master branch represents the rebased Clearcase branch and your dev branch has been 'git rebased' to master, this is exactly what you need!

cd /my/project/git
git checkout bug_fix
git diff master > bug_fix.patch
cd /my/clearcase/project
// checkout any files if necessary
patch -p2 < /my/git/project/bug_fix.patch

Build, test and submit in Clearcase - you're done!

Final Thoughts

Having a full understanding of your VCS's data model is essential to using a it correctly. Perhaps the root cause of why I prefer git over almost any other system is its simple conceptual model (Git for Computer Scientists does a nice job explaining the data model). Clearcase is typical enterprise software -- its feature sheet is very long and highlights words that CIOs love like "reliable", "maintainable", and "support contract", but the documentation is thrifty when discussing the systems internals. Version control is too essential and too difficult to trust to a system you don't understand. So I use git - behind the scenes if necessary.

Update (2008/8/5): As several commentators have noticed, if you can use Clearcase snapshot views instead of dynamic views, then you can directly init a git repo in the view storage directory. Then you can use git directly out of that directory or clone it. By creating the git repo directly in your snapshot view, you can substitute the rsync step with a "git pull" and the patch step with a "git push". This is a big win. Alas, my employer requires dynamic views due to tool limitations, so I didn't discuss this method in the original entry.


1 Hi Boss! What I'm discussing here is not really any less safe than having un-committed work in any working dir (which everybody does). But the threat of a knuckle slapping adds some drama to this post - don't you think? ;-)

2 Almost everything discussed in this post is true of any centralized version control system (CVS, Subversion, etc), not just Clearcase.

Technorati tags for this post:

« earlier :: later »