                           Repository Hooks
                           ================

GOALS.
======

   A hook is a program triggered by a repository read or write access.
   The hook is handed enough information to tell what the action is,
   what target(s) it's operating on, and who is doing it.  Depending
   on the hook's output or return status, the repository's hook driver
   may continue the action, stop it, or suspend it in some way.

   Subversion's hook system is being implemented in stages -- the
   parts needed for M3 are being written first, though the design
   encompasses goals beyond M3.  In the long term, the system must
   support:

      1. Commit emails.
         Able to report on date of commit, author, dirs and files
         changed, and information about the changes -- ranging from
         change summaries to full diffs.
         [Needed for M3.]

      2. Pre-commit guards based on content.
         Examine what is about to be committed, and prevent or allow
         the commit based on that.
         [Not strictly needed for M3, but will be provided anyway.]

      3. Pre-commit guards based on identity.
         Examine who is attempting to change what, and prevent or
         allow the commit accordingly.
         [Needed for M3.]

   4. Read authorization
         Examine who is attempting to read what, and prevent or allow
         the access accordingly.
         [Not needed for M3; designed now, but implemented post-M3.]


HOW IT WORKS.
=============

Subversion's hooks are programs that live in the repository's hooks/
directory:

   $ ls some-repo
   README   custom/   dav/   db/   hooks/   conf/
   $ ls some-repo/hooks/
   start-commit          pre-commit             post-commit
   start-commit.tmpl     pre-commit.tmpl        post-commit.tmpl
   read-sentinels        write-sentinels
   read-sentinels.tmpl   write-sentinels.tmpl
   $ 

The actual hooks are `start-commit', `pre-commit' and `post-commit'.
The template (.tmpl) files are example shell scripts to get you
started; look there for details about how each hook works.  When a
repository is created, the templates are created automatically -- to
make your own hook, just copy `foo.tmpl' to `foo' and edit.

(The `read-sentinels' and `write-sentinels' are not yet implemented
They are intended to be more like daemons than hooks.  A sentinel is
started up at the beginning of a user operation.  The Subversion
server communicates with the sentinel using a protocol yet to be
defined.  Depending on the sentinel's responses, Subversion may stop
or otherwise modify the operation.)

Here is when they are run:

   start-commit:  Before the committer's txn is even created.
   pre-commit:    When the txn is finished, but before it is committed.
   post-commit:   After the txn is committed, and we have a new rev.

Note that they must be executable by the user who will invoke them
(commonly the user httpd runs as), and that same user needs to be able
to access the repository.

Typically, `start-commit' is used to check that the user has commit
privileges at all.  Then the `pre-commit' hook is used to protect
against commits that are disallowed due to content or location (for
example, your site might require that all commits to a certain branch
include a ticket number from the bug tracker), and `post-commit' is
used to mail out commit messages.

The pre-commit and post-commit hooks may need to know things about the
change about to be committed (or that has just been committed).  The
solution is a standalone program, `svnlook', which was installed in
the same place as the `svn' binary.  Use `svnlook' to examine a txn or
revision tree.  It produces output that is both human- and
machine-readable, so hook scripts can easily parse it.  Note that
`svnlook' is read-only -- it can only inspect, not change the
repository.

Run "svnlook" with no arguments to see how it works.

More On Read and Write Sentinels (just discussion, not implemented yet!)
------------------------------------------------------------------------

   (Thanks to Thom Wood <thom@collab.net> for proposing this.)

   The `read-sentinels' and `write-sentinels' work somewhat differently.
   A sentinel is started whenever a revision or txn root object is opened
   (see svn_fs.h).  All operations on paths beneath that root are first
   "checked" with the sentinel; the sentinel's response determines
   whether the operation is permitted.
   
   Our hope is that sentinels can be kept very simple: they will simply
   take paths on stdin, and respond with "Okay" or "Not Okay" (or
   slightly more formal XML equivalents).  All kinds of read operations
   on a path will be treated as equivalent, as will all write operations.
   The relevant question will be simply: was the user allowed to read or
   write this path?
   
   The point of sentinels is to provide real-time feedback as a commit
   is being built (or even before the txn is started), or as a
   checkout or update is being produced -- but without the overhead of
   starting up a program anew for each path under the root.

   Almost all reading and writing functions in svn_fs.h will need to be
   wrapped by libsvn_repos, which will drive the sentinels:
   
      Read actions to be wrapped:
      ---------------------------
         svn_fs_revision_root
         svn_fs_is_dir
         svn_fs_is_file
         svn_fs_node_prop
         svn_fs_node_proplist
         svn_fs_txn_prop
         svn_fs_txn_proplist
         svn_fs_copied_from
         svn_fs_is_different
         svn_fs_dir_entries
         svn_fs_file_length
         svn_fs_file_contents
         svn_fs_youngest_rev
         svn_fs_revision_prop
         svn_fs_revision_proplist
   
      Write actions to be wrapped:
      ----------------------------
         svn_fs_begin_txn
         svn_fs_commit_txn
         svn_fs_txn_root
         svn_fs_change_txn_prop
         svn_fs_change_node_prop
         svn_fs_make_dir
         svn_fs_delete
         svn_fs_delete_tree
         svn_fs_rename
         svn_fs_copy
         svn_fs_link
         svn_fs_make_file
         svn_fs_apply_textdelta
         svn_fs_change_rev_prop
   
   The exact sentinel protocol is still TBD; obviously, a precise
   specification is very important for sentinel implementors.


FAQ (Frequently Anticipated Questions).
=======================================

   Q: Why is `svnlook' a read-only interface to the repository?

   A: Because if it changed the txn before commit, the working copy
      would have no way of knowing what happened, and would therefore
      be out of sync and not know it.  Subversion currently has no way
      to handle this situation, and maybe never will.  Someday the
      hooks may leave txns in a "holding" state (for supervised
      commits, a handy feature many have requested), but even then the
      working copy should be told definitively that the commit did not
      succeed.  Later on, the commit will come through as an update.
