Search Results: "spa"

19 May 2009

Gunnar Wolf: Main character for The Gunnar Wolf chronicles

Main character for The Gunnar Wolf chronicles
I am afraid to say this... But my good friend Kaz has just created a great iconic representation of this angry viking-like antihero on his crusade to spread Free Software and clobber every naysayer with the DFSG and his own personal interpretation of the Social Contract (where Guideline is defined as... Well, better left as an excercise to the reader. To the very patient reader). So, the unofficial, unsanctioned and not related in any way to this (or any other) person, dead or alive... But thanks, kaz, for keeping my name alive in this chaos that Internet has become, even while I cannot stand the stupid twitterosity: http://twitter.com/cgunnarwolf_en (English), http://twitter.com/cgunnarwolf_es (Spanish) (And both empty, as far as I can tell)

18 May 2009

Chris Lamb: Poor man's Google Checkout

Google Checkout recently gained support for taking recurring payments, a frequently requested enhancement for my Xen-based server. However, to use any of the non-trivial features we must provide Google with generate a signed XML file for each transaction. This would normally preclude the use of some server-side scripting, but if the details of transaction are static there is no reason we shouldn't be able to generate the relevant HTML ahead-of-time. The resulting HTML file can be hosted anywhere, is almost completely independent of the server configuration and greatly reduces the attack surface by being a simple static file. The main disadvantage of this approach (and indeed of this submission method in general) is that allows trivial replay attacks of previous transactions. Anyway, first we create our request XML:
$ head -n6 order.xml
<?xml version="1.0" encoding="UTF-8"?>
<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">
 <shopping-cart>
   <items>
     <item>
       <item-name>Lunar object affixed to slender carrying attachment</item-name>
Next, we construct a simple template:
$ cat order.html.in
<h1>Order stuff</h1>
<form method="POST"
    action="https://checkout.google.com/api/checkout/v2/checkout/Merchant/__MERCHANT_ID__">
 <input type="hidden" name="cart" value="__CART__">
 <input type="hidden" name="signature" value="__SIGNATURE__">
 <input type="image" name="Google Checkout" alt="Fast checkout through Google"
   src="http://checkout.google.com/buttons/checkout.gif?merchant_id=__MERCHANT_ID__&w=180&h=46&style=white&variant=text&loc=en_US"
   height="46" width="180">
</form>
Finally, we generate the final page from the above files using the following Makefile:
MERCHANT_ID  = # Enter your merchant ID here
MERCHANT_KEY = # Enter your merchant key here
FILES = order.html
all: $(FILES)
%.html: %.html.in %.xml
       sed -e 's __MERCHANT_ID__ $(MERCHANT_ID) g' \
           -e 's __CART__ '$$(base64 -w0 $*.xml)' g' \
           -e 's __SIGNATURE__ '$$( \
           openssl dgst -sha1 -hmac $(MERCHANT_KEY) -binary <$*.xml   base64 -w0)' ' \
           <$< >$@
clean:
       rm -f $(FILES)
.PHONY: clean
$ make
[...]
$ head -n4 index.html
<h1>Order stuff</h1>
<form method="POST"
    action="https://checkout.google.com/api/checkout/v2/checkout/Merchant/007">
 <input type="hidden" name="cart" value="iAgICAgICAgICAgIDxpdGVtLWRlc2NyaXB0aW9 [..]
Non-trivial dependencies are OpenSSL (to generate the HMAC-SHA-1 signature) and make. You should ensure that you don't upload or otherwise reveal your Makefile as it contains your merchant key.

16 May 2009

Pablo Lorenzzoni: Inspiring picture

Just this week I went to the movies to check the latest incarnation of Cap. Kirk, Mr. Spock et al. It really was a great movie I was expecting less, I have to admit. But the movie was not bad at all With all that space and beyond thing in my mind, yesterday I was surprised with a greatly inspiring picture taken from Hubble Florida, before STS-125 reach Hubble (thanks Florian Weimer for the heads-up): How inspiring can that be? You can find the original here, along with the explanation of how and when it was taken.

Holger Levsen: holidays in the sun

After i had to cancel my last attempt to go to Spain due to suddenly catching a heavy flu, I'm now having some holidays in the sun! Not quite like in those lyrics, rather some unexpected but long needed break from my normal routines. Part of them I'll be keeping here, ie I'll be going to C ceres in the next days for real... at least that's my plan now.

Loving regards to those people in Spain and Germany helping me making this possible, so that I can learn and enjoy and recover!

Marco d'Itri: Installing Debian on the Sheevaplug

This document explains how to use deboostrap --foreign to build from scratch and install a minimal Debian system on the Sheevaplug (but it is equally applicable to many other embedded systems). The only piece missing to be able to install from bare metal is a working kernel and initramfs pair, so this document assumes that you already have a kernel which can mount the root file system from a USB key. For the Sheevaplug, the factory kernel in the internal NAND flash will work fine. The Debian kernel package puts us in a chicken and egg situation: it cannot mount the root without an initramfs (because all drivers are modular), but we cannot build one until we can boot the system. I suppose that, as an exercise of style, somebody could create a minimal initramfs with busybox and the kernel modules needed to mount the root and then mount it manually, but if you really lack a working kernel then it's probably faster to boot the file system image for the first time using qemu and the "versatile" debian-installer target. The first step is to run the first stage of debootstrap on another system (which does not need to be ARM), to build a temporary root file system. I use the --variant and --include options to build the smallest possible system with network support, but they can be omitted.
debootstrap \
         --foreign --arch=armel \
         --variant=minbase \
         --include=linux-image-2.6-kirkwood,module-init-tools,udev,netbase,
                   net-tools,ifupdown,iproute,whiptail,vim-tiny \
         sid ./target/ http://ftp.it.debian.org/debian/
