summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--git_command.py3
-rw-r--r--git_config.py14
-rw-r--r--git_superproject.py81
-rw-r--r--subcmds/sync.py11
4 files changed, 98 insertions, 11 deletions
diff --git a/git_command.py b/git_command.py
index 04953f38..95db91f2 100644
--- a/git_command.py
+++ b/git_command.py
@@ -75,7 +75,8 @@ def RepoSourceVersion():
75 proj = os.path.dirname(os.path.abspath(__file__)) 75 proj = os.path.dirname(os.path.abspath(__file__))
76 env[GIT_DIR] = os.path.join(proj, '.git') 76 env[GIT_DIR] = os.path.join(proj, '.git')
77 result = subprocess.run([GIT, 'describe', HEAD], stdout=subprocess.PIPE, 77 result = subprocess.run([GIT, 'describe', HEAD], stdout=subprocess.PIPE,
78 encoding='utf-8', env=env, check=False) 78 stderr=subprocess.DEVNULL, encoding='utf-8',
79 env=env, check=False)
79 if result.returncode == 0: 80 if result.returncode == 0:
80 ver = result.stdout.strip() 81 ver = result.stdout.strip()
81 if ver.startswith('v'): 82 if ver.startswith('v'):
diff --git a/git_config.py b/git_config.py
index 978f6a59..3eaf201c 100644
--- a/git_config.py
+++ b/git_config.py
@@ -65,6 +65,15 @@ class GitConfig(object):
65 65
66 _USER_CONFIG = '~/.gitconfig' 66 _USER_CONFIG = '~/.gitconfig'
67 67
68 _ForSystem = None
69 _SYSTEM_CONFIG = '/etc/gitconfig'
70
71 @classmethod
72 def ForSystem(cls):
73 if cls._ForSystem is None:
74 cls._ForSystem = cls(configfile=cls._SYSTEM_CONFIG)
75 return cls._ForSystem
76
68 @classmethod 77 @classmethod
69 def ForUser(cls): 78 def ForUser(cls):
70 if cls._ForUser is None: 79 if cls._ForUser is None:
@@ -356,7 +365,10 @@ class GitConfig(object):
356 return c 365 return c
357 366
358 def _do(self, *args): 367 def _do(self, *args):
359 command = ['config', '--file', self.file, '--includes'] 368 if self.file == self._SYSTEM_CONFIG:
369 command = ['config', '--system', '--includes']
370 else:
371 command = ['config', '--file', self.file, '--includes']
360 command.extend(args) 372 command.extend(args)
361 373
362 p = GitCommand(None, 374 p = GitCommand(None,
diff --git a/git_superproject.py b/git_superproject.py
index 0c477060..2a47847a 100644
--- a/git_superproject.py
+++ b/git_superproject.py
@@ -23,11 +23,14 @@ Examples:
23""" 23"""
24 24
25import hashlib 25import hashlib
26import functools
26import os 27import os
27import sys 28import sys
29import time
28from typing import NamedTuple 30from typing import NamedTuple
29 31
30from git_command import git_require, GitCommand 32from git_command import git_require, GitCommand
33from git_config import RepoConfig
31from git_refs import R_HEADS 34from git_refs import R_HEADS
32from manifest_xml import LOCAL_MANIFEST_GROUP_PREFIX 35from manifest_xml import LOCAL_MANIFEST_GROUP_PREFIX
33 36
@@ -343,3 +346,81 @@ class Superproject(object):
343 346
344 manifest_path = self._WriteManfiestFile() 347 manifest_path = self._WriteManfiestFile()
345 return UpdateProjectsResult(manifest_path, False) 348 return UpdateProjectsResult(manifest_path, False)
349
350
351@functools.lru_cache(maxsize=None)
352def _UseSuperprojectFromConfiguration():
353 """Returns the user choice of whether to use superproject."""
354 user_cfg = RepoConfig.ForUser()
355 system_cfg = RepoConfig.ForSystem()
356 time_now = int(time.time())
357
358 user_value = user_cfg.GetBoolean('repo.superprojectChoice')
359 if user_value is not None:
360 user_expiration = user_cfg.GetInt('repo.superprojectChoiceExpire')
361 if user_expiration is not None and (user_expiration <= 0 or user_expiration >= time_now):
362 # TODO(b/190688390) - Remove prompt when we are comfortable with the new
363 # default value.
364 print(('You are currently enrolled in Git submodules experiment '
365 '(go/android-submodules-quickstart). Use --no-use-superproject '
366 'to override.\n'), file=sys.stderr)
367 return user_value
368
369 # We don't have an unexpired choice, ask for one.
370 system_value = system_cfg.GetBoolean('repo.superprojectChoice')
371 if system_value:
372 # The system configuration is proposing that we should enable the
373 # use of superproject. Present this to user for confirmation if we
374 # are on a TTY, or, when we are not on a TTY, accept the system
375 # default for this time only.
376 #
377 # TODO(b/190688390) - Remove prompt when we are comfortable with the new
378 # default value.
379 prompt = ('Repo can now use Git submodules (go/android-submodules-quickstart) '
380 'instead of manifests to represent the state of the Android '
381 'superproject, which results in faster syncs and better atomicity.\n\n')
382 if sys.stdout.isatty():
383 prompt += 'Would you like to opt in for two weeks (y/N)? '
384 response = input(prompt).lower()
385 time_choiceexpire = time_now + (86400 * 14)
386 if response in ('y', 'yes'):
387 userchoice = True
388 elif response in ('a', 'always'):
389 userchoice = True
390 time_choiceexpire = 0
391 elif response == 'never':
392 userchoice = False
393 time_choiceexpire = 0
394 elif response in ('n', 'no'):
395 userchoice = False
396 else:
397 # Unrecognized user response, assume the intention was no, but
398 # only for 2 hours instead of 2 weeks to balance between not
399 # being overly pushy while still retain the opportunity to
400 # enroll.
401 userchoice = False
402 time_choiceexpire = time_now + 7200
403
404 user_cfg.SetString('repo.superprojectChoiceExpire', str(time_choiceexpire))
405 user_cfg.SetBoolean('repo.superprojectChoice', userchoice)
406
407 return userchoice
408 else:
409 print('Accepting once since we are not on a TTY', file=sys.stderr)
410 return True
411
412 # For all other cases, we would not use superproject by default.
413 return False
414
415
416def UseSuperproject(opt, manifest):
417 """Returns a boolean if use-superproject option is enabled."""
418
419 if opt.use_superproject is not None:
420 return opt.use_superproject
421 else:
422 client_value = manifest.manifestProject.config.GetBoolean('repo.superproject')
423 if client_value is not None:
424 return client_value
425 else:
426 return _UseSuperprojectFromConfiguration()
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 8d89cf72..8defc932 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -278,16 +278,9 @@ later is required to fix a server side protocol bug.
278 branch = branch[len(R_HEADS):] 278 branch = branch[len(R_HEADS):]
279 return branch 279 return branch
280 280
281 def _UseSuperproject(self, opt):
282 """Returns True if use-superproject option is enabled"""
283 if opt.use_superproject is not None:
284 return opt.use_superproject
285 else:
286 return self.manifest.manifestProject.config.GetBoolean('repo.superproject')
287
288 def _GetCurrentBranchOnly(self, opt): 281 def _GetCurrentBranchOnly(self, opt):
289 """Returns True if current-branch or use-superproject options are enabled.""" 282 """Returns True if current-branch or use-superproject options are enabled."""
290 return opt.current_branch_only or self._UseSuperproject(opt) 283 return opt.current_branch_only or git_superproject.UseSuperproject(opt, self.manifest)
291 284
292 def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests): 285 def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests):
293 """Update revisionId of every project with the SHA from superproject. 286 """Update revisionId of every project with the SHA from superproject.
@@ -964,7 +957,7 @@ later is required to fix a server side protocol bug.
964 self._UpdateManifestProject(opt, mp, manifest_name) 957 self._UpdateManifestProject(opt, mp, manifest_name)
965 958
966 load_local_manifests = not self.manifest.HasLocalManifests 959 load_local_manifests = not self.manifest.HasLocalManifests
967 if self._UseSuperproject(opt): 960 if git_superproject.UseSuperproject(opt, self.manifest):
968 new_manifest_name = self._UpdateProjectsRevisionId(opt, args, load_local_manifests) 961 new_manifest_name = self._UpdateProjectsRevisionId(opt, args, load_local_manifests)
969 if not new_manifest_name: 962 if not new_manifest_name:
970 manifest_name = new_manifest_name 963 manifest_name = new_manifest_name