Skip to content

Commit 8535282

Browse files
gavinmakLUCI
authored andcommitted
sync: Add scaffolding for interleaved sync
Prepare for an interleaved fetch and checkout mode for `repo sync`. The goal of the new mode is to significantly speed up syncs by running fetch and checkout operations in parallel for different projects, rather than waiting for all fetches to complete before starting any checkouts. Bug: 421935613 Change-Id: I8c66d1e790c7bba6280e409b95238c5e4e61a9c8 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/482821 Reviewed-by: Scott Lee <[email protected]> Commit-Queue: Gavin Mak <[email protected]> Tested-by: Gavin Mak <[email protected]>
1 parent b262d0e commit 8535282

File tree

3 files changed

+95
-24
lines changed

3 files changed

+95
-24
lines changed

man/repo-smartsync.1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
2-
.TH REPO "1" "September 2024" "repo smartsync" "Repo Manual"
2+
.TH REPO "1" "June 2025" "repo smartsync" "Repo Manual"
33
.SH NAME
44
repo \- repo smartsync - manual page for repo smartsync
55
.SH SYNOPSIS
@@ -58,6 +58,9 @@ only update working tree, don't fetch
5858
use the existing manifest checkout as\-is. (do not
5959
update to the latest revision)
6060
.TP
61+
\fB\-\-interleaved\fR
62+
fetch and checkout projects in parallel (experimental)
63+
.TP
6164
\fB\-n\fR, \fB\-\-network\-only\fR
6265
fetch only, don't update working tree
6366
.TP

man/repo-sync.1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
2-
.TH REPO "1" "September 2024" "repo sync" "Repo Manual"
2+
.TH REPO "1" "June 2025" "repo sync" "Repo Manual"
33
.SH NAME
44
repo \- repo sync - manual page for repo sync
55
.SH SYNOPSIS
@@ -58,6 +58,9 @@ only update working tree, don't fetch
5858
use the existing manifest checkout as\-is. (do not
5959
update to the latest revision)
6060
.TP
61+
\fB\-\-interleaved\fR
62+
fetch and checkout projects in parallel (experimental)
63+
.TP
6164
\fB\-n\fR, \fB\-\-network\-only\fR
6265
fetch only, don't update working tree
6366
.TP

subcmds/sync.py

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ def _Options(self, p, show_smart=True):
423423
help="use the existing manifest checkout as-is. "
424424
"(do not update to the latest revision)",
425425
)
426+
p.add_option(
427+
"--interleaved",
428+
action="store_true",
429+
help="fetch and checkout projects in parallel (experimental)",
430+
)
426431
p.add_option(
427432
"-n",
428433
"--network-only",
@@ -1772,8 +1777,6 @@ def _ExecuteHelper(self, opt, args, errors):
17721777
e,
17731778
)
17741779

1775-
err_event = multiprocessing.Event()
1776-
17771780
rp = manifest.repoProject
17781781
rp.PreSync()
17791782
cb = rp.CurrentBranch
@@ -1825,6 +1828,64 @@ def _ExecuteHelper(self, opt, args, errors):
18251828
all_manifests=not opt.this_manifest_only,
18261829
)
18271830

1831+
if opt.interleaved:
1832+
sync_method = self._SyncInterleaved
1833+
else:
1834+
sync_method = self._SyncPhased
1835+
1836+
sync_method(
1837+
opt,
1838+
args,
1839+
errors,
1840+
manifest,
1841+
mp,
1842+
all_projects,
1843+
superproject_logging_data,
1844+
)
1845+
1846+
# Log the previous sync analysis state from the config.
1847+
self.git_event_log.LogDataConfigEvents(
1848+
mp.config.GetSyncAnalysisStateData(), "previous_sync_state"
1849+
)
1850+
1851+
# Update and log with the new sync analysis state.
1852+
mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
1853+
self.git_event_log.LogDataConfigEvents(
1854+
mp.config.GetSyncAnalysisStateData(), "current_sync_state"
1855+
)
1856+
1857+
self._local_sync_state.PruneRemovedProjects()
1858+
if self._local_sync_state.IsPartiallySynced():
1859+
logger.warning(
1860+
"warning: Partial syncs are not supported. For the best "
1861+
"experience, sync the entire tree."
1862+
)
1863+
1864+
if not opt.quiet:
1865+
print("repo sync has finished successfully.")
1866+
1867+
def _SyncPhased(
1868+
self,
1869+
opt,
1870+
args,
1871+
errors,
1872+
manifest,
1873+
mp,
1874+
all_projects,
1875+
superproject_logging_data,
1876+
):
1877+
"""Sync projects by separating network and local operations.
1878+
1879+
This method performs sync in two distinct, sequential phases:
1880+
1. Network Phase: Fetches updates for all projects from their remotes.
1881+
2. Local Phase: Checks out the updated revisions into the local
1882+
worktrees for all projects.
1883+
1884+
This approach ensures that the local work-tree is not modified until
1885+
all network operations are complete, providing a transactional-like
1886+
safety net for the checkout state.
1887+
"""
1888+
err_event = multiprocessing.Event()
18281889
err_network_sync = False
18291890
err_update_projects = False
18301891
err_update_linkfiles = False
@@ -1942,26 +2003,30 @@ def print_and_log(err_msg):
19422003
)
19432004
raise SyncError(aggregate_errors=errors)
19442005

1945-
# Log the previous sync analysis state from the config.
1946-
self.git_event_log.LogDataConfigEvents(
1947-
mp.config.GetSyncAnalysisStateData(), "previous_sync_state"
1948-
)
1949-
1950-
# Update and log with the new sync analysis state.
1951-
mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
1952-
self.git_event_log.LogDataConfigEvents(
1953-
mp.config.GetSyncAnalysisStateData(), "current_sync_state"
1954-
)
1955-
1956-
self._local_sync_state.PruneRemovedProjects()
1957-
if self._local_sync_state.IsPartiallySynced():
1958-
logger.warning(
1959-
"warning: Partial syncs are not supported. For the best "
1960-
"experience, sync the entire tree."
1961-
)
1962-
1963-
if not opt.quiet:
1964-
print("repo sync has finished successfully.")
2006+
def _SyncInterleaved(
2007+
self,
2008+
opt,
2009+
args,
2010+
errors,
2011+
manifest,
2012+
mp,
2013+
all_projects,
2014+
superproject_logging_data,
2015+
):
2016+
"""Sync projects by performing network and local operations in parallel.
2017+
2018+
This method processes each project (or groups of projects that share git
2019+
objects) independently. For each project, it performs the fetch and
2020+
checkout operations back-to-back. These independent tasks are run in
2021+
parallel.
2022+
2023+
It respects two constraints for correctness:
2024+
1. Projects in nested directories (e.g. 'foo' and 'foo/bar') are
2025+
processed in hierarchical order.
2026+
2. Projects that share git objects are processed serially to prevent
2027+
race conditions.
2028+
"""
2029+
raise NotImplementedError("Interleaved sync is not implemented yet.")
19652030

19662031

19672032
def _PostRepoUpgrade(manifest, quiet=False):

0 commit comments

Comments
 (0)