From 13a32fbe8004342cb59d7ca6779007104c024d06 Mon Sep 17 00:00:00 2001 From: Charles Zablit Date: Fri, 5 Dec 2025 12:07:36 +0000 Subject: [PATCH] [update-checkout] fix persistent --clone warning --- utils/update_checkout/tests/test_clone.py | 34 ++++++++++++ .../update_checkout/update_checkout.py | 52 +++++++++++++++---- 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/utils/update_checkout/tests/test_clone.py b/utils/update_checkout/tests/test_clone.py index c6d2967de1ce3..fa53586c2326a 100644 --- a/utils/update_checkout/tests/test_clone.py +++ b/utils/update_checkout/tests/test_clone.py @@ -11,6 +11,7 @@ # ===----------------------------------------------------------------------===# import os +import shutil from . import scheme_mock @@ -56,6 +57,39 @@ def test_clone_with_additional_scheme(self): # Test that we're actually checking out the 'extra' scheme based on the output self.assertIn("git checkout refs/heads/main", output) + def test_clone_missing_repos(self): + output = self.call( + [ + self.update_checkout_path, + "--config", + self.config_path, + "--source-root", + self.source_root, + "--clone", + ] + ) + self.assertNotIn( + "You don't have all swift sources. Call this script with --clone to get them.", + output, + ) + + repo = self.get_all_repos()[0] + repo_path = os.path.join(self.source_root, repo) + shutil.rmtree(repo_path) + output = self.call( + [ + self.update_checkout_path, + "--config", + self.config_path, + "--source-root", + self.source_root, + ] + ) + self.assertIn( + "You don't have all swift sources. Call this script with --clone to get them.", + output, + ) + class SchemeWithMissingRepoTestCase(scheme_mock.SchemeMockTestCase): def __init__(self, *args, **kwargs): diff --git a/utils/update_checkout/update_checkout/update_checkout.py b/utils/update_checkout/update_checkout/update_checkout.py index b927817a7f9d7..f8c3416d99a26 100755 --- a/utils/update_checkout/update_checkout/update_checkout.py +++ b/utils/update_checkout/update_checkout/update_checkout.py @@ -376,6 +376,46 @@ def _is_any_repository_locked(pool_args: List[UpdateArguments]) -> Set[str]: return locked_repositories +def _check_missing_clones( + args: CliArguments, config: Dict[str, Any], scheme_map: Dict[str, Any] +): + """ + Verify that all repositories defined in the scheme map are present in the + source root directory. If a repository is missing—and not explicitly skipped— + the user is prompted to re-run the script with the `--clone` option. + + This function also respects per-repository platform restrictions: if the + current platform is not listed for a repo, that repo is ignored. + + Args: + args (CliArguments): Parsed CLI arguments. + config (Dict[str, Any]): deserialized `update-checkout-config.json`. + scheme_map (Dict[str, str] | None): map of repo names to branches to check out. + + Returns: + Prints a warning if any required repository is missing. + """ + + directory_contents = {path.name for path in args.source_root.iterdir()} + current_platform = platform.system() + + for repo in scheme_map: + repo_config = config["repos"].get(repo, {}) + + if ( + "platforms" in repo_config + and current_platform not in repo_config["platforms"] + ): + continue + + if repo not in directory_contents and repo not in args.skip_repository_list: + print( + "You don't have all swift sources. " + "Call this script with --clone to get them." + ) + return + + def _move_llvm_project_to_first_index( pool_args: Union[List[UpdateArguments], List[AdditionalSwiftSourcesArguments]], ): @@ -855,17 +895,7 @@ def main() -> int: dump_repo_hashes(args, config, args.dump_hashes_config) return 0 - # Quick check whether somebody is calling update in an empty directory - directory_contents = args.source_root.iterdir() - if not ( - "cmark" in directory_contents - or "llvm" in directory_contents - or "clang" in directory_contents - ): - print( - "You don't have all swift sources. " - "Call this script with --clone to get them." - ) + _check_missing_clones(args=args, config=config, scheme_map=scheme_map) skipped_repositories, update_results = update_all_repositories( args, config, scheme_name, scheme_map, cross_repos_pr