diff --git a/docs/repo-hooks.md b/docs/repo-hooks.md index cbb1aac7c..cbc160b42 100644 --- a/docs/repo-hooks.md +++ b/docs/repo-hooks.md @@ -133,3 +133,44 @@ def main(project_list, worktree_list=None, **kwargs): kwargs: Leave this here for forward-compatibility. """ ``` + +### post-sync + +The `post-sync` hook allows you to execute a script automatically after +`repo sync` completes without errors. + +Note: This does not guarantee that all projects were synced or checked out. +For example: +- `repo sync -n` performs network fetches only and skips the checkout phase. +- `repo sync ` only updates the specified project(s). +- Partial failures may still result in a successful exit. + +This hook is useful for post-processing tasks such as setting up git hooks, +bootstrapping configuration files, or running project initialization logic. + +The hook is defined using the existing `` manifest block and is +optional. If the hook script fails or is missing, `repo sync` will still +complete successfully, and the error will be printed as a warning. + +Example: + +```xml + + + + +``` + +The `post-sync.py` file should be defined like: + +```py +def main(**kwargs): + """Main function invoked directly by repo. + + We must use the name "main" as that is what repo requires. + + Args: + kwargs: Leave this here for forward-compatibility. + """ + print("Running post-sync tasks...") +``` diff --git a/subcmds/sync.py b/subcmds/sync.py index 3a4151dfe..9efbddf16 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -79,6 +79,7 @@ from repo_logging import RepoLogger from repo_trace import Trace import ssh from wrapper import Wrapper +from hooks import RepoHook _ONE_DAY_S = 24 * 60 * 60 @@ -565,6 +566,7 @@ later is required to fix a server side protocol bug. action="store_true", help=optparse.SUPPRESS_HELP, ) + RepoHook.AddOptionGroup(p, 'post-sync') def _GetBranch(self, manifest_project): """Returns the branch name for getting the approved smartsync manifest. @@ -1741,6 +1743,21 @@ later is required to fix a server side protocol bug. except (KeyboardInterrupt, Exception) as e: raise RepoUnhandledExceptionError(e, aggregate_errors=errors) + # Run post-sync hook only after successful sync + self._RunPostSyncHook(opt) + + def _RunPostSyncHook(self, opt): + """Run post-sync hook if configured in manifest .""" + hook = RepoHook.FromSubcmd( + hook_type="post-sync", + manifest=self.manifest, + opt=opt, + abort_if_user_denies=False, + ) + success = hook.Run() + if not success: + print("Warning: post-sync hook reported failure.") + def _ExecuteHelper(self, opt, args, errors): manifest = self.outer_manifest if not opt.outer_manifest: