sync: Don't checkout if no worktree
Interleaved sync should not try checkout out a project if it's a mirror.
Change-Id: I2549faab197a3202d79a10e44b449b68d53e3fe7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/492942
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Scott Lee <ddoman@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
diff --git a/subcmds/sync.py b/subcmds/sync.py
index b02fdd0..c0310c5 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -2269,51 +2269,57 @@
checkout_finish = None
checkout_stderr = ""
- if fetch_success and not opt.network_only:
- checkout_start = time.time()
- stderr_capture = io.StringIO()
- try:
- with contextlib.redirect_stderr(stderr_capture):
- syncbuf = SyncBuffer(
- project.manifest.manifestProject.config,
- detach_head=opt.detach_head,
- )
- local_half_errors = []
- project.Sync_LocalHalf(
- syncbuf,
- force_sync=opt.force_sync,
- force_checkout=opt.force_checkout,
- force_rebase=opt.rebase,
- errors=local_half_errors,
- verbose=opt.verbose,
- )
- checkout_success = syncbuf.Finish()
- if local_half_errors:
- checkout_error = SyncError(
- aggregate_errors=local_half_errors
+ if fetch_success:
+ # We skip checkout if it's network-only or if the project has no
+ # working tree (e.g., a mirror).
+ if opt.network_only or not project.worktree:
+ checkout_success = True
+ else:
+ # This is a normal project that needs a checkout.
+ checkout_start = time.time()
+ stderr_capture = io.StringIO()
+ try:
+ with contextlib.redirect_stderr(stderr_capture):
+ syncbuf = SyncBuffer(
+ project.manifest.manifestProject.config,
+ detach_head=opt.detach_head,
)
- except KeyboardInterrupt:
- logger.error(
- "Keyboard interrupt while processing %s", project.name
- )
- except GitError as e:
- checkout_error = e
- logger.error(
- "error.GitError: Cannot checkout %s: %s", project.name, e
- )
- except Exception as e:
- checkout_error = e
- logger.error(
- "error: Cannot checkout %s: %s: %s",
- project.name,
- type(e).__name__,
- e,
- )
- finally:
- checkout_finish = time.time()
- checkout_stderr = stderr_capture.getvalue()
- elif fetch_success:
- checkout_success = True
+ local_half_errors = []
+ project.Sync_LocalHalf(
+ syncbuf,
+ force_sync=opt.force_sync,
+ force_checkout=opt.force_checkout,
+ force_rebase=opt.rebase,
+ errors=local_half_errors,
+ verbose=opt.verbose,
+ )
+ checkout_success = syncbuf.Finish()
+ if local_half_errors:
+ checkout_error = SyncError(
+ aggregate_errors=local_half_errors
+ )
+ except KeyboardInterrupt:
+ logger.error(
+ "Keyboard interrupt while processing %s", project.name
+ )
+ except GitError as e:
+ checkout_error = e
+ logger.error(
+ "error.GitError: Cannot checkout %s: %s",
+ project.name,
+ e,
+ )
+ except Exception as e:
+ checkout_error = e
+ logger.error(
+ "error: Cannot checkout %s: %s: %s",
+ project.name,
+ type(e).__name__,
+ e,
+ )
+ finally:
+ checkout_finish = time.time()
+ checkout_stderr = stderr_capture.getvalue()
# Consolidate all captured output.
captured_parts = []
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py
index 9cd19f1..5955e40 100644
--- a/tests/test_subcmds_sync.py
+++ b/tests/test_subcmds_sync.py
@@ -309,6 +309,7 @@
self.relpath = relpath
self.name = name or relpath
self.objdir = objdir or relpath
+ self.worktree = relpath
self.use_git_worktrees = False
self.UseAlternates = False
@@ -836,6 +837,25 @@
project.Sync_NetworkHalf.assert_called_once()
project.Sync_LocalHalf.assert_not_called()
+ def test_worker_no_worktree(self):
+ """Test interleaved sync does not checkout with no worktree."""
+ opt = self._get_opts()
+ project = self.projA
+ project.worktree = None
+ project.Sync_NetworkHalf = mock.Mock(
+ return_value=SyncNetworkHalfResult(error=None, remote_fetched=True)
+ )
+ project.Sync_LocalHalf = mock.Mock()
+ self.mock_context["projects"] = [project]
+
+ result_obj = self.cmd._SyncProjectList(opt, [0])
+ result = result_obj.results[0]
+
+ self.assertTrue(result.fetch_success)
+ self.assertTrue(result.checkout_success)
+ project.Sync_NetworkHalf.assert_called_once()
+ project.Sync_LocalHalf.assert_not_called()
+
def test_worker_fetch_fails_exception(self):
"""Test _SyncProjectList with an exception during fetch."""
opt = self._get_opts()