1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/usr/bin/env vpython3
# Copyright 2017 The Chromium Authors. All rights reserved.
# 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(object):
'''
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(object):
'''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 == os.errno.ENOENT:
raise Exception('mvn command not found. Please install Maven.')
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
|