Wed Jun 25 19:19:20 IST 2008
Being too smart is annoying
I was on my machine and wanted to run a remote instance on Firefox, with the display forwarded back to my machine. I had X forwarding over SSH and my DISPLAY enviroment variable all set up. But when I started 'firefox' on the remote commandline, it opened up an instance of firefox *locally*. WTF!!?
The fix to this is a 'MOZ_NO_REMOTE' env variable. Duh.
Wed Mar 19 20:28:26 IST 2008
Widescreen monitors and modelines
FWIW, here's the modeline for the Acer AL1516W that I generated for the Eee :
"1280x800@59" 83.44 1280 1312 1624 1656 800 816 824 841
Tue Mar 11 12:06:42 IST 2008
LibTracker::Client
Update : The code is at a stage where it's usable. The git repository is at http://repo.or.cz/w/LibTracker-Client-Perl.git. You can also grab the latest snapshot. The code is a lot of XS and some Perl. You would need libtrackerclient (and headers), glib-2.0 (and headers) and dbus-glib-1 (and headers) along with the obvious things like Perl headers and a C compiler.
Sat Mar 8 19:47:35 IST 2008
Git-Bugzilla integration
There's always SCMBug, but you can cook your own Git-Bugzilla integration very easily. SCMBug's fine, but it's a lot of code if all you want is simple cross-linking between Git, Bugzilla and Trac (btw - GitPlugin for Trac would throw up an error unless you have at least *two* commits in your repository - talk about undocumented easter bugs!).
Anyhoo - here's what I want :
1. Git should disallow any commit where the commit message does not have a bug number.
2. Git should add a comment to the corresponding bug on a commit, mentioning the author, the Trac changeset link, the commit message and the list of files which changed.
And here's the code to do it. First, the post-receive hook :
#!/usr/bin/perl -w use strict; # A hook script which integrates with bugzilla. It looks for bug IDs in # commit messages and adds the commit message as well as a link to the # changeset as a comment on the bug. # This program is released under the terms of the GNU General Public License # version 2. A copy of the license may be obtained by emailing the author, # or at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt # # The absolute lack of warranty and other disclaimers as per the license # apply. # # Copyright 2008, Devendra Gera. All rights reserved. # # Author : Devendra Gera### user configurable section # The bugzilla has contains the server, username and password for the targeted # bugzilla installation. There's NO 'http://' in the server line. my $bugzilla = { server => "10.147.251.90/bugzilla", user => "demonuser", password => "daemonuserspassword", }; # __PATH__ and __REVISION__ are replaced in $browser->{changeset} and # $browser->{revision} to get the changeset and revision URLs respectively. my $browser = { changeset => "http://10.147.251.90/projname/changeset/__REVISION__", revision => "http://10.147.251.90/projname/browser/__PATH__?rev=__REVISION__", }; # The bug_regex should extract the bug id from the commit message and place # it in $1 my $bug_regex = 'bug #(\d+)'; ##### End user configurable section use WWW::Bugzilla; my $input = <>; chomp $input; my ($oldrev, $newrev, $refname) = split /\s+/, $input; my $commit_msg = `git-whatchanged $oldrev..$newrev`; # prepare the changeset URL my $changeset_url = $browser->{ changeset }; $changeset_url =~ s/__REVISION__/$newrev/g; # author my ($author) = ( $commit_msg =~ /^Author:\s+(.*)$/m ); # files my @filelist = grep ( /^:/, split( /\n/, $commit_msg ) ); # prepare comment $commit_msg =~ s/^.*?Date://s; # eat everything till the Date: heder $commit_msg =~ s/^.*?\n//m; # eat the date line completely $commit_msg =~ s/^:.*?$//mg; # eat the file list from the msg. chomp $commit_msg; my ($bug_number) = ( $commit_msg =~ /$bug_regex/ ); my $comment = <<END_COMMENT; ------------------------------------ changeset $newrev [ $changeset_url ] by $author : $commit_msg ------------------------------------ Files changed : END_COMMENT $comment .= join("", @filelist) . "\n"; my $bz = WWW::Bugzilla->new( server => $bugzilla->{ server }, email => $bugzilla->{ user }, password => $bugzilla->{ password }, bug_number => $bug_number ); die "cannot connect to bugzilla" unless defined $bz; $bz->additional_comments( $comment ); $bz->commit;
And here's the update hook :
#!/usr/bin/perl -w
use strict;
my $refname = shift;
my $oldrev = shift;
my $newrev = shift;
my $commit_msg = `git-whatchanged $oldrev..$newrev`;
# check if the commit message contains a bug number
if($commit_msg !~ /bug #\d+/) {
exit -1;
}
exit 0;
The TODO :
1. Push every configurable thing to git's config file and access it via git-config.
2. Code cleanups. One definition of the bug regex (which is hardcoded in the update for now).
edit : the here doc in the code was causing a problem with formatting, eating up some of the code. Fixed now.
Sat Mar 8 18:45:35 IST 2008
WWW::Bugzilla fix
The problem is that WWW::Mechanize selects the first form on a page by default, and WWW::Bugzilla fails in WWW::Mechanize while setting any field to be updated (with a 'no such field' or 'no field called comment' etc. messages). On my Bugzilla install, there's a small bug search form in the header which makes that happen.
The fix is a single line and has been emailed to the author. Here it is :
@@ -614,6 +614,7 @@
my $mech = $self->{mech};
if ($self->{bug_number}) {
+ $mech->form_name( "changeform" );
foreach my $field ( keys %update_field_map ) {
$mech->field( $update_field_map{$field}, $self->{$field} ) if defined($self->{$field});
# handle special cases
Tue Mar 4 22:03:31 IST 2008
Network profiles in Ubuntu
There are various ways of managing multiple network profiles in Ubuntu, but I've never been a fan of NetworkManager. Commandlines work for me very well, and even there - multiple solutions exist with the help of packages like resolvconf etc. Here's my setup which is very Debian-ish and depends on this nice package called ifupdown.
First, there's the /etc/network/interfaces file :
# we always want the loopback auto lo iface lo inet loopback # mappings mapping eth0 script /etc/network/map-scheme map dhcp eth0-dhcp map emergency eth0-emergency mapping ath0 script /etc/network/map-scheme map office ath0-office map home ath0-home iface eth0-dhcp inet dhcp up iptables -F up lokkit -n -q --high --dhcp up /etc/init.d/lokkit restart iface ath0-office inet dhcp wpa-driver madwifi wpa-conf /etc/wpa_supplicant/office.conf up iptables -F up lokkit -n -q --high --dhcp up /etc/init.d/lokkit restart iface eth0-emergency inet static address 10.9.5.201 gateway 10.9.4.1 netmask 255.255.254.0 up iptables -F up lokkit -q --high up echo nameserver 172.31.6.5 > /etc/resolv.conf up echo nameserver 203.197.12.30 >> /etc/resolv.conf iface ath0-home inet dhcp wpa-driver madwifi wpa-conf /etc/wpa_supplicant/home.conf up iptables -F up lokkit -n -q --high --dhcp up /etc/init.d/lokkit restart
Notice the mappings section (and see 'man interfaces') - that allows me to say :
NETSCHEME="home" sudo ifup ath0
or
NETSCHEME="office" sudo ifup ath0
because the specified script (/etc/network/map-scheme) just looks up the NETSCHEME environment variable and spit out the correct mapping to go to. This thing, by the way, could be rigged to do arbitrarily complex tasks (look in /usr/share/doc/ifupdown/examples/ for sample scripts, including one which tries to ping some known IPs, and decides its location/profile based on successful pings - you could write one which looks for all known wireless SSIDs and then decide which profile to switch to). Here's my trivial script :
#!/usr/bin/perl -w
use strict;
my $scheme = $ENV{NETSCHEME} || "home";
while(<>) {
if ( s/$scheme\s+// ) {
print;
}
}
The conf files in /etc/wpa_supplicant/* are of course wpa_supplicant configuration files. See 'man wpa_supplicant.conf' for details.
Tue Mar 4 21:39:33 IST 2008
Break
Wed Feb 6 23:29:09 IST 2008
Eee PC!
One fallout is that I can't suspend - the SD card is a USB device and gets reset on suspend/resume. Also, the /var/log, /var/run, /var/tmp and /tmp are tmpfs filesystems. /var/cache/apt/ is a bind mount from the SD card to save the SSD from excessive writes.
Processing RAW images from my camera was a problem till I swapped the RAM with one of the modules from my Vostro 1400. GIMP works pretty smoothly now.
Tue Jan 29 17:00:44 IST 2008
Date::Manip, remind and remindme
I use remind(short howto) to keep my calendar of events and reminders. Its a wonderful utility - and all commandline. I split up the birthdays, anniversaries, personally important days, and the usual stuff into different files, and include them in my ~/.reminders file. Here's what my .reminders looks like :
gera@gera-laptop:~$ cat .reminders include /home/gera/reminders/birthdays include /home/gera/reminders/anniversaries include /home/gera/reminders/impdates include /home/gera/reminders/stuff
All this works well, except for a small issue. It takes too much time for me to add reminders for my day-to-day tasks. Firing up an editor and typing all that remind syntax is something that can be avoided. Also, it really hurts to look at the calendar to figure out fuzzy dates like "tomorrow", or "sat". I was planning to write this big Perl script which would do the heavy lifting for me. Instead, I found Date::Manip which already does the heavy lifting. It understands stuff like "tomorrow" and "sun". I just needed a small 'remindme' script then :
#!/usr/bin/perl -w
use strict;
use Date::Manip;
use Fcntl qw(:flock);
my $reminders = "$ENV{HOME}/reminders/stuff";
my $argstring = join (" ", @ARGV);
my ($when, $what);
(undef, $when, $what) = ($argstring =~ /^(on |)(.*?) to (.*)$/);
quit("what?") unless $what;
quit("when?") unless $when;
# form the line to be appended
my $date = ParseDate($when);
quit("cannot parse date") unless $date;
my $line = UnixDate($date, "REM %b %e %Y +1 MSG");
$line .= " $what %b.%\n";
# write in file
# open lock file
open LOCK, ">$reminders.lock" or quit("cannot open $reminders.lock : $!");
flock LOCK, LOCK_EX or quit("cannot obtain lock : $!");
# open data file, write and close data file
open REMINDERS, ">>$reminders" or quit("cannot open $reminders : $!");
print REMINDERS $line;
close REMINDERS;
# release locks
flock LOCK, LOCK_UN;
close LOCK;
exit (0);
sub quit
{
my $msg = shift;
print STDERR $msg, "\n";
exit (-1);
}
Now, I can use it like this :
$ remindme on sat to eat everything I can $ remindme tomorrow to pay the phone bill $ remindme next week to think up of something useful to say $ remindme next thursday to find something better to do
nifty, eh?
update: bugfixed the script. An extra space creeped up between the '+' and the '1'. Thanks to AmitU for pointing that out.
update 2: added the capability to get reminded n days in advance - a feature suggested by AmitU in the comments, but with a different syntax ("remindme next week to do this for 2 days"). Also, remindme's git repository and home page. The repository contains the bash-completion script as well.
Mon Jan 28 15:17:57 IST 2008
Commandline GTD with gtdo
But I stopped doing it.
Because I had nothing to manage my "projects" (tasks with multiple action items). I maintained a list of projects out-of-band, as a directory structure, which required me to identify the next task for a project and move it to my todo list. Of course it didn't work!
So I wrote gtdo. gtdo has a similar interface - todo.py was the inspiration - but in addition to the contexts (marked by a '@'), it supports groups (or "projects" - marked by a '/'). So, you might have a project about starting using GNUcash. Of course, the first step is to install/set-up GNUcash. Adding your portfolio comes later. If you have both these items in your todo list, the second one does nothing but adds noise and makes the list longer. The answer is to add them in a group /gnucash. If there are multiple tasks in a group, only the first one is displayed - till its marked done. By default, new tasks are added at the end of the queue in a group, but may be added at a specific position.
An example would be better than the ramble above (gtdo being aliased to 't'):
$ t add /gnucash @online install gnucash $ t add /frames @errands buy wood $ t add /email @online set up spamassassin $ t add /gnucash @online add portfolio to gnucashComes with standard todo.sh style bash-completion. The Git repository is available at http://repo.or.cz/w/gtdo.git. You can obtain a tarball by clicking here.
# only the immediate next task is displayed when you 'ls' $ t ls 1 : /gnucash @online install gnucash 2 : /frames @errands buy wood 3 : /email @online set up spamassassin
$ t ls @online 1 : /gnucash @online install gnucash 3 : /email @online set up spamassassin
# except when you specifically ask for a group $ t ls /gnucash 1 : /gnucash @online install gnucash 4 : /gnucash @online add portfolio to gnucash
# well, we need to fix F::Q::IndiaMutual before we add our portfolio # we'll try adding that as the second step in the /gnucash group $ t add /gnucash.2 fix F::Q::IndiaMutual
$ t ls /gnucash 1 : /gnucash @online install gnucash 4 : /gnucash fix F::Q::IndiaMutual 5 : /gnucash @online add portfolio to gnucash