20 August 2009

Share a git repository with unix groups

If you have a shared Linux/Unix box that all your developers use to share code with git, there are various ways of setting up the shared repository. If you just use git over ssh, you don't need to maintain any more servers.

The simplest possible solutions assume that there is a single user account and different developers are authenticated on the server with their ssh public keys. I needed to restrict which developers get access to different repositories, and to be able to switch these permissions on and off. Unix has already solved this problem of course, with users and groups. Here is how to use real users and groups on your unix server to control git access.

  1. Set up unix accounts for your users. "adduser jim"
  2. Set up groups for each project, "addgroup wonderproject-developers"
  3. Add the appropriate developers to the group "adduser jim wonderproject-developers"
  4. In a private directory on your server, logged in as yourself, make a directory for the git repository "mkdir wonderproject.git"
  5. Make the new group the group owner of the git repository "chgrp wonderproject-developers wonderproject.git/"
  6. Fix the perms so only the group and the owner can read and write the repository "chmod 770 wonderproject.git/"
  7. Make the repository setgid, so that any new files created inside it have group ownership the same as the directory "chmod g+s wonderproject.git"
  8. cd wonderproject.git
  9. create the git repository "git --bare init --shared=group" the --shared option ensures that git keeps the correct permissions when the various developers push commits into the repository.
  10. Now, if your project is empty, clone this new repository onto your desktop and start committing "git clone ssh://jim@git.example.com:port/path/to/repos/wonderproject.git
  11. If you have an existing repository on your desktop and you want to push it into the empty shared repository, edit your .git/config remote url to point at the new server url and then do a "git push --all"

30 June 2009

Switching off Expect: 100-Continue header with Apache HttpClient

Apache HTTP client version 4.0 (at least, the version bundled with the Android SDK) adds the header "Expect: 100-Continue" by default, which confuses many web servers. The following snippet switches this header off:

HttpClient client = new DefaultHttpClient();
client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

I was seeing an error response like the following before I switched this header off:

HTTP/1.1 417 Expectation Failed.
Date: Tue, 30 Jun 2009 10:03:59 GMT.
Server: hi.
Vary: Accept-Encoding.
Content-Length: 364.
Connection: close.
Content-Type: text/html; charset=iso-8859-1.

417 Expectation Failed
Expectation Failed
The expectation given in the Expect request-header field could not be met by this server.
The client sent Expect: 100-Continue but we only allow the 100-continue expectation.

Copying package selections with debian/ubuntu

This is documented in lots of places but it seems to always take me a while to find it. Here is how to install the set of packages from one machine to another.
  1. On the source machine: sudo dpkg --get-selections > output_file
  2. Transfer the output file to the target machine
  3. On the target machine: sudo dpkg --set-selections <>
  4. On the target machine: sudo apt-get -u dselect-upgrade

3 May 2009

Screen Tweaks on Ubuntu Jaunty

Screen is a must-have tool for anyone that spends time at the command line. I move my .screenrc file around with me whenever I move machine, and hadn't thought about it much for a while, but when I started screen on a Ubuntu Jaunty box with no .screenrc, I noticed that the system-wide screen config in /etc/screenrc is now quite useful.

The screenshot below shows the status line from the default config.


Using two whole lines for status messages seems a bit much but I'm a little old school when it comes to preserving display space. So you get load, CPU, free memory, a clock and named screens without any effort now.

I copied the /etc/screenrc to ~/.screenrc and added a few options

bind x
bind ^x
ignorecase on


The bind options stop C-ax, which normally detaches the terminal from screen, from working. I tend to type that keystroke by accident fairly frequently. The last option ignores case during history searches.

If you use lots of gnome-terminal windows or even tabs to manage your terminal sessions you should try screen, it will speed you up a lot once the keystrokes get wired into your muscle memory.

16 February 2009

MyFaces NoSuchMethodError

java.lang.NoSuchMethodError - org.apache.myfaces.component.html.ext.HtmlDataTable.refresh(Ljavax/faces/context/FacesContext;)V

This exception can be thrown by MyFaces when the page backing bean doesn't return a String that is mapped in the navigation-rules in faces-config.xml (or wherever you have your mapping file).

Check for typos or a missing entry in the navigation rules.

Hibernate gotcha: in clause with positional and named query parameters

Here's a gotcha that can break JPA QL queries with an IN clause when using Hibernate as the persistence provider. The problem happens when you use positional parameters rather than named parameters.

Code such as the following will break with positional parameters:
List states = widgetService.findSomeWidgetStates();
Query q = entityManager.createQuery("select count(w) from Widget w where w.state in (?)");
q.setParameter(1, states);
with the error message:
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field example.Widget.id to....
But if you change to named parameters, as in:
Query q = entityManager.createQuery("select count(w) from Widget w where w.state in (:widgetStates)");
q.setParameter("widgetStates", states);
Everything just works. So it seems named parameters are worth a little extra typing.