As usual when using debootstrap, some manual configuration is needed:
cd target/
echo bokassa.mi.bofh.it > etc/hostname
vi etc/network/interfaces
vi etc/resolv.conf
echo LANG=C > etc/default/locale
echo '127.0.0.1 localhost' > etc/hosts
cat <<END > etc/fstab
/dev/root / ext3 noatime 0 1
tmpfs /tmp tmpfs defaults 0 0
#/tmp /var/tmp none bind 0 0
END
I took some hints from http://wiki.debian.org/ReadonlyRoot to reduce writes to the flash file system:
# the blkid cache is evil anyway
ln -s /dev/null etc/blkid.tab
# this link will be created anyway by the package
ln -s /var/lib/initscripts/nologin etc/nologin
# it's better to not use a static mtab with modern kernels
ln -s /proc/mounts etc/mtab
# unless you plan to use multiple removable network interfaces, persistent
# interface names are not needed
: > etc/udev/rules.d/75-persistent-net-generator.rules
Two small workarounds are needed:
# if this is not set then the preinst of linux-image-* will die trying
# to ask a debconf question in the debootstrap second stage
echo 'do_initrd = yes' > etc/kernel-img.conf
# a workaround for bug #520742
: > etc/udev/disabled
Now you can format a USB pen drive and copy the root file system on it:
mke2fs /dev/sdb1
tune2fs -i 0 -c 0 /dev/sdb1
mount /dev/sdb1 /mnt/
rsync -aH target/ /mnt/
umount /mnt/
After powering the plug press a key to get to the U-Boot prompt and use the factory kernel to boot from USB:
setenv bootargs console=ttyS0,115200 root=/dev/sda1 rootdelay=10 panic=10 init=/bin/bash
run bootcmd
Then you can run the second stage of debootstrap, finish the bare minimal configuration and start init:
./debootstrap/debootstrap --second-stage
# disable the gettys for /dev/tty[1-6], which do not exist
vi /etc/inittab
# and add one for the serial console
echo 'T0:2345:respawn:/sbin/getty -L ttyS0 115200 linux' >> /etc/inittab
# do not forget to set the root password or you will not be able to login...
vi /etc/shadow
rm /etc/udev/disabled
exec /bin/bash
mount / -o ro,remount
exec /sbin/init
Congratulations, now you can login on the system and start to install the packages you like:
echo 'deb http://ftp.it.debian.org/debian/ unstable main' > /etc/apt/sources.list
echo 'APT   Install-Recommends "false";  ;' > /etc/apt/apt.conf.d/no-recommends
apt-get update
# dash is much faster
apt-get install dash
dpkg-divert --add /bin/sh
ln -sf dash /bin/sh
# I do not like these, YMMV
rm /vmlinuz /initrd.img
rmdir /selinux /srv
# the kernel is able to read the time from the RTC by itself, and this
# will allow using a read only root
echo HWCLOCKACCESS=no >> /etc/default/rcS
# faster boot
echo CONCURRENCY=shell >> /etc/default/rcS
# useless on this platform
mv /etc/rcS.d/S01glibc.sh /etc/rcS.d/K01glibc.sh
dpkg-reconfigure tzdata
apt-get install openssh-server screen iptables wget less
U-Boot requires that the kernel and initramfs have a special header:
apt-get uboot-mkimage
cd /boot/
mkimage -A arm -O linux -T kernel  -C none -a 0x00008000 -e 0x00008000 \
  -n Linux-2.6.29-2 -d vmlinuz-2.6.29-2-kirkwood uImage
mkimage -A arm -O linux -T ramdisk -C gzip -a 0x00000000 -e 0x00000000 \
  -n initramfs -d initrd.img-2.6.29-2-kirkwood uInitrd
Now you can reboot and configure u-boot to boot from the USB device. This is the variables scheme I like and it is not mandatory in any way, so I recommend that you read and understand the existing configuration before modifying it (some lines have been broken for readability):
setenv bootargs_nand $(bootargs)
setenv bootcmd_nand $(bootcmd)
setenv bootargs_root root=/dev/sda1
setenv bootargs_misc 'ro panic=10
  mtdparts=nand_mtd:0x400000@0x100000(uImage),0x1fb00000@0x500000(rootfs)'
setenv bootcmd_usb 'usb start; ext2load usb 0:1 0x00200000 /boot/uImage;
  ext2load usb 0:1 0x01100000 /boot/uInitrd'
setenv bootcmd 'setenv bootargs $(console) $(bootargs_root) $(bootargs_misc)
  $(bootargs_more); run bootcmd_usb; bootm 0x00200000 0x01100000'
Since now you are not using anymore the Marvell kernel tree it is mandatory to set these two variables and reboot:
setenv mainlineLinux yes
setenv arcNumber 2097
saveenv
reset
Installation to SD is identical, but requires an updated version of U-Boot with SD support. Due to a kernel bug which prevents autoloading the driver you will need to add mvsdio and mmc_block to /etc/initramfs-tools/modules and rebuild the initramfs. (Yes, the naming theme I use at home is "african dictators"...)

15 May 2009

Philipp Kern: Infinote-based Gobby hits Karmic

Gobby 0.5 (or to be more precise 0.4.92) just hit the Karmic Koala. Below you can see a screenshot of the new version (just click on it to get a large version). It is sadly not protocol compatible to the old version but it features local undo and redo! Furthermore it's not yet stable on-the-wire wise. The software itself is fairly stable but it could be a bit bumpy if the server protocol version goes out of date. Gobby 0.4.92 thumbnail If you want to try it out on earlier versions, I offer backports in the Infinote PPA for Intrepid and up. I hope to get to Hardy soon, sadly it needs some more backports. There is a public server available on gobby.0x539.de if you want to try it out (connections are encrypted, but all contents are public and can be deleted by everybody, wiki-like; so please be considerate and non-destructive). On local networks Gobby will look for servers through Avahi. That said Gobby is not yet able to host servers by itself, like the old version did. You have to install the infinoted server. You can do this on any computer, even on the local network and take advantage of Avahi. If you want encrypted connections you need to create certificates but if an unencrypted session is acceptable you can get an ad-hoc server by invoking infinoted --security-policy=no-tls without further configuration. It will persist content across invocations, too. Thanks to Greg Heynes, there will also be a KDE client for Gobby, called... Kobby! The first time someone actually uses the fact that the software uses a library for interoperability. Interesting that it's done now when the library's C instead of C++ (which obby was written in), with Qt being C++ anyway. I'm not yet aware of packages but I really hope that we can release with both. If you encounter problems, please report them to our Trac (preferred) or Launchpad.

Michael Banck: 15 May 2009

