• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5'''
6Utility functions for all things related to manipulating google play services
7related files.
8'''
9
10import argparse
11import filecmp
12import json
13import logging
14import os
15import re
16import sys
17
18sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
19from devil.utils import cmd_helper
20
21
22_XML_VERSION_NUMBER_PATTERN = re.compile(
23    r'<integer name="google_play_services_version">(\d+)<\/integer>')
24
25
26class DefaultsRawHelpFormatter(argparse.ArgumentDefaultsHelpFormatter,
27                               argparse.RawDescriptionHelpFormatter):
28  '''
29  Combines the features of RawDescriptionHelpFormatter and
30  ArgumentDefaultsHelpFormatter, providing defaults for the arguments and raw
31  text for the description.
32  '''
33  pass
34
35
36class ConfigParser(object):
37  '''Reads and writes the configuration files for play services related scripts
38
39  The configuration files are JSON files. Here is the data they are expected
40  to contain:
41
42   -  version_number
43      Number. Mirrors @integer/google_play_services_version from the library.
44      Example: 815000
45
46   -  sdk_version
47      Version of the Play Services SDK to retrieve, when preprocessing the
48      library from a maven/gradle repository.
49      Example: "8.1.0"
50
51   -  clients
52      List of strings. Name of the clients (or play services modules) to
53      include when preprocessing the library.
54      Example: ["play-services-base", "play-services-cast"]
55
56   -  version_xml_path
57      String. Path to the version.xml string describing the current version.
58      Should be relative to the library base directory
59      Example: "res/values/version.xml"
60
61   -  locale_whitelist
62      List of strings. List of locales to keep from the resources. Can be
63      obtained by generating an android build and looking at the content of
64      `out/Debug/gen/chrome/java/res`; or looking at the android section in
65      `//chrome/app/generated_resources.grd`
66      Example: ["am", "ar", "bg", "ca", "cs"]
67
68   - resource_whitelist
69     List of strings. List of resource files to explicitely keep in the final
70     output. Use it to keep drawables for example, as we currently remove them
71     all.
72     Example: ["play-services-base/res/drawables/foobar.xml"]
73  '''
74  _VERSION_NUMBER_KEY = 'version_number'
75
76  def __init__(self, path):
77    self.path = path
78    self._data = {}
79
80    with open(path, 'r') as stream:
81      self._data = json.load(stream)
82
83  @property
84  def version_number(self):
85    return self._data.get(self._VERSION_NUMBER_KEY)
86
87  @property
88  def sdk_version(self):
89    return self._data.get('sdk_version')
90
91  @property
92  def clients(self):
93    return self._data.get('clients') or []
94
95  @property
96  def version_xml_path(self):
97    return self._data.get('version_xml_path')
98
99  @property
100  def locale_whitelist(self):
101    return self._data.get('locale_whitelist') or []
102
103  @property
104  def resource_whitelist(self):
105    return self._data.get('resource_whitelist') or []
106
107  def UpdateVersionNumber(self, new_version_number):
108    '''Updates the version number and saves it in the configuration file. '''
109
110    with open(self.path, 'w') as stream:
111      self._data[self._VERSION_NUMBER_KEY] = new_version_number
112      stream.write(DumpTrimmedJson(self._data))
113
114
115def DumpTrimmedJson(json_data):
116  '''
117  Default formatting when dumping json to string has trailing spaces and lacks
118  a new line at the end. This function fixes that.
119  '''
120
121  out = json.dumps(json_data, sort_keys=True, indent=2)
122  out = out.replace(' ' + os.linesep, os.linesep)
123  return out + os.linesep
124
125
126def FileEquals(expected_file, actual_file):
127  '''
128  Returns whether the two files are equal. Returns False if any of the files
129  doesn't exist.
130  '''
131
132  if not os.path.isfile(actual_file) or not os.path.isfile(expected_file):
133    return False
134  return filecmp.cmp(expected_file, actual_file)
135
136
137def IsRepoDirty(repo_root):
138  '''Returns True if there are no staged or modified files, False otherwise.'''
139
140  # diff-index returns 1 if there are staged changes or modified files,
141  # 0 otherwise
142  cmd = ['git', 'diff-index', '--quiet', 'HEAD']
143  return cmd_helper.Call(cmd, cwd=repo_root) == 1
144
145
146def GetVersionNumberFromLibraryResources(version_xml):
147  '''
148  Extracts a Google Play services version number from its version.xml file.
149  '''
150
151  with open(version_xml, 'r') as version_file:
152    version_file_content = version_file.read()
153
154  match = _XML_VERSION_NUMBER_PATTERN.search(version_file_content)
155  if not match:
156    raise AttributeError('A value for google_play_services_version was not '
157                         'found in ' + version_xml)
158  return int(match.group(1))
159
160
161def MakeLocalCommit(repo_root, files_to_commit, message):
162  '''Makes a local git commit.'''
163
164  logging.debug('Staging files (%s) for commit.', files_to_commit)
165  if cmd_helper.Call(['git', 'add'] + files_to_commit, cwd=repo_root) != 0:
166    raise Exception('The local commit failed.')
167
168  logging.debug('Committing.')
169  if cmd_helper.Call(['git', 'commit', '-m', message], cwd=repo_root) != 0:
170    raise Exception('The local commit failed.')
171