OLD | NEW |
1 # Copyright (c) 2009, 2010, 2011 Google Inc. All rights reserved. | 1 # Copyright (c) 2009, 2010, 2011 Google Inc. All rights reserved. |
2 # Copyright (c) 2009 Apple Inc. All rights reserved. | 2 # Copyright (c) 2009 Apple Inc. All rights reserved. |
3 # | 3 # |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 import webkitpy.common.config | 35 import webkitpy.common.config |
36 from webkitpy.common.checkout.scm.scm import SCM | 36 from webkitpy.common.checkout.scm.scm import SCM |
37 from webkitpy.common.memoized import memoized | 37 from webkitpy.common.memoized import memoized |
38 from webkitpy.common.system.executive import Executive, ScriptError | 38 from webkitpy.common.system.executive import Executive, ScriptError |
39 | 39 |
40 _log = logging.getLogger(__name__) | 40 _log = logging.getLogger(__name__) |
41 | 41 |
42 | 42 |
43 class AmbiguousCommitError(Exception): | 43 class AmbiguousCommitError(Exception): |
| 44 |
44 def __init__(self, num_local_commits, has_working_directory_changes): | 45 def __init__(self, num_local_commits, has_working_directory_changes): |
45 Exception.__init__(self, "Found %s local commits and the working directo
ry is %s" % ( | 46 Exception.__init__(self, "Found %s local commits and the working directo
ry is %s" % ( |
46 num_local_commits, ["clean", "not clean"][has_working_directory_chan
ges])) | 47 num_local_commits, ["clean", "not clean"][has_working_directory_chan
ges])) |
47 self.num_local_commits = num_local_commits | 48 self.num_local_commits = num_local_commits |
48 self.has_working_directory_changes = has_working_directory_changes | 49 self.has_working_directory_changes = has_working_directory_changes |
49 | 50 |
50 | 51 |
51 class Git(SCM): | 52 class Git(SCM): |
52 | 53 |
53 # Git doesn't appear to document error codes, but seems to return | 54 # Git doesn't appear to document error codes, but seems to return |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 return git_commit[:-4] | 158 return git_commit[:-4] |
158 | 159 |
159 if '..' not in git_commit: | 160 if '..' not in git_commit: |
160 git_commit = git_commit + "^.." + git_commit | 161 git_commit = git_commit + "^.." + git_commit |
161 return git_commit | 162 return git_commit |
162 | 163 |
163 return self._remote_merge_base() | 164 return self._remote_merge_base() |
164 | 165 |
165 def changed_files(self, git_commit=None): | 166 def changed_files(self, git_commit=None): |
166 # FIXME: --diff-filter could be used to avoid the "extract_filenames" st
ep. | 167 # FIXME: --diff-filter could be used to avoid the "extract_filenames" st
ep. |
167 status_command = [self.executable_name, 'diff', '-r', '--name-status', "
--no-renames", "--no-ext-diff", "--full-index", self._merge_base(git_commit)] | 168 status_command = [self.executable_name, 'diff', '-r', '--name-status', |
| 169 "--no-renames", "--no-ext-diff", "--full-index", self.
_merge_base(git_commit)] |
168 # FIXME: I'm not sure we're returning the same set of files that SVN.cha
nged_files is. | 170 # FIXME: I'm not sure we're returning the same set of files that SVN.cha
nged_files is. |
169 # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) | 171 # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) |
170 return self._run_status_and_extract_filenames(status_command, self._stat
us_regexp("ADM")) | 172 return self._run_status_and_extract_filenames(status_command, self._stat
us_regexp("ADM")) |
171 | 173 |
172 def _added_files(self): | 174 def _added_files(self): |
173 return self._run_status_and_extract_filenames(self.status_command(), sel
f._status_regexp("A")) | 175 return self._run_status_and_extract_filenames(self.status_command(), sel
f._status_regexp("A")) |
174 | 176 |
175 def _deleted_files(self): | 177 def _deleted_files(self): |
176 return self._run_status_and_extract_filenames(self.status_command(), sel
f._status_regexp("D")) | 178 return self._run_status_and_extract_filenames(self.status_command(), sel
f._status_regexp("D")) |
177 | 179 |
(...skipping 27 matching lines...) Expand all Loading... |
205 match = re.search("^Date:\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{
2}) ([+-])(\d{2})(\d{2})$", git_log, re.MULTILINE) | 207 match = re.search("^Date:\s*(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{
2}) ([+-])(\d{2})(\d{2})$", git_log, re.MULTILINE) |
206 if not match: | 208 if not match: |
207 return "" | 209 return "" |
208 | 210 |
209 # Manually modify the timezone since Git doesn't have an option to show
it in UTC. | 211 # Manually modify the timezone since Git doesn't have an option to show
it in UTC. |
210 # Git also truncates milliseconds but we're going to ignore that for now
. | 212 # Git also truncates milliseconds but we're going to ignore that for now
. |
211 time_with_timezone = datetime.datetime(int(match.group(1)), int(match.gr
oup(2)), int(match.group(3)), | 213 time_with_timezone = datetime.datetime(int(match.group(1)), int(match.gr
oup(2)), int(match.group(3)), |
212 int(match.group(4)), int(match.gr
oup(5)), int(match.group(6)), 0) | 214 int(match.group(4)), int(match.gr
oup(5)), int(match.group(6)), 0) |
213 | 215 |
214 sign = 1 if match.group(7) == '+' else -1 | 216 sign = 1 if match.group(7) == '+' else -1 |
215 time_without_timezone = time_with_timezone - datetime.timedelta(hours=si
gn * int(match.group(8)), minutes=int(match.group(9))) | 217 time_without_timezone = time_with_timezone - \ |
| 218 datetime.timedelta(hours=sign * int(match.group(8)), minutes=int(mat
ch.group(9))) |
216 return time_without_timezone.strftime('%Y-%m-%dT%H:%M:%SZ') | 219 return time_without_timezone.strftime('%Y-%m-%dT%H:%M:%SZ') |
217 | 220 |
218 def create_patch(self, git_commit=None, changed_files=None): | 221 def create_patch(self, git_commit=None, changed_files=None): |
219 """Returns a byte array (str()) representing the patch file. | 222 """Returns a byte array (str()) representing the patch file. |
220 Patch files are effectively binary since they may contain | 223 Patch files are effectively binary since they may contain |
221 files of multiple different encodings.""" | 224 files of multiple different encodings.""" |
222 | 225 |
223 # Put code changes at the top of the patch and layout tests | 226 # Put code changes at the top of the patch and layout tests |
224 # at the bottom, this makes for easier reviewing. | 227 # at the bottom, this makes for easier reviewing. |
225 config_path = self._filesystem.dirname(self._filesystem.path_to_module('
webkitpy.common.config')) | 228 config_path = self._filesystem.dirname(self._filesystem.path_to_module('
webkitpy.common.config')) |
226 order_file = self._filesystem.join(config_path, 'orderfile') | 229 order_file = self._filesystem.join(config_path, 'orderfile') |
227 order = "" | 230 order = "" |
228 if self._filesystem.exists(order_file): | 231 if self._filesystem.exists(order_file): |
229 order = "-O%s" % order_file | 232 order = "-O%s" % order_file |
230 | 233 |
231 command = [self.executable_name, 'diff', '--binary', '--no-color', "--no
-ext-diff", "--full-index", "--no-renames", order, self._merge_base(git_commit),
"--"] | 234 command = [self.executable_name, 'diff', '--binary', '--no-color', "--no
-ext-diff", |
| 235 "--full-index", "--no-renames", order, self._merge_base(git_c
ommit), "--"] |
232 if changed_files: | 236 if changed_files: |
233 command += changed_files | 237 command += changed_files |
234 return self._run(command, decode_output=False, cwd=self.checkout_root) | 238 return self._run(command, decode_output=False, cwd=self.checkout_root) |
235 | 239 |
236 @memoized | 240 @memoized |
237 def commit_position_from_git_commit(self, git_commit): | 241 def commit_position_from_git_commit(self, git_commit): |
238 git_log = self.git_commit_detail(git_commit) | 242 git_log = self.git_commit_detail(git_commit) |
239 return self._commit_position_from_git_log(git_log) | 243 return self._commit_position_from_git_log(git_log) |
240 | 244 |
241 def checkout_branch(self, name): | 245 def checkout_branch(self, name): |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 if self.current_branch() != self._branch_tracking_remote_master(): | 309 if self.current_branch() != self._branch_tracking_remote_master(): |
306 return False | 310 return False |
307 if len(self._local_commits(self._branch_tracking_remote_master())) > 0: | 311 if len(self._local_commits(self._branch_tracking_remote_master())) > 0: |
308 return False | 312 return False |
309 return True | 313 return True |
310 | 314 |
311 def ensure_cleanly_tracking_remote_master(self): | 315 def ensure_cleanly_tracking_remote_master(self): |
312 self._discard_working_directory_changes() | 316 self._discard_working_directory_changes() |
313 self._run_git(['checkout', '-q', self._branch_tracking_remote_master()]) | 317 self._run_git(['checkout', '-q', self._branch_tracking_remote_master()]) |
314 self._discard_local_commits() | 318 self._discard_local_commits() |
OLD | NEW |