The other day, while "travelling Deutsche Bahn", I read an article in the venerable Frankfurter Allgemeine Zeitung. To my slight surprise, it included a link to some government document in form of a tinyurl.com URL - (http://tinyurl.com/cr8qso). As I had no internet acccess at the time I read the article, I had to defer checking out the link to some later time. Then I began to wonder how stable those URLs are compared to the stability of the link they service and of the newspaper article itself. The description of the link would probably allow for some targetted google searching, but is it not the responsibility of the newspaper to allow their readers to research the link in a couple of days, months or maybe years? Does tinyurl.com maybe have an enterprise feature where they guarantee long-living links to newspapers and similar customers?

14 May 2009

Antti-Juhani Kaijanaho: Asynchronous transput and gnutls

CC0
To the extent possible under law,
Antti-Juhani Kaijanaho has waived all copyright and related or neighboring rights to
Asynchronous transput and gnutls. This work is published from Finland.
GnuTLS is a wonderful thing. It even has a thick manual but nevertheless its documentation is severely lacking from the programmer s point of view (and there doesn t even seem to be independent howtos floating on the net). My hope is to remedy with this post, in small part, that problem. I spent the weekend adding STARTTLS support to the NNTP (reading) server component of Alue. Since Alue is written in C++ and uses the Boost ASIO library as its primary concurrency framework, it seemed prudent to use ASIO s SSL sublibrary. However, the result wasn t stable and debugging it looked unappetizing. So, I wrote my own TLS layer on top of ASIO, based on gnutls. Now, the gnutls API looks like it works only with synchronous transput: all TLS network operations are of the form do this and return when done ; for example gnutls_handshake returns once the handshake is finished. So how does one adapt this to asynchronous transput? Fortunately, there are (badly documented) hooks for this purpose. An application can tell gnutls to call application-supplied functions instead of the read(2) and write(2) system calls. Thus, when setting up a TLS session but before the handshake, I do the following:
                gnutls_transport_set_ptr(gs, this);
                gnutls_transport_set_push_function(gs, push_static);
                gnutls_transport_set_pull_function(gs, pull_static);
                gnutls_transport_set_lowat(gs, 0);
Here, gs is my private copy of the gnutls session structure, and the push_static and pull_static are static member functions in my sesssion wrapper class. The first line tells gnutls to give the current this pointer (a pointer to the current session wrapper) as the first argument to them. The last line tells gnutls not to try treating the this pointer as a Berkeley socket. The pull_static static member function just passes control on to a non-static member, for convenience:
ssize_t session::pull_static(void * th, void *b, size_t n)
 
        return static_cast<session *>(th)->pull(b, n);
 
The basic idea of the pull function is to try to return immediately with data from a buffer, and if the buffer is empty, to fail with an error code signalling the absence of data with the possibility that data may become available later (the POSIX EAGAIN code):
class session
 
        [...]
        std::vector<unsigned char> ins;
        size_t ins_low, ins_high;
        [...]
 ;
ssize_t session::pull(void *b, size_t n_wanted)
 
        unsigned char *cs = static_cast<unsigned char *>(b);
        if (ins_high - ins_low > 0)
         
                errno = EAGAIN;
                return -1;
         
        size_t n = ins_high - ins_low < n_wanted
                ?  ins_high - ins_low
                :  n_wanted;
        for (size_t i = 0; i < n; i++)
         
                cs[i] = ins[ins_low+i];
         
        ins_low += n;
        return n;
 
Here, ins_low is an index to the ins vector specifying the first byte which has not already been passed on to gnutls, while ins_high is an index to the ins vector specifying the first byte that does not contain data read from the network. The assertions 0 <= ins_low, ins_low <= ins_high and ins_high <= ins.size() are obvious invariants in this buffering scheme. The push case is simpler: all one needs to do is buffer the data that gnutls wants to send, for later transmission:
class session
 
        [...]
        std::vector<unsigned char> outs;
        size_t outs_low;
        [...]
 ;
ssize_t session::push(const void *b, size_t n)
 
        const unsigned char *cs = static_cast<const unsigned char *>(b);
        for (size_t i = 0; i < n; i++)
         
                outs.push_back(cs[i]);
         
        return n;
 
The low water mark outs_low (indicating the first byte that has not yet been sent to the network) is not needed in the push function. It would be possible for the push callback to signal EAGAIN, but it is not necessary in this scheme (assuming that one does not need to establish hard buffer limits). Once gnutls receives an EAGAIN condition from the pull callback, it suspends the current operation and returns to its caller with the gnutls condition GNUTLS_E_AGAIN. The caller must arrange for more data to become available to the pull callback (in this case by scheduling an asynchronous write of the data in the outs buffer scheme and scheduling an asynchronous read to the ins buffer scheme) and then call the operation again, allowing the operation to resume. The code so far does not actually perform any network transput. For this, I have written two auxiliary methods:
class session
 
        [...]
        bool read_active, write_active;
        [...]
 ;
void session::post_write()
 
        if (write_active) return;
        if (outs_low > 0 && outs_low == outs.size())
         
                outs.clear();
                outs_low = 0;
         
        else if (outs_low > 4096)
         
                outs.erase(outs.begin(), outs.begin() + outs_low);
                outs_low = 0;
         
        if (outs_low < outs.size())
         
                stream.async_write_some
                        (boost::asio::buffer(outs.data()+outs_low,
                                             outs.size()-outs_low),
                         boost::bind(&session::sent_some,
                                     this, _1, _2));
                write_active = true;
         
 
void session::post_read()
 
        if (read_active) return;
        if (ins_low > 0 && ins_low == ins.size())
         
                ins.clear();
                ins_low = 0;
                ins_high = 0;
         
        else if (ins_low > 4096)
         
                ins.erase(ins.begin(), ins.begin() + ins_low);
                ins_high -= ins_low;
                ins_low = 0;
         
        if (ins_high + 4096 >= ins.size()) ins.resize(ins_high + 4096);
        stream.async_read_some(boost::asio::buffer(ins.data()+ins_high,
                                                   ins.size()-ins_high),
                               boost::bind(&session::received_some,
                                           this, _1, _2));
        read_active = true;
 
Both helpers prune the buffers when necessary. (I should really remove those magic 4096s and make them a symbolic constant.) The data members read_active and write_active ensure that at most one asynchronous read and at most one asynchronous write is pending at any given time. My first version did not have this safeguard (instead trying to rely on the ASIO stream reset method to cancel any outstanding asynchronous transput at need), and the code sent some TLS records twice which is not good: sending the ServerHello twice is guaranteed to confuse the client. Once ASIO completes an asynchronous transput request, it calls the corresponding handler:
void session::received_some(boost::system::error_code ec, size_t n)
 
        read_active = false;
        if (ec)   pending_error = ec; return;  
        ins_high += n;
        post_pending_actions();
 
void session::sent_some(boost::system::error_code ec, size_t n)
 
        write_active = false;
        if (ec)   pending_error = ec; return;  
        outs_low += n;
        post_pending_actions();
 
Their job is to update the bookkeeping and to trigger the resumption of suspended gnutls operations (which is done by post_pending_actions). Now we have all the main pieces of the puzzle. The remaining pieces are obvious but rather messy, and I d rather not repeat them here (not even in a cleaned-up form). But their essential idea goes as follows: When called by the application code or when resumed by post_pending_actions, an asynchronous wrapper of a gnutls operation first examines the session state for a saved error code. If one is found, it is propagated to the application using the usual ASIO techniques, and the operation is cancelled. Otherwise, the wrapper calls the actual gnutls operation. When it returns, the wrapper examines the return value. If successful completion is indicated, the handler given by the application is posted in the ASIO io_service for later execution. If GNUTLS_E_AGAIN is indicated, post_read and post_write are called to schedule actual network transput, and the wrapper is suspended (by pushing it into a queue of pending actions). If any other kind of failure is indicated, it is propagated to the application using the usual ASIO techniques. The post_pending_actions merely empties the queue of pending actions and schedules the actions that it found in the queue for resumption. The code snippets above are not my actual working code. I have mainly removed from them some irrelevant details (mostly certain template parameters, debug logging and mutex handling). I don t expect the snippets to compile. I expect I will be able to post my actual git repository to the web in a couple of days. Please note that my (actual) code has received only rudimentary testing. I believe it is correct, but I won t be surprised to find it contains bugs in the edge cases. I hope this is, still, of some use to somebody :)

