summaryrefslogtreecommitdiff
path: root/tests/test_subcmds_sync.py
diff options
context:
space:
mode:
authorGavin Mak <gavinmak@google.com>2025-06-23 09:04:26 -0700
committerLUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com>2025-06-23 09:12:41 -0700
commitf7a3f99dc9e92556f3a0c588633b651439b5f7db (patch)
tree0fee33f4ed9245051266209a66ea972fc1164892 /tests/test_subcmds_sync.py
parent6b8e9fc8db47a29dbb288cb2109a78e2518e616a (diff)
downloadgit-repo-f7a3f99dc9e92556f3a0c588633b651439b5f7db.tar.gz
git-repo-f7a3f99dc9e92556f3a0c588633b651439b5f7db.zip
sync: Share self-update logic between sync modes
The logic for checking for repo self-updates lives in _FetchMain, which is part of the "phased" sync path. Extract this logic into a new _UpdateRepoProject helper method. Call this common helper from _ExecuteHelper before either sync mode begins, so the repo self-update check is always performed. Bug: 421935613 Change-Id: I9a804f43fbf6239c4146be446040be531f12fc8a Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/484041 Reviewed-by: Scott Lee <ddoman@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com> Tested-by: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'tests/test_subcmds_sync.py')
-rw-r--r--tests/test_subcmds_sync.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py
index e7213ed90..9cd19f104 100644
--- a/tests/test_subcmds_sync.py
+++ b/tests/test_subcmds_sync.py
@@ -527,6 +527,108 @@ class SyncCommand(unittest.TestCase):
self.assertIn(self.sync_network_half_error, e.aggregate_errors)
+class SyncUpdateRepoProject(unittest.TestCase):
+ """Tests for Sync._UpdateRepoProject."""
+
+ def setUp(self):
+ """Common setup."""
+ self.repodir = tempfile.mkdtemp(".repo")
+ self.manifest = manifest = mock.MagicMock(repodir=self.repodir)
+ # Create a repoProject with a mock Sync_NetworkHalf.
+ repoProject = mock.MagicMock(name="repo")
+ repoProject.Sync_NetworkHalf = mock.Mock(
+ return_value=SyncNetworkHalfResult(True, None)
+ )
+ manifest.repoProject = repoProject
+ manifest.IsArchive = False
+ manifest.CloneFilter = None
+ manifest.PartialCloneExclude = None
+ manifest.CloneFilterForDepth = None
+
+ git_event_log = mock.MagicMock(ErrorEvent=mock.Mock(return_value=None))
+ self.cmd = sync.Sync(manifest=manifest, git_event_log=git_event_log)
+
+ opt, _ = self.cmd.OptionParser.parse_args([])
+ opt.local_only = False
+ opt.repo_verify = False
+ opt.verbose = False
+ opt.quiet = True
+ opt.force_sync = False
+ opt.clone_bundle = False
+ opt.tags = False
+ opt.optimized_fetch = False
+ opt.retry_fetches = 0
+ opt.prune = False
+ self.opt = opt
+ self.errors = []
+
+ mock.patch.object(sync.Sync, "_GetCurrentBranchOnly").start()
+
+ def tearDown(self):
+ shutil.rmtree(self.repodir)
+ mock.patch.stopall()
+
+ def test_fetches_when_stale(self):
+ """Test it fetches when the repo project is stale."""
+ self.manifest.repoProject.LastFetch = time.time() - (
+ sync._ONE_DAY_S + 1
+ )
+
+ with mock.patch.object(sync, "_PostRepoFetch") as mock_post_fetch:
+ self.cmd._UpdateRepoProject(self.opt, self.manifest, self.errors)
+ self.manifest.repoProject.Sync_NetworkHalf.assert_called_once()
+ mock_post_fetch.assert_called_once()
+ self.assertEqual(self.errors, [])
+
+ def test_skips_when_fresh(self):
+ """Test it skips fetch when repo project is fresh."""
+ self.manifest.repoProject.LastFetch = time.time()
+
+ with mock.patch.object(sync, "_PostRepoFetch") as mock_post_fetch:
+ self.cmd._UpdateRepoProject(self.opt, self.manifest, self.errors)
+ self.manifest.repoProject.Sync_NetworkHalf.assert_not_called()
+ mock_post_fetch.assert_not_called()
+
+ def test_skips_local_only(self):
+ """Test it does nothing with --local-only."""
+ self.opt.local_only = True
+ self.manifest.repoProject.LastFetch = time.time() - (
+ sync._ONE_DAY_S + 1
+ )
+
+ with mock.patch.object(sync, "_PostRepoFetch") as mock_post_fetch:
+ self.cmd._UpdateRepoProject(self.opt, self.manifest, self.errors)
+ self.manifest.repoProject.Sync_NetworkHalf.assert_not_called()
+ mock_post_fetch.assert_not_called()
+
+ def test_post_repo_fetch_skipped_on_env_var(self):
+ """Test _PostRepoFetch is skipped when REPO_SKIP_SELF_UPDATE is set."""
+ self.manifest.repoProject.LastFetch = time.time()
+
+ with mock.patch.dict(os.environ, {"REPO_SKIP_SELF_UPDATE": "1"}):
+ with mock.patch.object(sync, "_PostRepoFetch") as mock_post_fetch:
+ self.cmd._UpdateRepoProject(
+ self.opt, self.manifest, self.errors
+ )
+ mock_post_fetch.assert_not_called()
+
+ def test_fetch_failure_is_handled(self):
+ """Test that a fetch failure is recorded and doesn't crash."""
+ self.manifest.repoProject.LastFetch = time.time() - (
+ sync._ONE_DAY_S + 1
+ )
+ fetch_error = GitError("Fetch failed")
+ self.manifest.repoProject.Sync_NetworkHalf.return_value = (
+ SyncNetworkHalfResult(False, fetch_error)
+ )
+
+ with mock.patch.object(sync, "_PostRepoFetch") as mock_post_fetch:
+ self.cmd._UpdateRepoProject(self.opt, self.manifest, self.errors)
+ self.manifest.repoProject.Sync_NetworkHalf.assert_called_once()
+ mock_post_fetch.assert_not_called()
+ self.assertEqual(self.errors, [fetch_error])
+
+
class InterleavedSyncTest(unittest.TestCase):
"""Tests for interleaved sync."""