Avoiding postfix error “status=deferred (unable to look up host”

My emails wouldn’t send when I was working from home, giving me this message in /var/log/mail.log:

Nov 11 12:38:16 machinename postfix/smtp[20672]: CF5D6D41CE2: to=, relay=none, delay=14416, delays=14416/0.01/0.07/0, dsn=4.3.5, status=deferred (Host or domain name not found. Name service error for name=relay.example.com type=AAAA: Host not found)

It turned out I was telling postfix not to use DNS to resolve the domain name of my mail relay server. There were several postfix config options I needed to remove to make this work:

# Make sure all of these are commented out or removed!
#default_transport = smtp
#relay_transport = smtp
#inet_protocols = ipv4
#smtp_host_lookup = native

The default values for these options are fine, but the ones shown above stop it working, so remove them or comment out with a # at the beginning of the line.

More at Postfix configuration parameters.

Finding the download count of GitHub releases

You can use the GitHub API to find out how many times the files in your releases have been downloaded.

For example, to find out how many downloads there have been of my Rabbit Escape project you can do:

curl -s https://api.github.com/repos/andybalaam/rabbit-escape/releases | egrep '"name"|"download_count"'

Or you can look through the information manually by visiting a URL like https://api.github.com/repos/andybalaam/rabbit-escape/releases in your browser.

To get the total I came up with this beautiful incantation:

curl -s https://api.github.com/repos/andybalaam/rabbit-escape/releases | egrep 'download_count'  | cut '-d:' -f 2 | sed 's/,/+/' | xargs echo | xargs -I N echo N 0  | bc

Android: using a TextView to show rich text in an AlertDialog

If you want to display a link or basic formatting in an AlertDialog on Android, you can do it by providing HTML.

The key parts you need are Html.fromHtml and TextView.setMovementMethod.

Make sure you pass the dialog’s context in to the constructor of the TextView, not the context of the current activity. Otherwise the colours in your TextView will be wrong and you may well end up with black text on a dark grey background.

AlertDialog dialog = new AlertDialog.Builder( activity )
    .setTitle( t( world.name ) )
    .setPositiveButton( "Yes!" )
    .setNeutralButton( "Maybe?" )

TextView view = new TextView( dialog.getContext() );
view.setText( Html.fromHtml( "<b>foo</b> <a href='#'>bar</a>" ) );
view.setMovementMethod( LinkMovementMethod.getInstance() );
view.setPadding( 10, 10, 10, 10 );

dialog.setView( view );

If you are on API level 11+, you can use AlertDialog.Builder’s getContext() method, so you don’t have to create the dialog until the end.

Difficult merges in Git – don’t panic!

A video in which I try to explain what merging and rebasing really are, to help you understand what is going on when Git presents you with scary-looking conflict messages. I also explain why you shouldn’t panic because it’s hard to lose your work, and how to get you work back if you really mess up:

Slides here: Difficult Merges in Git.

A commit represents the state of the world (and the history leading up to that state). A commit is not a diff.

Merging means making a new commit with two (or more) “parents” (previous commits) that represents the result of merging the changes from two different threads of development that happened separately. None of the already-committed commits are modified – you just get a new commit on top. History is more complicated, but true.

Rebasing means modifying the history of one thread of development so it looks like it happened after the other one. This involves modifying all the commits in that thread. There is no extra merge commit, so you lose the history of the merge that happened. History is simple, but it’s a lie, and if you messed up the rebasing process, you can’t get back to where you were (once your old commits have been garbage-collected).