def RunGit(self, project, cmd, retries=3): """Run a git command inside the given project. Args: project: repo_manifest.Project to run the command in. cmd: Command as a list of arguments. Callers should exclude 'git'. retries: Maximum number of retries for the git command. """ retry_util.RetryCommand(git.RunGit, retries, self.AbsoluteProjectPath(project), cmd, print_cmd=True, sleep=2, log_retries=True)
def RunSwarmingCommandWithRetries(max_retry, *args, **kwargs): """Wrapper for RunSwarmingCommand that will retry a command. Args: max_retry: See RetryCommand. *args: See RetryCommand and RunSwarmingCommand. **kwargs: See RetryCommand and RunSwarmingCommand. Returns: A SwarmingCommandResult object. Raises: RunCommandError: When the command fails. """ return retry_util.RetryCommand(RunSwarmingCommand, max_retry, *args, **kwargs)
def Sync(self, local_manifest=None, jobs=None, all_branches=True, network_only=False, detach=False): """Sync/update the source. Changes manifest if specified. Args: local_manifest: If true, checks out source to manifest. DEFAULT_MANIFEST may be used to set it back to the default manifest. jobs: May be set to override the default sync parallelism defined by the manifest. all_branches: If False, a repo sync -c is performed; this saves on sync'ing via grabbing only what is needed for the manifest specified branch. Defaults to True. TODO(davidjames): Set the default back to False once we've fixed http://crbug.com/368722 . network_only: If true, perform only the network half of the sync; skip the checkout. Primarily of use to validate a manifest (although if the manifest has bad copyfile statements, via skipping checkout the broken copyfile tag won't be spotted), or of use when the invoking code is fine w/ operating on bare repos, ie .repo/projects/*. detach: If true, throw away all local changes, even if on tracking branches. """ try: # Always re-initialize to the current branch. self.Initialize(local_manifest) # Fix existing broken mirroring configurations. self._EnsureMirroring() cmd = [self.repo_cmd, '--time', 'sync'] if jobs: cmd += ['--jobs', str(jobs)] if not all_branches or self._depth is not None: # Note that this option can break kernel checkouts. crbug.com/464536 cmd.append('-c') # Do the network half of the sync; retry as necessary to get the content. try: cros_build_lib.RunCommand(cmd + ['-n'], cwd=self.directory) except cros_build_lib.RunCommandError: if constants.SYNC_RETRIES > 0: # Retry on clean up and repo sync commands, # decrement max_retry for this command logging.warning( 'cmd %s failed, clean up repository and retry sync.' % cmd) retry_util.RetryCommand(self._CleanUpAndRunCommand, constants.SYNC_RETRIES - 1, cmd + ['-n'], cwd=self.directory, local_manifest=local_manifest) else: # No need to retry raise if network_only: return if detach: cmd.append('--detach') # Do the local sync; note that there is a couple of corner cases where # the new manifest cannot transition from the old checkout cleanly- # primarily involving git submodules. Thus we intercept, and do # a forced wipe, then a retry. try: cros_build_lib.RunCommand(cmd + ['-l'], cwd=self.directory) except cros_build_lib.RunCommandError: manifest = git.ManifestCheckout.Cached(self.directory) targets = set(project['path'].split('/', 1)[0] for project in manifest.ListCheckouts()) if not targets: # No directories to wipe, thus nothing we can fix. raise cros_build_lib.SudoRunCommand(['rm', '-rf'] + sorted(targets), cwd=self.directory) # Retry the sync now; if it fails, let the exception propagate. cros_build_lib.RunCommand(cmd + ['-l'], cwd=self.directory) # We do a second run to fix any new repositories created by repo to # use relative object pathways. Note that cros_sdk also triggers the # same cleanup- we however kick it erring on the side of caution. self._EnsureMirroring(True) self._DoCleanup() except cros_build_lib.RunCommandError as e: err_msg = e.Stringify(error=False, output=False) logging.error(err_msg) raise SrcCheckOutException(err_msg)
def Initialize(self, local_manifest=None, manifest_repo_url=None, extra_args=()): """Initializes a repository. Optionally forces a local manifest. Args: local_manifest: The absolute path to a custom manifest to use. This will replace .repo/manifest.xml. manifest_repo_url: A new value for manifest_repo_url. extra_args: Extra args to pass to 'repo init' """ self.AssertNotNested() if manifest_repo_url: self.manifest_repo_url = manifest_repo_url # Do a sanity check on the repo; if it exists and we can't pull a # manifest from it, we know it's fairly screwed up and needs a fresh # rebuild. if os.path.exists(os.path.join(self.directory, '.repo', 'manifest.xml')): cmd = [self.repo_cmd, 'manifest'] try: cros_build_lib.run(cmd, cwd=self.directory, capture_output=True) except cros_build_lib.RunCommandError: metrics.Counter( constants.MON_REPO_MANIFEST_FAILURE_COUNT).increment() logging.warning('Wiping %r due to `repo manifest` failure', self.directory) self._CleanUpRepoManifest(self.directory) self._repo_update_needed = False # Wipe local_manifest.xml if it exists- it can interfere w/ things in # bad ways (duplicate projects, etc); we control this repository, thus # we can destroy it. osutils.SafeUnlink(os.path.join(self.directory, 'local_manifest.xml')) # Force a repo update the first time we initialize an old repo checkout. # Don't update if there is nothing to update. if self._repo_update_needed: if IsARepoRoot(self.directory): self._RepoSelfupdate() self._repo_update_needed = False # Use our own repo, in case android.kernel.org (the default location) is # down. init_cmd = [ self.repo_cmd, 'init', '--manifest-url', self.manifest_repo_url ] if self.repo_url: init_cmd.extend(['--repo-url', self.repo_url]) if self._referenced_repo: init_cmd.extend(['--reference', self._referenced_repo]) if self._manifest: init_cmd.extend(['--manifest-name', self._manifest]) if self._depth is not None: init_cmd.extend(['--depth', str(self._depth)]) init_cmd.extend(extra_args) # Handle branch / manifest options. if self.branch: init_cmd.extend(['--manifest-branch', self.branch]) if self.repo_branch: init_cmd.extend(['--repo-branch', self.repo_branch]) if self.groups: init_cmd.extend(['--groups', self.groups]) def _StatusCallback(attempt, _): if attempt: metrics.Counter(constants.MON_REPO_INIT_RETRY_COUNT).increment( fields={'manifest_url': self.manifest_repo_url}) retry_util.RetryCommand(self._RepoInit, REPO_INIT_RETRY_LIMIT, init_cmd, sleep=DEFAULT_SLEEP_TIME, backoff_factor=2, log_retries=True, status_callback=_StatusCallback) if local_manifest and local_manifest != self._manifest: self._SwitchToLocalManifest(local_manifest)