@@ -1177,9 +1177,9 @@ def do_add_parser(self, parser_adder):
11771177 '--auto-cache' ,
11781178 help = '''automatically setup local cache repositories
11791179 in a flat folder hierarchy, but with an additional
1180- subfolder (hashed name) for different remote URLs.
1181- Each local cache repository is automatically cloned
1182- on first usage and synced on subsequent clones .
1180+ subfolder (hashed name) for different remote URLs. Each
1181+ local cache repository is automatically cloned on first
1182+ usage and synced on subsequent fetches (on demand) .
11831183 This cache has the lowest priority (Prio 2).''' ,
11841184 )
11851185
@@ -1203,7 +1203,8 @@ def do_add_parser(self, parser_adder):
12031203 workspace setup.
12041204 Only in case of auto-cache the 'west update' process updates the local
12051205 caches first, which then serve as the source for pulling changes into
1206- the workspace.
1206+ the workspace. Thereby, the auto-cache only fetches updates from remote
1207+ if the specified revision is not already present in the local cache.
12071208
12081209 Example: Assume your manifest describes this workspace structure:
12091210 (workspace)
@@ -1233,7 +1234,8 @@ def do_add_parser(self, parser_adder):
12331234 folder hierarchy is setup automatically. Each repository is stored under a
12341235 directory named after the basename of its remote URL. To prevent conflicts
12351236 between repos with same name, a hash of the remote URL is used as subfolder.
1236- Note: Each local cache repo is automatically synced on subsequent updates.
1237+ Note: Each local cache repo is automatically synced on subsequent updates
1238+ on demand (if the used revision is not cached yet).
12371239 (auto cache directory)
12381240 ├── bar.git
12391241 │ ├── <hash>
@@ -1757,13 +1759,60 @@ def handle_auto_cache(self, project):
17571759 # Then clone the repository into the local cache.
17581760 cache_dir_parent = Path (cache_dir ).parent
17591761 cache_dir_parent .mkdir (parents = True , exist_ok = True )
1762+ self .dbg (f'{ project .name } : Setup auto-cache for { project .url } in { cache_dir } ' )
17601763 project .git (
17611764 ['clone' , '--mirror' , '--' , project .url , os .fspath (cache_dir )], cwd = cache_dir_parent
17621765 )
17631766 self .create_auto_cache_info (project , cache_dir )
17641767 else :
1765- # The local cache already exists. Sync it with remote.
1766- project .git (['remote' , 'update' , '--prune' ], cwd = cache_dir )
1768+ # The local cache already exists
1769+
1770+ # helper function to check if git commands run successful
1771+ def check_git (cmd ) -> bool :
1772+ '''
1773+ run git command in the auto-cache directory without suppressed output
1774+ return True if the command was successful (returncode 0), otherwise False
1775+ '''
1776+ p = project .git (
1777+ cmd , cwd = cache_dir , capture_stdout = True , capture_stderr = True , check = False
1778+ )
1779+ return not p .returncode
1780+
1781+ # Check if the auto-cache is corrupt
1782+ corrupt = not check_git (['cat-file' , '-e' , 'HEAD' ])
1783+
1784+ # Check if the revision is already contained in the auto-cache.
1785+ contains_rev = check_git (['cat-file' , '-e' , f'{ project .revision } ^{{commit}}' ])
1786+
1787+ # Check if the remote is reachable
1788+ reachable = check_git (['ls-remote' ])
1789+
1790+ if not corrupt :
1791+ # early exit if auto-cache is intact, but remote is not reachable (even if
1792+ # fetch stratefy 'always' is specified), since we know that remote update will fail.
1793+ if not reachable :
1794+ self .dbg (
1795+ f'{ project .name } : remote ({ project .url } ) not reachable. '
1796+ 'Skip auto-cache update with remote.'
1797+ )
1798+ return
1799+
1800+ # early exit if auto-cache is intact and revision is already contained
1801+ if contains_rev and self .fs != 'always' :
1802+ self .dbg (
1803+ f'{ project .name } : auto-cache remote update is skipped '
1804+ f'as it already contains revision { project .revision } '
1805+ )
1806+ return
1807+
1808+ # The auto-cache needs to be updated.
1809+ self .dbg (f'{ project .name } : update auto-cache ({ cache_dir } ) with remote' )
1810+ project .git (['remote' , 'update' , '--prune' ], cwd = cache_dir , check = False )
1811+ else :
1812+ # Remove the auto-cache and freshly setup again.
1813+ self .small_banner (f'{ project .name } : remove corrupt auto-cache { cache_dir } ' )
1814+ shutil .rmtree (cache_dir )
1815+ self .handle_auto_cache (project )
17671816
17681817 def init_project (self , project ):
17691818 # update() helper. Initialize an uncloned project repository.
0 commit comments