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

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: 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') | tests/checkout_test.py » ('J')
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 # Copy the file first.
143 if os.path.isfile(filepath):
144 raise PatchApplicationFailed(
145 p.filename, 'File exist but was about to be overwriten')
146 shutil.copy2(
147 os.path.join(self.project_path, p.source_filename), filepath)
Dirk Pranke 2011/09/28 23:39:27 I'm a bit confused by this. Won't the file usually
M-A Ruel 2011/09/29 14:15:58 Added a check to be explicit about the consistency
140 if p.diff_hunks: 148 if p.diff_hunks:
141 stdout = subprocess2.check_output( 149 stdout = subprocess2.check_output(
142 ['patch', '-p%s' % p.patchlevel], 150 ['patch', '-u', '--binary', '-p%s' % p.patchlevel],
143 stdin=p.get(), 151 stdin=p.get(False),
144 stderr=subprocess2.STDOUT, 152 stderr=subprocess2.STDOUT,
145 cwd=self.project_path) 153 cwd=self.project_path)
146 elif p.is_new and not os.path.exists(filepath): 154 elif p.is_new and not os.path.exists(filepath):
147 # There is only a header. Just create the file. 155 # There is only a header. Just create the file.
148 open(filepath, 'w').close() 156 open(filepath, 'w').close()
149 for post in post_processors: 157 for post in post_processors:
150 post(self, p) 158 post(self, p)
151 except OSError, e: 159 except OSError, e:
152 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e)) 160 raise PatchApplicationFailed(p.filename, '%s%s' % (stdout, e))
153 except subprocess.CalledProcessError, e: 161 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): 294 for dir_to_create in reversed(dirs_to_create):
287 os.mkdir(os.path.join(self.project_path, dir_to_create)) 295 os.mkdir(os.path.join(self.project_path, dir_to_create))
288 stdout += self._check_output_svn( 296 stdout += self._check_output_svn(
289 ['add', dir_to_create, '--force'], credentials=False) 297 ['add', dir_to_create, '--force'], credentials=False)
290 298
291 filepath = os.path.join(self.project_path, p.filename) 299 filepath = os.path.join(self.project_path, p.filename)
292 if p.is_binary: 300 if p.is_binary:
293 with open(filepath, 'wb') as f: 301 with open(filepath, 'wb') as f:
294 f.write(p.get()) 302 f.write(p.get())
295 else: 303 else:
304 if p.source_filename:
305 # Copy the file first.
306 if os.path.isfile(filepath):
307 raise PatchApplicationFailed(
308 p.filename, 'File exist but was about to be overwriten')
309 shutil.copy2(
310 os.path.join(self.project_path, p.source_filename), filepath)
Dirk Pranke 2011/09/28 23:39:27 same question.
296 if p.diff_hunks: 311 if p.diff_hunks:
297 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force'] 312 cmd = ['patch', '-p%s' % p.patchlevel, '--forward', '--force']
298 stdout += subprocess2.check_output( 313 stdout += subprocess2.check_output(
299 cmd, stdin=p.get(), cwd=self.project_path) 314 cmd, stdin=p.get(False), cwd=self.project_path)
300 elif p.is_new and not os.path.exists(filepath): 315 elif p.is_new and not os.path.exists(filepath):
301 # There is only a header. Just create the file if it doesn't 316 # There is only a header. Just create the file if it doesn't
302 # exist. 317 # exist.
303 open(filepath, 'w').close() 318 open(filepath, 'w').close()
304 if p.is_new: 319 if p.is_new:
305 stdout += self._check_output_svn( 320 stdout += self._check_output_svn(
306 ['add', p.filename, '--force'], credentials=False) 321 ['add', p.filename, '--force'], credentials=False)
307 for prop in p.svn_properties: 322 for prop in p.svn_properties:
308 stdout += self._check_output_svn( 323 stdout += self._check_output_svn(
309 ['propset', prop[0], prop[1], p.filename], credentials=False) 324 ['propset', prop[0], prop[1], p.filename], credentials=False)
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 442
428 Ignores svn properties and raise an exception on unexpected ones. 443 Ignores svn properties and raise an exception on unexpected ones.
429 """ 444 """
430 post_processors = post_processors or self.post_processors or [] 445 post_processors = post_processors or self.post_processors or []
431 # It this throws, the checkout is corrupted. Maybe worth deleting it and 446 # It this throws, the checkout is corrupted. Maybe worth deleting it and
432 # trying again? 447 # trying again?
433 if self.remote_branch: 448 if self.remote_branch:
434 self._check_call_git( 449 self._check_call_git(
435 ['checkout', '-b', self.working_branch, 450 ['checkout', '-b', self.working_branch,
436 '%s/%s' % (self.remote, self.remote_branch), '--quiet']) 451 '%s/%s' % (self.remote, self.remote_branch), '--quiet'])
437 for p in patches: 452 for index, p in enumerate(patches):
438 try: 453 try:
439 stdout = '' 454 stdout = ''
440 if p.is_delete: 455 if p.is_delete:
441 stdout += self._check_output_git(['rm', p.filename]) 456 if (not os.path.exists(p.filename) and
457 any(p1.source_filename == p.filename for p1 in patches[0:index])):
458 # The file could already be deleted if a prior patch with file
459 # rename was already processed. To be sure, look at all the previous
460 # patches to see if they were a file rename.
461 pass
462 else:
463 stdout += self._check_output_git(['rm', p.filename])
442 else: 464 else:
443 dirname = os.path.dirname(p.filename) 465 dirname = os.path.dirname(p.filename)
444 full_dir = os.path.join(self.project_path, dirname) 466 full_dir = os.path.join(self.project_path, dirname)
445 if dirname and not os.path.isdir(full_dir): 467 if dirname and not os.path.isdir(full_dir):
446 os.makedirs(full_dir) 468 os.makedirs(full_dir)
447 if p.is_binary: 469 if p.is_binary:
448 with open(os.path.join(self.project_path, p.filename), 'wb') as f: 470 with open(os.path.join(self.project_path, p.filename), 'wb') as f:
449 f.write(p.get()) 471 f.write(p.get())
450 stdout += self._check_output_git(['add', p.filename]) 472 stdout += self._check_output_git(['add', p.filename])
451 else: 473 else:
452 # No need to do anything special with p.is_new or if not 474 # No need to do anything special with p.is_new or if not
453 # p.diff_hunks. git apply manages all that already. 475 # p.diff_hunks. git apply manages all that already.
454 stdout += self._check_output_git( 476 stdout += self._check_output_git(
455 ['apply', '--index', '-p%s' % p.patchlevel], stdin=p.get()) 477 ['apply', '--index', '-p%s' % p.patchlevel], stdin=p.get(True))
456 for prop in p.svn_properties: 478 for prop in p.svn_properties:
457 # Ignore some known auto-props flags through .subversion/config, 479 # Ignore some known auto-props flags through .subversion/config,
458 # bails out on the other ones. 480 # bails out on the other ones.
459 # TODO(maruel): Read ~/.subversion/config and detect the rules that 481 # TODO(maruel): Read ~/.subversion/config and detect the rules that
460 # applies here to figure out if the property will be correctly 482 # applies here to figure out if the property will be correctly
461 # handled. 483 # handled.
462 if not prop[0] in ('svn:eol-style', 'svn:executable'): 484 if not prop[0] in ('svn:eol-style', 'svn:executable'):
463 raise patch.UnsupportedPatchFormat( 485 raise patch.UnsupportedPatchFormat(
464 p.filename, 486 p.filename,
465 'Cannot apply svn property %s to file %s.' % ( 487 'Cannot apply svn property %s to file %s.' % (
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 user, message)) 739 user, message))
718 return 'FAKE' 740 return 'FAKE'
719 741
720 @property 742 @property
721 def project_name(self): 743 def project_name(self):
722 return self.checkout.project_name 744 return self.checkout.project_name
723 745
724 @property 746 @property
725 def project_path(self): 747 def project_path(self):
726 return self.checkout.project_path 748 return self.checkout.project_path
OLDNEW
« no previous file with comments | « apply_issue.py ('k') | patch.py » ('j') | tests/checkout_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698