Skip to content

Commit 1698789

Browse files
committed
update-checkout: Do not update repository if not listed in the given branch-scheme
Consider two branch-schemes: one maps all repositories, the other—a subset. Suppose repositories have been cloned using the first branch scheme. Previously, a successive update using the second branch-scheme would cause update-checkout to fail in an attempt to query the branch-scheme about the target branch for a repository it does not map, even though the update, given no further errors, can be considered successful.
1 parent 48c1931 commit 1698789

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

utils/update_checkout/tests/scheme_mock.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
('A.txt', 'a'),
2929
],
3030
'repo2': [
31-
# This is a series of changes to repo1. (File, NewContents)
31+
# This is a series of changes to repo2. (File, NewContents)
3232
('X.txt', 'X'),
3333
('Y.txt', 'Y'),
3434
('X.txt', 'z'),
@@ -97,7 +97,7 @@ def get_config_path(base_dir):
9797
return os.path.join(base_dir, 'test-config.json')
9898

9999

100-
def setup_mock_remote(base_dir):
100+
def setup_mock_remote(base_dir, base_config):
101101
create_dir(base_dir)
102102

103103
# We use local as a workspace for creating commits.
@@ -130,7 +130,6 @@ def setup_mock_remote(base_dir):
130130
call_quietly(['git', 'push', 'origin', 'main'],
131131
cwd=local_repo_path)
132132

133-
base_config = MOCK_CONFIG
134133
https_clone_pattern = os.path.join('file://%s' % REMOTE_PATH, '%s')
135134
base_config['https-clone-pattern'] = https_clone_pattern
136135

@@ -153,6 +152,7 @@ class SchemeMockTestCase(unittest.TestCase):
153152
def __init__(self, *args, **kwargs):
154153
super(SchemeMockTestCase, self).__init__(*args, **kwargs)
155154

155+
self.config = MOCK_CONFIG.copy()
156156
self.workspace = os.getenv(BASEDIR_ENV_VAR)
157157
if self.workspace is None:
158158
raise RuntimeError('Misconfigured test suite! Environment '
@@ -167,11 +167,19 @@ def __init__(self, *args, **kwargs):
167167

168168
def setUp(self):
169169
create_dir(self.source_root)
170-
(self.local_path, self.remote_path) = setup_mock_remote(self.workspace)
170+
(self.local_path, self.remote_path) = setup_mock_remote(
171+
self.workspace, self.config
172+
)
171173

172174
def tearDown(self):
173175
teardown_mock_remote(self.workspace)
174176

175177
def call(self, *args, **kwargs):
176178
kwargs['cwd'] = self.source_root
177179
call_quietly(*args, **kwargs)
180+
181+
def get_all_repos(self):
182+
return list(self.config["repos"].keys())
183+
184+
def add_branch_scheme(self, name, scheme):
185+
self.config["branch-schemes"][name] = scheme

utils/update_checkout/tests/test_clone.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#
1111
# ===----------------------------------------------------------------------===#
1212

13+
import os
14+
1315
from . import scheme_mock
1416

1517

@@ -23,3 +25,51 @@ def test_simple_clone(self):
2325
'--config', self.config_path,
2426
'--source-root', self.source_root,
2527
'--clone'])
28+
29+
for repo in self.get_all_repos():
30+
repo_path = os.path.join(self.source_root, repo)
31+
self.assertTrue(os.path.isdir(repo_path))
32+
33+
34+
class SchemeWithMissingRepoTestCase(scheme_mock.SchemeMockTestCase):
35+
def __init__(self, *args, **kwargs):
36+
super().__init__(*args, **kwargs)
37+
38+
self.base_args = [
39+
self.update_checkout_path,
40+
"--config",
41+
self.config_path,
42+
"--source-root",
43+
self.source_root,
44+
]
45+
46+
repos = self.get_all_repos()
47+
repos.pop()
48+
49+
self.scheme_name = "missing-repo"
50+
scheme = {
51+
"aliases": [self.scheme_name],
52+
"repos": dict((repo, "main") for repo in repos),
53+
}
54+
self.add_branch_scheme(self.scheme_name, scheme)
55+
56+
# Test that we do not clone a repository that is not listed in the
57+
# given branch-scheme.
58+
def test_clone(self):
59+
self.call(self.base_args + ["--scheme", self.scheme_name, "--clone"])
60+
61+
missing_repo_path = os.path.join(
62+
self.source_root, self.get_all_repos().pop()
63+
)
64+
self.assertFalse(os.path.isdir(missing_repo_path))
65+
66+
# Test that we do not update a repository that is not listed in the given
67+
# branch-scheme---doing so will cause an irrelevant failure in an attempt
68+
# to query the branch-scheme about the target branch for that repository.
69+
def test_update(self):
70+
# First, clone using the default branch-scheme, which has mappings for
71+
# all repositories.
72+
self.call(self.base_args + ["--clone"])
73+
74+
# Then, update using our custom scheme---a subset of the default one.
75+
self.call(self.base_args + ["--scheme", self.scheme_name])

utils/update_checkout/update_checkout/update_checkout.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,20 @@ def update_all_repositories(args, config, scheme_name, cross_repos_pr):
266266
if repo_name in args.skip_repository_list:
267267
print("Skipping update of '" + repo_name + "', requested by user")
268268
continue
269+
270+
# If the repository is not listed in the branch-scheme, skip it.
271+
if scheme_map and repo_name not in scheme_map:
272+
# If the repository exists locally, notify we are skipping it.
273+
if os.path.isdir(os.path.join(args.source_root, repo_name)):
274+
print(
275+
"Skipping update of '"
276+
+ repo_name
277+
+ "', repository not listed in the '"
278+
+ scheme_name
279+
+ "' branch-scheme"
280+
)
281+
continue
282+
269283
my_args = [args.source_root, config,
270284
repo_name,
271285
scheme_name,

0 commit comments

Comments
 (0)