For my own notes later, when I wonder why this thing is readonly.
This was generated by Claude.
FreshPorts moved from Subversion to git on 5 October 2026. The Subversion repository it came from, freshports-1, should never change again, but the Subversion server also hosts other repositories which are still in use. So the server stays up, and freshports-1 alone is now read-only.
Subversion runs hooks per repository, so a hook which refuses every change affects only the repository it is installed in. Reading still works: checkouts, svn log, svn diff and svnadmin dump.
1. Confirm the last revision
The git conversion was made from r6278. Before anything else, check that nothing was committed after it:
$ sudo svnlook youngest /usr/local/svn/repos/freshports-1
6278
2. Take a final backup
A complete dump of the repository as it was at the end:
# svnadmin dump -q /usr/local/svn/repos/freshports-1 | xz -9 > /var/backups/freshports-1-r6278.svndump.xz
It can be restored into a new repository with svnadmin create followed by xz -dc … | svnadmin load.
3. Refuse commits
The start-commit hook runs before Subversion creates a transaction. If it exits non-zero, the commit is refused, and whatever it printed on stderr is shown to the person committing:
# printf '#!/bin/sh\necho "freshports-1 is read-only: FreshPorts moved to git on 2026-10-05. See https://github.com/FreshPorts" >&2\nexit 1\n' > /usr/local/svn/repos/freshports-1/hooks/start-commit
# chmod 755 /usr/local/svn/repos/freshports-1/hooks/start-commit
The hook it creates:
#!/bin/sh
echo "freshports-1 is read-only: FreshPorts moved to git on 2026-10-05. See https://github.com/FreshPorts" >&2
exit 1
Testing so far
Reading still works, from a client host:
$ svn log -l 1 svn+ssh://svnusers@svn.int.unixathome.org/freshports-1
------------------------------------------------------------------------
r6278 | dvl | 2026-10-05 13:28:37 +0000 (Mon, 05 Oct 2026) | 41 lines
Give the make child a PATH which includes /usr/local/bin
…
A write attempt from the same host was refused:
$ svn mkdir -m test svn+ssh://svnusers@svn.int.unixathome.org/freshports-1/readonly-test
svn: E170001: Authorization failed
That refusal came from svnserve’s access control, before any hook ran; had the hook refused it, the message would have been the one above. So the read test passed, but the hook itself is not yet proven by this.
Still to do
Refuse revision-property changes and locks. These are the two other ways to change a Subversion repository: editing a log message or author after the fact, and taking a lock. The same hook serves for both:
# for h in pre-revprop-change pre-lock; do cp /usr/local/svn/repos/freshports-1/hooks/start-commit /usr/local/svn/repos/freshports-1/hooks/$h; done
Test the hooks on a copy. A file:// commit on the server bypasses svnserve’s access control but still runs the hooks. Doing it on a hot copy means a failed test cannot add a real r6279:
# svnadmin hotcopy /usr/local/svn/repos/freshports-1 /tmp/fp1-hooktest
# svn mkdir -m test file:///tmp/fp1-hooktest/readonly-test
# svn propset --revprop -r 6278 svn:log x file:///tmp/fp1-hooktest
# rm -rf /tmp/fp1-hooktest
Both commands should fail with the “freshports-1 is read-only” message.
Undoing it
Remove or rename the hooks in /usr/local/svn/repos/freshports-1/hooks/, and the repository accepts changes again.











