Support dynamic ${REPO_ROOT} path resolution

Some workspaces combine multiple components into a single checkout
by nesting them under subdirectories (e.g., 'android/', 'kernel/').
This breaks existing PREUPLOAD.cfg files designed for single-tree
layouts, as they hardcode tool paths relative to ${REPO_ROOT}
(e.g., `${REPO_ROOT}/vendor/google/tools/alint`).

This change introduces a fallback mechanism during variable expansion
as an alternative to requiring individual project owners to break
upstream compatibility.

If a path anchored by ${REPO_ROOT} does not exist at the workspace root,
repohooks will attempt to resolve it by checking against a
comma-separated list of fallback subdirectories defined in the
`fallback_subtrees` option under the `[Options]` section of
GLOBAL-PREUPLOAD.cfg. This option is restricted to GLOBAL-PREUPLOAD.cfg
as subtree path mapping is inherently a workspace-wide layout setting.

The configured subtrees are parsed by PreUploadConfig and passed
through HookOptions to Placeholders, preserving layer separation and
avoiding redundant disk I/O during hook execution.

Bug: 515602104
Test: ./run_tests
Change-Id: I8b80ccc3e4f633d55036491dd8f029a94f07880a
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repohooks/+/622561
Commit-Queue: Han Wang <nesthanwang@google.com>
Tested-by: Han Wang <nesthanwang@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
GitOrigin-RevId: 2a026ffe80b094acae73f143b5f40062d97d732b
1 file changed