Adapt Debian stuff to new build process debian
authorPaul Crowley <paul@lshift.net>
Mon, 09 Nov 2009 16:23:04 +0000
branchdebian
changeset 172 5dd3698fad54
parent 118 107906bfe2c6 (current diff)
parent 171 7b69d1d86254 (diff)
child 174 f141a4b9d5a9
Adapt Debian stuff to new build process
debian/dirs
debian/docs
debian/rules
doc/configuring-access
doc/file-conditions
doc/how-it-works
doc/security
install
--- a/.hgignore	Tue Oct 13 18:32:26 2009 +0100
+++ b/.hgignore	Mon Nov 09 16:23:04 2009 +0000
@@ -1,3 +1,4 @@
+^build/
 syntax: glob
 
 *~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Mon Nov 09 16:23:04 2009 +0000
@@ -0,0 +1,58 @@
+#!/usr/bin/env make -f
+
+TOPDIR=
+PREFIX=$(TOPDIR)/usr/local/share
+LIBDIR=$(PREFIX)/mercurial-server
+DOCDIR=$(PREFIX)/doc/mercurial-server
+ETCDIR=$(TOPDIR)/etc/mercurial-server
+NEWUSER=hg
+
+INSTALL=install
+
+build: build/html/index.html pythonbuild
+
+setup-adduser: installfiles adduser inituser
+
+# WARNING: this is experimental
+setup-useradd: installfiles useradd inituser
+
+installetc:
+	$(INSTALL) -d $(ETCDIR)
+	$(INSTALL) -m 644 -t $(ETCDIR) \
+	    src/init/conf/remote-hgrc src/init/conf/access.conf
+	$(INSTALL) -d $(ETCDIR)/keys/root
+	$(INSTALL) -d $(ETCDIR)/keys/user
+
+installdoc: build/html/index.html
+	$(INSTALL) -d $(DOCDIR)
+	$(INSTALL) -m 644 -t $(DOCDIR) README build/html/index.html
+
+build/html/index.html: doc/manual.docbook
+	xsltproc -o $@ /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl $^
+
+pythonbuild:
+	python setup.py build
+
+pythoninstall:
+	python setup.py install \
+	    --install-purelib=$(LIBDIR) \
+	    --install-platlib=$(LIBDIR) \
+	    --install-scripts=$(LIBDIR) \
+	    --install-data=$(LIBDIR)
+
+installfiles: installetc installdoc pythoninstall 
+
+adduser:
+	adduser --system --shell /bin/sh --group --disabled-password \
+	    --home /var/lib/mercurial-server \
+	    --gecos  "Mercurial repositories" $(NEWUSER)
+
+# WARNING: this is experimental
+useradd:
+	useradd --system --shell /bin/sh \
+	    --home /var/lib/mercurial-server --create-home \
+	    --comment  "Mercurial repositories" $(NEWUSER)
+
+inituser:
+	su -l -c "$(LIBDIR)/init/hginit $(LIBDIR)" $(NEWUSER)
+
--- a/README	Tue Oct 13 18:32:26 2009 +0100
+++ b/README	Mon Nov 09 16:23:04 2009 +0000
@@ -1,8 +1,6 @@
 mercurial-server
 
-mercurial-server makes a group of repositories available to the developers
-you choose, identified by ssh keys, with easy key and access management
-based on hg.
+mercurial-server gives your developers remote read/write access to centralized Mercurial repositories using SSH public key authentication; it provides convenient and fine-grained key management and access control. 
 
 http://www.lshift.net/mercurial-server.html
 
@@ -22,134 +20,17 @@
     with this program; if not, write to the Free Software Foundation, Inc.,
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-SUMMARY
-
-mercurial-server makes a group of repositories available to the developers
-you choose, identified by ssh keys, with easy key and access management
-based on hg.
-
-All of the repositories controlled by mercurial-server are owned by a
-single user (the "hg" user in what follows), but many remote users can act
-on them, and different users can have different permissions. We don't use
-file permissions to achieve that - instead, developers log in as the "hg"
-user when they connect to the repository host using ssh, using ssh URLs of
-the form "ssh://hg@repository-host/repository-name". A restricted shell
-prevents them from using this access for unauthorized purposes. Developers
-are authenticated only using SSH keys; no other form of authentication is
-supported. 
-
-To give a user access to the repository, place their key in an
-appropriately-named subdirectory of "/etc/mercurial-server/keys" and run
-"/usr/local/share/mercurial-server/refresh-auth". You can then control what
-access they have to what repositories by editing the control file
-"/etc/mercurial-server/access.conf", which can match the names of these keys
-against a glob pattern. 
-
-For convenient remote control of access, you can instead (if you have the
-privileges) make changes to a special repository called "hgadmin", which
-contains its own "access.conf" file and "keys" directory. Changes pushed to
-this repository take effect immediately. The two "access.conf" files are
-concatenated, and the keys directories merged.
-
-QUICK START
+Though mercurial-server is currently targeted at Debian-based systems such as Ubuntu, other users have reported success getting it running on other Unix-based systems such as Red Hat. Running it on a non-Unix system such as Windows is not supported. You will need root privileges to install it. 
 
-You and all developers using this system will need an SSH public key, and
-will almost certainly want to be running ssh-agent (or its equivalent, eg
-Pageant under Windows). If you're not familiar with ssh-agent, you should
-learn about that before using this.
-
-In what follows, certain operations (eg installing mercurial-server itself)
-have to be done on the repository server (which we call "repository-host"),
-but any operation that involves checking in or out of Mercurial can be done
-wherever is most convenient to you; the most usual arrangment would be that
-you'd do these things at the machine you sit at, and on which you run
-ssh-agent, which is what authenticates you when you talk to the repository
-server.
+The best way to install mercurial-server is using your package management system.  However, there is some provision for installing it directly.  On Debian based systems such as Ubuntu, use the command
 
