diff options
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | docs/repo-hooks.md | 105 |
2 files changed, 107 insertions, 0 deletions
| @@ -11,4 +11,6 @@ that you can put anywhere in your path. | |||
| 11 | * Source: https://code.google.com/p/git-repo/ | 11 | * Source: https://code.google.com/p/git-repo/ |
| 12 | * Overview: https://source.android.com/source/developing.html | 12 | * Overview: https://source.android.com/source/developing.html |
| 13 | * Docs: https://source.android.com/source/using-repo.html | 13 | * Docs: https://source.android.com/source/using-repo.html |
| 14 | * [repo Manifest Format](./docs/manifest-format.txt) | ||
| 15 | * [repo Hooks](./docs/repo-hooks.md) | ||
| 14 | * [Submitting patches](./SUBMITTING_PATCHES.md) | 16 | * [Submitting patches](./SUBMITTING_PATCHES.md) |
diff --git a/docs/repo-hooks.md b/docs/repo-hooks.md new file mode 100644 index 00000000..c8eb945f --- /dev/null +++ b/docs/repo-hooks.md | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | # repo hooks | ||
| 2 | |||
| 3 | [TOC] | ||
| 4 | |||
| 5 | Repo provides a mechanism to hook specific stages of the runtime with custom | ||
| 6 | python modules. All the hooks live in one git project which is checked out by | ||
| 7 | the manifest (specified during `repo init`), and the manifest itself defines | ||
| 8 | which hooks are registered. | ||
| 9 | |||
| 10 | These are useful to run linters, check formatting, and run quick unittests | ||
| 11 | before allowing a step to proceed (e.g. before uploading a commit to Gerrit). | ||
| 12 | |||
| 13 | A complete example can be found in the Android project. It can be easily | ||
| 14 | re-used by any repo based project and is not specific to Android.<br> | ||
| 15 | https://android.googlesource.com/platform/tools/repohooks | ||
| 16 | |||
| 17 | ## Approvals | ||
| 18 | |||
| 19 | When a hook is processed the first time, the user is prompted for approval. | ||
| 20 | We don't want to execute arbitrary code without explicit consent. For manifests | ||
| 21 | fetched via secure protocols (e.g. https://), the user is prompted once. For | ||
| 22 | insecure protocols (e.g. http://), the user is prompted whenever the registered | ||
| 23 | repohooks project is updated and a hook is triggered. | ||
| 24 | |||
| 25 | ## Manifest Settings | ||
| 26 | |||
| 27 | For the full syntax, see the [repo manifest format](./manifest-format.txt). | ||
| 28 | |||
| 29 | Here's a short example from | ||
| 30 | [Android](https://android.googlesource.com/platform/manifest/+/master/default.xml). | ||
| 31 | The `<project>` line checks out the repohooks git repo to the local | ||
| 32 | `tools/repohooks/` path. The `<repo-hooks>` line says to look in the project | ||
| 33 | with the name `platform/tools/repohooks` for hooks to run during the | ||
| 34 | `pre-upload` phase. | ||
| 35 | |||
| 36 | ```xml | ||
| 37 | <project path="tools/repohooks" name="platform/tools/repohooks" /> | ||
| 38 | <repo-hooks in-project="platform/tools/repohooks" enabled-list="pre-upload" /> | ||
| 39 | ``` | ||
| 40 | |||
| 41 | ## Source Layout | ||
| 42 | |||
| 43 | The repohooks git repo should have a python file with the same name as the hook. | ||
| 44 | So if you want to support the `pre-upload` hook, you'll need to create a file | ||
| 45 | named `pre-upload.py`. Repo will dynamically load that module when processing | ||
| 46 | the hook and then call the `main` function in it. | ||
| 47 | |||
| 48 | Hooks should have their `main` accept `**kwargs` for future compatibility. | ||
| 49 | |||
| 50 | ## Runtime | ||
| 51 | |||
| 52 | Hook return values are ignored. | ||
| 53 | |||
| 54 | Any uncaught exceptions from the hook will cause the step to fail. This is | ||
| 55 | intended as a fallback safety check though rather than the normal flow. If | ||
| 56 | you want your hook to trigger a failure, it should call `sys.exit()` (after | ||
| 57 | displaying relevant diagnostics). | ||
| 58 | |||
| 59 | Output (stdout & stderr) are not filtered in any way. Hooks should generally | ||
| 60 | not be too verbose. A short summary is nice, and some status information when | ||
| 61 | long running operations occur, but long/verbose output should be used only if | ||
| 62 | the hook ultimately fails. | ||
| 63 | |||
| 64 | The hook runs from the top level of the git repo where the operation is started. | ||
| 65 | e.g. If you're in the git repo `src/foo/`, that is where the hook runs, even if | ||
| 66 | the `repo` command was started from a subdir like `src/foo/bar/`. | ||
| 67 | |||
| 68 | Python's `sys.path` is modified so that the top of repohooks directory comes | ||
| 69 | first. This should help simplify the hook logic to easily allow importing of | ||
| 70 | local modules. | ||
| 71 | |||
| 72 | Repo does not modify the state of the git checkout. This means that the hooks | ||
| 73 | might be running in a dirty git repo with many commits and checked out to the | ||
| 74 | latest one. If the hook wants to operate on specific git commits, it needs to | ||
| 75 | manually discover the list of pending commits, extract the diff/commit, and | ||
| 76 | then check it directly. Hooks should not normally modify the active git repo | ||
| 77 | (such as checking out a specific commit to run checks) without first prompting | ||
| 78 | the user. Although user interaction is discouraged in the common case, it can | ||
| 79 | be useful when deploying automatic fixes. | ||
| 80 | |||
| 81 | ## Hooks | ||
| 82 | |||
| 83 | Here are all the points available for hooking. | ||
| 84 | |||
| 85 | ### pre-upload | ||
| 86 | |||
| 87 | This hook runs when people run `repo upload`. | ||
| 88 | |||
| 89 | The `pre-upload.py` file should be defined like: | ||
| 90 | |||
| 91 | ```py | ||
| 92 | def main(project_list, worktree_list=None, **kwargs): | ||
| 93 | """Main function invoked directly by repo. | ||
| 94 | |||
| 95 | We must use the name "main" as that is what repo requires. | ||
| 96 | |||
| 97 | Args: | ||
| 98 | project_list: List of projects to run on. | ||
| 99 | worktree_list: A list of directories. It should be the same length as | ||
| 100 | project_list, so that each entry in project_list matches with a | ||
| 101 | directory in worktree_list. If None, we will attempt to calculate | ||
| 102 | the directories automatically. | ||
| 103 | kwargs: Leave this here for forward-compatibility. | ||
| 104 | """ | ||
| 105 | ``` | ||
