Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2014 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2014 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 | 5 |
| 6 """This module contains functions for using git.""" | 6 """This module contains functions for using git.""" |
| 7 | 7 |
| 8 import os | 8 import os |
| 9 import re | 9 import re |
| 10 import shell_utils | 10 import shell_utils |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 self.commit_and_upload(use_commit_queue=self._commit_queue) | 145 self.commit_and_upload(use_commit_queue=self._commit_queue) |
| 146 finally: | 146 finally: |
| 147 shell_utils.run([GIT, 'checkout', 'master']) | 147 shell_utils.run([GIT, 'checkout', 'master']) |
| 148 if self._delete_when_finished: | 148 if self._delete_when_finished: |
| 149 shell_utils.run([GIT, 'branch', '-D', self._branch_name]) | 149 shell_utils.run([GIT, 'branch', '-D', self._branch_name]) |
| 150 | 150 |
| 151 | 151 |
| 152 class NewGitCheckout(object): | 152 class NewGitCheckout(object): |
| 153 """Creates a new local checkout of a Git repository.""" | 153 """Creates a new local checkout of a Git repository.""" |
| 154 | 154 |
| 155 def __init__(self, repository, refspec=None, subdir=None, | 155 def __init__(self, repository, commithash='HEAD', |
|
borenet
2014/08/19 15:24:28
Should the default for commithash be None, since y
epoger
2014/08/19 15:42:05
I'd rather make the default behavior explicit, and
| |
| 156 containing_dir=None): | 156 subdir=None, containing_dir=None): |
| 157 """Check out a new local copy of the repository. | 157 """Set parameters for this local copy of a Git repository. |
| 158 | 158 |
| 159 Because this is a new checkout, rather than a reference to an existing | 159 Because this is a new checkout, rather than a reference to an existing |
| 160 checkout on disk, it is safe to assume that the calling thread is the | 160 checkout on disk, it is safe to assume that the calling thread is the |
| 161 only thread manipulating the checkout. | 161 only thread manipulating the checkout. |
| 162 | 162 |
| 163 You can use the 'with' statement to create this object in such a way that | 163 You must use the 'with' statement to create this object: |
| 164 it cleans up after itself: | |
| 165 | 164 |
| 166 with NewGitCheckout(*args) as checkout: | 165 with NewGitCheckout(*args) as checkout: |
| 167 # use checkout instance | 166 # use checkout instance |
| 168 # the checkout is automatically cleaned up here | 167 # the checkout is automatically cleaned up here |
| 169 | 168 |
| 170 Args: | 169 Args: |
| 171 repository: name of the remote repository | 170 repository: URL of the remote repository (e.g., |
| 172 refspec: an arbitrary remote ref (e.g., the name of a branch); | 171 'https://skia.googlesource.com/common') or path to a local repository |
| 173 if None, allow the git command to pick a default | 172 (e.g., '/path/to/repo/.git') to check out a copy of |
| 173 commithash: rewind the local checkout to a particular commithash | |
| 174 subdir: if specified, the caller only wants access to files within this | 174 subdir: if specified, the caller only wants access to files within this |
| 175 subdir in the repository. | 175 subdir in the repository. |
| 176 For now, we check out the entire repository regardless of this param, | 176 For now, we check out the entire repository regardless of this param, |
| 177 and just hide the rest of the repository; but later on we may | 177 and just hide the rest of the repository; but later on we may |
| 178 optimize performance by only checking out this part of the repo. | 178 optimize performance by only checking out this part of the repo. |
| 179 containing_dir: if specified, the new checkout will be created somewhere | 179 containing_dir: if specified, the new checkout will be created somewhere |
| 180 within this directory; otherwise, a system-dependent default location | 180 within this directory; otherwise, a system-dependent default location |
| 181 will be used, as determined by tempfile.mkdtemp() | 181 will be used, as determined by tempfile.mkdtemp() |
| 182 """ | 182 """ |
| 183 # _git_root points to the tree holding the git checkout in its entirety; | 183 self._repository = repository |
| 184 # _file_root points to the files the caller wants to look at | 184 self._commithash = commithash |
| 185 self._git_root = tempfile.mkdtemp(dir=containing_dir) | 185 self._subdir = subdir |
| 186 if subdir: | 186 self._containing_dir = containing_dir |
| 187 self._file_root = os.path.join(self._git_root, subdir) | 187 self._git_root = None |
| 188 else: | 188 self._file_root = None |
| 189 self._file_root = self._git_root | |
| 190 | 189 |
| 191 pull_cmd = [GIT, 'pull', repository] | |
| 192 if refspec: | |
| 193 pull_cmd.append(refspec) | |
| 194 self._run_in_git_root(args=[GIT, 'init']) | |
| 195 self._run_in_git_root(args=pull_cmd) | |
| 196 | 190 |
| 197 @property | 191 @property |
| 198 def root(self): | 192 def root(self): |
| 199 """Returns the root directory containing the checked-out files. | 193 """Returns the root directory containing the checked-out files. |
| 200 | 194 |
| 201 If you specified the subdir parameter in the constructor, this directory | 195 If you specified the subdir parameter in the constructor, this directory |
| 202 will point at just the subdir you requested. | 196 will point at just the subdir you requested. |
| 203 """ | 197 """ |
| 204 return self._file_root | 198 return self._file_root |
| 205 | 199 |
| 206 def commithash(self): | 200 def commithash(self): |
| 207 """Returns the commithash of the local checkout.""" | 201 """Returns the commithash of the local checkout.""" |
| 208 return self._run_in_git_root( | 202 return self._run_in_git_root( |
| 209 args=[GIT, 'rev-parse', 'HEAD']).strip() | 203 args=[GIT, 'rev-parse', 'HEAD']).strip() |
| 210 | 204 |
| 211 def __enter__(self): | 205 def __enter__(self): |
| 206 """Check out a new local copy of the repository. | |
| 207 | |
| 208 Uses the parameters that were passed into the constructor. | |
| 209 """ | |
| 210 # _git_root points to the tree holding the git checkout in its entirety; | |
| 211 # _file_root points to the files the caller wants to look at | |
| 212 self._git_root = tempfile.mkdtemp(dir=self._containing_dir) | |
| 213 if self._subdir: | |
| 214 self._file_root = os.path.join(self._git_root, self._subdir) | |
| 215 else: | |
| 216 self._file_root = self._git_root | |
| 217 | |
| 218 self._run_in_git_root(args=[GIT, 'clone', self._repository, '.']) | |
| 219 if self._commithash: | |
| 220 self._run_in_git_root(args=[GIT, 'checkout', self._commithash]) | |
|
borenet
2014/08/19 15:24:28
This doesn't create a new branch like your old cod
epoger
2014/08/19 15:42:06
We don't really need the new branch, so this is fi
| |
| 221 | |
| 212 return self | 222 return self |
| 213 | 223 |
| 214 # pylint: disable=W0622 | 224 # pylint: disable=W0622 |
| 215 def __exit__(self, type, value, traceback): | 225 def __exit__(self, type, value, traceback): |
| 216 shutil.rmtree(self._git_root) | 226 shutil.rmtree(self._git_root) |
| 217 | 227 |
| 218 def _run_in_git_root(self, args): | 228 def _run_in_git_root(self, args): |
| 219 """Run an external command with cwd set to self._git_root. | 229 """Run an external command with cwd set to self._git_root. |
| 220 | 230 |
| 221 Returns the command's output as a byte string. | 231 Returns the command's output as a byte string. |
| 222 | 232 |
| 223 Raises an Exception if the command fails. | 233 Raises an Exception if the command fails. |
| 224 """ | 234 """ |
| 225 return subprocess.check_output(args=args, cwd=self._git_root) | 235 return subprocess.check_output(args=args, cwd=self._git_root) |
| OLD | NEW |