Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: checkout.py

Issue 8038056: Fix handling of file renames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Rebase against HEAD Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « apply_issue.py ('k') | patch.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # coding=utf8 1 # coding=utf8
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Manages a project checkout. 5 """Manages a project checkout.
6 6
7 Includes support for svn, git-svn and git. 7 Includes support for svn, git-svn and git.
8 """ 8 """
9 9
10 from __future__ import with_statement 10 from __future__ import with_statement
11 import ConfigParser 11 import ConfigParser
12 import fnmatch 12 import fnmatch
13 import logging 13 import logging
14 import os 14 import os
15 import re 15 import re
16 import shutil
16 import subprocess 17 import subprocess
17 import sys 18 import sys
18 import tempfile 19 import tempfile
19 20
20 import patch 21 import patch
21 import scm 22 import scm
22 import subprocess2 23 import subprocess2
23 24
24 25
25 def get_code_review_setting(path, key, 26 def get_code_review_setting(path, key,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 dirname = os.path.dirname(p.filename) 131 dirname = os.path.dirname(p.filename)
131 full_dir = os.path.join(self.project_path, dirname) 132 full_dir = os.path.join(self.project_path, dirname)
132 if dirname and not os.path.isdir(full_dir): 133 if dirname and not os.path.isdir(full_dir):
133 os.makedirs(full_dir) 134 os.makedirs(full_dir)
134 135
135 filepath = os.path.join(self.project_path, p.filename) 136 filepath = os.path.join(self.project_path, p.filename)
136 if p.is_binary: 137 if p.is_binary:
137 with open(filepath, 'wb') as f: 138 with open(filepath, 'wb') as f:
138 f.write(p.get()) 139 f.write(p.get())
139 else: 140 else:
141 if p.source_filename:
142 if not p.is_new:
143 raise PatchApplicationFailed(
144 p.filename,
145 'File has a source filename specified but is not new')
146 # Copy the file first.
147 if os.path.isfile(filepath):
148 raise PatchApplicationFailed(
149 p.filename, 'File exist but was about to be overwriten')
150 shutil.copy2(
151 os.path.join(self.project_path, p.source_filename), filepath)
140 if p.diff_hunks: 152 if p.diff_hunks:
141 stdout = subprocess2.check_output( 153 stdout = subprocess2.check_output(
142 ['patch', '-p%s' % p.patchlevel], 154 ['patch', '-u', '--binary', '-p%s' % p.patchlevel],
143 stdin=p.get(), 155 stdin=p.get(False),
144 stderr=subprocess2.STDOUT, 156 stderr=subprocess2.STDOUT,
145 cwd=self.project_path) 157 cwd=self.project_path)
146 elif p.is_new and not os.path.exists(filepath): 158 elif p.is_new and not os.path.exists(filepath):
147 # There is only a header. Just create the file. 159 # There is only a header. Just create the file.
148 open(filepath, 'w').close() 160 open(filepath, 'w').close()
149 for post in post_processors: 161 for post in post_processors:
150 post(self, p) 162 post(self, p)
151 except OSError, e: 163 except OSError, e:
152 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e)) 164 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e))
153 except subprocess.CalledProcessError, e: 165 except subprocess.CalledProcessError, e:
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 for dir_to_create in reversed(dirs_to_create): 298 for dir_to_create in reversed(dirs_to_create):
287 os.mkdir(os.path.join(self.project_path, dir_to_create)) 299 os.mkdir(os.path.join(self.project_path, dir_to_create))
288 stdout += self._check_output_svn( 300 stdout += self._check_output_svn(
289 ['add', dir_to_create, '--force'], credentials=False) 301 ['add', dir_to_create, '--force'], credentials=False)
290 302
291 filepath = os.path.join(self.project_path, p.filename) 303 filepath = os.path.join(self.project_path, p.filename)
292 if p.is_binary: 304 if p.is_binary:
293 with open(filepath, 'wb') as f: 305 with open(filepath, 'wb') as f:
294 f.write(p.get()) 306 f.write(p.get())
295 else: 307 else:
308 if p.source_filename:
309 if not p.is_new:
310 raise PatchApplicationFailed(
311 p.filename,
312 'File has a source filename specified but is not new')
313 # Copy the file first.
314 if os.path.isfile(filepath):
315 raise PatchApplicationFailed(
316 p.filename, 'File exist but was about to be overwriten')
317 shutil.copy2(
318 os.path.join(self.project_path, p.source_filename), filepath)
296 if p.diff_hunks: 319 if p.diff_hunks:
297 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force'] 320 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force']
298 stdout += subprocess2.check_output( 321 stdout += subprocess2.check_output(
299 cmd, stdin=p.get(), cwd=self.project_path) 322 cmd, stdin=p.get(False), cwd=self.project_path)
300 elif p.is_new and not os.path.exists(filepath): 323 elif p.is_new and not os.path.exists(filepath):
301 # There is only a header. Just create the file if it doesn't 324 # There is only a header. Just create the file if it doesn't
302 # exist. 325 # exist.
303 open(filepath, 'w').close() 326 open(filepath, 'w').close()
304 if p.is_new: 327 if p.is_new:
305 stdout += self._check_output_svn( 328 stdout += self._check_output_svn(
306 ['add', p.filename, '--force'], credentials=False) 329 ['add', p.filename, '--force'], credentials=False)
307 for prop in p.svn_properties: 330 for prop in p.svn_properties:
308 stdout += self._check_output_svn( 331 stdout += self._check_output_svn(
309 ['propset', prop[0], prop[1], p.filename], credentials=False) 332 ['propset', prop[0], prop[1], p.filename], credentials=False)
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 450
428 Ignores svn properties and raise an exception on unexpected ones. 451 Ignores svn properties and raise an exception on unexpected ones.
429 """ 452 """
430 post_processors = post_processors or self.post_processors or [] 453 post_processors = post_processors or self.post_processors or []
431 # It this throws, the checkout is corrupted. Maybe worth deleting it and 454 # It this throws, the checkout is corrupted. Maybe worth deleting it and
432 # trying again? 455 # trying again?
433 if self.remote_branch: 456 if self.remote_branch:
434 self._check_call_git( 457 self._check_call_git(
435 ['checkout', '-b', self.working_branch, 458 ['checkout', '-b', self.working_branch,
436 '%s/%s' % (self.remote, self.remote_branch), '--quiet']) 459 '%s/%s' % (self.remote, self.remote_branch), '--quiet'])
437 for p in patches: 460 for index, p in enumerate(patches):
438 try: 461 try:
439 stdout = '' 462 stdout = ''
440 if p.is_delete: 463 if p.is_delete:
441 stdout += self._check_output_git(['rm', p.filename]) 464 if (not os.path.exists(p.filename) and
465 any(p1.source_filename == p.filename for p1 in patches[0:index])):
466 # The file could already be deleted if a prior patch with file
467 # rename was already processed. To be sure, look at all the previous
468 # patches to see if they were a file rename.
469 pass
470 else:
471 stdout += self._check_output_git(['rm', p.filename])
442 else: 472 else:
443 dirname = os.path.dirname(p.filename) 473 dirname = os.path.dirname(p.filename)
444 full_dir = os.path.join(self.project_path, dirname) 474 full_dir = os.path.join(self.project_path, dirname)
445 if dirname and not os.path.isdir(full_dir): 475 if dirname and not os.path.isdir(full_dir):
446 os.makedirs(full_dir) 476 os.makedirs(full_dir)
447 if p.is_binary: 477 if p.is_binary:
448 with open(os.path.join(self.project_path, p.filename), 'wb') as f: 478 with open(os.path.join(self.project_path, p.filename), 'wb') as f:
449 f.write(p.get()) 479 f.write(p.get())
450 stdout += self._check_output_git(['add', p.filename]) 480 stdout += self._check_output_git(['add', p.filename])
451 else: 481 else:
452 # No need to do anything special with p.is_new or if not 482 # No need to do anything special with p.is_new or if not
453 # p.diff_hunks. git apply manages all that already. 483 # p.diff_hunks. git apply manages all that already.
454 stdout += self._check_output_git( 484 stdout += self._check_output_git(
455 ['apply', '--index', '-p%s' % p.patchlevel], stdin=p.get()) 485 ['apply', '--index', '-p%s' % p.patchlevel], stdin=p.get(True))
456 for prop in p.svn_properties: 486 for prop in p.svn_properties:
457 # Ignore some known auto-props flags through .subversion/config, 487 # Ignore some known auto-props flags through .subversion/config,
458 # bails out on the other ones. 488 # bails out on the other ones.
459 # TODO(maruel): Read ~/.subversion/config and detect the rules that 489 # TODO(maruel): Read ~/.subversion/config and detect the rules that
460 # applies here to figure out if the property will be correctly 490 # applies here to figure out if the property will be correctly
461 # handled. 491 # handled.
462 if not prop[0] in ('svn:eol-style', 'svn:executable'): 492 if not prop[0] in ('svn:eol-style', 'svn:executable'):
463 raise patch.UnsupportedPatchFormat( 493 raise patch.UnsupportedPatchFormat(
464 p.filename, 494 p.filename,
465 'Cannot apply svn property %s to file %s.' % ( 495 'Cannot apply svn property %s to file %s.' % (
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 user, message)) 747 user, message))
718 return 'FAKE' 748 return 'FAKE'
719 749
720 @property 750 @property
721 def project_name(self): 751 def project_name(self):
722 return self.checkout.project_name 752 return self.checkout.project_name
723 753
724 @property 754 @property
725 def project_path(self): 755 def project_path(self):
726 return self.checkout.project_path 756 return self.checkout.project_path
OLDNEW
« no previous file with comments | « apply_issue.py ('k') | patch.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698