Julian Andres Klode: PHP, MySQL, PostgreSQL, etc.


Well, I m currently writing a PHP and SQL application at school, so here are some of my thoughts on the problems I encounter. PHP is crap Many PHP applications are low quality applications. The problem is that PHP makes it hard for developers to write good applications. PHP developers tend to use many global variables, global code, and not many classes or functions. And when writing applications for the web, PHP makes it easy to mix PHP and HTML, in my opinion even too easy. Well-written applications follow some basic rules. First, separate your code into functions and classes, and (2) split your code over multiple files. And there is one rule which is especially important for non-commandline applications: (3) seperate logic and presentation. This means if you write a web application, use a template engine. PHP error and exception handling is also an interesting topic. The problem here lies in the distinction between the both. In my opinion, there should only be one way to handle such stuff: Using exceptions. Exceptions are a very widespread way to program today, and are used in languages like Java and Python for cases where PHP uses errors. The concept of PHP s errors results in code like @do_something or die("blah"); being written in libraries which is a problem as it clearly violates rule (3) I wrote above, because there is no way to catch this die() error. Furthemore, PHP has no clear concept of namespaces in the current stable versions (< 5.3). PHP 5.3 finally gets namespaces, but using a backslash character, which looks really bad and makes everyone think of eithers Windows systems or escape characters. There are even more problems with PHP. From time to time, PHP just crashes with a segmentation fault. MySQL vs. PostgreSQL MySQL seems to have many problems with checking data, which can confuse me. It got better in MySQL 5 with the introduction of the new sql_modes like STRICT_ALL_TABLES and TRADITIONAL. And using storage engines like InnoDB also allows you to take advantage of stuff like foreign keys and transactions. But MySQL is still problematic. For example, in an application I wrote I had multiple entries identified by a numeric id (an INTEGER). One day, I wanted to check whether my error handling was OK and requested an entry with the invalid ID 1X , which resulted in SELECT * from A where id='1X';. Now I expected to get an error or at least no result, but MySQL happily proceeded with the query and returned the entry with the ID 1. I tried the same thing on PostgreSQL and got an error message that 1X is not integer, as I expected it. As another example, when I run the same PHP application using PDO on a MySQL database and a PostgreSQL database, I always get strings from the MySQL database whereas I get integers from PostgreSQL if the columns are integers. Another thing which PostgreSQL does better than MySQL is password encryption. MySQL only provides access to the standard crypt() function and by default only generates DES passwords. It allows other methods to be used (although not all are available everywhere and therefore not documented), but it provides no way to create a salt for them, which makes them not very useful. PostgreSQL in contrast provides less encryption methods but it provides the gen_salt() function which can be used to generate salts for blowfish encryption (gen_salt('bf')). Another problem is that MySQL simply ignores references when they are added to the column definition instead of a separate FOREIGN KEY . Because MySQL gives no errors when a feature like REFERENCES is not supported, developers may think that the feature is supported and write code using this feature just to realize later that what they wrote does not what they want. And you can t write AGPL applications using MySQL client libraries, because MySQL is GPL-2 which is incompatible with the AGPL. You might think that the FOSS License Exception helps here, but this only lists (among others) the GPL-3. Or am I wrong? But PostgreSQL has other problems, at least when it comes to the performance of the information_schema.columns view. This may be related to the fact that PostgreSQL has > 1000 rows whereas MySQL only has 250. And PostgreSQL may be a bit harder to configure. Final words All in all, PHP and MySQL are not the best choices for writing applications. They are to tolerant, and do not treat errors in an acceptable way by aborting the current action. I can get around some problems in PHP by using error handlers which raise exceptions and setting error_reporting to E_ALL, but in fact this should be the default. MySQL problems can be solved to a large extend by setting sql_mode to TRADTIONAL and using InnoDB databases, which should in my opinion be the default and not an option. My recommendation is to use PostgreSQL servers and for the applications: use frameworks (if you are allowed to, which may not be always the case [e.g. when you are learning SQL, using a ORM is clearly the wrong way]), document your code, separate your code into classes and functions, and make sure you are not using to many global variables. And use a SCM to track your changes. Posted in General

13 May 2009

Jonathan McDowell: Breaking the Web of Trust

With all the discussion about SHA-1 weaknesses and generation of new OpenPGP keys going on there's some concern about how the web of trust will be affected. I'm particularly interested in the impact on Debian; while it's possible to add new keys and keep the old ones around that hasn't worked so well for us with the migration away from PGPv3 keys. We still have 125 v3 keys left, many of them for users who also have a v4 key but haven't asked for the v3 key to be removed or responded to my email prodding them about it. I don't want to repeat that.

So if we're looking at key replacement we need to have some idea about where our Web of Trust currently stands, and what effect various changes might have on it. I managed to find the keyrings Debian shipped all the way back to slink and ran the keyanalyze and cwot stats against them. I then took the current keyring, pull in all the updates for the keys in it (so that any signatures from newly generated keys would be included) and ran the stats again. Finally I took details of 12 key migrations (mostly from Debian Planet but also a couple of others I knew about) and calculated what the effect of removing each key would be. These stats are cumulative and I replaced the most well connected (by centrality) keys first.

The results are below.

