document repo hooks mechanism
Change-Id: I9e25b92c846f887f515efcc706cf5a869645e0ec
diff --git a/README.md b/README.md
index e35f8e9..250d08e 100644
--- a/README.md
+++ b/README.md
@@ -11,4 +11,6 @@
* Source: https://code.google.com/p/git-repo/
* Overview: https://source.android.com/source/developing.html
* Docs: https://source.android.com/source/using-repo.html
+* [repo Manifest Format](./docs/manifest-format.txt)
+* [repo Hooks](./docs/repo-hooks.md)
* [Submitting patches](./SUBMITTING_PATCHES.md)
diff --git a/docs/repo-hooks.md b/docs/repo-hooks.md
new file mode 100644
index 0000000..c8eb945
--- /dev/null
+++ b/docs/repo-hooks.md
@@ -0,0 +1,105 @@
+# repo hooks
+
+[TOC]
+
+Repo provides a mechanism to hook specific stages of the runtime with custom
+python modules. All the hooks live in one git project which is checked out by
+the manifest (specified during `repo init`), and the manifest itself defines
+which hooks are registered.
+
+These are useful to run linters, check formatting, and run quick unittests
+before allowing a step to proceed (e.g. before uploading a commit to Gerrit).
+
+A complete example can be found in the Android project. It can be easily
+re-used by any repo based project and is not specific to Android.<br>
+https://android.googlesource.com/platform/tools/repohooks
+
+## Approvals
+
+When a hook is processed the first time, the user is prompted for approval.
+We don't want to execute arbitrary code without explicit consent. For manifests
+fetched via secure protocols (e.g. https://), the user is prompted once. For
+insecure protocols (e.g. http://), the user is prompted whenever the registered
+repohooks project is updated and a hook is triggered.
+
+## Manifest Settings
+
+For the full syntax, see the [repo manifest format](./manifest-format.txt).
+
+Here's a short example from
+[Android](https://android.googlesource.com/platform/manifest/+/master/default.xml).
+The `<project>` line checks out the repohooks git repo to the local
+`tools/repohooks/` path. The `<repo-hooks>` line says to look in the project
+with the name `platform/tools/repohooks` for hooks to run during the
+`pre-upload` phase.
+
+```xml
+<project path="tools/repohooks" name="platform/tools/repohooks" />
+<repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" />
+```
+
+## Source Layout
+
+The repohooks git repo should have a python file with the same name as the hook.
+So if you want to support the `pre-upload` hook, you'll need to create a file
+named `pre-upload.py`. Repo will dynamically load that module when processing
+the hook and then call the `main` function in it.
+
+Hooks should have their `main` accept `**kwargs` for future compatibility.
+
+## Runtime
+
+Hook return values are ignored.
+
+Any uncaught exceptions from the hook will cause the step to fail. This is
+intended as a fallback safety check though rather than the normal flow. If
+you want your hook to trigger a failure, it should call `sys.exit()` (after
+displaying relevant diagnostics).
+
+Output (stdout & stderr) are not filtered in any way. Hooks should generally
+not be too verbose. A short summary is nice, and some status information when
+long running operations occur, but long/verbose output should be used only if
+the hook ultimately fails.
+
+The hook runs from the top level of the git repo where the operation is started.
+e.g. If you're in the git repo `src/foo/`, that is where the hook runs, even if
+the `repo` command was started from a subdir like `src/foo/bar/`.
+
+Python's `sys.path` is modified so that the top of repohooks directory comes
+first. This should help simplify the hook logic to easily allow importing of
+local modules.
+
+Repo does not modify the state of the git checkout. This means that the hooks
+might be running in a dirty git repo with many commits and checked out to the
+latest one. If the hook wants to operate on specific git commits, it needs to
+manually discover the list of pending commits, extract the diff/commit, and
+then check it directly. Hooks should not normally modify the active git repo
+(such as checking out a specific commit to run checks) without first prompting
+the user. Although user interaction is discouraged in the common case, it can
+be useful when deploying automatic fixes.
+
+## Hooks
+
+Here are all the points available for hooking.
+
+### pre-upload
+
+This hook runs when people run `repo upload`.
+
+The `pre-upload.py` file should be defined like:
+
+```py
+def main(project_list, worktree_list=None, **kwargs):
+ """Main function invoked directly by repo.
+
+ We must use the name "main" as that is what repo requires.
+
+ Args:
+ project_list: List of projects to run on.
+ worktree_list: A list of directories. It should be the same length as
+ project_list, so that each entry in project_list matches with a
+ directory in worktree_list. If None, we will attempt to calculate
+ the directories automatically.
+ kwargs: Leave this here for forward-compatibility.
+ """
+```