| #!/usr/bin/env vpython3 |
| # Copyright 2017 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import errno |
| import logging |
| import os |
| import shutil |
| import sys |
| |
| sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) |
| import devil_chromium # pylint: disable=unused-import |
| from devil.utils import cmd_helper |
| from devil.utils import parallelizer |
| |
| |
| def _MakeDirsIfAbsent(path): |
| try: |
| os.makedirs(path) |
| except OSError as err: |
| if err.errno != errno.EEXIST or not os.path.isdir(path): |
| raise |
| |
| |
| class MavenDownloader: |
| ''' |
| Downloads and installs the requested artifacts from the Google Maven repo. |
| The artifacts are expected to be specified in the format |
| "group_id:artifact_id:version:file_type", as the default file type is JAR |
| but most Android libraries are provided as AARs, which would otherwise fail |
| downloading. See Install() |
| ''' |
| |
| # Remote repository to download the artifacts from. The support library and |
| # Google Play service are only distributed there, but third party libraries |
| # could use Maven Central or JCenter for example. The default Maven remote |
| # is Maven Central. |
| _REMOTE_REPO = 'https://maven.google.com' |
| |
| # Default Maven repository. |
| _DEFAULT_REPO_PATH = os.path.join( |
| os.path.expanduser('~'), '.m2', 'repository') |
| |
| def __init__(self, debug=False): |
| self._repo_path = MavenDownloader._DEFAULT_REPO_PATH |
| self._remote_url = MavenDownloader._REMOTE_REPO |
| self._debug = debug |
| |
| def Install(self, target_repo, artifacts, include_poms=False): |
| logging.info('Installing %d artifacts...', len(artifacts)) |
| downloaders = [_SingleArtifactDownloader(self, artifact, target_repo) |
| for artifact in artifacts] |
| if self._debug: |
| for downloader in downloaders: |
| downloader.Run(include_poms) |
| else: |
| parallelizer.SyncParallelizer(downloaders).Run(include_poms) |
| logging.info('%d artifacts installed to %s', len(artifacts), target_repo) |
| |
| @property |
| def repo_path(self): |
| return self._repo_path |
| |
| @property |
| def remote_url(self): |
| return self._remote_url |
| |
| @property |
| def debug(self): |
| return self._debug |
| |
| |
| class _SingleArtifactDownloader: |
| '''Handles downloading and installing a single Maven artifact.''' |
| |
| _POM_FILE_TYPE = 'pom' |
| |
| def __init__(self, download_manager, artifact, target_repo): |
| self._download_manager = download_manager |
| self._artifact = artifact |
| self._target_repo = target_repo |
| |
| def Run(self, include_pom=False): |
| parts = self._artifact.split(':') |
| if len(parts) != 4: |
| raise Exception('Artifacts expected as ' |
| '"group_id:artifact_id:version:file_type".') |
| group_id, artifact_id, version, file_type = parts |
| self._InstallArtifact(group_id, artifact_id, version, file_type) |
| |
| if include_pom and file_type != _SingleArtifactDownloader._POM_FILE_TYPE: |
| self._InstallArtifact(group_id, artifact_id, version, |
| _SingleArtifactDownloader._POM_FILE_TYPE) |
| |
| def _InstallArtifact(self, group_id, artifact_id, version, file_type): |
| logging.debug('Processing %s', self._artifact) |
| |
| download_relpath = self._DownloadArtifact( |
| group_id, artifact_id, version, file_type) |
| logging.debug('Downloaded.') |
| |
| install_path = self._ImportArtifact(download_relpath) |
| logging.debug('Installed %s', os.path.relpath(install_path)) |
| |
| def _DownloadArtifact(self, group_id, artifact_id, version, file_type): |
| ''' |
| Downloads the specified artifact using maven, to its standard location, see |
| MavenDownloader._DEFAULT_REPO_PATH. |
| ''' |
| cmd = ['mvn', |
| 'org.apache.maven.plugins:maven-dependency-plugin:RELEASE:get', |
| '-DremoteRepositories={}'.format(self._download_manager.remote_url), |
| '-Dartifact={}:{}:{}:{}'.format(group_id, artifact_id, version, |
| file_type)] |
| |
| stdout = None if self._download_manager.debug else open(os.devnull, 'wb') |
| |
| try: |
| ret_code = cmd_helper.Call(cmd, stdout=stdout) |
| if ret_code != 0: |
| raise Exception('Command "{}" failed'.format(' '.join(cmd))) |
| except OSError as e: |
| if e.errno == errno.ENOENT: |
| raise Exception('mvn command not found. Please install Maven.') from e |
| raise |
| |
| return os.path.join(os.path.join(*group_id.split('.')), |
| artifact_id, |
| version, |
| '{}-{}.{}'.format(artifact_id, version, file_type)) |
| |
| def _ImportArtifact(self, artifact_path): |
| src_dir = os.path.join(self._download_manager.repo_path, artifact_path) |
| dst_dir = os.path.join(self._target_repo, os.path.dirname(artifact_path)) |
| |
| _MakeDirsIfAbsent(dst_dir) |
| shutil.copy(src_dir, dst_dir) |
| |
| return dst_dir |