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

Side by Side Diff: checkout.py

Issue 273543002: Have apply_patch.py/checkout.py stage git patches instead of committing them (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Actually remove base_ref Created 6 years, 7 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') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 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 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 import ConfigParser 10 import ConfigParser
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 """Checks out a clean copy of the tree and removes any local modification. 124 """Checks out a clean copy of the tree and removes any local modification.
125 125
126 This function shouldn't throw unless the remote repository is inaccessible, 126 This function shouldn't throw unless the remote repository is inaccessible,
127 there is no free disk space or hard issues like that. 127 there is no free disk space or hard issues like that.
128 128
129 Args: 129 Args:
130 revision: The revision it should sync to, SCM specific. 130 revision: The revision it should sync to, SCM specific.
131 """ 131 """
132 raise NotImplementedError() 132 raise NotImplementedError()
133 133
134 def apply_patch(self, patches, post_processors=None, verbose=False, 134 def apply_patch(self, patches, post_processors=None, verbose=False):
135 name=None, email=None):
136 """Applies a patch and returns the list of modified files. 135 """Applies a patch and returns the list of modified files.
137 136
138 This function should throw patch.UnsupportedPatchFormat or 137 This function should throw patch.UnsupportedPatchFormat or
139 PatchApplicationFailed when relevant. 138 PatchApplicationFailed when relevant.
140 139
141 Args: 140 Args:
142 patches: patch.PatchSet object. 141 patches: patch.PatchSet object.
143 """ 142 """
144 raise NotImplementedError() 143 raise NotImplementedError()
145 144
(...skipping 13 matching lines...) Expand all
159 158
160 class RawCheckout(CheckoutBase): 159 class RawCheckout(CheckoutBase):
161 """Used to apply a patch locally without any intent to commit it. 160 """Used to apply a patch locally without any intent to commit it.
162 161
163 To be used by the try server. 162 To be used by the try server.
164 """ 163 """
165 def prepare(self, revision): 164 def prepare(self, revision):
166 """Stubbed out.""" 165 """Stubbed out."""
167 pass 166 pass
168 167
169 def apply_patch(self, patches, post_processors=None, verbose=False, 168 def apply_patch(self, patches, post_processors=None, verbose=False):
170 name=None, email=None):
171 """Ignores svn properties.""" 169 """Ignores svn properties."""
172 post_processors = post_processors or self.post_processors or [] 170 post_processors = post_processors or self.post_processors or []
173 for p in patches: 171 for p in patches:
174 stdout = [] 172 stdout = []
175 try: 173 try:
176 filepath = os.path.join(self.project_path, p.filename) 174 filepath = os.path.join(self.project_path, p.filename)
177 if p.is_delete: 175 if p.is_delete:
178 os.remove(filepath) 176 os.remove(filepath)
179 stdout.append('Deleted.') 177 stdout.append('Deleted.')
180 else: 178 else:
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 assert bool(self.commit_user) >= bool(self.commit_pwd) 342 assert bool(self.commit_user) >= bool(self.commit_pwd)
345 343
346 def prepare(self, revision): 344 def prepare(self, revision):
347 # Will checkout if the directory is not present. 345 # Will checkout if the directory is not present.
348 assert self.svn_url 346 assert self.svn_url
349 if not os.path.isdir(self.project_path): 347 if not os.path.isdir(self.project_path):
350 logging.info('Checking out %s in %s' % 348 logging.info('Checking out %s in %s' %
351 (self.project_name, self.project_path)) 349 (self.project_name, self.project_path))
352 return self._revert(revision) 350 return self._revert(revision)
353 351
354 def apply_patch(self, patches, post_processors=None, verbose=False, 352 def apply_patch(self, patches, post_processors=None, verbose=False):
355 name=None, email=None):
356 post_processors = post_processors or self.post_processors or [] 353 post_processors = post_processors or self.post_processors or []
357 for p in patches: 354 for p in patches:
358 stdout = [] 355 stdout = []
359 try: 356 try:
360 filepath = os.path.join(self.project_path, p.filename) 357 filepath = os.path.join(self.project_path, p.filename)
361 # It is important to use credentials=False otherwise credentials could 358 # It is important to use credentials=False otherwise credentials could
362 # leak in the error message. Credentials are not necessary here for the 359 # leak in the error message. Credentials are not necessary here for the
363 # following commands anyway. 360 # following commands anyway.
364 if p.is_delete: 361 if p.is_delete:
365 stdout.append(self._check_output_svn( 362 stdout.append(self._check_output_svn(
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 ['log', '-q', self.svn_url, '-r', '%s:%s' % (rev1, rev2)]) 546 ['log', '-q', self.svn_url, '-r', '%s:%s' % (rev1, rev2)])
550 except subprocess.CalledProcessError: 547 except subprocess.CalledProcessError:
551 return None 548 return None
552 # Ignore the '----' lines. 549 # Ignore the '----' lines.
553 return len([l for l in out.splitlines() if l.startswith('r')]) - 1 550 return len([l for l in out.splitlines() if l.startswith('r')]) - 1
554 551
555 552
556 class GitCheckout(CheckoutBase): 553 class GitCheckout(CheckoutBase):
557 """Manages a git checkout.""" 554 """Manages a git checkout."""
558 def __init__(self, root_dir, project_name, remote_branch, git_url, 555 def __init__(self, root_dir, project_name, remote_branch, git_url,
559 commit_user, post_processors=None, base_ref=None): 556 commit_user, post_processors=None):
560 super(GitCheckout, self).__init__(root_dir, project_name, post_processors) 557 super(GitCheckout, self).__init__(root_dir, project_name, post_processors)
561 self.base_ref = base_ref
562 self.git_url = git_url 558 self.git_url = git_url
563 self.commit_user = commit_user 559 self.commit_user = commit_user
564 self.remote_branch = remote_branch 560 self.remote_branch = remote_branch
565 # The working branch where patches will be applied. It will track the 561 # The working branch where patches will be applied. It will track the
566 # remote branch. 562 # remote branch.
567 self.working_branch = 'working_branch' 563 self.working_branch = 'working_branch'
568 # There is no reason to not hardcode origin. 564 # There is no reason to not hardcode origin.
569 self.remote = 'origin' 565 self.remote = 'origin'
570 # There is no reason to not hardcode master. 566 # There is no reason to not hardcode master.
571 self.master_branch = 'master' 567 self.master_branch = 'master'
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 self.remote, self.remote_branch) 620 self.remote, self.remote_branch)
625 self._check_call_git( 621 self._check_call_git(
626 ['pull', self.remote, 622 ['pull', self.remote,
627 '%s:%s' % (self.remote_branch, remote_tracked_path), 623 '%s:%s' % (self.remote_branch, remote_tracked_path),
628 '--quiet']) 624 '--quiet'])
629 625
630 def _get_head_commit_hash(self): 626 def _get_head_commit_hash(self):
631 """Gets the current revision (in unicode) from the local branch.""" 627 """Gets the current revision (in unicode) from the local branch."""
632 return unicode(self._check_output_git(['rev-parse', 'HEAD']).strip()) 628 return unicode(self._check_output_git(['rev-parse', 'HEAD']).strip())
633 629
634 def apply_patch(self, patches, post_processors=None, verbose=False, 630 def apply_patch(self, patches, post_processors=None, verbose=False):
iannucci 2014/05/08 07:29:48 (also, this code terrifies me to no end. There is
M-A Ruel 2014/05/08 16:40:18 It is simple; - It properly applies svn generated
635 name=None, email=None):
636 """Applies a patch on 'working_branch' and switches to it. 631 """Applies a patch on 'working_branch' and switches to it.
637 632
638 Also commits the changes on the local branch. 633 The changes remain staged on the current branch.
639 634
640 Ignores svn properties and raise an exception on unexpected ones. 635 Ignores svn properties and raise an exception on unexpected ones.
641 """ 636 """
642 post_processors = post_processors or self.post_processors or [] 637 post_processors = post_processors or self.post_processors or []
643 # It this throws, the checkout is corrupted. Maybe worth deleting it and 638 # It this throws, the checkout is corrupted. Maybe worth deleting it and
644 # trying again? 639 # trying again?
645 if self.remote_branch: 640 if self.remote_branch:
646 self._check_call_git( 641 self._check_call_git(
647 ['checkout', '-b', self.working_branch, '-t', self.remote_branch, 642 ['checkout', '-b', self.working_branch, '-t', self.remote_branch,
648 '--quiet']) 643 '--quiet'])
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 print align_stdout(stdout) 697 print align_stdout(stdout)
703 except OSError, e: 698 except OSError, e:
704 raise PatchApplicationFailed(p, '%s%s' % (align_stdout(stdout), e)) 699 raise PatchApplicationFailed(p, '%s%s' % (align_stdout(stdout), e))
705 except subprocess.CalledProcessError, e: 700 except subprocess.CalledProcessError, e:
706 raise PatchApplicationFailed( 701 raise PatchApplicationFailed(
707 p, 702 p,
708 'While running %s;\n%s%s' % ( 703 'While running %s;\n%s%s' % (
709 ' '.join(e.cmd), 704 ' '.join(e.cmd),
710 align_stdout(stdout), 705 align_stdout(stdout),
711 align_stdout([getattr(e, 'stdout', '')]))) 706 align_stdout([getattr(e, 'stdout', '')])))
712 # Once all the patches are processed and added to the index, commit the
713 # index.
714 cmd = ['commit', '-m', 'Committed patch']
715 if name and email:
716 cmd = ['-c', 'user.email=%s' % email, '-c', 'user.name=%s' % name] + cmd
717 if verbose:
718 cmd.append('--verbose')
719 self._check_call_git(cmd)
720 if self.base_ref:
721 base_ref = self.base_ref
722 else:
723 base_ref = '%s/%s' % (self.remote,
724 self.remote_branch or self.master_branch)
725 found_files = self._check_output_git( 707 found_files = self._check_output_git(
726 ['diff', base_ref, '--ignore-submodules', 708 ['diff', '--ignore-submodules',
727 '--name-only']).splitlines(False) 709 '--name-only', '--staged']).splitlines(False)
728 assert sorted(patches.filenames) == sorted(found_files), ( 710 assert sorted(patches.filenames) == sorted(found_files), (
729 'Found extra %s locally, %s not patched' % ( 711 'Found extra %s locally, %s not patched' % (
730 sorted(set(found_files) - set(patches.filenames)), 712 sorted(set(found_files) - set(patches.filenames)),
731 sorted(set(patches.filenames) - set(found_files)))) 713 sorted(set(patches.filenames) - set(found_files))))
732 714
733 def commit(self, commit_message, user): 715 def commit(self, commit_message, user):
734 """Commits, updates the commit message and pushes.""" 716 """Commits, updates the commit message and pushes."""
735 assert self.commit_user 717 assert self.commit_user
736 assert isinstance(commit_message, unicode) 718 assert isinstance(commit_message, unicode)
737 current_branch = self._check_output_git( 719 current_branch = self._check_output_git(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 self.checkout = checkout 801 self.checkout = checkout
820 self.post_processors = (post_processors or []) + ( 802 self.post_processors = (post_processors or []) + (
821 self.checkout.post_processors or []) 803 self.checkout.post_processors or [])
822 804
823 def prepare(self, revision): 805 def prepare(self, revision):
824 return self.checkout.prepare(revision) 806 return self.checkout.prepare(revision)
825 807
826 def get_settings(self, key): 808 def get_settings(self, key):
827 return self.checkout.get_settings(key) 809 return self.checkout.get_settings(key)
828 810
829 def apply_patch(self, patches, post_processors=None, verbose=False, 811 def apply_patch(self, patches, post_processors=None, verbose=False):
830 name=None, email=None):
831 return self.checkout.apply_patch( 812 return self.checkout.apply_patch(
832 patches, post_processors or self.post_processors, verbose) 813 patches, post_processors or self.post_processors, verbose)
833 814
834 def commit(self, message, user): # pylint: disable=R0201 815 def commit(self, message, user): # pylint: disable=R0201
835 logging.info('Would have committed for %s with message: %s' % ( 816 logging.info('Would have committed for %s with message: %s' % (
836 user, message)) 817 user, message))
837 return 'FAKE' 818 return 'FAKE'
838 819
839 def revisions(self, rev1, rev2): 820 def revisions(self, rev1, rev2):
840 return self.checkout.revisions(rev1, rev2) 821 return self.checkout.revisions(rev1, rev2)
841 822
842 @property 823 @property
843 def project_name(self): 824 def project_name(self):
844 return self.checkout.project_name 825 return self.checkout.project_name
845 826
846 @property 827 @property
847 def project_path(self): 828 def project_path(self):
848 return self.checkout.project_path 829 return self.checkout.project_path
OLDNEW
« no previous file with comments | « apply_issue.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698