<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lukáš Lalinský &#187; Tools</title>
	<atom:link href="http://oxygene.sk/lukas/category/tools/feed/" rel="self" type="application/rss+xml" />
	<link>http://oxygene.sk/lukas</link>
	<description>Random notes and stuff</description>
	<lastBuildDate>Thu, 02 Feb 2012 20:17:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Goodbye Launchpad</title>
		<link>http://oxygene.sk/lukas/2011/04/goodbye-launchpad/</link>
		<comments>http://oxygene.sk/lukas/2011/04/goodbye-launchpad/#comments</comments>
		<pubDate>Sat, 23 Apr 2011 09:13:22 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[acoustid]]></category>
		<category><![CDATA[bzr]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[launchpad]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=1396</guid>
		<description><![CDATA[All Acoustid components are now migrated to GitHub: Chromaprint Acoustid Fingerprinter Acoustid Server Acoustid Index Chromaprint plug-in for GStreamer Even though I still prefer the idea of Bazaar, the tools built around Git and especially GitHub make it worth switching &#8230; <a href="http://oxygene.sk/lukas/2011/04/goodbye-launchpad/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>All Acoustid components are now migrated to GitHub:</p>
<ul>
<li><a href="https://github.com/lalinsky/chromaprint">Chromaprint</a></li>
<li><a href="https://github.com/lalinsky/acoustid-fingerprinter">Acoustid Fingerprinter</a></li>
<li><a href="https://github.com/lalinsky/acoustid-server">Acoustid Server</a></li>
<li><a href="https://github.com/lalinsky/acoustid-index">Acoustid Index</a></li>
<li><a href="https://github.com/lalinsky/gst-chromaprint">Chromaprint plug-in for GStreamer</a></li>
</ul>
<p>Even though I <em>still</em> prefer the idea of Bazaar, the tools built around Git and especially GitHub make it worth switching for me. I started using Bazaar a long time ago because it was the only VCS that was able to work on Windows back then. I built several tools to make it more comfortable for me, but I get the feeling the situation is not improving. Maybe Git really is the VCS we should all use&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2011/04/goodbye-launchpad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making Fail2ban with IPFW firewall on FreeBSD work</title>
		<link>http://oxygene.sk/lukas/2011/04/making-fail2ban-with-ipfw-firewall-on-freebsd-work/</link>
		<comments>http://oxygene.sk/lukas/2011/04/making-fail2ban-with-ipfw-firewall-on-freebsd-work/#comments</comments>
		<pubDate>Sat, 23 Apr 2011 08:58:56 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[fail2ban]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[ipfw]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=1357</guid>
		<description><![CDATA[The internet is a nasty place, everybody is trying to hack into your servers if they are publicly accessible. Even though I always disable password authentication, so there is very little chance somebody could &#8220;guess&#8221; my private RSA key, I &#8230; <a href="http://oxygene.sk/lukas/2011/04/making-fail2ban-with-ipfw-firewall-on-freebsd-work/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The internet is a nasty place, everybody is trying to hack into your servers if they are publicly accessible. Even though I always disable password authentication, so there is very little chance somebody could &#8220;guess&#8221; my private RSA key, I don&#8217;t like <code>/var/log/auth.log</code> being spammed. <a href="http://www.fail2ban.org/wiki/index.php/Main_Page">Fail2ban</a> is a nice solution to that I use on Linux with iptables, but it was not working for me on FreeBSD with IPFW.</p>
<p>My firewall is configured to drop everything by default, so it needs to have rules with connections that it should be allowed. However, the default IPFW ban action looks like this:</p>
<pre>
actionban = ipfw add deny tcp from &lt;ip> to &lt;localhost> dst-port &lt;port>
</pre>
<p>This inserts the rule at the end of the rule list, just before the default rule. This doesn&#8217;t work for me, because it&#8217;s after my own rule rule that allows traffic on that port from any address, so the newly added rule has no effect. I ended up modifying the IPFW action configuration file (<code>$PREFIX/etc/fail2ban/action.d/ipfw.conf</code>) to dynamically generate rule numbers that are before my own rules:</p>
<pre>
actionban = USEDNUMS=`ipfw list | perl -pe 's/(\d{5}) .*\n/$1|/' | perl -pe 's/\|$//'`
            NUM=`jot -w '%%05d' - &lt;minnum> &lt;maxnum> | grep -vE "($USEDNUMS)" | head -n1`
            ipfw add $NUM deny tcp from &lt;ip> to &lt;localhost> dst-port &lt;port>
</pre>
<p>This only uses rule numbers between <code>&lt;minnum></code> and <code>&lt;maxnum></code>, selecting the first one that is available. I can set the variables in my <code>jails.conf</code> configuration like this:</p>
<pre>
[ssh-ipfw]

enabled  = true
filter   = sshd
action   = ipfw[localhost=any,minnum=01110,maxnum=01199]
logpath  = /var/log/auth.log
ignoreip = 168.192.0.1
</pre>
<p>The default unban action is also problematic. I was testing the above from a server that has some traffic on another port explicitly allowed. However, when canceling the SSH ban, Fail2ban deleted also my own rule because it was using only the IP for firewall rule matching. Changing it like this works for me, but it&#8217;s still not ideal:</p>
<pre>
actionunban = ipfw delete `ipfw list | grep -i 'deny tcp from <ip> to <localhost>' | awk '{print $1;}'`
</pre>
<p>Ideally I would like to check also the port numbers, but I can&#8217;t find an easy way to resolve the service name to a port number.</p>
<p>The final version of the IPFW Fail2ban action configuration file that I&#8217;m using is <a href="http://dl.dropbox.com/u/5215054/ipfw.conf">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2011/04/making-fail2ban-with-ipfw-firewall-on-freebsd-work/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>MusicBrainz database replication</title>
		<link>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/</link>
		<comments>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 09:06:17 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=833</guid>
		<description><![CDATA[I wanted to work on the Acoustid lookup web service and for this I needed to setup a MusicBrainz replicated database slave. Normally I&#8217;d use the Perl code from mb_server, but I didn&#8217;t want to mess up the setup I &#8230; <a href="http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wanted to work on the Acoustid lookup web service and for this I needed to setup a MusicBrainz replicated database slave. Normally I&#8217;d use the Perl code from mb_server, but I didn&#8217;t want to mess up the setup I have on the machine hosting <a href="http://acoustid.org/">acoustid.org</a> with CPAN packages. I had a plan to write a non-Perl version of the replicated code earlier, but only yesterday I really needed it. It turned out to be easier than I expected, so I already have a working version that I use to update my local MB database. <a href="https://github.com/lalinsky/mbslave">Get it from GitHub</a>, if you would like to give it a try.</p>
<p>It has scripts for importing the database dumps as well as applying replication packets, so it can be used creating a MB database from scratch as well as updating an existing one. Instructions for setting up a new database can be found in the <a href="https://github.com/lalinsky/mbslave/blob/master/README.txt">README</a> file.</p>
<p>There are a few differences between these scripts and <a href="http://bugs.musicbrainz.org/browser/mb_server/branches/RELEASE_20090524-BRANCH/admin">mb_server</a>:</p>
<ol>
<li>Depends only on Python and <a href="http://initd.org/psycopg/">psycopg2</a>. Should be easy to set it up on non-Linux platforms, but I&#8217;ve not tested that.</li>
<li>Doesn&#8217;t require additional space for extracting the database dump tarballs. It decompresses and imports the files on-the-fly.</li>
<li>Can be configured to import the MB database into any schema, not just &#8220;public&#8221;.</li>
<li>Can be configured to not replicate specific tables (e.g. direct search indexes, PUIDs).</li>
<li>Regrouped transactions. The MB replication packet consists of multiple transactions (each of which has multiple database operations). The original replication code in mb_server imports the transactions exactly as they were executed in the master database. My code applies the whole packet in a single transaction. This is a small disadvantage, but from an external point of view (external scripts, triggers), there is no practical difference.</li>
<li>New code, possibly buggy.</li>
</ol>
<p>The code currently assumes that you know how to setup the MusicBrainz database, so it doesn&#8217;t do many checks. It it turns out it&#8217;s useful also to somebody else, I can make it more robust.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Custom file associations on GNOME</title>
		<link>http://oxygene.sk/lukas/2010/09/custom-file-associations-on-gnome/</link>
		<comments>http://oxygene.sk/lukas/2010/09/custom-file-associations-on-gnome/#comments</comments>
		<pubDate>Sun, 26 Sep 2010 15:21:13 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[emusic]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=668</guid>
		<description><![CDATA[It seems that there is no GUI method settings associations for custom files in GNOME. I&#8217;ve had this problem before with dbmodel before. It writes save its data in XML files that end with the extension &#8220;.dmf&#8221;. The problem is &#8230; <a href="http://oxygene.sk/lukas/2010/09/custom-file-associations-on-gnome/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It seems that there is no GUI method settings associations for custom files in GNOME. I&#8217;ve had this problem before with <a href="oxygene.sk/lukas/dbmodel/">dbmodel</a> before. It writes save its data in XML files that end with the extension &#8220;.dmf&#8221;. The problem is that GNOME&#8217;s file associations work with MIME types and by default GNOME doesn&#8217;t know anything about these silly .dmf files, it only sees XML files, so if I want to automatically open .dmf files with dbmodel, I can either set it for all XML files or for nothing. I eventually gave up on trying to do this, but since I started to use eMusic and switched to Chrome, it become much more annoying.</p>
<p>The problem is that eMusic download files are also XML files, so I can&#8217;t set the association just for &#8220;.emx&#8221; files. Another problem is that to open the files from Chrome, I can only use the default GNOME association. I can&#8217;t use any other application without going to Nautilus and looking up the executable. The correct way to fix this seems to be to <a href="http://library.gnome.org/devel/integration-guide/stable/mime.html.en">add a new MIME type</a>:</p>
<pre>mkdir -p ~/.local/share/mime/packages
vim ~/.local/share/mime/packages/emusic.xml
update-mime-database ~/.local/share/mime/</pre>
<p>Where the <code>emusic.xml</code> file contains the following:</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
    &lt;mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"&gt;
        &lt;mime-type type="application/x-emusic"&gt;
        &lt;comment&gt;eMusic Download File&lt;/comment&gt;
        &lt;glob pattern="*.emx"/&gt;
    &lt;/mime-type&gt;
&lt;/mime-info&gt;
</pre>
<p>After running the commands, Nautilus identifies the .emx files as eMusic Download Files, so I can set to open them in the eMusic Download Manager, without touching the configuration for generic XML files.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/09/custom-file-associations-on-gnome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-compiling with CMake and Autotools</title>
		<link>http://oxygene.sk/lukas/2010/09/cross-compiling-with-cmake-and-autotools/</link>
		<comments>http://oxygene.sk/lukas/2010/09/cross-compiling-with-cmake-and-autotools/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 11:24:09 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[autotools]]></category>
		<category><![CDATA[cmake]]></category>
		<category><![CDATA[cross-compile]]></category>
		<category><![CDATA[mingw]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=657</guid>
		<description><![CDATA[The last time I needed to build a Windows binary, I found it easier to cross-compile it from Linux than to setup a development environment on a freshly installed Windows machine. The problem is that even though it&#8217;s not hard, &#8230; <a href="http://oxygene.sk/lukas/2010/09/cross-compiling-with-cmake-and-autotools/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://oxygene.sk/lukas/2010/07/introducing-chromaprint/">The last time</a> I needed to build a Windows binary, I found it easier to cross-compile it from Linux than to setup a development environment on a freshly installed Windows machine. The problem is that even though it&#8217;s not hard, you need to remember some obscure options. Today I needed to build a <a href="http://forums.musicbrainz.org/viewtopic.php?pid=11111#p11111">new version of ISRCsubmit</a> and I had to search for the recipe again. So, let&#8217;s document it somewhere I can find it in the future&#8230;</p>
<p>First, you need the <code>mingw32</code> package, which contains the compiler toolkit plus all the required WinAPI libraries. For cross-compiling CMake projects, you also need a file with paths to the MinGW toolkit:</p>
<pre>
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_C_COMPILER i586-mingw32msvc-gcc)
set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++)
set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc /home/lukas/projects/win32build)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
</pre>
<p>I have a special directory for installing compiled binaries, which makes it easier to use previously compiled libraries, so that&#8217;s included in the file. To compile a Windows version of <a href="http://musicbrainz.org/doc/libmusicbrainz">libmusicbrainz</a>, which uses CMake, you can use a serie of command like this:</p>
<pre>
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/home/lukas/projects/mingw.cmake -DCMAKE_INSTALL_PREFIX=/home/lukas/projects/win32build/
make
make install
</pre>
<p>To build libmusicbrainz I also needed <a href="http://www.webdav.org/neon/">neon</a>, which uses autotools. Fortunately, cross-compiling autotools projects is usually also quite simple, but neon doesn&#8217;t support MinGW out of the box, so <a href="https://build.opensuse.org/package/view_file?file=neon-0.29.1-mingw.patch&#038;package=mingw32-libneon&#038;project=windows:mingw:win32&#038;srcmd5=eb762d7b7894e4ebd1cda4f69a6b5c60">one patch</a> is necessary. After applying the patch, it can be compiled like this:</p>
<pre>
./configure --host=i586-mingw32msvc --disable-debug --disable-webdav --prefix=/home/lukas/projects/win32build/
make
make install
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/09/cross-compiling-with-cmake-and-autotools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Submit tags from Quod Libet to MusicBrainz</title>
		<link>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/</link>
		<comments>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 13:58:15 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[quod libet]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=514</guid>
		<description><![CDATA[I wanted to write something like this for a long time, but for some reason never did it. MusicBrainz has support for folksonomy tagging since 2007, but the coverage of track tags is still not very good. I try to &#8230; <a href="http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wanted to write something like this for a long time, but for some reason never did it. MusicBrainz has support for folksonomy tagging since 2007, but the coverage of track tags is still not very good. I try to keep some tags in the &#8220;genre&#8221; tag in audio files, but even with one-time import tool, I&#8217;m sure I&#8217;d not remember to run this on new files. So the idea here is to submit these tags to MusicBrainz as I listen to the files in my music player (<a href="http://code.google.com/p/quodlibet/">Quod Libet</a>). It&#8217;s inspired by a Quod Libet plugin called <a href="http://code.google.com/p/thisfred-quodlibet-plugins/">LastFMTagger</a>, which does something similar, but for Last.fm. I had some free time today, so I wrote a <a href="http://dl.dropbox.com/u/5215054/mbtagsubmit.py">plugin</a> that does one-way synchronization of tags from Quod Libet to MusicBrainz. You can install the plugin using the following commands:</p>
<pre>
mkdir -p ~/.quodlibet/plugins/events/
cd ~/.quodlibet/plugins/events/
wget http://dl.dropbox.com/u/5215054/mbtagsubmit.py
</pre>
<p>After you enable it and let it know your MusicBrainz username and password (Music → Plugins), it will watch the songs you listen and if any of them has a &#8220;musicbrainz_trackid&#8221; and at least one &#8220;genre&#8221; tag, it will use the MusicBrainz web service to submit them. The submission normally happens only every half an hour, but if you change many files in a short time, it will submit them in batches of 20 tracks (the maximum number allowed by the web service) every 2 minutes.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tomboy&#8217;s &#8220;Start Here&#8221; note</title>
		<link>http://oxygene.sk/lukas/2010/05/tomboys-start-here-note/</link>
		<comments>http://oxygene.sk/lukas/2010/05/tomboys-start-here-note/#comments</comments>
		<pubDate>Sun, 02 May 2010 19:13:27 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[dropbox]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[tomboy]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=486</guid>
		<description><![CDATA[I use Dropbox to synchronize my Tomboy notes. This works very well, but there is a problem when setting it up on a new computer. Tomboy has a special &#8220;Start Here&#8221; note, which is used mainly for organizing other notes. &#8230; <a href="http://oxygene.sk/lukas/2010/05/tomboys-start-here-note/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://www.dropbox.com/">Dropbox</a> to synchronize my <a href="http://projects.gnome.org/tomboy/">Tomboy</a> notes. This works very well, but there is a problem when setting it up on a new computer. Tomboy has a special &#8220;Start Here&#8221; note, which is used mainly for organizing other notes. When I tell it to synchronize notes from the Dropbox directory and overwrite the existing default notes, it will do so, but it doesn&#8217;t change it&#8217;s &#8220;Start Here&#8221; note pointer. As as result, Tomboy is not aware that my new Start Here note is the one it should use. As far as I know, there is no way fix this using Tomboy itself. It can be done only using GConf. Here is an example how to do it from the command line:</p>
<pre>$ grep 'Start Here' -R ~/.local/share/tomboy/ -l
/home/lukas/.local/share/tomboy/Backup/4a47410a-4976-4cb6-8ddc-fd744710dba7.note
/home/lukas/.local/share/tomboy/<b>7d41fff6-6cae-44bc-87b9-6486c809e7ee</b>.note
$ gconftool-2 --set /apps/tomboy/start_note --type string 'note://tomboy/7d41fff6-6cae-44bc-87b9-6486c809e7ee'
</pre>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/05/tomboys-start-here-note/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8220;Punchcard&#8221; graphs for Bazaar</title>
		<link>http://oxygene.sk/lukas/2010/03/punchcard-graphs-for-bazaar/</link>
		<comments>http://oxygene.sk/lukas/2010/03/punchcard-graphs-for-bazaar/#comments</comments>
		<pubDate>Sat, 13 Mar 2010 14:23:26 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[bzr]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[picard]]></category>
		<category><![CDATA[qbzr]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=421</guid>
		<description><![CDATA[GitHub has a nice feature called &#8220;Punchcard&#8221;. It&#8217;s a graph that represents numbers of commits by day and hour (example). You can easily see wherether a project was hacked over weekends or nights, if it&#8217;s done by full-time employees, etc. &#8230; <a href="http://oxygene.sk/lukas/2010/03/punchcard-graphs-for-bazaar/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>GitHub has a nice feature called &#8220;Punchcard&#8221;. It&#8217;s a graph that represents numbers of commits by day and hour (<a href="http://github.com/lalinsky/musicbrainz-server/graphs/punch_card">example</a>). You can easily see wherether a project was hacked over weekends or nights, if it&#8217;s done by full-time employees, etc. There are two problems though:</p>
<ol>
<li>It ignores timezones. All timestamps are treated as if they were somewhere in the US. For projects where committers live across the world (most open source projects) it&#8217;s therefore almost useless.</li>
<li>It only works for GitHub projects, obviously.</li>
</ol>
<p>I&#8217;ve put together a little Bazaar plugin that can generate similar graphs for Bazaar branches. You can get the plugin <a href="http://bzr.oxygene.sk/bzr-plugins/punchcard">here</a>. It requires PyQt for image drawing, but many Bazaar users should already have PyQt installed. Once you install the plugin, you can generate a &#8220;Punchcard&#8221; by running a command like this in a branch directory:</p>
<pre>bzr punchcard project-punchcard.png
</pre>
<p>For example, for <a href="http://wiki.bazaar.canonical.com/QBzr">QBzr</a> you will get this graph:<br />
<a href="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-qbzr-2010-03-13.png"><img title="punchcard-qbzr-2010-03-13"  class="aligncenter size-full wp-image-443" src="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-qbzr-2010-03-13.png" alt="" width="600" /></a></p>
<p>You can see that the project is done by people who obviously have too much free time. There is activity pretty much any time. I guess only on weekend nights, people are tired and enjoy some sleep. :)</p>
<p>On the other hand, <a href="http://musicbrainz.org/doc/PicardTagger">Picard</a> was hacked by people with good sleep patterns over evenings and weekends:<br />
<a href="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-picard-2010-03-13.png"><img src="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-picard-2010-03-13.png" alt="" title="punchcard-picard-2010-03-13" width="600" class="aligncenter size-full wp-image-443" /></a></p>
<p><a href="http://musicbrainz.org/">MusicBrainz Server</a> is in a similar situation, minus the good sleep patterns:</p>
<p><a href="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-mbserver-2010-03-13.png"><img src="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-mbserver-2010-03-13.png" alt="" title="punchcard-mbserver-2010-03-13" width="600" class="aligncenter size-full wp-image-448" /></a></p>
<p>The last example is <a href="http://bazaar.canonical.com/en/">Bazaar</a>. It&#8217;s mostly written by full-time employees and it shows:<br />
<a href="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-bzr-2010-03-13.png"><img src="http://oxygene.sk/lukas/blog/wp-content/uploads/punchcard-bzr-2010-03-13.png" alt="" title="punchcard-bzr-2010-03-13" width="600" class="aligncenter size-full wp-image-454" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/03/punchcard-graphs-for-bazaar/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mercurial, part 1</title>
		<link>http://oxygene.sk/lukas/2010/01/mercurial-part-1/</link>
		<comments>http://oxygene.sk/lukas/2010/01/mercurial-part-1/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 08:00:38 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[fail]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=283</guid>
		<description><![CDATA[I&#8217;ve been using Mercurial at work for two months now and the expectations I had about it didn&#8217;t change to anything better. I guess it looks cool for people who are used to SVN, or even CVS, and are not &#8230; <a href="http://oxygene.sk/lukas/2010/01/mercurial-part-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using Mercurial at work for two months now and the expectations I had about it didn&#8217;t change to anything better. I guess it looks cool for people who are used to SVN, or even CVS, and are not familiar with other DVCS. I must say that as a Bazaar user, I miss a lot of things. There are some that can be worked around, for something you just have to be extra careful and for something you are out of luck. I really don&#8217;t get how people use Mercurial for managing large projects.</p>
<h3>Cheap Branches</h3>
<p>One of the main reason people use DVCS is cheap branching. The most surprising thing for me was that Mercurial doesn&#8217;t offer many choices. It doesn&#8217;t have the concept of branches, like Bazaar or Git. All you have is an immutable repository that can contain multiple head revisions. By default, you are expected to clone the whole repository. As <a href="http://oxygene.sk/lukas/2009/10/working-with-branches-in-bazaar/">I mentioned earlier</a>, I tend to work with many feature branches, so I prefer to have just one working tree.</p>
<p>One way to partially solve this problem is the <a href="http://mercurial.selenic.com/wiki/BookmarksExtension">bookmarks extension</a>. It basically allows you to have dynamic tags that move to new revisions as you commit. The initial configuration looks like this:</p>
<pre>[extensions]
bookmarks =
[bookmarks]
track.current = True</pre>
<p>The next step is to go to your clone and set the main/trunk/master/etc. bookmark:</p>
<pre>hg bookmark main</pre>
<p>This is necessary, so that you easily know which revisions represents the project&#8217;s &#8220;mainline&#8221;. With the configuration I mentioned, the extension will track your current bookmark and update only that one. To set the current bookmark, you can use update:</p>
<pre>hg up -r main</pre>
<p>It&#8217;s important to always have the current bookmark set to <em>main</em> whenever you are fetching changes from the mainline. Otherwise you will have to manually fix the bookmark&#8217;s revision.</p>
<p>Creating new &#8220;feature branches&#8221; is easy then:</p>
<pre>hg bookmark -r main my-feature
hg up -r my-feature</pre>
<p>One important thing to remember is that after you use this, the repository will contain multiple heads. This means you can&#8217;t use plain <code>hg push</code> to push changes to remote repositories. You always have to specify the revision, for example:</p>
<pre>hg push -r main https://hg.example.com/projects/trunk</pre>
<h3>Merging</h3>
<p>When it comes to merging, Mercurial doesn&#8217;t make your life easier at all. The default assumption is that visual merging is the preferred way to go. Maybe I&#8217;m just too stupid, but I don&#8217;t get visual merge tools. I just don&#8217;t know how to use them. I prefer merging changes manually in my text editor, after I see the changes for the whole project. Mercurial would start up the merge tool for each file linearly, which means you don&#8217;t have a global picture of impact on the project, when you are supposed to resolve a merge. I just can&#8217;t work that way.</p>
<p>Fortunately, Mercurial does have an internal three-way merge algorithm, that can leave conflict markers in the merged files and let me do my job. You can configure it this way:</p>
<pre>[ui]
merge = internal:merge</pre>
<p>This actually uses the merge code from Bazaar, so I expected I&#8217;ll be done quickly. There is one problem though. Instead of using patience diff, like Bazaar, it uses its own diff algorithm. The result is that in Bazaar the algorithm works just fine, in Mercurial it produces horrible results. That&#8217;s actually pretty funny, considering the fact that I used ideas from Mercurial&#8217;s diff code to implement the C version of patience diff in Bazaar.</p>
<p>Next step, the <a href="http://mercurial.selenic.com/wiki/MergeProgram">Mercurial wiki</a> suggests <code>diff3</code> as a possible non-interactive merge tool. There are no examples how to configure it, but something like this technically works:</p>
<pre>[ui]
merge = diff3
[merge-tools]
diff3.args = -m $local $base $other &gt; $output</pre>
<p>In my experience, this produces even worse results than <code>internal:merge</code>, so there is no reason to use it.</p>
<p>The last idea was to use the <code>merge</code> program from <a href="http://www.gnu.org/software/rcs/">RCS</a> (yes, that&#8217;s right, using an ancient VCS to fix issues in a &#8220;modern&#8221; VCS). I must say that installing RCS in 2010 feels weird, but as long as I can get my job done&#8230; Once it was installed, I used this configuration:</p>
<pre>[ui]
merge = merge</pre>
<p>I was surprised that the results were acceptably good. Not perfect, but I knew I can&#8217;t expect more from a three-way merge. Ideally I&#8217;d like Bazaar&#8217;s merge algorithm with patience diff, but I probably won&#8217;t find time to port it, so <code>merge</code> will stay as my default merge tool for some time.</p>
<p>That&#8217;s only the first part of the problem though. Now you have files with conflict markers and you need to resolve them. Based on my experience with other version control systems, I assumed conflicts would be listed in <code>hg status</code>, but I was wrong. They are nicely hidden here:</p>
<pre>hg resolve -l | grep '^U'</pre>
<p>After manually resolving the conflicts, you can use the following command to mark the files as resolved:</p>
<pre>hg resolve -m path/to/file</pre>
<p><em>To be continued&#8230;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/01/mercurial-part-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Redirect HTTP requests to HTTPS in Apache</title>
		<link>http://oxygene.sk/lukas/2010/01/redirect-http-requests-to-https-in-apache/</link>
		<comments>http://oxygene.sk/lukas/2010/01/redirect-http-requests-to-https-in-apache/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 18:20:26 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=271</guid>
		<description><![CDATA[One more short snippet, that might be useful to me in the future. If you have a website served by Apache and want your clients to only use HTTPS, you can use this mod_rewrite configuration: RewriteEngine On RewriteCond %{HTTPS} off &#8230; <a href="http://oxygene.sk/lukas/2010/01/redirect-http-requests-to-https-in-apache/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One more short snippet, that might be useful to me in the future. If you have a website served by Apache and want your clients to only use HTTPS, you can use this <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">mod_rewrite</a> configuration:</p>
<pre>RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]</pre>
<p>If the server then gets any HTTP request, it will redirect the client to the same URL, but with the <code>https</code> scheme. This means that actual requests will be only ever served via HTTPS.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/01/redirect-http-requests-to-https-in-apache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

