| 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 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. |