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 |