| 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 |