TotalSCSReachableMSDCentrality
1999-02-06 (slink)22836(15.78%)50 (21.92%)2.9022
2000-01-03 (potato)375104 (27.73%)180 (48.00%)4.3382
2001-09-22 (woody)948538 (56.75%)704 (74.26%)4.73202008.6249
2005-05-28 (sarge/etch) 1106883 (79.83%)969 (87.61%)3.34852074.6604
2007-12-0411911001 (84.04%)1062 (89.16%)3.11032113.3747
2009-01-18 (lenny)1126947 (84.10%)1010 (89.69%)3.04891941.2594
2009-04-04 (squeeze/sid)1121946 (84.38%)1008 (89.91%)3.04661936.9761
2009-05-06 (current)1067894 (83.78%)958 (89.78%)2.96701759.4363
TotalSCSReachableMSDCentrality
base1067904 (84.72%)959 (89.87%)2.96401776.4389
update-93sam1067902 (84.53%) 958 (89.78%)2.97341780.9874
update-joerg1067900 (84.34%) 958 (89.78%)2.97761780.7578
update-aurel321067898 (84.16%) 957 (89.69%)2.98031779.2497
update-noodles1067896 (83.97%) 956 (89.59%)2.98311777.8326
update-jaldhar1067896 (83.97%) 955 (89.50%)2.98551779.9193
update-srivasta1067896 (83.97%) 955 (89.50%)2.99041784.3382
update-ana1067895 (83.88%) 954 (89.40%)2.99261784.3102
update-nobse1067893 (83.69%) 953 (89.31%)2.99471782.2392
update-neilm1067892 (83.59%) 951 (89.12%)2.99741782.6098
update-reg1067891 (83.50%) 950 (89.03%)2.99771780.8515
update-rmayorga1067890 (83.41%) 949 (88.94%)2.99841779.4910
update-evgeni1067889 (83.31%) 948 (88.84%)2.99741776.6445

This is actually more hopeful than I thought. There's an obvious weakening as a result of the migrations, but the MSD stays under 3 and the centrality stays fairly constant too. The reachable/SCS counts do decrease, but at this point it looks fairly linear rather than an instant partition. Of course the more keys that are removed the more likely this is to drop off suddenly. Counteracting that DebConf9 is coming up which will provide a good opportunity for normally geographically disperse groups to cross sign, reinforcing the WoT for these new keys.

Either way I at least have a better handle on the current state of play, which gives me something to work with when thinking about how to proceed. For now, bed.

Jaldhar Vyas: I Am Special, I Am Special, I Am Me.

Debian Times asked me a few questions I received my first invitation to AARP membership. Aren't you supposed to be atleast 50? Speaking of old age, the other day I overheard Shailaja tell her little brother while a Seinfeld rerun was on TV, "That's a classic. That's what they [indicating me and my wife] used to watch in the olden times." Look what came in the mail today: Ph33r! I am me. The best me I can be.

Peter Eisentraut: The Big Shots

As the occasional thinker about open-source development practices, communities, and issues, I have been wondering for a while: What are the largest open-source projects? What projects have the most code, the most users, and the most issues to deal with, and how do they cope?

