blob: f1b4f231b5b2b959d0a0b89b313539cc7a9c73e8 [file] [log] [blame]
Raman Tenneti6a872c92021-01-14 19:17:50 -08001# Copyright (C) 2021 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Gavin Makea2e3302023-03-11 06:46:20 +000015"""Provide functionality to get projects and their commit ids from Superproject.
Raman Tenneti6a872c92021-01-14 19:17:50 -080016
17For more information on superproject, check out:
18https://en.wikibooks.org/wiki/Git/Submodules_and_Superprojects
19
20Examples:
LaMont Jonesff6b1da2022-06-01 21:03:34 +000021 superproject = Superproject(manifest, name, remote, revision)
Raman Tenneti784e16f2021-06-11 17:29:45 -070022 UpdateProjectsResult = superproject.UpdateProjectsRevisionId(projects)
Raman Tenneti6a872c92021-01-14 19:17:50 -080023"""
24
Raman Tenneticeba2dd2021-02-22 16:54:56 -080025import hashlib
Xin Li0cb6e922021-06-16 10:19:00 -070026import functools
Raman Tenneti6a872c92021-01-14 19:17:50 -080027import os
28import sys
Xin Li0cb6e922021-06-16 10:19:00 -070029import time
Raman Tenneti784e16f2021-06-11 17:29:45 -070030from typing import NamedTuple
Raman Tenneti6a872c92021-01-14 19:17:50 -080031
Raman Tennetie253b432021-06-02 10:05:54 -070032from git_command import git_require, GitCommand
Xin Li0cb6e922021-06-16 10:19:00 -070033from git_config import RepoConfig
Daniel Kutik035f22a2022-12-13 12:34:23 +010034from git_refs import GitRefs
Raman Tenneti6a872c92021-01-14 19:17:50 -080035
Gavin Makea2e3302023-03-11 06:46:20 +000036_SUPERPROJECT_GIT_NAME = "superproject.git"
37_SUPERPROJECT_MANIFEST_NAME = "superproject_override.xml"
Raman Tenneti8d43dea2021-02-07 16:30:27 -080038
Raman Tenneti6a872c92021-01-14 19:17:50 -080039
Raman Tenneti784e16f2021-06-11 17:29:45 -070040class SyncResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000041 """Return the status of sync and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070042
Gavin Makea2e3302023-03-11 06:46:20 +000043 # Whether the superproject sync was successful.
44 success: bool
45 # Whether the caller should exit.
46 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070047
48
49class CommitIdsResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000050 """Return the commit ids and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070051
Gavin Makea2e3302023-03-11 06:46:20 +000052 # A dictionary with the projects/commit ids on success, otherwise None.
53 commit_ids: dict
54 # Whether the caller should exit.
55 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070056
57
58class UpdateProjectsResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000059 """Return the overriding manifest file and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070060
Gavin Makea2e3302023-03-11 06:46:20 +000061 # Path name of the overriding manifest file if successful, otherwise None.
62 manifest_path: str
63 # Whether the caller should exit.
64 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070065
66
Raman Tenneti6a872c92021-01-14 19:17:50 -080067class Superproject(object):
Gavin Makea2e3302023-03-11 06:46:20 +000068 """Get commit ids from superproject.
Raman Tenneti6a872c92021-01-14 19:17:50 -080069
Gavin Makea2e3302023-03-11 06:46:20 +000070 Initializes a local copy of a superproject for the manifest. This allows
71 lookup of commit ids for all projects. It contains _project_commit_ids which
72 is a dictionary with project/commit id entries.
Raman Tenneti6a872c92021-01-14 19:17:50 -080073 """
Raman Tenneti6a872c92021-01-14 19:17:50 -080074
Gavin Makea2e3302023-03-11 06:46:20 +000075 def __init__(
76 self,
77 manifest,
78 name,
79 remote,
80 revision,
81 superproject_dir="exp-superproject",
82 ):
83 """Initializes superproject.
LaMont Jonesd56e2eb2022-04-07 18:14:46 +000084
Gavin Makea2e3302023-03-11 06:46:20 +000085 Args:
86 manifest: A Manifest object that is to be written to a file.
87 name: The unique name of the superproject
88 remote: The RemoteSpec for the remote.
89 revision: The name of the git branch to track.
90 superproject_dir: Relative path under |manifest.subdir| to checkout
91 superproject.
92 """
93 self._project_commit_ids = None
94 self._manifest = manifest
95 self.name = name
96 self.remote = remote
97 self.revision = self._branch = revision
98 self._repodir = manifest.repodir
99 self._superproject_dir = superproject_dir
100 self._superproject_path = manifest.SubmanifestInfoDir(
101 manifest.path_prefix, superproject_dir
102 )
103 self._manifest_path = os.path.join(
104 self._superproject_path, _SUPERPROJECT_MANIFEST_NAME
105 )
106 git_name = hashlib.md5(remote.name.encode("utf8")).hexdigest() + "-"
107 self._remote_url = remote.url
108 self._work_git_name = git_name + _SUPERPROJECT_GIT_NAME
109 self._work_git = os.path.join(
110 self._superproject_path, self._work_git_name
111 )
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000112
Gavin Makea2e3302023-03-11 06:46:20 +0000113 # The following are command arguemnts, rather than superproject
114 # attributes, and were included here originally. They should eventually
115 # become arguments that are passed down from the public methods, instead
116 # of being treated as attributes.
117 self._git_event_log = None
118 self._quiet = False
119 self._print_messages = False
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000120
Gavin Makea2e3302023-03-11 06:46:20 +0000121 def SetQuiet(self, value):
122 """Set the _quiet attribute."""
123 self._quiet = value
Raman Tenneti6a872c92021-01-14 19:17:50 -0800124
Gavin Makea2e3302023-03-11 06:46:20 +0000125 def SetPrintMessages(self, value):
126 """Set the _print_messages attribute."""
127 self._print_messages = value
Raman Tennetiae86a462021-07-27 08:54:59 -0700128
Gavin Makea2e3302023-03-11 06:46:20 +0000129 @property
130 def project_commit_ids(self):
131 """Returns a dictionary of projects and their commit ids."""
132 return self._project_commit_ids
Raman Tenneti8db30d62021-07-06 21:30:06 -0700133
Gavin Makea2e3302023-03-11 06:46:20 +0000134 @property
135 def manifest_path(self):
136 """Returns the manifest path if the path exists or None."""
137 return (
138 self._manifest_path if os.path.exists(self._manifest_path) else None
139 )
Raman Tennetid8e8ae82021-09-15 16:32:33 -0700140
Gavin Makea2e3302023-03-11 06:46:20 +0000141 def _LogMessage(self, fmt, *inputs):
142 """Logs message to stderr and _git_event_log."""
143 message = f"{self._LogMessagePrefix()} {fmt.format(*inputs)}"
144 if self._print_messages:
145 print(message, file=sys.stderr)
146 self._git_event_log.ErrorEvent(message, fmt)
Raman Tenneti5637afc2021-08-11 09:26:30 -0700147
Gavin Makea2e3302023-03-11 06:46:20 +0000148 def _LogMessagePrefix(self):
149 """Returns the prefix string to be logged in each log message"""
150 return (
151 f"repo superproject branch: {self._branch} url: {self._remote_url}"
152 )
Raman Tenneti5637afc2021-08-11 09:26:30 -0700153
Gavin Makea2e3302023-03-11 06:46:20 +0000154 def _LogError(self, fmt, *inputs):
155 """Logs error message to stderr and _git_event_log."""
156 self._LogMessage(f"error: {fmt}", *inputs)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800157
Gavin Makea2e3302023-03-11 06:46:20 +0000158 def _LogWarning(self, fmt, *inputs):
159 """Logs warning message to stderr and _git_event_log."""
160 self._LogMessage(f"warning: {fmt}", *inputs)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800161
Gavin Makea2e3302023-03-11 06:46:20 +0000162 def _Init(self):
163 """Sets up a local Git repository to get a copy of a superproject.
Raman Tenneti9e787532021-02-01 11:47:06 -0800164
Gavin Makea2e3302023-03-11 06:46:20 +0000165 Returns:
166 True if initialization is successful, or False.
167 """
168 if not os.path.exists(self._superproject_path):
169 os.mkdir(self._superproject_path)
170 if not self._quiet and not os.path.exists(self._work_git):
171 print(
172 "%s: Performing initial setup for superproject; this might "
173 "take several minutes." % self._work_git
174 )
175 cmd = ["init", "--bare", self._work_git_name]
176 p = GitCommand(
177 None,
178 cmd,
179 cwd=self._superproject_path,
180 capture_stdout=True,
181 capture_stderr=True,
182 )
183 retval = p.Wait()
184 if retval:
185 self._LogWarning(
186 "git init call failed, command: git {}, "
187 "return code: {}, stderr: {}",
188 cmd,
189 retval,
190 p.stderr,
191 )
192 return False
193 return True
Joanna Wang0e4f1e72022-12-08 17:46:28 -0500194
Gavin Makea2e3302023-03-11 06:46:20 +0000195 def _Fetch(self):
196 """Fetches a superproject for the manifest based on |_remote_url|.
Joanna Wang0e4f1e72022-12-08 17:46:28 -0500197
Gavin Makea2e3302023-03-11 06:46:20 +0000198 This runs git fetch which stores a local copy the superproject.
Raman Tenneti9e787532021-02-01 11:47:06 -0800199
Gavin Makea2e3302023-03-11 06:46:20 +0000200 Returns:
201 True if fetch is successful, or False.
202 """
203 if not os.path.exists(self._work_git):
204 self._LogWarning("git fetch missing directory: {}", self._work_git)
205 return False
206 if not git_require((2, 28, 0)):
207 self._LogWarning(
208 "superproject requires a git version 2.28 or later"
209 )
210 return False
211 cmd = [
212 "fetch",
213 self._remote_url,
214 "--depth",
215 "1",
216 "--force",
217 "--no-tags",
218 "--filter",
219 "blob:none",
220 ]
Raman Tenneti6a872c92021-01-14 19:17:50 -0800221
Gavin Makea2e3302023-03-11 06:46:20 +0000222 # Check if there is a local ref that we can pass to --negotiation-tip.
223 # If this is the first fetch, it does not exist yet.
224 # We use --negotiation-tip to speed up the fetch. Superproject branches
225 # do not share commits. So this lets git know it only needs to send
226 # commits reachable from the specified local refs.
227 rev_commit = GitRefs(self._work_git).get(f"refs/heads/{self.revision}")
228 if rev_commit:
229 cmd.extend(["--negotiation-tip", rev_commit])
Raman Tenneti6a872c92021-01-14 19:17:50 -0800230
Gavin Makea2e3302023-03-11 06:46:20 +0000231 if self._branch:
232 cmd += [self._branch + ":" + self._branch]
233 p = GitCommand(
234 None,
235 cmd,
236 cwd=self._work_git,
237 capture_stdout=True,
238 capture_stderr=True,
239 )
240 retval = p.Wait()
241 if retval:
242 self._LogWarning(
243 "git fetch call failed, command: git {}, "
244 "return code: {}, stderr: {}",
245 cmd,
246 retval,
247 p.stderr,
248 )
249 return False
250 return True
Raman Tennetice64e3d2021-02-08 13:27:41 -0800251
Gavin Makea2e3302023-03-11 06:46:20 +0000252 def _LsTree(self):
253 """Gets the commit ids for all projects.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800254
Gavin Makea2e3302023-03-11 06:46:20 +0000255 Works only in git repositories.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800256
Gavin Makea2e3302023-03-11 06:46:20 +0000257 Returns:
258 data: data returned from 'git ls-tree ...' instead of None.
259 """
260 if not os.path.exists(self._work_git):
261 self._LogWarning(
262 "git ls-tree missing directory: {}", self._work_git
263 )
264 return None
265 data = None
266 branch = "HEAD" if not self._branch else self._branch
267 cmd = ["ls-tree", "-z", "-r", branch]
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000268
Gavin Makea2e3302023-03-11 06:46:20 +0000269 p = GitCommand(
270 None,
271 cmd,
272 cwd=self._work_git,
273 capture_stdout=True,
274 capture_stderr=True,
275 )
276 retval = p.Wait()
277 if retval == 0:
278 data = p.stdout
279 else:
280 self._LogWarning(
281 "git ls-tree call failed, command: git {}, "
282 "return code: {}, stderr: {}",
283 cmd,
284 retval,
285 p.stderr,
286 )
287 return data
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800288
Gavin Makea2e3302023-03-11 06:46:20 +0000289 def Sync(self, git_event_log):
290 """Gets a local copy of a superproject for the manifest.
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000291
Gavin Makea2e3302023-03-11 06:46:20 +0000292 Args:
293 git_event_log: an EventLog, for git tracing.
Raman Tenneti8d43dea2021-02-07 16:30:27 -0800294
Gavin Makea2e3302023-03-11 06:46:20 +0000295 Returns:
296 SyncResult
297 """
298 self._git_event_log = git_event_log
299 if not self._manifest.superproject:
300 self._LogWarning(
301 "superproject tag is not defined in manifest: {}",
302 self._manifest.manifestFile,
303 )
304 return SyncResult(False, False)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800305
Gavin Makea2e3302023-03-11 06:46:20 +0000306 _PrintBetaNotice()
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800307
Gavin Makea2e3302023-03-11 06:46:20 +0000308 should_exit = True
309 if not self._remote_url:
310 self._LogWarning(
311 "superproject URL is not defined in manifest: {}",
312 self._manifest.manifestFile,
313 )
314 return SyncResult(False, should_exit)
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800315
Gavin Makea2e3302023-03-11 06:46:20 +0000316 if not self._Init():
317 return SyncResult(False, should_exit)
318 if not self._Fetch():
319 return SyncResult(False, should_exit)
320 if not self._quiet:
321 print(
322 "%s: Initial setup for superproject completed." % self._work_git
323 )
324 return SyncResult(True, False)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800325
Gavin Makea2e3302023-03-11 06:46:20 +0000326 def _GetAllProjectsCommitIds(self):
327 """Get commit ids for all projects from superproject and save them.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800328
Gavin Makea2e3302023-03-11 06:46:20 +0000329 Commit ids are saved in _project_commit_ids.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800330
Gavin Makea2e3302023-03-11 06:46:20 +0000331 Returns:
332 CommitIdsResult
333 """
334 sync_result = self.Sync(self._git_event_log)
335 if not sync_result.success:
336 return CommitIdsResult(None, sync_result.fatal)
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800337
Gavin Makea2e3302023-03-11 06:46:20 +0000338 data = self._LsTree()
339 if not data:
340 self._LogWarning(
341 "git ls-tree failed to return data for manifest: {}",
342 self._manifest.manifestFile,
343 )
344 return CommitIdsResult(None, True)
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800345
Gavin Makea2e3302023-03-11 06:46:20 +0000346 # Parse lines like the following to select lines starting with '160000'
347 # and build a dictionary with project path (last element) and its commit
348 # id (3rd element).
349 #
350 # 160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00
351 # 120000 blob acc2cbdf438f9d2141f0ae424cec1d8fc4b5d97f\tbootstrap.bash\x00 # noqa: E501
352 commit_ids = {}
353 for line in data.split("\x00"):
354 ls_data = line.split(None, 3)
355 if not ls_data:
356 break
357 if ls_data[0] == "160000":
358 commit_ids[ls_data[3]] = ls_data[2]
Raman Tenneti784e16f2021-06-11 17:29:45 -0700359
Gavin Makea2e3302023-03-11 06:46:20 +0000360 self._project_commit_ids = commit_ids
361 return CommitIdsResult(commit_ids, False)
Raman Tenneti784e16f2021-06-11 17:29:45 -0700362
Gavin Makea2e3302023-03-11 06:46:20 +0000363 def _WriteManifestFile(self):
364 """Writes manifest to a file.
Raman Tenneti784e16f2021-06-11 17:29:45 -0700365
Gavin Makea2e3302023-03-11 06:46:20 +0000366 Returns:
367 manifest_path: Path name of the file into which manifest is written
368 instead of None.
369 """
370 if not os.path.exists(self._superproject_path):
371 self._LogWarning(
372 "missing superproject directory: {}", self._superproject_path
373 )
374 return None
375 manifest_str = self._manifest.ToXml(
376 groups=self._manifest.GetGroupsStr(), omit_local=True
377 ).toxml()
378 manifest_path = self._manifest_path
379 try:
380 with open(manifest_path, "w", encoding="utf-8") as fp:
381 fp.write(manifest_str)
382 except IOError as e:
383 self._LogError("cannot write manifest to : {} {}", manifest_path, e)
384 return None
385 return manifest_path
Raman Tenneti784e16f2021-06-11 17:29:45 -0700386
Gavin Makea2e3302023-03-11 06:46:20 +0000387 def _SkipUpdatingProjectRevisionId(self, project):
388 """Checks if a project's revision id needs to be updated or not.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800389
Gavin Makea2e3302023-03-11 06:46:20 +0000390 Revision id for projects from local manifest will not be updated.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800391
Gavin Makea2e3302023-03-11 06:46:20 +0000392 Args:
393 project: project whose revision id is being updated.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800394
Gavin Makea2e3302023-03-11 06:46:20 +0000395 Returns:
396 True if a project's revision id should not be updated, or False,
397 """
398 path = project.relpath
399 if not path:
400 return True
401 # Skip the project with revisionId.
402 if project.revisionId:
403 return True
404 # Skip the project if it comes from the local manifest.
405 return project.manifest.IsFromLocalManifest(project)
Raman Tenneti784e16f2021-06-11 17:29:45 -0700406
Gavin Makea2e3302023-03-11 06:46:20 +0000407 def UpdateProjectsRevisionId(self, projects, git_event_log):
408 """Update revisionId of every project in projects with the commit id.
Raman Tenneti784e16f2021-06-11 17:29:45 -0700409
Gavin Makea2e3302023-03-11 06:46:20 +0000410 Args:
411 projects: a list of projects whose revisionId needs to be updated.
412 git_event_log: an EventLog, for git tracing.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800413
Gavin Makea2e3302023-03-11 06:46:20 +0000414 Returns:
415 UpdateProjectsResult
416 """
417 self._git_event_log = git_event_log
418 commit_ids_result = self._GetAllProjectsCommitIds()
419 commit_ids = commit_ids_result.commit_ids
420 if not commit_ids:
421 return UpdateProjectsResult(None, commit_ids_result.fatal)
422
423 projects_missing_commit_ids = []
424 for project in projects:
425 if self._SkipUpdatingProjectRevisionId(project):
426 continue
427 path = project.relpath
428 commit_id = commit_ids.get(path)
429 if not commit_id:
430 projects_missing_commit_ids.append(path)
431
432 # If superproject doesn't have a commit id for a project, then report an
433 # error event and continue as if do not use superproject is specified.
434 if projects_missing_commit_ids:
435 self._LogWarning(
436 "please file a bug using {} to report missing "
437 "commit_ids for: {}",
438 self._manifest.contactinfo.bugurl,
439 projects_missing_commit_ids,
440 )
441 return UpdateProjectsResult(None, False)
442
443 for project in projects:
444 if not self._SkipUpdatingProjectRevisionId(project):
445 project.SetRevisionId(commit_ids.get(project.relpath))
446
447 manifest_path = self._WriteManifestFile()
448 return UpdateProjectsResult(manifest_path, False)
Xin Li0cb6e922021-06-16 10:19:00 -0700449
450
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000451@functools.lru_cache(maxsize=10)
452def _PrintBetaNotice():
Gavin Makea2e3302023-03-11 06:46:20 +0000453 """Print the notice of beta status."""
454 print(
455 "NOTICE: --use-superproject is in beta; report any issues to the "
456 "address described in `repo version`",
457 file=sys.stderr,
458 )
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000459
460
Xin Li0cb6e922021-06-16 10:19:00 -0700461@functools.lru_cache(maxsize=None)
462def _UseSuperprojectFromConfiguration():
Gavin Makea2e3302023-03-11 06:46:20 +0000463 """Returns the user choice of whether to use superproject."""
464 user_cfg = RepoConfig.ForUser()
465 time_now = int(time.time())
Xin Li0cb6e922021-06-16 10:19:00 -0700466
Gavin Makea2e3302023-03-11 06:46:20 +0000467 user_value = user_cfg.GetBoolean("repo.superprojectChoice")
468 if user_value is not None:
469 user_expiration = user_cfg.GetInt("repo.superprojectChoiceExpire")
470 if (
471 user_expiration is None
472 or user_expiration <= 0
473 or user_expiration >= time_now
474 ):
475 # TODO(b/190688390) - Remove prompt when we are comfortable with the
476 # new default value.
477 if user_value:
478 print(
479 (
480 "You are currently enrolled in Git submodules "
481 "experiment (go/android-submodules-quickstart). Use "
482 "--no-use-superproject to override.\n"
483 ),
484 file=sys.stderr,
485 )
486 else:
487 print(
488 (
489 "You are not currently enrolled in Git submodules "
490 "experiment (go/android-submodules-quickstart). Use "
491 "--use-superproject to override.\n"
492 ),
493 file=sys.stderr,
494 )
495 return user_value
Xin Li0cb6e922021-06-16 10:19:00 -0700496
Gavin Makea2e3302023-03-11 06:46:20 +0000497 # We don't have an unexpired choice, ask for one.
498 system_cfg = RepoConfig.ForSystem()
499 system_value = system_cfg.GetBoolean("repo.superprojectChoice")
500 if system_value:
501 # The system configuration is proposing that we should enable the
502 # use of superproject. Treat the user as enrolled for two weeks.
503 #
504 # TODO(b/190688390) - Remove prompt when we are comfortable with the new
505 # default value.
506 userchoice = True
507 time_choiceexpire = time_now + (86400 * 14)
508 user_cfg.SetString(
509 "repo.superprojectChoiceExpire", str(time_choiceexpire)
510 )
511 user_cfg.SetBoolean("repo.superprojectChoice", userchoice)
512 print(
513 "You are automatically enrolled in Git submodules experiment "
514 "(go/android-submodules-quickstart) for another two weeks.\n",
515 file=sys.stderr,
516 )
517 return True
Xin Li0cb6e922021-06-16 10:19:00 -0700518
Gavin Makea2e3302023-03-11 06:46:20 +0000519 # For all other cases, we would not use superproject by default.
520 return False
Xin Li0cb6e922021-06-16 10:19:00 -0700521
522
LaMont Jones5fa912b2022-04-14 14:41:13 +0000523def PrintMessages(use_superproject, manifest):
Gavin Makea2e3302023-03-11 06:46:20 +0000524 """Returns a boolean if error/warning messages are to be printed.
LaMont Jones5fa912b2022-04-14 14:41:13 +0000525
Gavin Makea2e3302023-03-11 06:46:20 +0000526 Args:
527 use_superproject: option value from optparse.
528 manifest: manifest to use.
529 """
530 return use_superproject is not None or bool(manifest.superproject)
Raman Tennetib55769a2021-08-13 11:47:24 -0700531
532
LaMont Jones5fa912b2022-04-14 14:41:13 +0000533def UseSuperproject(use_superproject, manifest):
Gavin Makea2e3302023-03-11 06:46:20 +0000534 """Returns a boolean if use-superproject option is enabled.
Xin Li0cb6e922021-06-16 10:19:00 -0700535
Gavin Makea2e3302023-03-11 06:46:20 +0000536 Args:
537 use_superproject: option value from optparse.
538 manifest: manifest to use.
LaMont Jonesff6b1da2022-06-01 21:03:34 +0000539
Gavin Makea2e3302023-03-11 06:46:20 +0000540 Returns:
541 Whether the superproject should be used.
542 """
LaMont Jones5fa912b2022-04-14 14:41:13 +0000543
Gavin Makea2e3302023-03-11 06:46:20 +0000544 if not manifest.superproject:
545 # This (sub) manifest does not have a superproject definition.
546 return False
547 elif use_superproject is not None:
548 return use_superproject
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000549 else:
Gavin Makea2e3302023-03-11 06:46:20 +0000550 client_value = manifest.manifestProject.use_superproject
551 if client_value is not None:
552 return client_value
553 elif manifest.superproject:
554 return _UseSuperprojectFromConfiguration()
555 else:
556 return False