Norbert Hartl

mostly brackets and pipes

Public Monticello Repository

Smalltalk is different to other languages in many ways. One of the big differences is that smalltalk does not come in files. It does come as an image. The image is a great thing to work on but for the other world it is just a big binary blob. As all of the source code is kept inside the image you cannot utilize any of these popular source code management systems that are out there.

A lot of smalltalk projects use monticello for their work and so do I. I was thinking about releasing some of my current code to the public. The code belongs to smalltalk in general and to gemstone in detail. Somehow I was reluctant to open a project on squeaksource and I didn’t want to open a project on gemsource. I had to idea to store my stuff just on one of my servers. So far so good…

Tinkering with the idea a few moments I recognized that this isn’t as easy as I thought at first. There are some conditions to be met. Basically it is a WebDAV share that is publicly accessible. But there is more:

  • the share shall be accessible anonymously in read-only fashion
  • the share is writable by providing credentials
  • files can be created arbitrarily but they can’t be overwritten or deleted

The last point of the list is the hairy one. WebDAV only allows to use HTTP methods for doing stuff. But creating a file without allowing to edit it again is AFAIK not doable with plain WebDAV. The next idea was to use umask. Researching the topic showed that a lot people are suffering from the lack of proper umask support but there is no good solution for years. The solution seems to be mod_rewriteas always (thanks Daniel for pointing this out).

basic setup of the WebDAV share

At first we make the WebDAV share work in apache. We just add a <directory> section in a virtual host section to create the share.# Monticello repository

<Directory /var/domains/selfish.org/web/source.docs/mc/>
   Options Indexes FollowSymLinks
   Order allow,deny
   Allow from all
   DAV On
   <LimitExcept GET PROPFIND OPTIONS REPORT>
      Require user norbert
   </LimitExcept>
</Directory>

The “Dav On” instruction enables WebDAV support. The LimitExcept section enables anonymous read access. Everything beyond needs some credentials.

enable collaboration

I want my repository to be available for others, too. (open source only is fun this way :) ). Therefor we need to support write access. Only a single account with public password is needed for enabling write access. This raises the barrier for bots to make use of your repository for different things and still is easy to use for potential collaborators. Write access in WebDAV terms is the HTTP PUT method. To use a different rule for PUT and enable credentials we have the following to do:

We add basic authentication to our directory:

AuthType BasicAuthName "selfish monticello repository"
AuthUserFile "/var/domains/selfish.org/etc/htpasswd"

Then we have to exclude the PUT method from the existing Limit sectionThe former rule changes from

<LimitExcept GET PROPFIND OPTIONS REPORT>

to

<LimitExcept GET PROPFIND OPTIONS REPORT PUT>

Now we can add a special rule for handling PUT requests

<Limit PUT>
   Require valid-user
</Limit>

We now have anonymous read access and write access if credentials are provided.

enabling file protection

We don’t want to have existing files overwritten. Monticello always stores a new file on the server. So we must protect the existing files from accidentially being overwritten. The only solution I found was using mod_rewrite. Adding the rewrite rule to the Limit section:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^PUT
RewriteCond %{REQUEST_FILENAME} -f 
RewriteRule . - [F,L]

You can read it as “If the incoming request has the PUT method and the file it tries to access exists in the filesystem than give back a FORBIDDEN HTTP error message (403) and do nothing”

This does not prevent new files from being created but existing files from being overwritten. Now we have a public repository that enables widely other people to contribute and at the same time it protects the files to stay as the author has intended it. The whole configuration now looks like this

# Monticello repository
<Directory /var/domains/selfish.org/web/source.docs/mc/>
   Options Indexes FollowSymLinks
   Order allow,deny
   Allow from all
   AuthType BasicAuthName "selfish monticello repository"
   AuthUserFile "/var/domains/selfish.org/etc/htpasswd"
   DAV On
   # Allow public retrieving of files without authentication
   # PUT is handled in the next rule
   # every other action needs admin privileges
   <LimitExcept GET PROPFIND OPTIONS REPORT PUT>
      Require user norbert
   </LimitExcept>
   # for every valid user allow uploading files if the file does not
   # exist, yet
   <Limit PUT>
      RewriteEngine On
      RewriteCond %{REQUEST_METHOD} ^PUT
      RewriteCond %{REQUEST_FILENAME} -f
      RewriteRule . - [F,L]
      Require valid-user
   </Limit>
</Directory>

The resulting repository is publicly available here. I will put most of my stuff (that does not belong to squeaksource or gemsource) there