The Debian archive should provide some insights into the first one or two questions, as it contains a very large portion of all available and relevant open-source software and exposes them in a fairly standard form. In the old days one might have gotten out grep-dctrl to create some puzzling statistics, but nowadays this information is actually available in an SQL database: the Ultimate Debian Database (UDD). (And it's in PostgreSQL. And it comes with a postgresql_autodoc-generated schema documentation. Excellent.)

So here is a first question. Well, the zeroth question would have been, which source packages have the largest unpacked orig tarball, but that information doesn't seem to be available, either via UDD or via apt. So the first question anyway is, which source packages produce the largest installation size across all their binary packages:
udd=> SELECT source, sum(installed_size)/1024 AS mib FROM packages WHERE distribution = 'debian' AND release = 'sid' AND component = 'main' AND architecture IN ('all', 'i386') AND section 
 'debug' GROUP BY source, version ORDER BY mib DESC LIMIT 30;                                                                                   
source mib
------------------+------
openoffice.org 1797
kde-l10n 648
gcj-4.4 544
vtk 465
linux-2.6 404
openclipart 353
vegastrike-data 311
ghc6 308
gclcvs 303
wesnoth 300
fpc 269
axiom 256
webkit 255
gcc-snapshot 255
lazarus 241
kdebase-workspace 226
plt-scheme 221
torcs-data-tracks 219
scilab 213
openscenegraph 211
eclipse 210
sagemath 201
insighttoolkit 198
acl2 195
kdebindings 181
atlas 165
gcl 163
trilinos 153
paraview 153
asterisk 144
(30 rows)
This produces a few well-known packages, but also a number of obscure ones. If you look closer, many of them appear to be themed around scientific, numerical, visualization, Scheme, Lisp, that sort of thing. Hmm.

Here is another idea. Take a package's installation footprint and multiply it by its popularity contest installation count. So you get some kind of maintenance effort score, either because the package is large or because you have a lot of users or both.
SELECT rank() OVER (ORDER BY score DESC), source, sum(installed_size::numeric * insts) AS score FROM packages JOIN popcon USING (package) WHERE distribution = 'debian' AND release = 'sid' AND component = 'main' AND architecture IN ('all', 'i386') GROUP BY source, version ORDER BY score DESC LIMIT 30;
rank source score
-----+-----------------------------+-------------
1 openoffice.org 12638492332
2 mysql-dfsg-5.0 3411344560
3 eglibc 3371485240
4 perl 3019183024
5 evolution 2669948000
6 samba 2308923872
7 mesa 1853902860
8 texlive-base 1684245516
9 gcj-4.3 1610495484
10 foomatic-db-engine 1608178104
11 foomatic-db 1423947704
12 inkscape 1413910080
13 qt4-x11 1258220636
14 gcc-4.3 1248741312
15 kdelibs 1021058256
16 gnome-applets 998434136
17 xulrunner 958232688
18 coreutils 954766896
19 openssl 877067672
20 ncurses 827679424
21 python2.5 815826384
22 aptitude 808161380
23 gimp 786015124
24 gnome-utils 781756328
25 nautilus 774319690
26 openoffice.org-dictionaries 761075576
27 eclipse 756072380
28 dpkg 736626200
29 openclipart 731244240
30 wine 707967500
(30 rows)
(Yeah, they run this thing on PostgreSQL 8.4 beta 1.)

I noticed linux-2.6 is suspiciously absent because of a low popcon score (?!?).

I don't want to dump the entire database into this blog post, but if you try this yourself you can look at about the first 200 to 300 places to find reasonably large and complex projects before it gets a bit more obscure. A few highlights:
  51   gnupg                           455660464
59 php5 386417572
60 mutt 381148176
83 icu 258602756
84 xorg-server 255186332
101 exim4 224857700
107 openssh 215792828
113 tar 201520400
114 postgresql-8.3 196844584
115 libx11 195856564
116 ruby1.8 194681656
272 emacs22 62047476
This is obviously still biased in a lot of ways, but it does show the major projects.

The UDD is also an interesting use case that shows how you can deploy a PostgreSQL database as a semi-public service with direct access. A great tool, and a great tool to build other great tools on top of.

Martin Michlmayr: Update on QNAP TS-119/TS-219 kernel support

I mentioned a few weeks ago that initial kernel support for the QNAP TS-119 and TS-219 Turbo NAS got accepted for 2.6.30 but that there were some issues left. Here's an update: The SATA and flash fixes are already in our 2.6.29 kernel.

Jordi Mallach: Spanish Cup final in Val ncia

Val ncia is again taken over by football fans, who have come from all over the Basque Country and Catalunya to watch the Copa de Espa a final in Mestalla stadium. The city is literally tinted in red, white, blue and maroon and thousands of supporters (more than 60.000) have flooded the streets. If you can't beat them, join them, so for a change, I'm going to join the crazyness and will go to the Athletic Hiria to watch the game in the middle of the leonera. I can't wait to see how the Basque and Catalan supporters who have tickets for the game will react when the King of Spain enters the VIP area in Mestalla. Apparently, more powerful loudspeakers have been installed in the stadium in an attempt to mitigate what I expect to be the biggest catcall in a Spanish football stadium since we have a King... Gora Bar a, Visca l'Athletic!

Runa Sandvik: Oh btw

  1. I will be working for the Tor project in this year s Google Summer of Code. I have started a new blog for GSoC-related updates.
  2. I am excited about Diego s accepted GSoC proposal for Debian; debbugs web UI.
  3. I m in NM.
  4. I will be in London during June and July. Any Debian-people up for a geeknic or something?
  5. I m looking forward to meeting the people involved in the London Hackspace project and I hope they find a place soon.

12 May 2009

Julien Valroff: HADOPI law finally voted by my local representative

As expected, the French HADOPI law was voted earlier today by the Assembl e Nationale. As expected, my local representative voted in favour of this law. I had however kept a secret hope that he would abstain for this vote, following to the email I have received from his assistant following to our meeting. Mr Vannson planned to take the floor during the finale discussions. He had sent me for review the text they wrote, which perfectly matched my arguments, and even referred to the law as a Rube Goldberg machine ( Ma conviction est que nous avons mont une usine gaz in the original version). This text also stated that he was netiher convinced nor satisfied by the law.

His speech planned for the final discussions of the law never happened, and was replaced by a single line question to the Minister, during a meeting of the Law Commission.
This question was even technically incorrect as he refers to firewall, whereas I had (with a great help from other members of APRIL) amended this part of the text to refer to usage control software :
M. Fran ois Vannson. Les logiciels pare-feu ne risquent-ils pas, madame la ministre, de nuire aux logiciels libres ?
Mme la ministre. Il n y a aucune menace sur les logiciels libres, qui peuvent tout fait accepter des logiciels de s curisation.
From: http://www.assemblee-nationale.fr/13/rapports/r1626.asp Which could be approximately translated as follows:
M. Fran ois Vannson. Mrs Minister, aren t firewall a threat on Free Software?
Mrs Minister. There is no threat on Free Software who can accept well accept securisation software.
I must hence express my real disappointment.
Now, let s hope this law won t be applicable, following the idea of most of its opponents. I won t write to my local representative, as I think it is totally hopeless. I guess he will get the pingbacks from this blog post, as his own political weblog runs on Free Software!

11 May 2009

Sandro Tosi: PyCon3 Italia is over: retrospective and perspective for myself

PyCon3 Italia ended yesterday. It was simply great! great talks, gorgeous speakers and so on.

Sadly, when I left these kind of confs there's always a bad taste in my month... I see so many great people that made it, that are satisfied, brilliant and accomplish great results.

Now I feel like I'm one of many, but I want to be one above many; one of Them. Ok, ok, sounds a little bit presumptuous and we all know I'll never be like them but why not trying? ;)

The same thing happened after PyCon2, and I decided I wanted to do more, to be more.

Since an year passed, I think I've done a bit of my proposal: I started using Python as much as I can, I get involved in some project python-related (to name some: reportbug, bts-link, matplotlib) and I'm about at the half of writing a book on matplotlib (that I was offered to write).

I can be a little satisfied by this, but of course, I want to do more! :)

Once the book will be done, I'll probably still be involved with matplotlib evolution, eventually with more important contributions, but I will also search for new challenges.

It might sound ambitious, but I have a strange feeling that python core "stuff" (being the interpreter, the stdlib or near) could be something I can have a look at ;) It could also come up as a too big project to work on in my spare time, but I'll rebase my plan once I've fight for it and lose, not before.

James Morrison: Same Cities

On thursday I went out to see Loquat, The Greycoats, and Head like a kite. Head like a kite was a lot of fun, they had a dancing panda and foam heads (the ones you put whigs on) to throw around the audience. The strange part of the night was that I met Mark Johnson again. Mark was someone who knew a bunch of the same people as me in secondary school, then we both did co-op Math/CS degrees at UWaterloo, and since leaving school have both lived in the bay area. I didn't know Mark was in SF until this week, well, now we've met again, four years later.

Random thought:
Why are Canadians more patriotic when they are away from Canada? I saw a guy with a flag on his ipod shuffle while running yesterday.

10 May 2009

Ana Beatriz Guerrero Lopez: Creating a new GPG key

I wanted to renew my GPG key for some time and after reading the latest news, I finally have generated a new key today.
pub   4096R/6AA15948 2009-05-10
      Key fingerprint = 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
uid                  Ana Beatriz Guerrero L pez <ana@ekaia.org>
uid                  Ana Beatriz Guerrero L pez <ana@debian.org>
sub   4096R/2497B8B2 2009-05-10

Since I tend to forget this stuff, I am blogging all the steps I have followed.
Long and verbose post follows
Update .gnupg/gpg.conf Add at the end of the file:
personal-digest-preferences SHA256
cert-digest-algo SHA256
Create key
ana@pryan:~$ gpg --gen-key
 ...        
Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 5
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
  
Real name: Ana Beatriz Guerrero L pez
Email address: ana@ekaia.org
Comment:
You are using the  utf-8  character set.
You selected this USER-ID:
     Ana Beatriz Guerrero L pez <ana@ekaia.org> 
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
   
