sync: Support SYNC_BRANCH to override the smart sync branch

`repo sync -s` always sends the manifest branch to the manifest server
as the `branch` argument of GetApprovedManifest. Some servers map one
manifest branch to several server-side (CI) branches, and the only way
to pick among them was indirectly through the target.

Honor a SYNC_BRANCH environment variable, mirroring SYNC_TARGET: if set
and non-empty, send it instead of the manifest branch. An empty value
is treated as unset. -t/--smart-tag is unaffected.

Bug: 568962967
Test: ./run_tests
Change-Id: I26700e8997c21487f83011258100fd91a5c87508
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/639123
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
This commit is contained in:
Rahul Yadav authored and gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com committed 2026-10-09 07:00:47 -07:00
1 parent 0a4e68f9d2
commit 340b587e94
3 files changed
+87 -3

No files matched your search

+71
View File
@@ -2982,3 +2982,74 @@ class TestSmartSyncSetupRemoteHelper(unittest.TestCase):
"Stderr was: debugging logs",
str(context.exception),
)
class TestSmartSyncSetupBranch(unittest.TestCase):
"""Tests for how _SmartSyncSetup picks the branch sent to the server."""
def setUp(self) -> None:
self.cmd = sync.Sync()
self.opt = mock.MagicMock()
self.opt.quiet = True
self.opt.smart_sync = True
self.opt.smart_tag = None
self.manifest = mock.MagicMock()
self.manifest.manifest_server = (
"http://android-smartsync.corp.google.com/manifestserver"
)
self.manifest.manifest_server_helper = None
self.smart_sync_manifest_path = "/fake/path/to/manifest.xml"
self.mock_server = mock.MagicMock()
self.mock_server.GetApprovedManifest.return_value = [
True,
"<manifest></manifest>",
]
self.cmd._GetBranch = mock.MagicMock(return_value="main")
self.cmd._ReloadManifest = mock.MagicMock()
self.cmd._ResolveManifestServerTransport = mock.MagicMock(
return_value=(self.manifest.manifest_server, mock.MagicMock())
)
def _RunSetup(self, env: Dict[str, str]) -> str:
with mock.patch.dict(os.environ, env, clear=True), mock.patch(
"xmlrpc.client.Server", return_value=self.mock_server
), mock.patch("builtins.open", mock.mock_open()):
return self.cmd._SmartSyncSetup(
self.opt, self.smart_sync_manifest_path, self.manifest
)
def test_default_branch(self) -> None:
"""Without SYNC_BRANCH the manifest branch is used."""
self._RunSetup({})
self.cmd._GetBranch.assert_called_once_with(
self.manifest.manifestProject
)
self.mock_server.GetApprovedManifest.assert_called_once_with("main")
def test_sync_branch(self) -> None:
"""SYNC_BRANCH replaces the manifest branch."""
self._RunSetup({"SYNC_BRANCH": "git_main-abfs"})
self.cmd._GetBranch.assert_not_called()
self.mock_server.GetApprovedManifest.assert_called_once_with(
"git_main-abfs"
)
def test_sync_branch_with_target(self) -> None:
"""SYNC_BRANCH and SYNC_TARGET are both forwarded."""
self._RunSetup(
{
"SYNC_BRANCH": "git_main-abfs",
"SYNC_TARGET": "cf_x86_64_phone-trunk_staging-eng",
}
)
self.mock_server.GetApprovedManifest.assert_called_once_with(
"git_main-abfs", "cf_x86_64_phone-trunk_staging-eng"
)
def test_empty_sync_branch(self) -> None:
"""An empty SYNC_BRANCH falls back to the manifest branch."""
self._RunSetup({"SYNC_BRANCH": ""})
self.cmd._GetBranch.assert_called_once_with(
self.manifest.manifestProject
)
self.mock_server.GetApprovedManifest.assert_called_once_with("main")