OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """ Check out the Skia sources. """ | |
7 | |
8 | |
9 from build_step import BuildStep, BuildStepFailure | |
10 | |
11 from common import chromium_utils | |
12 from py.utils.git_utils import GIT | |
13 from utils import file_utils | |
14 from utils import gclient_utils | |
15 from py.utils import misc | |
16 from py.utils import shell_utils | |
17 | |
18 import ast | |
19 import config_private | |
20 import os | |
21 import re | |
22 import sys | |
23 | |
24 | |
25 LOCAL_GIT_MIRROR_URL = 'http://192.168.1.120/git-mirror/skia' | |
26 SKIA_GIT_URL_TO_REPLACE = config_private.SKIA_GIT_URL[:-len('.git')] | |
27 | |
28 | |
29 def _MaybeUseSkiaLabMirror(revision=None): | |
30 """If the SkiaLab mirror is reachable, set the gitconfig to use that instead | |
31 of the remote repo. | |
32 | |
33 Args: | |
34 revision: optional string; commit hash to which we're syncing. This is a | |
35 safety net; in the case that the mirror does not yet have this commit, | |
36 we will use the remote repo instead. | |
37 """ | |
38 # Attempt to reach the SkiaLab git mirror. | |
39 mirror_is_accessible = False | |
40 print 'Attempting to reach the SkiaLab git mirror...' | |
41 try: | |
42 shell_utils.run([GIT, 'ls-remote', | |
43 LOCAL_GIT_MIRROR_URL + '.git', | |
44 revision or 'HEAD', '--exit-code'], timeout=10) | |
45 mirror_is_accessible = True | |
46 except (shell_utils.CommandFailedException, shell_utils.TimeoutException): | |
47 pass | |
48 | |
49 # Find the global git config entries and loop over them, removing the ones | |
50 # which aren't needed and adding a URL override for the git mirror if it is | |
51 # accessible and not already present. | |
52 try: | |
53 configs = shell_utils.run([GIT, 'config', '--global', | |
54 '--list']).splitlines() | |
55 except shell_utils.CommandFailedException: | |
56 configs = [] | |
57 | |
58 already_overriding_url = False | |
59 for config in configs: | |
60 override_url = None | |
61 match = re.match('url.(.+).insteadof=', config) | |
62 if match: | |
63 override_url = match.groups()[0] | |
64 if override_url: | |
65 if override_url == LOCAL_GIT_MIRROR_URL and mirror_is_accessible: | |
66 print 'Already have URL override for SkiaLab git mirror.' | |
67 already_overriding_url = True | |
68 else: | |
69 print 'Removing unneeded URL override for %s' % override_url | |
70 try: | |
71 shell_utils.run([GIT, 'config', '--global', | |
72 '--remove-section', config.split('.insteadof')[0]]) | |
73 except shell_utils.CommandFailedException as e: | |
74 if 'No such section!' in e.output: | |
75 print '"insteadof" section already removed; continuing...' | |
76 else: | |
77 raise | |
78 | |
79 if mirror_is_accessible and not already_overriding_url: | |
80 print ('SkiaLab git mirror appears to be accessible. Changing gitconfig to ' | |
81 'use the mirror.') | |
82 shell_utils.run([GIT, 'config', '--global', | |
83 'url.%s.insteadOf' % LOCAL_GIT_MIRROR_URL, | |
84 SKIA_GIT_URL_TO_REPLACE]) | |
85 | |
86 # Some debugging info that might help us figure things out... | |
87 try: | |
88 shell_utils.run([GIT, 'config', '--global', '--list']) | |
89 except shell_utils.CommandFailedException: | |
90 pass | |
91 | |
92 | |
93 class Update(BuildStep): | |
94 def __init__(self, timeout=10000, no_output_timeout=6000, attempts=5, | |
95 **kwargs): | |
96 super(Update, self).__init__(timeout=timeout, | |
97 no_output_timeout=no_output_timeout, | |
98 attempts=attempts, | |
99 **kwargs) | |
100 | |
101 def _Run(self): | |
102 # Run "gclient" before doing anything else to ensure that we get the | |
103 # necessary stuff installed. | |
104 gclient_utils.GClient() | |
105 | |
106 _MaybeUseSkiaLabMirror(self._revision) | |
107 | |
108 # We receive gclient_solutions as a list of dictionaries flattened into a | |
109 # double-quoted string. This invocation of literal_eval converts that string | |
110 # into a list of strings. | |
111 solutions = ast.literal_eval(self._args['gclient_solutions'][1:-1]) | |
112 | |
113 # TODO(borenet): Move the gclient solutions parsing logic into a function. | |
114 | |
115 # Parse each solution dictionary from a string and add it to a list, while | |
116 # building a string to pass as a spec to gclient, to indicate which | |
117 # branches should be downloaded. | |
118 solution_dicts = [] | |
119 gclient_spec = 'solutions = [' | |
120 for solution in solutions: | |
121 gclient_spec += solution | |
122 solution_dicts += ast.literal_eval(solution) | |
123 gclient_spec += ']' | |
124 | |
125 # Set the DEPS target_os if necessary. | |
126 if self._deps_target_os: | |
127 gclient_spec += '\ntarget_os = ["%s"]' % self._deps_target_os | |
128 | |
129 # Run "gclient config" with the spec we just built. | |
130 gclient_utils.Config(spec=gclient_spec) | |
131 | |
132 revisions = [] | |
133 for solution in solution_dicts: | |
134 if solution['name'] == gclient_utils.SKIA_TRUNK: | |
135 revisions.append((solution['name'], self._revision)) | |
136 else: | |
137 url_split = solution['url'].split('@') | |
138 if len(url_split) > 1: | |
139 revision = url_split[1] | |
140 revisions.append((solution['name'], revision)) | |
141 | |
142 try: | |
143 if self._is_try: | |
144 # Clean our checkout to make sure we don't have a patch left over. | |
145 if (os.path.isdir('skia') and | |
146 os.path.isdir(os.path.join('skia', '.git'))): | |
147 with misc.ChDir('skia'): | |
148 gclient_utils.Revert() | |
149 | |
150 # Run "gclient sync" | |
151 gclient_utils.Sync( | |
152 revisions=revisions, | |
153 verbose=True, | |
154 force=True, | |
155 delete_unversioned_trees=True) | |
156 got_revision = gclient_utils.GetCheckedOutHash() | |
157 except Exception: | |
158 # If the sync fails, clear the checkout and try again. | |
159 print 'Initial sync failed.' | |
160 # Attempt to remove the skia directory first. | |
161 if os.path.isdir('skia'): | |
162 print 'Removing "skia"' | |
163 chromium_utils.RemoveDirectory('skia') | |
164 # Now, remove *everything* in the build directory. | |
165 build_dir = os.path.abspath(os.curdir) | |
166 with misc.ChDir(os.pardir): | |
167 print 'Attempting to clear %s' % build_dir | |
168 file_utils.clear_directory(build_dir) | |
169 # Try to sync again. | |
170 print 'Attempting to sync again.' | |
171 gclient_utils.Config(spec=gclient_spec) | |
172 gclient_utils.Sync( | |
173 revisions=revisions, | |
174 verbose=True, | |
175 force=True, | |
176 delete_unversioned_trees=True, | |
177 jobs=1) | |
178 got_revision = gclient_utils.GetCheckedOutHash() | |
179 | |
180 # If the revision we actually got differs from what was requested, raise an | |
181 # exception. | |
182 if self._revision and got_revision != self._revision: | |
183 raise BuildStepFailure('Actually-synced revision "%s" is different from ' | |
184 'the requested revision "%s".' % ( | |
185 repr(got_revision), repr(self._revision))) | |
186 | |
187 # Print the obtained revision number so that the master can parse it. | |
188 print 'Skia updated to %s' % got_revision | |
189 | |
190 | |
191 if '__main__' == __name__: | |
192 sys.exit(BuildStep.RunBuildStep(Update)) | |
OLD | NEW |