gpg: key 6AA15948 marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
  
gpg: 3 marginal(s) needed, 1 complete(s) needed, classic trust model
gpg: depth: 0  valid:   3  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 3u
pub   4096R/6AA15948 2009-05-10
      Key fingerprint = 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
uid                  Ana Beatriz Guerrero L pez <ana@ekaia.org>
Note that this key cannot be used for encryption.  You may want to use
the command  edit-key  to generate a subkey for this purpose.
Add other UID
ana@pryan:~$ gpg --edit-key 0x6AA15948
 ...
command> adduid
Real name: Ana Beatriz Guerrero L pez
Email address: ana@debian.org
Comment:
You are using the  utf-8' character set.
You selected this USER-ID:
    "Ana Beatriz Guerrero L pez <ana@debian.org>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a passphrase to unlock the secret key for
user: "Ana Beatriz Guerrero L pez <ana@ekaia.org>"
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ unknown] (2). Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Change preferences
ana@pryan:~$ gpg --edit-key 0x6AA15948
 ...
Command> showpref
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@debian.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA1, SHA256, RIPEMD160
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA1, SHA256, RIPEMD160
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Command>  setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
Set preference list to:
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Really update the preferences? (y/N) y
gpg: WARNING: no user ID has been marked as primary.  This command may
              cause a different user ID to become the assumed primary.
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@debian.org> 
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@debian.org>
[ultimate] (2). Ana Beatriz Guerrero L pez <ana@ekaia.org>
Command> showpref
[ultimate] (1)  Ana Beatriz Guerrero L pez <ana@debian.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
[ultimate] (2). Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Cipher: AES256, AES192, AES, CAST5, 3DES
     Digest: SHA512, SHA384, SHA256, SHA224, SHA1
     Compression: ZLIB, BZIP2, ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
Command> save
Set primary UID
ana@pryan:~$ gpg --edit-key 0x6AA15948
  ...
Command> uid 1
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)* Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> primary
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@ekaia.org> 
4096-bit RSA key, ID 6AA15948, created 2009-05-10
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
[ultimate] (1)* Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Add subkey for encryption
ana@pryan:~$ gpg --edit-key 0x6AA15948
  ...
Command> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Ana Beatriz Guerrero L pez <ana@ekaia.org>"
4096-bit RSA key, ID 6AA15948, created 2009-05-10
Please select what kind of key you want:
   (2) DSA (sign only)
   (4) Elgamal (encrypt only)
   (5) RSA (sign only)
   (6) RSA (encrypt only)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
        = key expires in n days
      w = key expires in n weeks
      m = key expires in n months
      y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
  
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/2497B8B2  created: 2009-05-10  expires: never       usage: E
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Command> save
Sign my new key with my old key
ana@pryan:~$ gpg --default-key E8C43461 --sign-key 6AA15948
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
sub  4096R/2497B8B2  created: 2009-05-10  expires: never       usage: E
[ultimate] (1). Ana Beatriz Guerrero L pez <ana@ekaia.org>
[ultimate] (2)  Ana Beatriz Guerrero L pez <ana@debian.org>
Really sign all user IDs? (y/N) y
pub  4096R/6AA15948  created: 2009-05-10  expires: never       usage: SC
                     trust: ultimate      validity: ultimate
 Primary key fingerprint: 7A33 ECAA 188B 96F2 7C91  7288 B346 4F89 6AA1 5948
     Ana Beatriz Guerrero L pez <ana@ekaia.org>
     Ana Beatriz Guerrero L pez <ana@debian.org>
Are you sure that you want to sign this key with your
key  Ana Beatriz Guerrero L pez <ana@ekaia.org>  (E8C43461)
Really sign? (y/N) y
You need a passphrase to unlock the secret key for
user:  Ana Beatriz Guerrero L pez <ana@ekaia.org> 
1024-bit DSA key, ID E8C43461, created 2004-12-06
  
Send new key to key server
gpg --keyserver pgp.mit.edu --send-key 6AA15948

Ond&#345;ej &#268;ert&iacute;k: My experience with running an opensource project

Nir Aides, the author of the excellent winpdb debugger, sent me the following email on September 21, 2008, so I asked him if I can copy his email and reply in form of a blog post (so that other people can comment and join the discussion) and he agreed. It took me almost a year to reply, but I made it. :)

Hi Ondrej,

How are you?

I am about to publish a new free software project, a new simple PHP framework, and I am interested in your advice.

You started SymPy and were able to make other people join you and develop it with you.
How did you do it?
How did it happen?
Did you actively call for other people or they spontaneously showed interest and joined you?
Are the other major contributor people who were your friends before you started the project?
Did you need to create or manage the project in a particular way to make it attractive to other people?
Are there things you are aware of that promote collaboration or demote it?

I was never successful in doing the same with Winpdb, which while it became reasonably popular, no one has ever joined me to develop it, except for a notable tutorial contribution by Chris Lasher which was developed independently.

Now with the new project, I am wondering what are my chances of making other people try it and take it on. On the one hand it is a new and fresh code base in an interesting field, on the other hand, why would anyone bother to spend their energy on this new project when they have Symfony or Drupal?

What do you think?

BTW, Ohloh believes you have a median of 19,000 lines of changed code per month since the start of their log. Can this be true? Is this humanly possible? According to it SymPy has over 1,000,000 lines of code? I can't understand these numbers. Winpdb has about 25,000 lines after 3 years of development. And from my experience 1,000,000 lines of code projects need about 20-50 full time developers to work on for 2-5 years which is about 40-250 man years. And as if this is not enough you are listed as owner in a dozen other projects in Google code and have enough time to become an awarded scientist. How is this possible?

http://www.ohloh.net/p/sympy/contributors/

BTW2, do you still use Winpdb? If you find yourself using it less, can you say what are the reasons, or what it would take to make it more useful?

BTW3, How is SymPy doing?

Cheers,
Nir



So my most honest answer how to run a successful opensource project is: I don't know.

But nevertheless I tried to summarize some of my ideas and experience and some guidelines that I try to follow, maybe it will be useful to you Nir, or anyone else.

First of all, there has to be a public mailinglist (easily accessible), public bug tracker, nice webpage, easy to find downloads, frequent releases (once a month is good, but in the worst case at least 4 times a year) and a set of guidelines to follow in order to contribute. So that's a must, if the project doesn't have the above, it's almost impossible to become successful. However, that is just a start, just a playground. There are still many projects that have the above and yet they totally fail to attract developers.