-Ensure there is no user called "hg" on the repository host, and run
-"./install". This installs the mercurial-server files and control files, and
-creates and sets up the "hg" user.
-
-Place your SSH public key in the directory "/etc/mercurial-server/keys/root".
-I suggest creating yourself a directory and naming the key after your hostname
-(ie the file is called something like
-"/etc/mercurial-server/keys/root/yourname/yourhostname") so that you can
-easily manage users who have a different key on each host they use. Then run
-"/usr/local/share/mercurial-server/refresh-auth".
-
-The repository is now ready to use, and you are now the sole user able to
-change and create repositories on this repository host.  
-
-CREATING REPOSITORIES
-
-To create a new repository, you clone a local repository onto the remote
-server. So if you want a new empty repository called "myproject", you can do
-(as yourself):
+    sudo make setup-adduser
 
-    hg init myproject
-    hg clone myproject ssh://hg@repository-host/myproject
-
-ADDING OTHER USERS
-
-Because your key is in the "keys/root" subdirectory, you have the equivalent
-of "root privileges" over mercurial-server (not the whole computer, just
-mercurial-server). You can add other root users by putting their keys next to
-yours, or you can make less privileged users by putting their keys in the
-"keys/users" subdirectory - these users will be able to read and write to any
-repository (except one - see below) but will not be able to create new
-repositories. As always, when you change "/etc/mercurial-server/keys" you need
-to re-run "/usr/local/share/mercurial-server/refresh-auth".
-
-LOGGING
-
-Every push and pull is logged with the key used: see the file .hg/serve-log in
-each repository.
-
-USING HGADMIN
-
-It can be inconvenient to log on to the repository server, become root, copy
-keys around, and run "refresh-auth" every time you want to change user
-privileges. This is where mercurial-server shines :-) Suppose you have another
-user's SSH public key in the file "/tmp/theirkey" (on the machine you sit at,
-not necessarily the repository server) and you want to give them user-level
-access to the repository server. Run these commands:
+On Red Hat and possibly other variants of Unix, try
 
-    hg clone ssh://hg@repository-server/hgadmin
-    cd hgadmin
-    mkdir keys/users/thatuser
-    cp /tmp/theirkey keys/users/thatuser/theirhostname
-    hg add
-    hg commit -m "Added key for thatuser"
-    hg push
-
-In other words, hgadmin is a version controlled version of
-"/etc/mercurial-server", and changes to it take effect immediately -
-"refresh-auth" is run after every push. 
-
-With the default access.conf file (see doc/configuring-access for more
-details) only users in "keys/root" can act on "hgadmin" - those with keys in
-"keys/users" cannot even read this repository. So multiple admins can use
-Mercurial's version control to cooperate on controlling access to the
-repository server in a natural way.
+    sudo make setup-useradd
 
-You can also create an "access.conf" file in hgadmin, and this is appended to
-/etc/mercurial-server/access.conf whenever this is read - in other words,
-rules in the latter take precedence over those in the former. So once you're
-working with "hgadmin", it can be convenient to remove all the keys in
-"/etc/mercurial-server/keys" and all the entries in
-"/etc/mercurial-server/access.conf" and use hgadmin to control everything. If
-you find yourself locked out, you can get back in again by restoring some of
-the entries you removed from these files.
-
-MORE INFORMATION
-
-For more on how to use mercurial-server and configure access, see the files in
-the doc directory.
-
-THANKS
-
-Thanks for reading this far. If you use mercurial-server, please tell me about
-it.
+See doc/manual.docbook for the rest of the documentation.
 
 Paul Crowley, paul@lshift.net, 2009
 
--- a/debian/dirs	Tue Oct 13 18:32:26 2009 +0100
+++ b/debian/dirs	Mon Nov 09 16:23:04 2009 +0000
@@ -1,5 +1,6 @@
 usr/share/mercurial-server
 usr/share/mercurial-server/init
+usr/share/mercurial-server/init/conf
 usr/share/mercurial-server/mercurialserver
 usr/share/doc/mercurial-server
 etc/mercurial-server
--- a/debian/docs	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-README
-doc/configuring-access
-doc/file-conditions
-doc/how-it-works
-doc/security
-
--- a/debian/rules	Tue Oct 13 18:32:26 2009 +0100
+++ b/debian/rules	Mon Nov 09 16:23:04 2009 +0000
@@ -16,7 +16,6 @@
 
 	touch configure-stamp
 
-
 build: build-stamp
 
 build-stamp: configure-stamp  
@@ -43,27 +42,9 @@
 	dh_installdirs
 
 	# Add here commands to install the package into debian/mercurial-server.
-	cp \
-	    src/hg-ssh \
-	    src/refresh-auth \
-	    debian/mercurial-server/usr/share/mercurial-server
-	cp \
-	    src/mercurialserver/__init__.py \
-	    src/mercurialserver/paths.py \
-	    src/mercurialserver/changes.py \
-	    src/mercurialserver/access.py \
-	    src/mercurialserver/servelog.py \
-	    src/mercurialserver/refreshauth.py \
-	    src/mercurialserver/ruleset.py \
-	    debian/mercurial-server/usr/share/mercurial-server/mercurialserver
-	cp \
-	    src/init/hginit \
-	    src/init/hgadmin-hgrc \
-	    debian/mercurial-server/usr/share/mercurial-server/init
-	cp \
-	    src/init/conf/remote-hgrc \
-	    src/init/conf/access.conf \
-	    debian/mercurial-server/etc/mercurial-server
+	$(MAKE) installfiles \
+	    TOPDIR=debian/mercurial-server \
+	    PREFIX=debian/mercurial-server/usr/share
 
 # Build architecture-independent files here.
 binary-indep: build install
@@ -83,7 +64,7 @@
 #	dh_installemacsen
 #	dh_installpam
 #	dh_installmime
-#	dh_python
+	dh_python
 #	dh_installinit
 #	dh_installcron
 #	dh_installinfo
