mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[update-checkout] add a check for locked repositories
This commit is contained in:
@@ -145,10 +145,11 @@ def setup_mock_remote(base_dir, base_config):
|
||||
|
||||
BASEDIR_ENV_VAR = 'UPDATECHECKOUT_TEST_WORKSPACE_DIR'
|
||||
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
UPDATE_CHECKOUT_EXECUTABLE = 'update-checkout.cmd' if os.name == 'nt' else 'update-checkout'
|
||||
UPDATE_CHECKOUT_PATH = os.path.abspath(os.path.join(CURRENT_FILE_DIR,
|
||||
os.path.pardir,
|
||||
os.path.pardir,
|
||||
'update-checkout'))
|
||||
UPDATE_CHECKOUT_EXECUTABLE))
|
||||
|
||||
|
||||
class SchemeMockTestCase(unittest.TestCase):
|
||||
|
||||
89
utils/update_checkout/tests/test_locked_repository.py
Normal file
89
utils/update_checkout/tests/test_locked_repository.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from update_checkout.update_checkout import _is_any_repository_locked
|
||||
|
||||
class TestIsAnyRepositoryLocked(unittest.TestCase):
|
||||
@patch("os.path.exists")
|
||||
@patch("os.path.isdir")
|
||||
@patch("os.listdir")
|
||||
def test_repository_with_lock_file(self, mock_listdir, mock_isdir, mock_exists):
|
||||
pool_args = [
|
||||
("/fake_path", None, "repo1"),
|
||||
("/fake_path", None, "repo2"),
|
||||
]
|
||||
|
||||
def listdir_side_effect(path):
|
||||
if "repo1" in path:
|
||||
return ["index.lock", "config"]
|
||||
elif "repo2" in path:
|
||||
return ["HEAD", "config"]
|
||||
return []
|
||||
|
||||
mock_exists.return_value = True
|
||||
mock_isdir.return_value = True
|
||||
mock_listdir.side_effect = listdir_side_effect
|
||||
|
||||
result = _is_any_repository_locked(pool_args)
|
||||
self.assertEqual(result, {"repo1"})
|
||||
|
||||
@patch("os.path.exists")
|
||||
@patch("os.path.isdir")
|
||||
@patch("os.listdir")
|
||||
def test_repository_without_git_dir(self, mock_listdir, mock_isdir, mock_exists):
|
||||
pool_args = [
|
||||
("/fake_path", None, "repo1"),
|
||||
]
|
||||
|
||||
mock_exists.return_value = False
|
||||
mock_isdir.return_value = False
|
||||
mock_listdir.return_value = []
|
||||
|
||||
result = _is_any_repository_locked(pool_args)
|
||||
self.assertEqual(result, set())
|
||||
|
||||
@patch("os.path.exists")
|
||||
@patch("os.path.isdir")
|
||||
@patch("os.listdir")
|
||||
def test_repository_with_git_file(self, mock_listdir, mock_isdir, mock_exists):
|
||||
pool_args = [
|
||||
("/fake_path", None, "repo1"),
|
||||
]
|
||||
|
||||
mock_exists.return_value = True
|
||||
mock_isdir.return_value = False
|
||||
mock_listdir.return_value = []
|
||||
|
||||
result = _is_any_repository_locked(pool_args)
|
||||
self.assertEqual(result, set())
|
||||
|
||||
@patch("os.path.exists")
|
||||
@patch("os.path.isdir")
|
||||
@patch("os.listdir")
|
||||
def test_repository_with_multiple_lock_files(self, mock_listdir, mock_isdir, mock_exists):
|
||||
pool_args = [
|
||||
("/fake_path", None, "repo1"),
|
||||
]
|
||||
|
||||
mock_exists.return_value = True
|
||||
mock_isdir.return_value = True
|
||||
mock_listdir.return_value = ["index.lock", "merge.lock", "HEAD"]
|
||||
|
||||
result = _is_any_repository_locked(pool_args)
|
||||
self.assertEqual(result, {"repo1"})
|
||||
|
||||
@patch("os.path.exists")
|
||||
@patch("os.path.isdir")
|
||||
@patch("os.listdir")
|
||||
def test_repository_with_no_lock_files(self, mock_listdir, mock_isdir, mock_exists):
|
||||
pool_args = [
|
||||
("/fake_path", None, "repo1"),
|
||||
]
|
||||
|
||||
mock_exists.return_value = True
|
||||
mock_isdir.return_value = True
|
||||
mock_listdir.return_value = ["HEAD", "config", "logs"]
|
||||
|
||||
result = _is_any_repository_locked(pool_args)
|
||||
self.assertEqual(result, set())
|
||||
|
||||
@@ -16,6 +16,7 @@ import re
|
||||
import sys
|
||||
import traceback
|
||||
from multiprocessing import Lock, Pool, cpu_count, freeze_support
|
||||
from typing import Set, List, Any
|
||||
|
||||
from build_swift.build_swift.constants import SWIFT_SOURCE_ROOT
|
||||
|
||||
@@ -67,8 +68,11 @@ def check_parallel_results(results, op):
|
||||
if r is not None:
|
||||
if fail_count == 0:
|
||||
print("======%s FAILURES======" % op)
|
||||
print("%s failed (ret=%d): %s" % (r.repo_path, r.ret, r))
|
||||
fail_count += 1
|
||||
if isinstance(r, str):
|
||||
print(r)
|
||||
continue
|
||||
print("%s failed (ret=%d): %s" % (r.repo_path, r.ret, r))
|
||||
if r.stderr:
|
||||
print(r.stderr)
|
||||
return fail_count
|
||||
@@ -329,6 +333,30 @@ def get_scheme_map(config, scheme_name):
|
||||
|
||||
return None
|
||||
|
||||
def _is_any_repository_locked(pool_args: List[Any]) -> Set[str]:
|
||||
"""Returns the set of locked repositories.
|
||||
|
||||
A repository is considered to be locked if its .git directory contains a
|
||||
file ending in ".lock".
|
||||
|
||||
Args:
|
||||
pool_args (List[Any]): List of arguments passed to the
|
||||
`update_single_repository` function.
|
||||
|
||||
Returns:
|
||||
Set[str]: The names of the locked repositories if any.
|
||||
"""
|
||||
|
||||
repos = [(x[0], x[2]) for x in pool_args]
|
||||
locked_repositories = set()
|
||||
for source_root, repo_name in repos:
|
||||
dot_git_path = os.path.join(source_root, repo_name, ".git")
|
||||
if not os.path.exists(dot_git_path) or not os.path.isdir(dot_git_path):
|
||||
continue
|
||||
for file in os.listdir(dot_git_path):
|
||||
if file.endswith(".lock"):
|
||||
locked_repositories.add(repo_name)
|
||||
return locked_repositories
|
||||
|
||||
def update_all_repositories(args, config, scheme_name, scheme_map, cross_repos_pr):
|
||||
pool_args = []
|
||||
@@ -363,6 +391,12 @@ def update_all_repositories(args, config, scheme_name, scheme_map, cross_repos_p
|
||||
cross_repos_pr]
|
||||
pool_args.append(my_args)
|
||||
|
||||
locked_repositories: set[str] = _is_any_repository_locked(pool_args)
|
||||
if len(locked_repositories) > 0:
|
||||
return [
|
||||
f"'{repo_name}' is locked by git. Cannot update it."
|
||||
for repo_name in locked_repositories
|
||||
]
|
||||
return run_parallel(update_single_repository, pool_args, args.n_processes)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user