# Fetch Command Contract The `repo.fetchcmd` configuration allows specifying a custom command to be executed during `repo sync` to fetch objects, instead of using standard `git fetch`. This is particularly useful in environments with virtualized filesystems or lazy checkouts where fetching metadata and downloading file contents should be decoupled. The checkout half of a sync has a counterpart, `repo.reprojectcmd`; see `docs/reproject-cmd.md`. ## Configuration To use this feature, set the following in `.repo/manifests.git/config`: ```ini [repo] fetchcmd = "your custom command here" uselocalgitdirs = true ``` Setting `repo.fetchcmd` **requires** `repo.uselocalgitdirs` to be set to `true`. ## Environment Variables The custom command is executed in a subshell populated with standard project-context environment variables. For details on standard variables (such as `REPO_PROJECT`, `REPO_PATH`, `REPO_PROJECT_FETCH_URL`, etc.), see the Environment section in `repo help forall` or `subcmds/forall.py`. The following environment variable is specific to `repo.fetchcmd`: * `REPO_TREV`: The target commit hash when the revision is already pinned to a commit (e.g. via a superproject or a commit SHA in the manifest), or empty when `REPO_RREV` is an unpinned branch or tag to be resolved by the fetch command. ## Contract ### Postconditions on exit 0 After the fetch command exits with status 0, `repo` expects the following postconditions to be met: 1. When the manifest revision names a branch or tag, the mapped local tracking ref (e.g. `refs/remotes/REPO_REMOTE/` for a branch, or `refs/tags/` for a tag) must name the target commit, and must equal `REPO_TREV` if `REPO_TREV` was non-empty. A tag ref may name an annotated tag of the target commit. 2. `FETCH_HEAD` must name the same target commit. 3. The target commit, and the commit graph from it far enough to compute merge bases with local branches, must be readable from the object store. They may be materialized lazily, when first read. ### Invariants * The command should be idempotent; repeating the same fetch should be a no-op. * Only `FETCH_HEAD`, `refs/remotes/*`, and `refs/tags/*` should be modified to preserve `repo sync --network-only` semantics. `HEAD` and local branches must not be touched by the fetch command. * Dirty worktree state must be preserved. * The command is **not** executed for `MetaProject`s (i.e. the internal `repo` repository itself at `.repo/repo` and the `manifests` repository at `.repo/manifests`). ### Failure * A non-zero exit status aborts the project's sync, and the command's stderr is surfaced to the user. * After exit 0, `repo` checks postconditions 1 and 2 by comparing the object IDs that the refs record (`git rev-parse --verify `), so it does not read the object store during the network half of the sync. It peels the IDs to commits only when they differ, as for an annotated tag. Any mismatch is treated as a failure. * A target commit missing from the object store fails the checkout that reads it.