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 | |
7 """ Apply a diff to patch a Skia checkout. """ | |
8 | |
9 | |
10 from ast import literal_eval | |
11 from build_step import BuildStep, BuildStepFailure | |
12 from py.utils import shell_utils | |
13 from py.utils.git_utils import GIT | |
14 import os | |
15 import shutil | |
16 import sys | |
17 import tempfile | |
18 import urllib | |
19 import urllib2 | |
20 | |
21 | |
22 if os.name == 'nt': | |
23 SVN = 'svn.bat' | |
24 else: | |
25 SVN = 'svn' | |
26 | |
27 | |
28 class ApplyPatch(BuildStep): | |
29 def _Run(self): | |
30 if self._args['patch'] == 'None': | |
31 raise BuildStepFailure('No patch given!') | |
32 | |
33 # patch is a tuple of the form (int, str), where patch[0] is the "level" of | |
34 # the patch and patch[1] is the URL of the diff. | |
35 patch_level, encoded_patch_url = literal_eval(self._args['patch'].decode()) | |
36 patch_url = urllib.quote(encoded_patch_url, safe="%/:=&?~+!$,;'@()*[]") | |
37 print 'Patch level: %d' % patch_level | |
38 print 'Diff file URL:' | |
39 print patch_url | |
40 | |
41 # Write the patch file into a temporary directory. Unfortunately, temporary | |
42 # files created by the tempfile module don't behave properly on Windows, so | |
43 # we create a temporary directory and write the file inside it. | |
44 temp_dir = tempfile.mkdtemp() | |
45 try: | |
46 patch_file_name = os.path.join(temp_dir, 'skiabot_patch') | |
47 patch_file = open(patch_file_name, 'wb') | |
48 try: | |
49 if 'svn' in patch_url: | |
50 # TODO(borenet): Create an svn_utils module and use it instead. It | |
51 # would be nice to find a way to share | |
52 # https://skia.googlesource.com/skia/+/master/tools/svn.py | |
53 patch_contents = shell_utils.run([SVN, 'cat', patch_url], echo=False) | |
54 else: | |
55 patch_contents = urllib2.urlopen(patch_url).read() | |
56 if not patch_contents: | |
57 raise Exception('Got an empty patch!') | |
58 patch_file.write(patch_contents) | |
59 finally: | |
60 patch_file.close() | |
61 print 'Saved patch to %s' % patch_file.name | |
62 | |
63 def get_patch_cmd(level, patch_filename): | |
64 return [GIT, 'apply', '-p%d' % level, '-v', '--ignore-space-change', | |
65 '--ignore-whitespace', patch_filename] | |
66 | |
67 try: | |
68 # First, check that the patch can be applied at the given level. | |
69 shell_utils.run(get_patch_cmd(patch_level, patch_file.name) + | |
70 ['--check']) | |
71 except shell_utils.CommandFailedException as e: | |
72 # If the patch can't be applied at the requested level, try 0 or 1, | |
73 # depending on what we just tried. | |
74 print e | |
75 patch_level = (patch_level + 1) % 2 | |
76 print 'Trying patch level %d instead...' % patch_level | |
77 shell_utils.run(get_patch_cmd(patch_level, patch_file.name)) | |
78 | |
79 finally: | |
80 shutil.rmtree(temp_dir) | |
81 | |
82 | |
83 if '__main__' == __name__: | |
84 sys.exit(BuildStep.RunBuildStep(ApplyPatch)) | |
OLD | NEW |