So I think the most important principle is that I always think how to employ other people in what I do. If I have some plan in my head how to do something, e.g. how to move some things forward, I always create exact steps and put it to issues, or our mailinglist, so that each step can be done by someone who is completely new to sympy. So I try to look at things from other people's perspective and think -- ok, I quite like this SymPy project and I'd like to get this done (for example a new release, or something fixed, or implemented), but I have no idea how to start and what exactly needs to be done.

So what I try to do if someone comes to our list and asks for something, is that I create a new issue for it and think how I would fix it if I had time. Then write the necessary steps in the issue and invite the submitter to fix it and I offer help with explaining anything and guiding. Now there are two things that can happen. Either the submitter has time and a will to go forward and in this case he starts wrestling with it and whenever he has some code or a question, I need to find time, review it and offer some way out. Or the submitter is too busy, in which case the instructions simply rest in the issues and the next time someone asks for the feature, the instructions are already there. I don't have estimates how frequent either case is.

When I am working on something myself, I try not to code privately, but also put up issues first and put the steps needed in the issues, so that it's easy for other people to join in.

In general, the most precious value for me is the fact that someone else had to sit down at his computer and wrote the patch. So I do everything possible to get new (or more) people interested in the development. Some people think that only super programmers can do a decent job and it's useless to invest time in people that may just have started with Python. They are wrong. Among the SymPy developers (around 65 people total have contributed patches so far at the time of writing this post), we have all kinds of people. We have people from high school, we have a retired US army engineer, we have physicists, mathematicians, biologists, engineers, teachers, or just hobbyists, who do it for fun. Unfortunately, we do not have many women (I think no patch that made it into sympy was contributed by a woman, but I may be wrong), so if anyone has any ideas how to get more women involved, let me know (I know we have several women fans, so that's a good start:). We have people whose first open source project they ever contributed to was sympy and people who are new to Python.

Many times the first patch that a new potential developer submits is not perfect, usually it's faster for me to write it myself, than to help with the first patch, however my rule is to always help the submitter do that. Sometimes he sends a second patch, or a third, and usually it needs less and less work on my side and it already pays off, because he is then able to fix things himself, if he discovers a bug and sympy has just won a one more contributor.

So I came to the conclusion that all that is needed is an enthusiasm. You don't even have to know Python (as you can learn all these things on the way) and you can still do useful things for us and really spare our time.

To answer another question from Nir's email, SymPy has about 130000 lines of code and another about 20000 lines of tests, so I think those stats are wrong. Also the changed lines of code is in my opinion wrong, we usually have about 250 new patches per release (this depends how often we release and other things).

Yes, I am involved in couple other projects, e.g. Debian, Sage, ipython, scipy, hpfem.org (and couple more), basically everything that has to do with numeric simulation and Python, but my activity there varies. The most time consuming thing in the last couple years was definitely school, I was finishing my master in Theoretical Physics in Prague and then moved to the Nevada/Reno and I just finished my first semester here at PhD in Chemical Physics, and sometimes it was just crazy, e.g. I finished teaching at 7pm and instead of going home and sleep, I stayed in my office, fixed 10 sympy issues that were holding off a release, finished at 1am, went home (by bike, since I don't have a car yet), slept couple hours and then did just school again for a week, other people reviewed the issues in the meantime, and then I made the release (instead of sleeping again). In the last semester it was not unusual that I got home at 1am every week day, then slept most of Saturday to catch up, on Sunday I did some laundry and shopping, and the rest of time I did grading and homeworks for all my classes and teaching, no time for anything else (e.g. no friends, no girls, no rest, no hobby, no opensource stuff, nothing). So sometimes one has to work pretty hard to get through it, but fortunately it's behind me finally, if all goes well, I should be just doing research from now on and have a real life too. Also I am sorry I didn't manage to reply sooner. :)

To answer the other questions:
Are the other major contributor people who were your friends before you started the project?
No, not a single major contributor was my friend before I started the project. Every single one of them become a developer using the procedure I described above, e.g. first showed on the list or in the issues, and maybe even the very first patch was not a high quality one (and if I was stupid and arrogant, or didn't see the big potential, I would just ignore them). But when given a chance, they became extremely good developers and sympy would simply just not be here without them.

Did you actively call for other people or they spontaneously showed interest and joined you?
I very much encourage everyone to contribute, but the initial interest must be in them, e.g. they at least have to show around the mailinglist/issues, so that I know about them. But once I know they are interested in some issue, yes, I try to invite them to fix it, with my help.

One observation I made is that I have to always think in the spirit "how to earn new money, not how to spare the money I already have", e.g. when applied to sympy, how to get new developers, how to develop the new great things etc. Even if I am super busy as I was, I still have to think this way. Once I start thinking how to conserve and preserve what we already have, I am done, finished and that's the road to hell.

If I am open, positive, full of energy, I can see people joining me and we can do great things together. It probably sounds obvious, but it was not for me, when for example some people I worked with, started their own projects, when I got busy, and started to compete, instead of helping sympy out. And I felt betrayed, after so much work that I invested into it and started to become protective. And then I realised that's wrong. I can never stop other people do what they want to do. If they want to have their own project, they will have it. If they don't want to help sympy out, they won't (and what is more important, there is nothing wrong with either of that). It's that simple and being protective only makes things worse.

There is also a question of the license that you use for the project, e.g. one should basically only choose between BSD (maybe also MIT or Apache), LGPL and GPL (there are also several versions of the GPL licenses). Unfortunately the fact is, that there are people who will never contribute a code under a permissive BSD license (because it's not protecting their work enough) and there are also other people who really want to code to be BSD (or other permissive license) so they can sell it and they don't need to consult with lawyers what they are or aren't allowed to do and also so that they can combine it with any other code (opensource or not). It also depends if one wants to combine (and distribute) other codes together. So choosing a license is also important. I believe that for sympy BSD is the best and for other projects (like Sage) GPL is the best and one has to decide on a case by case basis. For Winpdb, I would make it BSD too, since you can get more people using it.

To conclude, SymPy is a little more than 2 years old, and it has been a great ride so far and more things are coming, e.g. this summer we have 5 Google Summer of Code students and people are starting it to use in their research and we plan to use it in our codes at our group here in Reno too, so things look promising. I am really glad, we managed to build such a community, so that when I am busy, as I was the last semester, other people help out with patches, reviews and other things, so that the project doesn't stall and when I got rid of my school duties now, we can move things forward a lot.

So maybe you can get inspired by some of the ideas above. I am also interested in any discussion about this (feel free to post a comment below, or send me an email, or just write to a sympy list about what you think).

Next.

Previous.