29 Nov 2013

Extending git a little bit: patch-set

A while back, Peter Hutterer posted to his blog about some git extensions he had written to make the patch submission processes somewhat easier using a git workflow. Instead of using
$ git format-patch <...>
to create a set of patches, he wrote a new script which is invoked as
$ git patch-set <...>
Each invocation creates a new patches/patches-<date>-<revlist> directory under a project's top-level directory and stores the set of patches there as one group. As a convenience, it also creates a <top>/patches/latest link to point to the location of the set of patches produced by the most recent git patch-set invocation.

Why would you ever need something like this? If you're working with a set of patches and some of them need to be re-worked, it can become confusing to remember which set of all the xxxx-your-change.patch files in your current directory need to be sent with git send-email. Using this tool helps keep each group of patches you generate separate from each other so when it comes time to send your patches upstream, you only need to run:

$ git send-email patches/latest/*patch
I decided to give Peter's extension a try today and found it quite nice.

As I was exploring his git extensions I also stumbled upon git-extras which is quite nice too, and a little more polished.

While using Peter's git patch-set, it seems obvious to me that he uses a specific set of options to git format-patch which, I assume, are what he needs to use when submitting patches to the projects on which he works. Unfortunately I need to use a different set of options. So instead of hard-coding the set I want for my needs, I decided to fork his repository and update his git-patch-set script to be more generic. My changes assume the last argument in the git patch-set <...> command is the rev-list, but that all other options are to be passed to the internal call to git format-patch without assuming any defaults. So now I can use the following command to get my patches made the way I need:
$ git patch-set -M --subject-prefix="component][PATCH" \ --cover-letter master..mywork

I also added a Makefile in order to make it easier to install into one's system.

11 Nov 2013

Rebinding Bash Readline C-w

For the past couple months I have been forcing myself to learn and (most importantly) use more bash/readline shortcuts. Since I am more accustomed to vi than to emacs, I've been using vi input mode.

For example, say I'm typing a very long command and just about at the end of typing said command I realize that this command won't work just yet, I have to do something else before issuing the current command. Up until this point I would normally solve this problem by:
  1. holding Backspace for a couple seconds to delete the current, long command
  2. typing and issuing the new command
  3. typing in the long command all over again
Using bash/readline vi shortcuts this sequence can be improved to:
  1. hitting Esc to get out of input mode
  2. entering # to comment out but run the current command (although this appears to do nothing, it actually does put it into the history)
  3. typing and issuing the new command
  4. hitting Esc 
  5. pressing k (to go "up" in the history) twice
  6. hitting x to delete the initial # 
  7. then Enter to run the already-typed long command
Although the second sequence appears longer and more complicated, it does save a lot of typing and is actually faster and simpler (once you get the hang of it).

The one thing that has been rather annoying is the C-w binding.

While typing (i.e. in input mode) you can press C-u (for example) to delete everything on the current line you've typed in so far. Or you can use C-w to just delete the last "word". The reason I put "word" in quotes is because different commands use different definitions for word boundaries. If I'm typing in a path (e.g. /usr/local/bin/cmd), does the last path element count as a word, or the entire path? Or if I'm typing in a bunch of words separated by dashes (e.g. core-image-minimal) should C-w delete the entire phrase, or just back to the last dash?

As it turns out, by default C-w only considers "words" to be separated by whitespace. But more often I would prefer that punctuation be included too.

Thankfully the distinction between using whitespace-delimited words and punctuation-delimited words has already been considered. By default C-w is linked to the unix-word-rubout command (which only considers whitespace), but what I really want is for it to be linked to the backward-word-kill command (which also considers punctuation).

Following the advice here I simply edited my .bashrc to add:

stty werase undef
bind '"\C-w":backward-kill-word'

and now C-w will erase backwards to either the most recent whitespace or the most recent punctuation.

Note: I found that using

$ bind -P

was helpful to see which commands are currently linked to which control sequences.