@@ -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
19672032def _PostRepoUpgrade (manifest , quiet = False ):
0 commit comments