blob: fca0e6f76cc13d45bea490732b3d203de1ad006d [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
Xin Li0cb6e922021-06-16 10:19:00 -070025import functools
Mike Frysinger64477332023-08-21 21:20:32 -040026import hashlib
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
Mike Frysinger64477332023-08-21 21:20:32 -040032from git_command import git_require
33from git_command import GitCommand
Xin Li0cb6e922021-06-16 10:19:00 -070034from git_config import RepoConfig
Daniel Kutik035f22a2022-12-13 12:34:23 +010035from git_refs import GitRefs
Raman Tenneti6a872c92021-01-14 19:17:50 -080036
Mike Frysinger64477332023-08-21 21:20:32 -040037
Gavin Makea2e3302023-03-11 06:46:20 +000038_SUPERPROJECT_GIT_NAME = "superproject.git"
39_SUPERPROJECT_MANIFEST_NAME = "superproject_override.xml"
Raman Tenneti8d43dea2021-02-07 16:30:27 -080040
Raman Tenneti6a872c92021-01-14 19:17:50 -080041
Raman Tenneti784e16f2021-06-11 17:29:45 -070042class SyncResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000043 """Return the status of sync and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070044
Gavin Makea2e3302023-03-11 06:46:20 +000045 # Whether the superproject sync was successful.
46 success: bool
47 # Whether the caller should exit.
48 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070049
50
51class CommitIdsResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000052 """Return the commit ids and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070053
Gavin Makea2e3302023-03-11 06:46:20 +000054 # A dictionary with the projects/commit ids on success, otherwise None.
55 commit_ids: dict
56 # Whether the caller should exit.
57 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070058
59
60class UpdateProjectsResult(NamedTuple):
Gavin Makea2e3302023-03-11 06:46:20 +000061 """Return the overriding manifest file and whether caller should exit."""
Raman Tenneti784e16f2021-06-11 17:29:45 -070062
Gavin Makea2e3302023-03-11 06:46:20 +000063 # Path name of the overriding manifest file if successful, otherwise None.
64 manifest_path: str
65 # Whether the caller should exit.
66 fatal: bool
Raman Tenneti784e16f2021-06-11 17:29:45 -070067
68
Mike Frysingerd4aee652023-10-19 05:13:32 -040069class Superproject:
Gavin Makea2e3302023-03-11 06:46:20 +000070 """Get commit ids from superproject.
Raman Tenneti6a872c92021-01-14 19:17:50 -080071
Emily Shaffer8a6d1722023-09-15 13:26:38 -070072 Initializes a bare local copy of a superproject for the manifest. This
73 allows lookup of commit ids for all projects. It contains
74 _project_commit_ids which is a dictionary with project/commit id entries.
Raman Tenneti6a872c92021-01-14 19:17:50 -080075 """
Raman Tenneti6a872c92021-01-14 19:17:50 -080076
Gavin Makea2e3302023-03-11 06:46:20 +000077 def __init__(
78 self,
79 manifest,
80 name,
81 remote,
82 revision,
83 superproject_dir="exp-superproject",
84 ):
85 """Initializes superproject.
LaMont Jonesd56e2eb2022-04-07 18:14:46 +000086
Gavin Makea2e3302023-03-11 06:46:20 +000087 Args:
88 manifest: A Manifest object that is to be written to a file.
89 name: The unique name of the superproject
90 remote: The RemoteSpec for the remote.
91 revision: The name of the git branch to track.
92 superproject_dir: Relative path under |manifest.subdir| to checkout
93 superproject.
94 """
95 self._project_commit_ids = None
96 self._manifest = manifest
97 self.name = name
98 self.remote = remote
99 self.revision = self._branch = revision
100 self._repodir = manifest.repodir
101 self._superproject_dir = superproject_dir
102 self._superproject_path = manifest.SubmanifestInfoDir(
103 manifest.path_prefix, superproject_dir
104 )
105 self._manifest_path = os.path.join(
106 self._superproject_path, _SUPERPROJECT_MANIFEST_NAME
107 )
108 git_name = hashlib.md5(remote.name.encode("utf8")).hexdigest() + "-"
109 self._remote_url = remote.url
110 self._work_git_name = git_name + _SUPERPROJECT_GIT_NAME
111 self._work_git = os.path.join(
112 self._superproject_path, self._work_git_name
113 )
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000114
Gavin Makea2e3302023-03-11 06:46:20 +0000115 # The following are command arguemnts, rather than superproject
116 # attributes, and were included here originally. They should eventually
117 # become arguments that are passed down from the public methods, instead
118 # of being treated as attributes.
119 self._git_event_log = None
120 self._quiet = False
121 self._print_messages = False
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000122
Gavin Makea2e3302023-03-11 06:46:20 +0000123 def SetQuiet(self, value):
124 """Set the _quiet attribute."""
125 self._quiet = value
Raman Tenneti6a872c92021-01-14 19:17:50 -0800126
Gavin Makea2e3302023-03-11 06:46:20 +0000127 def SetPrintMessages(self, value):
128 """Set the _print_messages attribute."""
129 self._print_messages = value
Raman Tennetiae86a462021-07-27 08:54:59 -0700130
Gavin Makea2e3302023-03-11 06:46:20 +0000131 @property
132 def project_commit_ids(self):
133 """Returns a dictionary of projects and their commit ids."""
134 return self._project_commit_ids
Raman Tenneti8db30d62021-07-06 21:30:06 -0700135
Gavin Makea2e3302023-03-11 06:46:20 +0000136 @property
137 def manifest_path(self):
138 """Returns the manifest path if the path exists or None."""
139 return (
140 self._manifest_path if os.path.exists(self._manifest_path) else None
141 )
Raman Tennetid8e8ae82021-09-15 16:32:33 -0700142
Gavin Makea2e3302023-03-11 06:46:20 +0000143 def _LogMessage(self, fmt, *inputs):
144 """Logs message to stderr and _git_event_log."""
145 message = f"{self._LogMessagePrefix()} {fmt.format(*inputs)}"
146 if self._print_messages:
147 print(message, file=sys.stderr)
148 self._git_event_log.ErrorEvent(message, fmt)
Raman Tenneti5637afc2021-08-11 09:26:30 -0700149
Gavin Makea2e3302023-03-11 06:46:20 +0000150 def _LogMessagePrefix(self):
151 """Returns the prefix string to be logged in each log message"""
152 return (
153 f"repo superproject branch: {self._branch} url: {self._remote_url}"
154 )
Raman Tenneti5637afc2021-08-11 09:26:30 -0700155
Gavin Makea2e3302023-03-11 06:46:20 +0000156 def _LogError(self, fmt, *inputs):
157 """Logs error message to stderr and _git_event_log."""
158 self._LogMessage(f"error: {fmt}", *inputs)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800159
Gavin Makea2e3302023-03-11 06:46:20 +0000160 def _LogWarning(self, fmt, *inputs):
161 """Logs warning message to stderr and _git_event_log."""
162 self._LogMessage(f"warning: {fmt}", *inputs)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800163
Gavin Makea2e3302023-03-11 06:46:20 +0000164 def _Init(self):
165 """Sets up a local Git repository to get a copy of a superproject.
Raman Tenneti9e787532021-02-01 11:47:06 -0800166
Gavin Makea2e3302023-03-11 06:46:20 +0000167 Returns:
168 True if initialization is successful, or False.
169 """
170 if not os.path.exists(self._superproject_path):
171 os.mkdir(self._superproject_path)
172 if not self._quiet and not os.path.exists(self._work_git):
173 print(
174 "%s: Performing initial setup for superproject; this might "
175 "take several minutes." % self._work_git
176 )
177 cmd = ["init", "--bare", self._work_git_name]
178 p = GitCommand(
179 None,
180 cmd,
181 cwd=self._superproject_path,
182 capture_stdout=True,
183 capture_stderr=True,
184 )
185 retval = p.Wait()
186 if retval:
187 self._LogWarning(
188 "git init call failed, command: git {}, "
189 "return code: {}, stderr: {}",
190 cmd,
191 retval,
192 p.stderr,
193 )
194 return False
195 return True
Joanna Wang0e4f1e72022-12-08 17:46:28 -0500196
Gavin Makea2e3302023-03-11 06:46:20 +0000197 def _Fetch(self):
198 """Fetches a superproject for the manifest based on |_remote_url|.
Joanna Wang0e4f1e72022-12-08 17:46:28 -0500199
Gavin Makea2e3302023-03-11 06:46:20 +0000200 This runs git fetch which stores a local copy the superproject.
Raman Tenneti9e787532021-02-01 11:47:06 -0800201
Gavin Makea2e3302023-03-11 06:46:20 +0000202 Returns:
203 True if fetch is successful, or False.
204 """
205 if not os.path.exists(self._work_git):
206 self._LogWarning("git fetch missing directory: {}", self._work_git)
207 return False
208 if not git_require((2, 28, 0)):
209 self._LogWarning(
210 "superproject requires a git version 2.28 or later"
211 )
212 return False
213 cmd = [
214 "fetch",
215 self._remote_url,
216 "--depth",
217 "1",
218 "--force",
219 "--no-tags",
220 "--filter",
221 "blob:none",
222 ]
Raman Tenneti6a872c92021-01-14 19:17:50 -0800223
Gavin Makea2e3302023-03-11 06:46:20 +0000224 # Check if there is a local ref that we can pass to --negotiation-tip.
225 # If this is the first fetch, it does not exist yet.
226 # We use --negotiation-tip to speed up the fetch. Superproject branches
227 # do not share commits. So this lets git know it only needs to send
228 # commits reachable from the specified local refs.
229 rev_commit = GitRefs(self._work_git).get(f"refs/heads/{self.revision}")
230 if rev_commit:
231 cmd.extend(["--negotiation-tip", rev_commit])
Raman Tenneti6a872c92021-01-14 19:17:50 -0800232
Gavin Makea2e3302023-03-11 06:46:20 +0000233 if self._branch:
234 cmd += [self._branch + ":" + self._branch]
235 p = GitCommand(
236 None,
237 cmd,
Emily Shaffer8a6d1722023-09-15 13:26:38 -0700238 gitdir=self._work_git,
239 bare=True,
Gavin Makea2e3302023-03-11 06:46:20 +0000240 capture_stdout=True,
241 capture_stderr=True,
242 )
243 retval = p.Wait()
244 if retval:
245 self._LogWarning(
246 "git fetch call failed, command: git {}, "
247 "return code: {}, stderr: {}",
248 cmd,
249 retval,
250 p.stderr,
251 )
252 return False
253 return True
Raman Tennetice64e3d2021-02-08 13:27:41 -0800254
Gavin Makea2e3302023-03-11 06:46:20 +0000255 def _LsTree(self):
256 """Gets the commit ids for all projects.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800257
Gavin Makea2e3302023-03-11 06:46:20 +0000258 Works only in git repositories.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800259
Gavin Makea2e3302023-03-11 06:46:20 +0000260 Returns:
261 data: data returned from 'git ls-tree ...' instead of None.
262 """
263 if not os.path.exists(self._work_git):
264 self._LogWarning(
265 "git ls-tree missing directory: {}", self._work_git
266 )
267 return None
268 data = None
269 branch = "HEAD" if not self._branch else self._branch
270 cmd = ["ls-tree", "-z", "-r", branch]
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000271
Gavin Makea2e3302023-03-11 06:46:20 +0000272 p = GitCommand(
273 None,
274 cmd,
Emily Shaffer8a6d1722023-09-15 13:26:38 -0700275 gitdir=self._work_git,
276 bare=True,
Gavin Makea2e3302023-03-11 06:46:20 +0000277 capture_stdout=True,
278 capture_stderr=True,
279 )
280 retval = p.Wait()
281 if retval == 0:
282 data = p.stdout
283 else:
284 self._LogWarning(
285 "git ls-tree call failed, command: git {}, "
286 "return code: {}, stderr: {}",
287 cmd,
288 retval,
289 p.stderr,
290 )
291 return data
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800292
Gavin Makea2e3302023-03-11 06:46:20 +0000293 def Sync(self, git_event_log):
294 """Gets a local copy of a superproject for the manifest.
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000295
Gavin Makea2e3302023-03-11 06:46:20 +0000296 Args:
297 git_event_log: an EventLog, for git tracing.
Raman Tenneti8d43dea2021-02-07 16:30:27 -0800298
Gavin Makea2e3302023-03-11 06:46:20 +0000299 Returns:
300 SyncResult
301 """
302 self._git_event_log = git_event_log
303 if not self._manifest.superproject:
304 self._LogWarning(
305 "superproject tag is not defined in manifest: {}",
306 self._manifest.manifestFile,
307 )
308 return SyncResult(False, False)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800309
Gavin Makea2e3302023-03-11 06:46:20 +0000310 _PrintBetaNotice()
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800311
Gavin Makea2e3302023-03-11 06:46:20 +0000312 should_exit = True
313 if not self._remote_url:
314 self._LogWarning(
315 "superproject URL is not defined in manifest: {}",
316 self._manifest.manifestFile,
317 )
318 return SyncResult(False, should_exit)
Raman Tenneti21dce3d2021-02-09 00:26:31 -0800319
Gavin Makea2e3302023-03-11 06:46:20 +0000320 if not self._Init():
321 return SyncResult(False, should_exit)
322 if not self._Fetch():
323 return SyncResult(False, should_exit)
324 if not self._quiet:
325 print(
326 "%s: Initial setup for superproject completed." % self._work_git
327 )
328 return SyncResult(True, False)
Raman Tenneti6a872c92021-01-14 19:17:50 -0800329
Gavin Makea2e3302023-03-11 06:46:20 +0000330 def _GetAllProjectsCommitIds(self):
331 """Get commit ids for all projects from superproject and save them.
Raman Tenneti6a872c92021-01-14 19:17:50 -0800332
Gavin Makea2e3302023-03-11 06:46:20 +0000333 Commit ids are saved in _project_commit_ids.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800334
Gavin Makea2e3302023-03-11 06:46:20 +0000335 Returns:
336 CommitIdsResult
337 """
338 sync_result = self.Sync(self._git_event_log)
339 if not sync_result.success:
340 return CommitIdsResult(None, sync_result.fatal)
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800341
Gavin Makea2e3302023-03-11 06:46:20 +0000342 data = self._LsTree()
343 if not data:
344 self._LogWarning(
345 "git ls-tree failed to return data for manifest: {}",
346 self._manifest.manifestFile,
347 )
348 return CommitIdsResult(None, True)
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800349
Gavin Makea2e3302023-03-11 06:46:20 +0000350 # Parse lines like the following to select lines starting with '160000'
351 # and build a dictionary with project path (last element) and its commit
352 # id (3rd element).
353 #
354 # 160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00
355 # 120000 blob acc2cbdf438f9d2141f0ae424cec1d8fc4b5d97f\tbootstrap.bash\x00 # noqa: E501
356 commit_ids = {}
357 for line in data.split("\x00"):
358 ls_data = line.split(None, 3)
359 if not ls_data:
360 break
361 if ls_data[0] == "160000":
362 commit_ids[ls_data[3]] = ls_data[2]
Raman Tenneti784e16f2021-06-11 17:29:45 -0700363
Gavin Makea2e3302023-03-11 06:46:20 +0000364 self._project_commit_ids = commit_ids
365 return CommitIdsResult(commit_ids, False)
Raman Tenneti784e16f2021-06-11 17:29:45 -0700366
Gavin Makea2e3302023-03-11 06:46:20 +0000367 def _WriteManifestFile(self):
368 """Writes manifest to a file.
Raman Tenneti784e16f2021-06-11 17:29:45 -0700369
Gavin Makea2e3302023-03-11 06:46:20 +0000370 Returns:
371 manifest_path: Path name of the file into which manifest is written
372 instead of None.
373 """
374 if not os.path.exists(self._superproject_path):
375 self._LogWarning(
376 "missing superproject directory: {}", self._superproject_path
377 )
378 return None
379 manifest_str = self._manifest.ToXml(
380 groups=self._manifest.GetGroupsStr(), omit_local=True
381 ).toxml()
382 manifest_path = self._manifest_path
383 try:
384 with open(manifest_path, "w", encoding="utf-8") as fp:
385 fp.write(manifest_str)
Jason R. Coombsae824fb2023-10-20 23:32:40 +0545386 except OSError as e:
Gavin Makea2e3302023-03-11 06:46:20 +0000387 self._LogError("cannot write manifest to : {} {}", manifest_path, e)
388 return None
389 return manifest_path
Raman Tenneti784e16f2021-06-11 17:29:45 -0700390
Gavin Makea2e3302023-03-11 06:46:20 +0000391 def _SkipUpdatingProjectRevisionId(self, project):
392 """Checks if a project's revision id needs to be updated or not.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800393
Gavin Makea2e3302023-03-11 06:46:20 +0000394 Revision id for projects from local manifest will not be updated.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800395
Gavin Makea2e3302023-03-11 06:46:20 +0000396 Args:
397 project: project whose revision id is being updated.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800398
Gavin Makea2e3302023-03-11 06:46:20 +0000399 Returns:
400 True if a project's revision id should not be updated, or False,
401 """
402 path = project.relpath
403 if not path:
404 return True
405 # Skip the project with revisionId.
406 if project.revisionId:
407 return True
408 # Skip the project if it comes from the local manifest.
409 return project.manifest.IsFromLocalManifest(project)
Raman Tenneti784e16f2021-06-11 17:29:45 -0700410
Gavin Makea2e3302023-03-11 06:46:20 +0000411 def UpdateProjectsRevisionId(self, projects, git_event_log):
412 """Update revisionId of every project in projects with the commit id.
Raman Tenneti784e16f2021-06-11 17:29:45 -0700413
Gavin Makea2e3302023-03-11 06:46:20 +0000414 Args:
415 projects: a list of projects whose revisionId needs to be updated.
416 git_event_log: an EventLog, for git tracing.
Raman Tenneti1fd7bc22021-02-04 14:39:38 -0800417
Gavin Makea2e3302023-03-11 06:46:20 +0000418 Returns:
419 UpdateProjectsResult
420 """
421 self._git_event_log = git_event_log
422 commit_ids_result = self._GetAllProjectsCommitIds()
423 commit_ids = commit_ids_result.commit_ids
424 if not commit_ids:
425 return UpdateProjectsResult(None, commit_ids_result.fatal)
426
427 projects_missing_commit_ids = []
428 for project in projects:
429 if self._SkipUpdatingProjectRevisionId(project):
430 continue
431 path = project.relpath
432 commit_id = commit_ids.get(path)
433 if not commit_id:
434 projects_missing_commit_ids.append(path)
435
436 # If superproject doesn't have a commit id for a project, then report an
437 # error event and continue as if do not use superproject is specified.
438 if projects_missing_commit_ids:
439 self._LogWarning(
440 "please file a bug using {} to report missing "
441 "commit_ids for: {}",
442 self._manifest.contactinfo.bugurl,
443 projects_missing_commit_ids,
444 )
445 return UpdateProjectsResult(None, False)
446
447 for project in projects:
448 if not self._SkipUpdatingProjectRevisionId(project):
449 project.SetRevisionId(commit_ids.get(project.relpath))
450
451 manifest_path = self._WriteManifestFile()
452 return UpdateProjectsResult(manifest_path, False)
Xin Li0cb6e922021-06-16 10:19:00 -0700453
454
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000455@functools.lru_cache(maxsize=10)
456def _PrintBetaNotice():
Gavin Makea2e3302023-03-11 06:46:20 +0000457 """Print the notice of beta status."""
458 print(
459 "NOTICE: --use-superproject is in beta; report any issues to the "
460 "address described in `repo version`",
461 file=sys.stderr,
462 )
LaMont Jones2cc3ab72022-04-13 15:58:58 +0000463
464
Xin Li0cb6e922021-06-16 10:19:00 -0700465@functools.lru_cache(maxsize=None)
466def _UseSuperprojectFromConfiguration():
Gavin Makea2e3302023-03-11 06:46:20 +0000467 """Returns the user choice of whether to use superproject."""
468 user_cfg = RepoConfig.ForUser()
469 time_now = int(time.time())
Xin Li0cb6e922021-06-16 10:19:00 -0700470
Gavin Makea2e3302023-03-11 06:46:20 +0000471 user_value = user_cfg.GetBoolean("repo.superprojectChoice")
472 if user_value is not None:
473 user_expiration = user_cfg.GetInt("repo.superprojectChoiceExpire")
474 if (
475 user_expiration is None
476 or user_expiration <= 0
477 or user_expiration >= time_now
478 ):
479 # TODO(b/190688390) - Remove prompt when we are comfortable with the
480 # new default value.
481 if user_value:
482 print(
483 (
484 "You are currently enrolled in Git submodules "
485 "experiment (go/android-submodules-quickstart). Use "
486 "--no-use-superproject to override.\n"
487 ),
488 file=sys.stderr,
489 )
490 else:
491 print(
492 (
493 "You are not currently enrolled in Git submodules "
494 "experiment (go/android-submodules-quickstart). Use "
495 "--use-superproject to override.\n"
496 ),
497 file=sys.stderr,
498 )
499 return user_value
Xin Li0cb6e922021-06-16 10:19:00 -0700500
Gavin Makea2e3302023-03-11 06:46:20 +0000501 # We don't have an unexpired choice, ask for one.
502 system_cfg = RepoConfig.ForSystem()
503 system_value = system_cfg.GetBoolean("repo.superprojectChoice")
504 if system_value:
505 # The system configuration is proposing that we should enable the
506 # use of superproject. Treat the user as enrolled for two weeks.
507 #
508 # TODO(b/190688390) - Remove prompt when we are comfortable with the new
509 # default value.
510 userchoice = True
511 time_choiceexpire = time_now + (86400 * 14)
512 user_cfg.SetString(
513 "repo.superprojectChoiceExpire", str(time_choiceexpire)
514 )
515 user_cfg.SetBoolean("repo.superprojectChoice", userchoice)
516 print(
517 "You are automatically enrolled in Git submodules experiment "
518 "(go/android-submodules-quickstart) for another two weeks.\n",
519 file=sys.stderr,
520 )
521 return True
Xin Li0cb6e922021-06-16 10:19:00 -0700522
Gavin Makea2e3302023-03-11 06:46:20 +0000523 # For all other cases, we would not use superproject by default.
524 return False
Xin Li0cb6e922021-06-16 10:19:00 -0700525
526
LaMont Jones5fa912b2022-04-14 14:41:13 +0000527def PrintMessages(use_superproject, manifest):
Gavin Makea2e3302023-03-11 06:46:20 +0000528 """Returns a boolean if error/warning messages are to be printed.
LaMont Jones5fa912b2022-04-14 14:41:13 +0000529
Gavin Makea2e3302023-03-11 06:46:20 +0000530 Args:
531 use_superproject: option value from optparse.
532 manifest: manifest to use.
533 """
534 return use_superproject is not None or bool(manifest.superproject)
Raman Tennetib55769a2021-08-13 11:47:24 -0700535
536
LaMont Jones5fa912b2022-04-14 14:41:13 +0000537def UseSuperproject(use_superproject, manifest):
Gavin Makea2e3302023-03-11 06:46:20 +0000538 """Returns a boolean if use-superproject option is enabled.
Xin Li0cb6e922021-06-16 10:19:00 -0700539
Gavin Makea2e3302023-03-11 06:46:20 +0000540 Args:
541 use_superproject: option value from optparse.
542 manifest: manifest to use.
LaMont Jonesff6b1da2022-06-01 21:03:34 +0000543
Gavin Makea2e3302023-03-11 06:46:20 +0000544 Returns:
545 Whether the superproject should be used.
546 """
LaMont Jones5fa912b2022-04-14 14:41:13 +0000547
Gavin Makea2e3302023-03-11 06:46:20 +0000548 if not manifest.superproject:
549 # This (sub) manifest does not have a superproject definition.
550 return False
551 elif use_superproject is not None:
552 return use_superproject
LaMont Jonesd56e2eb2022-04-07 18:14:46 +0000553 else:
Gavin Makea2e3302023-03-11 06:46:20 +0000554 client_value = manifest.manifestProject.use_superproject
555 if client_value is not None:
556 return client_value
557 elif manifest.superproject:
558 return _UseSuperprojectFromConfiguration()
559 else:
560 return False