summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/build/android/pylib/utils/maven_downloader.py
blob: 7247f7c88c9ca61cc51ed2c3b60b5b3bd79bdb31 (plain)
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