--- a/doc/configuring-access	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-ACCESS.CONF
-
-Out of the box, there are just two kinds of users: the ones with keys in
-"keys/root" and those in "keys/users". However, you can change this by
-editing "access.conf". There are two "access.conf" files, one in
-"/etc/mercurial-server" and one in "hgadmin"; the two are simply
-concatenated before being read.
-
-Each line of access.conf has the following syntax:
-
-<rule> <condition> <condition> ...
-
-Rule is one of
-
-init - allow any operation, including the creation of new repositories
-write - allow reads and writes to this file in this repository
-read - allow the repo to be read but reject matching writes
-deny - deny all requests
-
-A condition is a globpattern matched against a relative path. The two most
-important conditions are
-
-    user=<globpattern> - user's key
-    repo=<globpattern> - repo (as the user supplies it)
-
-The first rule in the file which has all its conditions satisfied is used
-to determine whether an action is allowed. If no rule is matched the
-request is denied.
-
-"*" only matches one directory level, where "**" matches as many as you
-want. More precisely, "*" matches zero or more characters not including "/"
-while "**" matches zero or more characters including "/".
-
-Blank lines and lines that start with "#" are ignored.
-
-access.conf ships with the following contents:
-
-    init user=root/**
-    deny repo=hgadmin
-    write user=users/**
-
-This means: keys in "root" can do anything; keys in "users" cannot create
-repositories, cannot even read the hgadmin repository, but can read and
-write any other repository; no other key has any access.
-
-More advanced access configuration is covered in file-conditions.
-
--- a/doc/file-conditions	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-FILE CONDITIONS
-
-Read configuring-access before you read this.
-
-mercurial-server supports file and branch conditions, which restrict an
-operation depending on what files it modifies and what branch the work is
-on. However, the way these conditions work is subtle and can be
-counterintuitive - if you want to keep things simple, stick to user and
-repo conditions, and then things are likely to work the way you would
-expect.
-
-File and branch conditions are added to the conditions against which a rule
-matches, just like user and repo conditions; they have this form:
-
-    file=<globpattern> - file in the repo
-    branch=<globpattern> - name of the branch
-
-However, in order to understand what effect adding these conditions will
-have, it helps to understand how and when these rules are applied.
-
-The rules file is used to make four decisions:
-
-- Whether to allow a repository to be created
-- Whether to allow access to a repository
-- Whether to allow a changeset on a particular branch at all
-- Whether to allow a changeset to change a particular file
-
-When the first two of these decisions are being made, nothing is known
-about what files might be changed, and so all file conditions automatically
-succeed for the purpose of such decisions. This means that doing tricky
-things with file conditions can have counterintuitive consequences:
-
-- You cannot limit read access to a subset of a repository with a "read"
-rule and a file condition: any user who has access to a repository can read
-all of it and its full history. Such a rule can only have the effect of
-masking a later "write" rule, as in this example:
-
-   read repo=specialrepo file=dontwritethis
-   write repo=specialrepo
-
-allows all users to read specialrepo, and to write to all files *except*
-that any changeset which writes to "dontwritethis" will be rejected.
-
-- For similar reasons, don't give "init" rules file conditions.
-
-- Don't try to deny write access to a particular file on a particular
-branch - a developer can write to the file on another branch and then merge
-it in. Either deny all writes to the branch from that user, or allow them
-to write to all the files they can write to on any branch. In other words,
-something like this will have the intended effect:
-
-  write user=docs/* branch=docs file=docs/*
-
-But something like this will not have the intended effect; it will
-effectively allow these users to write to any file on any branch, by
-writing it to "docs" first:
-
-  write user=docs/* branch=docs
-  write user=docs/* file=docs/*
-  read user=docs/*
-
-
--- a/doc/how-it-works	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-HOW IT WORKS
-
-When a developer attempts to connect to a repository via ssh, the SSH
-daemon searches for a match for that user's key in
-~hg/.ssh/authorized_keys. If the developer is authorised to connect to the
-repository they will have an entry in this file. The entry includes a
-"command" prefix which specifies that the restricted shell
-"/usr/local/share/mercurial-server/hg-ssh" should be used; this shell is
-passed an argument identifying the developer. The shell parses the command
-the developer is trying to execute, and consults a rules file to see if
-that developer is allowed to perform that action on that repository.
-
-The file ~hg/.ssh/authorized_keys is generated by "refresh-auth", which
-recurses through two directories of files containing SSH keys and generates
-an entry in authorized_keys for each one, using the name of the key file as
-the identifier for the developer. These keys will live in the "keys"
-subdirectory "/etc/mercurial-server" and the "keys" subdirectory of a
-repository called "hgadmin". A hook in this repository re-runs
-"refresh-auth" on the most recent version after every push.
-
-When users try to commit new changesets, a hook is run which consults the
-rules file to decide whether to allow the changeset into the repository.
-This can depend not only on the user and the repository, but also the
-branch and files in the changeset.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/manual.docbook	Mon Nov 09 16:23:04 2009 +0000
@@ -0,0 +1,527 @@
+<?xml version="1.0" encoding="utf-8"?>
+<article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en"
+  xmlns:xlink="http://www.w3.org/1999/xlink">
+<info>
+  <title>Sharing Mercurial repositories with mercurial-server</title>
+  <author><firstname>Paul</firstname><surname>Crowley</surname></author>
+  <copyright><year>2009</year><holder>Paul Crowley, LShift Ltd</holder></copyright>
+</info>
+<section>
+<title>About mercurial-server</title>
+<para>
+Home page: <link xlink:href="http://www.lshift.net/mercurial-server.html"/>
+</para>
+<para>
+mercurial-server gives your developers remote read/write access to
+centralized <link xlink:href="http://hg-scm.org/">Mercurial</link>
+repositories using SSH public key authentication; it provides convenient
+and fine-grained key management and access control.
+</para>
+<para>
+Though mercurial-server is currently targeted at Debian-based systems such
+as Ubuntu, other users have reported success getting it running on other
+Unix-based systems such as Red Hat. Running it on a non-Unix system such as
+Windows is not supported. You will need root privileges to install it.
+</para>
+</section>
+<section>
+<title>Step by step</title>
+<para>
+mercurial-server authenticates users not using passwords but using SSH
+public keys; everyone who wants access to a mercurial-server repository
+will need such a key. In combination with <command>ssh-agent</command> (or
+equivalents such as the Windows program <link
+xlink:href="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">Pageant</link>),
+this means that users will not need to type in a password to access the
+repository. If you're not familiar with SSH public keys, the <link
+xlink:href="http://sial.org/howto/openssh/publickey-auth/">OpenSSH Public
+Key Authentication tutorial</link> may be helpful.
+</para>
+<section>
+<title>Installing mercurial-server</title>
+<para>
+In what follows, we assume that your username is <systemitem
+class="username">jay</systemitem>, that you usually sit at a machine called
+<systemitem class="systemname">spoon</systemitem> and you wish to
+install mercurial-server on <systemitem
+class="systemname">jeeves</systemitem>. We assume that you have created your SSH public key, set up your SSH agent with this key, and that this key gives you access to <systemitem
+class="systemname">jeeves</systemitem>.  
+</para>
+<para>First install mercurial-server on <systemitem
+class="systemname">jeeves</systemitem>:</para>
+<screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>scp mercurial-server_0.6.1_amd64.deb jeeves:</userinput>
+<computeroutput>mercurial-server_0.6.1_amd64.deb 100%
+jay@spoon:~$ </computeroutput><userinput>ssh -A jeeves</userinput>
+<computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo dpkg -i mercurial-server_0.6.1_amd64.deb</userinput>
+<computeroutput>[sudo] password for jay: 
+Selecting previously deselected package mercurial-server.
+(Reading database ... 144805 files and directories currently installed.)
+Unpacking mercurial-server (from .../mercurial-server_0.6.1_amd64.deb) ...
+Setting up mercurial-server (0.6.1) ...
+jay@jeeves:~$ </computeroutput></screen>
+<para>
+mercurial-server is now installed on the repository host.  Next, we need to give you permission to access its repositories.
+</para>
+<screen><computeroutput>jay@jeeves:~$ </computeroutput><userinput>ssh-add -L > my-key</userinput>
+<computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo mkdir -p /etc/mercurial-server/keys/root/jay</userinput>
+<computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo cp my-key /etc/mercurial-server/keys/root/jay/spoon</userinput>
+<computeroutput>jay@jeeves:~$ </computeroutput><userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput>
+<computeroutput>jay@jeeves:~$ </computeroutput><userinput>exit</userinput>
+<computeroutput>Connection to jeeves closed.
+jay@spoon:~$ </computeroutput></screen>
+<para>
+You can now create repositories on the remote machine and have complete
+read-write access to all of them.
+</para>
+</section>
+<section>
+<title>Creating repositories</title>
+<para>
+To store a repository on the server, clone it over.
+</para>
+<screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>cd myproj</userinput>
+<computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>hg clone . ssh://hg@jeeves/jays/project</userinput>
+<computeroutput>searching for changes
+remote: adding changesets
+remote: adding manifests
+remote: adding file changes
+remote: added 119 changesets with 284 changes to 61 files
+jay@spoon:~/myproj$ </computeroutput><userinput>hg pull ssh://hg@jeeves/jays/project</userinput>
+<computeroutput>pulling from ssh://hg@jeeves/jays/project
+searching for changes
+no changes found
+<computeroutput>jay@spoon:~/myproj$ </computeroutput><userinput>cd ..</userinput>
+jay@spoon:~$ </computeroutput></screen>
+</section>
+<section>
+<title>Adding other users</title>
+<para>
+At this stage, no-one but you has any access to any repositories you
+create on this system. In order to give anyone else access, you'll need a
+copy of their SSH public key; we'll assume you have that key in
+<filename>~/sam-saucer-key.pub</filename>.  To manage access, you make changes to the special <filename
+class='directory'>hgadmin</filename> repository.
+</para>
+<screen><computeroutput>jay@spoon:~$ </computeroutput><userinput>hg clone ssh://hg@jeeves/hgadmin</userinput>
+<computeroutput>destination directory: hgadmin
+no changes found
+updating working directory
+0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+jay@spoon:~$ </computeroutput><userinput>cd hgadmin</userinput>
+<computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>mkdir -p keys/users/sam</userinput>
+<computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>cp ~/sam-saucer-key.pub keys/users/sam/saucer</userinput>
+<computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg add</userinput>
+<computeroutput>adding keys/users/sam/saucer
+jay@spoon:~/hgadmin$ </computeroutput><userinput>hg commit -m "Add Sam's key"</userinput>
+<computeroutput>jay@spoon:~/hgadmin$ </computeroutput><userinput>hg push</userinput>
+<computeroutput>pushing to ssh://hg@jeeves/hgadmin
+searching for changes
+remote: adding changesets
+remote: adding manifests
+remote: adding file changes
+remote: added 1 changesets with 1 changes to 1 files
+jay@spoon:~/hgadmin$ </computeroutput></screen>
+<para>
+Sam can now read and write to your
+<uri>ssh://hg@jeeves/jays/project</uri> repository.
+Most other changes to access control can be made simply by making and
+pushing changes to <filename
+class='directory'>hgadmin</filename>, and you can use Mercurial to
+cooperate with other root users in the normal way.
+</para>
+<para>
+If you prefer, you could give them access by
+logging into <systemitem class="systemname">jeeves</systemitem>,
+putting the key in the right place under <filename
+class='directory'>/etc/mercurial-server/keys</filename>, and re-running
+<userinput>sudo -u hg /usr/share/mercurial-server/refresh-auth</userinput>.
+However, using <filename
+class='directory'>hgadmin</filename> is usually more convenient if you need to make more than a very few changes; it also makes it easier to share administration with others and provides a log of all changes.
+</para>
+</section>
+</section>
+<section>
+<title>Access control</title>
+<para>
+Out of the box, mercurial-server supports two kinds of users: "root" users and normal users.  If you followed the steps above, you are a "root" user because your key is under <filename class='directory'>keys/root</filename>, while the other user you gave access to is a normal user since their key is under <filename class='directory'>keys/users</filename>.  Keys that are not in either of these directories will by default have no access to anything.
+</para>
+<para>
+Root users can edit <filename
+class='directory'>hgadmin</filename>, create new repositories and read and write to existing ones.  Normal users cannot access <filename
+class='directory'>hgadmin</filename> or create new repositories, but they can read and write to any other repository.
+</para>
+<section>
+<title>Using access.conf</title>
+<para>
+mercurial-server offers much more fine-grained access control than this division into two classes of users.  Let's suppose you wish to give Pat access to the <filename
+class='directory'>widget</filename> repository, but no other.  We first copy Pat's SSH public key into the <filename
+class='directory'>keys/pat</filename> directory in <filename
+class='directory'>hgadmin</filename>.  This tells mercurial-server about Pat's key, but gives Pat no access to anything because the key is not under either <filename
+class='directory'>keys/root</filename> or <filename
+class='directory'>keys/users</filename>.  To grant this key access, we must give mercurial-server a new access rule, so we create a file in <filename
+class='directory'>hgadmin</filename> called <filename>access.conf</filename>, with the following contents:</para>
+<programlisting># Give Pat access to the "widget" repository
+write repo=widget user=pat
+</programlisting>
+<para>
+Pat will have read and write access to the <filename
+class='directory'>widget</filename> repository as soon as we add, commit, and push these files.
+</para>
+<para>
+Each line of <filename>access.conf</filename> has the following syntax:
+</para>
+<programlisting><replaceable>rule</replaceable> <replaceable>condition</replaceable> <replaceable>condition...</replaceable>
+</programlisting>
+<para>
+Blank lines and lines that start with <code>#</code> are ignored. Rule is
+one of
+</para>
+<itemizedlist>
+<listitem>
+<literal>init</literal>: allow reads, writes, and the creation of new repositories
+</listitem>
+<listitem>
+<literal>write</literal>: allow reads and writes
+</listitem>
+<listitem>
+<literal>read</literal>: allow only read operations
+</listitem>
+<listitem>
+<literal>deny</literal>: deny all requests
+</listitem>
+</itemizedlist>
+<para>
+A condition is a globpattern matched against a relative path. The two most
+important conditions are
+</para>
+<itemizedlist>
+<listitem>
+<code>user=<replaceable>globpattern</replaceable></code>: path to the user's key
+</listitem>
+<listitem>
+<code>repo=<replaceable>globpattern</replaceable></code>: path to the repository
+</listitem>
+</itemizedlist>
+<para>
+<code>*</code> only matches one directory level, where <code>**</code>
+matches as many as you want. More precisely, <code>*</code> matches zero or
+more characters not including <code>/</code> while <code>**</code> matches
+zero or more characters including <code>/</code>. So
+<code>projects/*</code> matches <filename
+class='directory'>projects/foo</filename> but not <filename
+class='directory'>projects/foo/bar</filename>, while
+<code>projects/**</code> matches both.
+</para>
+<para>
+When considering a request, mercurial-server steps through all the rules in
+<filename>/etc/mercurial-server/access.conf</filename> and then all the
+rules in <filename>access.conf</filename> in <filename
+class='directory'>hgadmin</filename>
+looking for a rule which matches on every condition. The first match
+determines whether the request will be allowed; if there is no match in
+either file, the request will be denied.
+</para>
+<para>
+By default, <filename>/etc/mercurial-server/access.conf</filename> has the
+following rules:
+</para>
+<programlisting>init user=root/**
+deny repo=hgadmin
+write user=users/**
+</programlisting>
+<para>
+These rules ensure that root users can do any operation on any repository,
+that no other users can access the <filename
+class='directory'>hgadmin</filename> repository,
+and that those with keys in <filename
+class='directory'>keys/users</filename> can read or write to any repository
+but not create repositories.  Some examples of how these rules work:
+</para>
+<itemizedlist>
+<listitem>
+User <filename class='directory'>root/jay</filename> creates a repository
+<filename class='directory'>foo/bar/baz</filename>. This matches the first
+rule and so will be allowed.
+</listitem>
+<listitem>
+User <filename class='directory'>root/jay</filename> changes repository
+<filename class='directory'>hgadmin</filename>. Again, this matches the
+first rule and so will be allowed; later rules have no effect.
+</listitem>
+<listitem>
+User <filename class='directory'>users/sam</filename> tries to read
+repository <filename class='directory'>hgadmin</filename>. This does not
+match the first rule, but matches the second, and so will be denied.
+</listitem>
+<listitem>
+User <filename class='directory'>users/sam</filename> tries to create
+repository <filename class='directory'>sams-project</filename>. This does
+not match the first two rules, but matches the third; this is a
+<literal>write</literal> rule, which doesn't grant the privilege to create
+repositories, so the request will be denied.
+</listitem>
+<listitem>
+User <filename class='directory'>users/sam</filename> writes to existing
+repository <filename class='directory'>projects/main</filename>. Again,
+this matches the third rule, which allows the request.
+</listitem>
+<listitem>
+User <filename class='directory'>pat</filename> tries to write to existing
+repository <filename class='directory'>widget</filename>. Until we change
+the <filename>access.conf</filename> file in <filename
+class='directory'>hgadmin</filename>, this will match no rule, and so will
+be denied.
+</listitem>
+<listitem>
+Any request from a user whose key not under the <filename
+class='directory'>keys</filename> directory at all will always be denied,
+no matter what rules are in effect; because of the way SSH authentication
+works, they will be prompted to enter a password, but no password will
+work. This can't be changed.
+</listitem>
+</itemizedlist>
+</section>
+<section>
+<title>/etc/mercurial-server and hgadmin</title>
+<para>
+mercurial-server consults two distinct locations to collect information about what to allow: <filename
+class='directory'>/etc/mercurial-server</filename> and its own <filename
+class='directory'>hgadmin</filename> repository.  This is useful for several reasons:
+</para>
+<itemizedlist>
+<listitem>
+Some users may not need the convenience of access control via mercurial; for these users updating <filename
+class='directory'>/etc/mercurial-server</filename> may offer a simpler route.
+</listitem>
+<listitem>
+<filename class='directory'>/etc/mercurial-server</filename> is suitable
+for management with tools such as <link
+xlink:href="http://reductivelabs.com/products/puppet">Puppet</link>
+</listitem>
+<listitem>
+If a change to <filename
+class='directory'>hgadmin</filename> leaves you "locked out", <filename
+class='directory'>/etc/mercurial-server</filename> allows you a way back in.
+</listitem>
+<listitem>
+At install time, all users are "locked out", and so some mechanism to allow some users in is needed.
+</listitem>
+</itemizedlist>
+<para>
+Rules in <filename>/etc/mercurial-server/access.conf</filename> are checked before those in <filename
+class='directory'>hgadmin</filename>, and keys in <filename class='directory'>/etc/mercurial-server/keys</filename> will be present no matter how <filename
+class='directory'>hgadmin</filename> changes.
+</para>
+<para>
+We anticipate that once mercurial-server is successfully installed and
+working you will usually want to use <filename
+class='directory'>hgadmin</filename> for most
+access control tasks. Once you have the right keys and
+<filename>access.conf</filename> set up in <filename
+class='directory'>hgadmin</filename>, you
+can delete <filename>/etc/mercurial-server/access.conf</filename> and all
+of <filename class='directory'>/etc/mercurial-server/keys</filename>,
+turning control entirely over to <filename
+class='directory'>hgadmin</filename>.
+</para>
+<para>
+<filename>/etc/mercurial-server/remote-hgrc</filename> is in the
+<systemitem>HGRCPATH</systemitem> for all remote access to mercurial-server
+repositories. This file contains the hooks that mercurial-server uses for
+access control and logging. You can add hooks to this file, but obviously
+breaking the existing hooks will disable the relevant functionality and
+isn't advisable.
+</para>
+</section>
+<section>
+<title>File and branch conditions</title>
+<para>
+mercurial-server supports file and branch conditions, which restrict an
+operation depending on what files it modifies and what branch the work is
+on. </para>
+<caution>
+The way these conditions work is subtle and can be counterintuitive. Unless
+you need what they provide, ignore this section, stick to user and repo
+conditions, and then things are likely to work the way you would expect. If
+you do need what they provide, read what follows very carefully.
+</caution>
+<para>
+File and branch conditions are added to the conditions against which a rule
+matches, just like user and repo conditions; they have this form:
+</para>
+<itemizedlist>
+<listitem>
+<code>file=<replaceable>globpattern</replaceable></code>: file within the repo
+</listitem>
+<listitem>
+<code>branch=<replaceable>globpattern</replaceable></code>: Mercurial branch name
+</listitem>
+</itemizedlist>
+<para>
+However, in order to understand what effect adding these conditions will
+have, it helps to understand how and when these rules are applied.
+</para>
+<para>
+The rules file is used to make three decisions:
+</para>
+<itemizedlist>
+<listitem>
+Whether to allow a repository to be created
+</listitem>
+<listitem>
+Whether to allow any access to a repository
+</listitem>
+<listitem>
+Whether to allow a changeset
+</listitem>
+</itemizedlist>
+<para>
+When the first two of these decisions are being made, nothing is known
+about any changsets that might be pushed, and so all file and branch
+conditions automatically succeed for the purpose of such decisions. For the
+third condition, every file changed in the changeset must be allowed by a
+<literal>write</literal> or <literal>init</literal> rule for the changeset
+to be allowed.
+</para>
+<para>
+This means that doing tricky things with file conditions can have
+counterintuitive consequences:
+</para>
+<itemizedlist>
+<listitem>
+<para>You cannot limit read access to a subset of a repository with a <literal>read</literal>
+rule and a file condition: any user who has access to a repository can read
+all of it and its full history. Such a rule can only have the effect of
+masking a later <literal>write</literal> rule, as in this example:</para>
+<programlisting>read repo=specialrepo file=dontwritethis
+write repo=specialrepo
+</programlisting>
+<para>
+allows all users to read <literal>specialrepo</literal>, and to write to all files
+<emphasis>except</emphasis> that any changeset which writes to
+<filename>dontwritethis</filename> will be rejected.
+</para>
+</listitem>
+<listitem>
+For similar reasons, don't give <literal>init</literal> rules file conditions.
+</listitem>
+<listitem>
+<para>Don't try to deny write access to a particular file on a particular
+branch&#x2014;a developer can write to the file on another branch and then merge
+it in. Either deny all writes to the branch from that user, or allow them
+to write to all the files they can write to on any branch.
+</para>
+<programlisting>write user=docs/* branch=docs file=docs/*
+</programlisting>
+<para>
+This rule grants users whose keys are in the <filename
+class='directory'>docs</filename> subdirectory the power to push changesets
+into any repository only if those changesets are on the
+<literal>docs</literal> branch and they affect only those files directly
+under the <filename class='directory'>docs</filename> directory. However,
+the rules below have more counterintuitive consequences.
+</para>
+<programlisting>write user=docs/* branch=docs
+write user=docs/* file=docs/*
+read user=docs/*
+</programlisting>
+<para>
+These rules grant users whose keys are in the <filename
+class='directory'>docs</filename> subdirectory the power to change any file directly under the <filename class='directory'>docs</filename> directory, or any file at all in the <literal>docs</literal> branch.  Indirectly, however, this adds up to the power to change any file on any branch, simply by making the change on the docs branch and then merging the change into another branch.
+</para>
+</listitem>
+</itemizedlist>
+</section>
+</section>
+<section>
+<title>How mercurial-server works</title>
+<para>
+All of the repositories controlled by mercurial-server are owned by a
+single user, the <systemitem
+class="username">hg</systemitem> user, which is why all URLs for
+mercurial-server repositories start with <uri>ssh://hg@...</uri>.
+Each SSH key that has access to the repository has an entry in
+<filename>~hg/.ssh/authorized_keys</filename>; this is how the SSH daemon
+knows to give that key access. When the user connects over SSH, their
+commands are run in a custom restricted shell; this shell knows which key
+was used to connect, determines what the user is trying to do, checks the
+access rules to decide whether to allow it, and if allowed invokes
+Mercurial internally, without forking.
+</para>
+<para>
+This restricted shell also ensures that certain Mercurial extensions are
+loaded when the user acts on a repository; these extensions check the
+access control rules for any changeset that the user tries to commit, and
+log all pushes and pulls into a per-repository access log.
+</para>
+<para>
+<command>refresh-auth</command> recurses through the <filename
+class='directory'>/etc/mercurial-server/keys</filename> and the <filename
+class='directory'>keys</filename> directory in the
+<filename
+class='directory'>hgadmin</filename> repository, creating an entry in
+<filename>~hg/.ssh/authorized_keys</filename> for each one. This is redone
+automatically whenever a change is pushed to <filename
+class='directory'>hgadmin</filename>.
+</para>
+</section>
+<section>
+<title>Security</title>
+<para>
+mercurial-server relies entirely on <command>sshd</command> to grant access to remote users.
+As a result, it runs no daemons, installs no setuid programs, and no part
+of it runs as <systemitem
+class="username">root</systemitem> except the install process: all programs run as the user
+<systemitem
+class="username">hg</systemitem>. Any attack on mercurial-server can only be started if the attacker
+already has a public key in <filename>~hg/.ssh/authorized_keys</filename>,
+otherwise <command>sshd</command> will bar the way.
+</para>
+<para>
+No matter what command the user tries to run on the remote system via SSH,
+mercurial-server is run. It parses the command line the user asked for, and
+interprets and runs the corresponding operation itself if access is
+allowed, so users can only read and add to history within repositories;
+they cannot run any other command. In addition, every push and pull is
+logged with a datestamp, changeset ID and the key that performed the
+operation.
+</para>
+<para>
+However, while the first paragraph holds no matter what bugs
+mercurial-server contains, the second depends on the relevant code being
+correct; though the entire codebase is short, mercurial-server is a fairly
+new program and may harbour bugs. Backups are essential!
+</para>
+</section>
+<section>
+<title>Legalese</title>
+<para>
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+</para>
+<para>
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+</para>
+<para>
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc., 51
+Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+</para>
+</section>
+<section>
+<title>Thanks</title>
+<para>
+Thanks for reading this far. If you use mercurial-server, please tell me about
+it.
+</para>
+<para>
+Paul Crowley, <email>paul@lshift.net</email>, 2009
+</para>
+</section>
+</article>
+
--- a/doc/security	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-SECURITY OF MERCURIAL-SERVER
-
-mercurial-server relies entirely on sshd to grant access to remote users.
-As a result, it runs no daemons, installs no setuid programs, and no part
-of it runs as root except the install process: all programs run as the user
-hg. And any attack on mercurial-server can only be started if the Bad Guys
-already have a public key in ~hg/.ssh/authorized_keys, otherwise sshd will
-bar the way.
-
-No matter what command the user tries to run on the remote system via ssh,
-mercurial-server is run. It parses the command line the user asked for, and
-interprets and runs the corresponding hg operation itself if access is
-allowed, so users can only read and add to history within repositories;
-they cannot run any other hg command. In addition, every push and pull is
-logged with a datestamp, changeset ID and the key that performed the
-operation.
-
-However, while the first paragraph holds no matter what bugs
-mercurial-server contains, the second depends on the relevant code being
-correct; though the entire codebase is short, mercurial-server is a fairly
-new program and may harbour bugs. Backups are essential!
--- a/install	Tue Oct 13 18:32:26 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import shutil
-import os
-import pwd
-import subprocess
-import optparse
-
-oparser = optparse.OptionParser()
-
-oparser.add_option("--prefix")
-oparser.add_option("--root")
-oparser.set_defaults(root="", prefix="/usr/local")
-(options, args) = oparser.parse_args()
-
-if len(args) > 0:
-    oparser.print_help()
-    sys.exit(-1)
-
-# This must be run as root, because it must create an hg user.
-# Normally the clean thing to do is let it fail with a permission error
-# if a non-root user tries to run it, but I don't want anyone thinking
-# that they can make it work as non-root by changing install paths.
-# Patches for doing this more cleanly welcome of course.
-
-if os.getgid() != 0:
-    print >>sys.stderr, "Install must be run as root user"
-    sys.exit(-1)
-
-
-def installFiles(d, *sources):
-    d = options.root + d
-    os.makedirs(d)
-    for f in sources:
-        shutil.copy(f, d)
-
-installFiles(options.prefix + '/share/mercurial-server',
-    'src/hg-ssh',
-    'src/refresh-auth')
-installFiles(options.prefix + '/share/mercurial-server/mercurialserver',
-    'src/mercurialserver/__init__.py',
-    'src/mercurialserver/paths.py',
-    'src/mercurialserver/changes.py',
-    'src/mercurialserver/access.py',
-    'src/mercurialserver/servelog.py',
-    'src/mercurialserver/refreshauth.py',
-    'src/mercurialserver/ruleset.py')
-installFiles(options.prefix + '/share/mercurial-server/init',
-    'src/init/hginit',
-    'src/init/hgadmin-hgrc')
-installFiles(options.prefix + '/share/doc/mercurial-server',
-    'README',
-    'doc/configuring-access',
-    'doc/file-conditions',
-    'doc/how-it-works',
-    'doc/security')
-installFiles('/etc/mercurial-server',
-    'src/init/conf/remote-hgrc',
-    'src/init/conf/access.conf')
-installFiles('/etc/mercurial-server/keys/root')
-installFiles('/etc/mercurial-server/keys/users')
-
-def becomeFunc(u):
-    p = pwd.getpwnam(u)
-    def become():
-        os.setgid(p.pw_gid)
-        os.setegid(p.pw_gid)
-        os.setuid(p.pw_uid)
-        os.seteuid(p.pw_uid)
-    return become
-
-if options.root == '':
-    try:
-       pwd.getpwnam('hg')
-    except KeyError:
-        subprocess.check_call(
-            "adduser --system --shell /bin/sh --group --disabled-password".split() + 
-            ["--gecos", "Mercurial repositories", "hg"])
-        subprocess.check_call([options.prefix + '/share/mercurial-server/init/hginit',
-            options.prefix + '/share/mercurial-server'],
-            preexec_fn = becomeFunc('hg'))
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py	Mon Nov 09 16:23:04 2009 +0000
@@ -0,0 +1,26 @@
+# WARNING: this file is NOT meant to be directly executed, but
+# run from the Makefile.
+
+from distutils.core import setup
+
+setup(
+    name="mercurial-server",
+    description="Centralized Mercurial repository manager",
+    url="http://www.lshift.net/mercurial-server.html",
+    version="0.6+", # FIXME: infer this
+    package_dir = {'': 'src'},
+    packages = ["mercurialserver"],
+    requires = ["mercurial"], # FIXME: what version?
+    scripts = ['src/hg-ssh', 'src/refresh-auth'],
+    data_files = [
+        ('init', [
+            'src/init/hginit', 
+            'src/init/dot-mercurial-server', 
+            'src/init/hgadmin-hgrc'
+        ]), ('init/conf', [
+            'src/init/conf/remote-hgrc',
+            'src/init/conf/access.conf',
+        ]),
+    ],
+)
+
--- a/src/hg-ssh	Tue Oct 13 18:32:26 2009 +0100
+++ b/src/hg-ssh	Mon Nov 09 16:23:04 2009 +0000
@@ -84,13 +84,11 @@
 # Use a different hgrc for remote pulls - this way you can set
 # up access.py for everything at once without affecting local operations
 
-os.environ['HGRCPATH'] = paths.getEtcPath() + "/remote-hgrc"
-
-os.chdir('repos')
+os.environ['HGRCPATH'] = paths.getHgrcPaths()
 
-for f in [
-    paths.getEtcPath() + "/access.conf", 
-    os.getcwd() + "/hgadmin/access.conf"]:
+os.chdir(paths.getReposPath())
+
+for f in paths.getAccessPaths():
     if os.path.isfile(f):
         ruleset.rules.readfile(f)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/init/dot-mercurial-server	Mon Nov 09 16:23:04 2009 +0000
@@ -0,0 +1,9 @@
+# WARNING: a .mercurial-server file in your home directory means
+# that refresh-auth can and will trash your ~/.ssh/authorized_keys file.
+
+[paths]
+repos = ~/repos
+keys = /etc/mercurial-server/keys:~/repos/hgadmin/keys
+access = /etc/mercurial-server/access.conf:~/repos/hgadmin/access.conf
+hgrc = /etc/mercurial-server/remote-hgrc
+
--- a/src/init/hginit	Tue Oct 13 18:32:26 2009 +0100
+++ b/src/init/hginit	Mon Nov 09 16:23:04 2009 +0000
@@ -2,8 +2,16 @@
 
 set -e
 
-cd ~hg
+cd
+
+if [ -e .ssh/authorized_keys ] ; then
+    echo "This user already exists with authorized keys, aborting"
+    exit -1
+fi
+
+cp $1/init/dot-mercurial-server .mercurial-server
 mkdir -p repos/hgadmin .ssh
 cd repos/hgadmin
 hg init .
 cp $1/init/hgadmin-hgrc .hg/hgrc
+
--- a/src/mercurialserver/paths.py	Tue Oct 13 18:32:26 2009 +0100
+++ b/src/mercurialserver/paths.py	Mon Nov 09 16:23:04 2009 +0000
@@ -1,10 +1,43 @@
 # Copyright 2008-2009 LShift Ltd
 
-# Crude but it will do
-
 import sys
 import os.path
+import mercurial.config
 
+globalconfig = None
+
+def _getConf():
+    global globalconfig
+    if globalconfig is None:
+        globalconfig = mercurial.config.config()
+        globalconfig.read(os.path.expanduser("~/.mercurial-server"))
+    return globalconfig
+
+def configExists():
+    try:
+        _getConf()
+        return True
+    except:
+        return False
+
+def _getPath(name):
+    return os.path.expanduser(_getConf()["paths"][name])
+
+def _getPaths(name): 
+    return [os.path.expanduser(p)
+        for p in _getConf()["paths"][name].split(":")]
+
+
+def getExePath(): return _getPath("exe")
+def getReposPath(): return _getPath("repos")
+
+def getKeysPaths(): return _getPaths("keys")
+def getAccessPaths(): return _getPaths("access")
+
+# This goes into an env var, so pass it on verbatim.
+def getHgrcPaths(): return _getConf()["paths"]["hgrc"]
+
+# Work out where we are, don't use config.
 def setExePath():
     global _exePath
     _exePath = os.path.dirname(os.path.abspath(sys.argv[0]))
@@ -12,5 +45,3 @@
 def getExePath():
     return _exePath
 
-def getEtcPath():
-    return "/etc/mercurial-server"
--- a/src/mercurialserver/refreshauth.py	Tue Oct 13 18:32:26 2009 +0100
+++ b/src/mercurialserver/refreshauth.py	Mon Nov 09 16:23:04 2009 +0000
@@ -9,16 +9,14 @@
 import base64
 import os
 import os.path
-import pwd
 import subprocess
 from mercurialserver import paths
 
 goodkey = re.compile("[/A-Za-z0-9._-]+$")
 
-def refreshAuth(pw_dir):
-    akeyfile = pw_dir + "/.ssh/authorized_keys"
+def refreshAuth():
+    akeyfile = os.path.expanduser("~/.ssh/authorized_keys")
     wrappercommand = paths.getExePath() + "/hg-ssh"
-    keydirs = [paths.getEtcPath() + "/keys", pw_dir + "/repos/hgadmin/keys"]
     prefix='no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command='
 
     if os.path.exists(akeyfile):
@@ -31,7 +29,7 @@
             f.close()
 
     akeys = open(akeyfile + "_new", "w")
-    for keyroot in keydirs:
+    for keyroot in paths.getKeysPaths():
         kr = keyroot + "/"
         #print "Processing keyroot", keyroot
         for root, dirs, files in os.walk(keyroot):
@@ -63,6 +61,5 @@
     os.rename(akeyfile + "_new", akeyfile)
     
 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
-    pentry = pwd.getpwuid(os.geteuid())
-    refreshAuth(pentry.pw_dir)
+    refreshAuth()
 
--- a/src/refresh-auth	Tue Oct 13 18:32:26 2009 +0100
+++ b/src/refresh-auth	Mon Nov 09 16:23:04 2009 +0000
@@ -8,19 +8,17 @@
 
 import sys
 import os
-import pwd
 from mercurialserver import refreshauth, paths
 
 if len(sys.argv) != 1:
     sys.stderr.write("refresh-auth: must be called with no arguments (%s)\n" % sys.argv)
     sys.exit(-1)
 
-pentry = pwd.getpwuid(os.geteuid())
-if pentry.pw_name != "hg":
-    # FIXME: re-execute
+# To protect the authorized_keys file for innocent users, you have to have
+# a ~/.mercurial-server file to run this.
+if not paths.configExists():
     print >>sys.stderr, "Must be run as the 'hg' user"
     sys.exit(-1)
 
 paths.setExePath()
-
-refreshauth.refreshAuth(pentry.pw_dir)
+refreshauth.refreshAuth()