OLD | NEW |
1 # Copyright 2009 Google Inc. All Rights Reserved. | 1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 # | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # found in the LICENSE file. |
4 # you may not use this file except in compliance with the License. | |
5 # You may obtain a copy of the License at | |
6 # | |
7 # http://www.apache.org/licenses/LICENSE-2.0 | |
8 # | |
9 # Unless required by applicable law or agreed to in writing, software | |
10 # distributed under the License is distributed on an "AS IS" BASIS, | |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 # See the License for the specific language governing permissions and | |
13 # limitations under the License. | |
14 | 4 |
15 """Gclient-specific SCM-specific operations.""" | 5 """Gclient-specific SCM-specific operations.""" |
16 | 6 |
17 import logging | 7 import logging |
18 import os | 8 import os |
19 import re | 9 import re |
20 import subprocess | 10 import subprocess |
21 import sys | |
22 import xml.dom.minidom | |
23 | 11 |
| 12 import scm |
24 import gclient_utils | 13 import gclient_utils |
25 # TODO(maruel): Temporary. | |
26 from scm import CaptureGit, CaptureGitStatus, CaptureSVN | |
27 from scm import CaptureSVNHeadRevision, CaptureSVNInfo, CaptureSVNStatus | |
28 from scm import RunSVN, RunSVNAndFilterOutput, RunSVNAndGetFileList | |
29 | 14 |
30 | 15 |
31 ### SCM abstraction layer | 16 ### SCM abstraction layer |
32 | 17 |
33 | |
34 # Factory Method for SCM wrapper creation | 18 # Factory Method for SCM wrapper creation |
35 | 19 |
36 def CreateSCM(url=None, root_dir=None, relpath=None, scm_name='svn'): | 20 def CreateSCM(url=None, root_dir=None, relpath=None, scm_name='svn'): |
37 # TODO(maruel): Deduce the SCM from the url. | 21 # TODO(maruel): Deduce the SCM from the url. |
38 scm_map = { | 22 scm_map = { |
39 'svn' : SVNWrapper, | 23 'svn' : SVNWrapper, |
40 'git' : GitWrapper, | 24 'git' : GitWrapper, |
41 } | 25 } |
42 | 26 |
43 if url and (url.startswith('git:') or | 27 if url and (url.startswith('git:') or |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 if not command in commands: | 70 if not command in commands: |
87 raise gclient_utils.Error('Unknown command %s' % command) | 71 raise gclient_utils.Error('Unknown command %s' % command) |
88 | 72 |
89 if not command in dir(self): | 73 if not command in dir(self): |
90 raise gclient_utils.Error('Command %s not implemnted in %s wrapper' % ( | 74 raise gclient_utils.Error('Command %s not implemnted in %s wrapper' % ( |
91 command, self.scm_name)) | 75 command, self.scm_name)) |
92 | 76 |
93 return getattr(self, command)(options, args, file_list) | 77 return getattr(self, command)(options, args, file_list) |
94 | 78 |
95 | 79 |
96 class GitWrapper(SCMWrapper): | 80 class GitWrapper(SCMWrapper, scm.GIT): |
97 """Wrapper for Git""" | 81 """Wrapper for Git""" |
98 | 82 |
99 def cleanup(self, options, args, file_list): | 83 def cleanup(self, options, args, file_list): |
100 """Cleanup working copy.""" | 84 """Cleanup working copy.""" |
101 __pychecker__ = 'unusednames=args,file_list,options' | 85 __pychecker__ = 'unusednames=args,file_list,options' |
102 self._RunGit(['prune'], redirect_stdout=False) | 86 self._Run(['prune'], redirect_stdout=False) |
103 self._RunGit(['fsck'], redirect_stdout=False) | 87 self._Run(['fsck'], redirect_stdout=False) |
104 self._RunGit(['gc'], redirect_stdout=False) | 88 self._Run(['gc'], redirect_stdout=False) |
105 | 89 |
106 def diff(self, options, args, file_list): | 90 def diff(self, options, args, file_list): |
107 __pychecker__ = 'unusednames=args,file_list,options' | 91 __pychecker__ = 'unusednames=args,file_list,options' |
108 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 92 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) |
109 self._RunGit(['diff', merge_base], redirect_stdout=False) | 93 self._Run(['diff', merge_base], redirect_stdout=False) |
110 | 94 |
111 def export(self, options, args, file_list): | 95 def export(self, options, args, file_list): |
112 __pychecker__ = 'unusednames=file_list,options' | 96 __pychecker__ = 'unusednames=file_list,options' |
113 assert len(args) == 1 | 97 assert len(args) == 1 |
114 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 98 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
115 if not os.path.exists(export_path): | 99 if not os.path.exists(export_path): |
116 os.makedirs(export_path) | 100 os.makedirs(export_path) |
117 self._RunGit(['checkout-index', '-a', '--prefix=%s/' % export_path], | 101 self._Run(['checkout-index', '-a', '--prefix=%s/' % export_path], |
118 redirect_stdout=False) | 102 redirect_stdout=False) |
119 | 103 |
120 def update(self, options, args, file_list): | 104 def update(self, options, args, file_list): |
121 """Runs git to update or transparently checkout the working copy. | 105 """Runs git to update or transparently checkout the working copy. |
122 | 106 |
123 All updated files will be appended to file_list. | 107 All updated files will be appended to file_list. |
124 | 108 |
125 Raises: | 109 Raises: |
126 Error: if can't get URL for relative path. | 110 Error: if can't get URL for relative path. |
127 """ | 111 """ |
128 | 112 |
129 if args: | 113 if args: |
130 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args)) | 114 raise gclient_utils.Error("Unsupported argument(s): %s" % ",".join(args)) |
131 | 115 |
132 url, revision = gclient_utils.SplitUrlRevision(self.url) | 116 url, revision = gclient_utils.SplitUrlRevision(self.url) |
133 rev_str = "" | 117 rev_str = "" |
134 if options.revision: | 118 if options.revision: |
135 # Override the revision number. | 119 # Override the revision number. |
136 revision = str(options.revision) | 120 revision = str(options.revision) |
137 if revision: | 121 if revision: |
138 url = '%s@%s' % (url, revision) | 122 url = '%s@%s' % (url, revision) |
139 rev_str = ' at %s' % revision | 123 rev_str = ' at %s' % revision |
140 | 124 |
141 if options.verbose: | 125 if options.verbose: |
142 print("\n_____ %s%s" % (self.relpath, rev_str)) | 126 print("\n_____ %s%s" % (self.relpath, rev_str)) |
143 | 127 |
144 if not os.path.exists(self.checkout_path): | 128 if not os.path.exists(self.checkout_path): |
145 self._RunGit(['clone', url, self.checkout_path], | 129 self._Run(['clone', url, self.checkout_path], |
146 cwd=self._root_dir, redirect_stdout=False) | 130 cwd=self._root_dir, redirect_stdout=False) |
147 if revision: | 131 if revision: |
148 self._RunGit(['reset', '--hard', revision], redirect_stdout=False) | 132 self._Run(['reset', '--hard', revision], redirect_stdout=False) |
149 files = self._RunGit(['ls-files']).split() | 133 files = self._Run(['ls-files']).split() |
150 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 134 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
151 return | 135 return |
152 | 136 |
153 self._RunGit(['remote', 'update'], redirect_stdout=False) | 137 self._Run(['remote', 'update'], redirect_stdout=False) |
154 new_base = 'origin' | 138 new_base = 'origin' |
155 if revision: | 139 if revision: |
156 new_base = revision | 140 new_base = revision |
157 files = self._RunGit(['diff', new_base, '--name-only']).split() | 141 files = self._Run(['diff', new_base, '--name-only']).split() |
158 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 142 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
159 self._RunGit(['rebase', '-v', new_base], redirect_stdout=False) | 143 self._Run(['rebase', '-v', new_base], redirect_stdout=False) |
160 print "Checked out revision %s." % self.revinfo(options, (), None) | 144 print "Checked out revision %s." % self.revinfo(options, (), None) |
161 | 145 |
162 def revert(self, options, args, file_list): | 146 def revert(self, options, args, file_list): |
163 """Reverts local modifications. | 147 """Reverts local modifications. |
164 | 148 |
165 All reverted files will be appended to file_list. | 149 All reverted files will be appended to file_list. |
166 """ | 150 """ |
167 __pychecker__ = 'unusednames=args' | 151 __pychecker__ = 'unusednames=args' |
168 path = os.path.join(self._root_dir, self.relpath) | 152 path = os.path.join(self._root_dir, self.relpath) |
169 if not os.path.isdir(path): | 153 if not os.path.isdir(path): |
170 # revert won't work if the directory doesn't exist. It needs to | 154 # revert won't work if the directory doesn't exist. It needs to |
171 # checkout instead. | 155 # checkout instead. |
172 print("\n_____ %s is missing, synching instead" % self.relpath) | 156 print("\n_____ %s is missing, synching instead" % self.relpath) |
173 # Don't reuse the args. | 157 # Don't reuse the args. |
174 return self.update(options, [], file_list) | 158 return self.update(options, [], file_list) |
175 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 159 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) |
176 files = self._RunGit(['diff', merge_base, '--name-only']).split() | 160 files = self._Run(['diff', merge_base, '--name-only']).split() |
177 self._RunGit(['reset', '--hard', merge_base], redirect_stdout=False) | 161 self._Run(['reset', '--hard', merge_base], redirect_stdout=False) |
178 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 162 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
179 | 163 |
180 def revinfo(self, options, args, file_list): | 164 def revinfo(self, options, args, file_list): |
181 """Display revision""" | 165 """Display revision""" |
182 __pychecker__ = 'unusednames=args,file_list,options' | 166 __pychecker__ = 'unusednames=args,file_list,options' |
183 return self._RunGit(['rev-parse', 'HEAD']) | 167 return self._Run(['rev-parse', 'HEAD']) |
184 | 168 |
185 def runhooks(self, options, args, file_list): | 169 def runhooks(self, options, args, file_list): |
186 self.status(options, args, file_list) | 170 self.status(options, args, file_list) |
187 | 171 |
188 def status(self, options, args, file_list): | 172 def status(self, options, args, file_list): |
189 """Display status information.""" | 173 """Display status information.""" |
190 __pychecker__ = 'unusednames=args,options' | 174 __pychecker__ = 'unusednames=args,options' |
191 if not os.path.isdir(self.checkout_path): | 175 if not os.path.isdir(self.checkout_path): |
192 print('\n________ couldn\'t run status in %s:\nThe directory ' | 176 print('\n________ couldn\'t run status in %s:\nThe directory ' |
193 'does not exist.' % self.checkout_path) | 177 'does not exist.' % self.checkout_path) |
194 else: | 178 else: |
195 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 179 merge_base = self._Run(['merge-base', 'HEAD', 'origin']) |
196 self._RunGit(['diff', '--name-status', merge_base], redirect_stdout=False) | 180 self._Run(['diff', '--name-status', merge_base], redirect_stdout=False) |
197 files = self._RunGit(['diff', '--name-only', merge_base]).split() | 181 files = self._Run(['diff', '--name-only', merge_base]).split() |
198 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 182 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
199 | 183 |
200 def _RunGit(self, args, cwd=None, checkrc=True, redirect_stdout=True): | 184 def _Run(self, args, cwd=None, checkrc=True, redirect_stdout=True): |
| 185 # TODO(maruel): Merge with Capture? |
201 stdout=None | 186 stdout=None |
202 if redirect_stdout: | 187 if redirect_stdout: |
203 stdout=subprocess.PIPE | 188 stdout=subprocess.PIPE |
204 if cwd == None: | 189 if cwd == None: |
205 cwd = self.checkout_path | 190 cwd = self.checkout_path |
206 cmd = ['git'] | 191 cmd = [self.COMMAND] |
207 cmd.extend(args) | 192 cmd.extend(args) |
208 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) | 193 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) |
209 if checkrc and sp.returncode: | 194 if checkrc and sp.returncode: |
210 raise gclient_utils.Error('git command %s returned %d' % | 195 raise gclient_utils.Error('git command %s returned %d' % |
211 (args[0], sp.returncode)) | 196 (args[0], sp.returncode)) |
212 output = sp.communicate()[0] | 197 output = sp.communicate()[0] |
213 if output != None: | 198 if output is not None: |
214 return output.strip() | 199 return output.strip() |
215 | 200 |
216 | 201 |
217 class SVNWrapper(SCMWrapper): | 202 class SVNWrapper(SCMWrapper, scm.SVN): |
218 """ Wrapper for SVN """ | 203 """ Wrapper for SVN """ |
219 | 204 |
220 def cleanup(self, options, args, file_list): | 205 def cleanup(self, options, args, file_list): |
221 """Cleanup working copy.""" | 206 """Cleanup working copy.""" |
222 __pychecker__ = 'unusednames=file_list,options' | 207 __pychecker__ = 'unusednames=file_list,options' |
223 command = ['cleanup'] | 208 command = ['cleanup'] |
224 command.extend(args) | 209 command.extend(args) |
225 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 210 self.Run(command, os.path.join(self._root_dir, self.relpath)) |
226 | 211 |
227 def diff(self, options, args, file_list): | 212 def diff(self, options, args, file_list): |
228 # NOTE: This function does not currently modify file_list. | 213 # NOTE: This function does not currently modify file_list. |
229 __pychecker__ = 'unusednames=file_list,options' | 214 __pychecker__ = 'unusednames=file_list,options' |
230 command = ['diff'] | 215 command = ['diff'] |
231 command.extend(args) | 216 command.extend(args) |
232 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 217 self.Run(command, os.path.join(self._root_dir, self.relpath)) |
233 | 218 |
234 def export(self, options, args, file_list): | 219 def export(self, options, args, file_list): |
235 __pychecker__ = 'unusednames=file_list,options' | 220 __pychecker__ = 'unusednames=file_list,options' |
236 assert len(args) == 1 | 221 assert len(args) == 1 |
237 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 222 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
238 try: | 223 try: |
239 os.makedirs(export_path) | 224 os.makedirs(export_path) |
240 except OSError: | 225 except OSError: |
241 pass | 226 pass |
242 assert os.path.exists(export_path) | 227 assert os.path.exists(export_path) |
243 command = ['export', '--force', '.'] | 228 command = ['export', '--force', '.'] |
244 command.append(export_path) | 229 command.append(export_path) |
245 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 230 self.Run(command, os.path.join(self._root_dir, self.relpath)) |
246 | 231 |
247 def update(self, options, args, file_list): | 232 def update(self, options, args, file_list): |
248 """Runs SCM to update or transparently checkout the working copy. | 233 """Runs SCM to update or transparently checkout the working copy. |
249 | 234 |
250 All updated files will be appended to file_list. | 235 All updated files will be appended to file_list. |
251 | 236 |
252 Raises: | 237 Raises: |
253 Error: if can't get URL for relative path. | 238 Error: if can't get URL for relative path. |
254 """ | 239 """ |
255 # Only update if git is not controlling the directory. | 240 # Only update if git is not controlling the directory. |
(...skipping 16 matching lines...) Expand all Loading... |
272 if revision: | 257 if revision: |
273 forced_revision = True | 258 forced_revision = True |
274 url = '%s@%s' % (url, revision) | 259 url = '%s@%s' % (url, revision) |
275 rev_str = ' at %s' % revision | 260 rev_str = ' at %s' % revision |
276 | 261 |
277 if not os.path.exists(checkout_path): | 262 if not os.path.exists(checkout_path): |
278 # We need to checkout. | 263 # We need to checkout. |
279 command = ['checkout', url, checkout_path] | 264 command = ['checkout', url, checkout_path] |
280 if revision: | 265 if revision: |
281 command.extend(['--revision', str(revision)]) | 266 command.extend(['--revision', str(revision)]) |
282 RunSVNAndGetFileList(options, command, self._root_dir, file_list) | 267 self.RunAndGetFileList(options, command, self._root_dir, file_list) |
283 return | 268 return |
284 | 269 |
285 # Get the existing scm url and the revision number of the current checkout. | 270 # Get the existing scm url and the revision number of the current checkout. |
286 from_info = CaptureSVNInfo(os.path.join(checkout_path, '.'), '.') | 271 from_info = self.CaptureInfo(os.path.join(checkout_path, '.'), '.') |
287 if not from_info: | 272 if not from_info: |
288 raise gclient_utils.Error("Can't update/checkout %r if an unversioned " | 273 raise gclient_utils.Error("Can't update/checkout %r if an unversioned " |
289 "directory is present. Delete the directory " | 274 "directory is present. Delete the directory " |
290 "and try again." % | 275 "and try again." % |
291 checkout_path) | 276 checkout_path) |
292 | 277 |
293 if options.manually_grab_svn_rev: | 278 if options.manually_grab_svn_rev: |
294 # Retrieve the current HEAD version because svn is slow at null updates. | 279 # Retrieve the current HEAD version because svn is slow at null updates. |
295 if not revision: | 280 if not revision: |
296 from_info_live = CaptureSVNInfo(from_info['URL'], '.') | 281 from_info_live = self.CaptureInfo(from_info['URL'], '.') |
297 revision = str(from_info_live['Revision']) | 282 revision = str(from_info_live['Revision']) |
298 rev_str = ' at %s' % revision | 283 rev_str = ' at %s' % revision |
299 | 284 |
300 if from_info['URL'] != base_url: | 285 if from_info['URL'] != base_url: |
301 to_info = CaptureSVNInfo(url, '.') | 286 to_info = self.CaptureInfo(url, '.') |
302 if not to_info.get('Repository Root') or not to_info.get('UUID'): | 287 if not to_info.get('Repository Root') or not to_info.get('UUID'): |
303 # The url is invalid or the server is not accessible, it's safer to bail | 288 # The url is invalid or the server is not accessible, it's safer to bail |
304 # out right now. | 289 # out right now. |
305 raise gclient_utils.Error('This url is unreachable: %s' % url) | 290 raise gclient_utils.Error('This url is unreachable: %s' % url) |
306 can_switch = ((from_info['Repository Root'] != to_info['Repository Root']) | 291 can_switch = ((from_info['Repository Root'] != to_info['Repository Root']) |
307 and (from_info['UUID'] == to_info['UUID'])) | 292 and (from_info['UUID'] == to_info['UUID'])) |
308 if can_switch: | 293 if can_switch: |
309 print("\n_____ relocating %s to a new checkout" % self.relpath) | 294 print("\n_____ relocating %s to a new checkout" % self.relpath) |
310 # We have different roots, so check if we can switch --relocate. | 295 # We have different roots, so check if we can switch --relocate. |
311 # Subversion only permits this if the repository UUIDs match. | 296 # Subversion only permits this if the repository UUIDs match. |
312 # Perform the switch --relocate, then rewrite the from_url | 297 # Perform the switch --relocate, then rewrite the from_url |
313 # to reflect where we "are now." (This is the same way that | 298 # to reflect where we "are now." (This is the same way that |
314 # Subversion itself handles the metadata when switch --relocate | 299 # Subversion itself handles the metadata when switch --relocate |
315 # is used.) This makes the checks below for whether we | 300 # is used.) This makes the checks below for whether we |
316 # can update to a revision or have to switch to a different | 301 # can update to a revision or have to switch to a different |
317 # branch work as expected. | 302 # branch work as expected. |
318 # TODO(maruel): TEST ME ! | 303 # TODO(maruel): TEST ME ! |
319 command = ["switch", "--relocate", | 304 command = ["switch", "--relocate", |
320 from_info['Repository Root'], | 305 from_info['Repository Root'], |
321 to_info['Repository Root'], | 306 to_info['Repository Root'], |
322 self.relpath] | 307 self.relpath] |
323 RunSVN(command, self._root_dir) | 308 self.Run(command, self._root_dir) |
324 from_info['URL'] = from_info['URL'].replace( | 309 from_info['URL'] = from_info['URL'].replace( |
325 from_info['Repository Root'], | 310 from_info['Repository Root'], |
326 to_info['Repository Root']) | 311 to_info['Repository Root']) |
327 else: | 312 else: |
328 if CaptureSVNStatus(checkout_path): | 313 if self.CaptureStatus(checkout_path): |
329 raise gclient_utils.Error("Can't switch the checkout to %s; UUID " | 314 raise gclient_utils.Error("Can't switch the checkout to %s; UUID " |
330 "don't match and there is local changes " | 315 "don't match and there is local changes " |
331 "in %s. Delete the directory and " | 316 "in %s. Delete the directory and " |
332 "try again." % (url, checkout_path)) | 317 "try again." % (url, checkout_path)) |
333 # Ok delete it. | 318 # Ok delete it. |
334 print("\n_____ switching %s to a new checkout" % self.relpath) | 319 print("\n_____ switching %s to a new checkout" % self.relpath) |
335 gclient_utils.RemoveDirectory(checkout_path) | 320 gclient_utils.RemoveDirectory(checkout_path) |
336 # We need to checkout. | 321 # We need to checkout. |
337 command = ['checkout', url, checkout_path] | 322 command = ['checkout', url, checkout_path] |
338 if revision: | 323 if revision: |
339 command.extend(['--revision', str(revision)]) | 324 command.extend(['--revision', str(revision)]) |
340 RunSVNAndGetFileList(options, command, self._root_dir, file_list) | 325 self.RunAndGetFileList(options, command, self._root_dir, file_list) |
341 return | 326 return |
342 | 327 |
343 | 328 |
344 # If the provided url has a revision number that matches the revision | 329 # If the provided url has a revision number that matches the revision |
345 # number of the existing directory, then we don't need to bother updating. | 330 # number of the existing directory, then we don't need to bother updating. |
346 if not options.force and str(from_info['Revision']) == revision: | 331 if not options.force and str(from_info['Revision']) == revision: |
347 if options.verbose or not forced_revision: | 332 if options.verbose or not forced_revision: |
348 print("\n_____ %s%s" % (self.relpath, rev_str)) | 333 print("\n_____ %s%s" % (self.relpath, rev_str)) |
349 return | 334 return |
350 | 335 |
351 command = ["update", checkout_path] | 336 command = ["update", checkout_path] |
352 if revision: | 337 if revision: |
353 command.extend(['--revision', str(revision)]) | 338 command.extend(['--revision', str(revision)]) |
354 RunSVNAndGetFileList(options, command, self._root_dir, file_list) | 339 self.RunAndGetFileList(options, command, self._root_dir, file_list) |
355 | 340 |
356 def revert(self, options, args, file_list): | 341 def revert(self, options, args, file_list): |
357 """Reverts local modifications. Subversion specific. | 342 """Reverts local modifications. Subversion specific. |
358 | 343 |
359 All reverted files will be appended to file_list, even if Subversion | 344 All reverted files will be appended to file_list, even if Subversion |
360 doesn't know about them. | 345 doesn't know about them. |
361 """ | 346 """ |
362 __pychecker__ = 'unusednames=args' | 347 __pychecker__ = 'unusednames=args' |
363 path = os.path.join(self._root_dir, self.relpath) | 348 path = os.path.join(self._root_dir, self.relpath) |
364 if not os.path.isdir(path): | 349 if not os.path.isdir(path): |
365 # svn revert won't work if the directory doesn't exist. It needs to | 350 # svn revert won't work if the directory doesn't exist. It needs to |
366 # checkout instead. | 351 # checkout instead. |
367 print("\n_____ %s is missing, synching instead" % self.relpath) | 352 print("\n_____ %s is missing, synching instead" % self.relpath) |
368 # Don't reuse the args. | 353 # Don't reuse the args. |
369 return self.update(options, [], file_list) | 354 return self.update(options, [], file_list) |
370 | 355 |
371 for file_status in CaptureSVNStatus(path): | 356 for file_status in self.CaptureStatus(path): |
372 file_path = os.path.join(path, file_status[1]) | 357 file_path = os.path.join(path, file_status[1]) |
373 if file_status[0][0] == 'X': | 358 if file_status[0][0] == 'X': |
374 # Ignore externals. | 359 # Ignore externals. |
375 logging.info('Ignoring external %s' % file_path) | 360 logging.info('Ignoring external %s' % file_path) |
376 continue | 361 continue |
377 | 362 |
378 if logging.getLogger().isEnabledFor(logging.INFO): | 363 if logging.getLogger().isEnabledFor(logging.INFO): |
379 logging.info('%s%s' % (file[0], file[1])) | 364 logging.info('%s%s' % (file[0], file[1])) |
380 else: | 365 else: |
381 print(file_path) | 366 print(file_path) |
(...skipping 14 matching lines...) Expand all Loading... |
396 gclient_utils.RemoveDirectory(file_path) | 381 gclient_utils.RemoveDirectory(file_path) |
397 else: | 382 else: |
398 logging.error('no idea what is %s.\nYou just found a bug in gclient' | 383 logging.error('no idea what is %s.\nYou just found a bug in gclient' |
399 ', please ping maruel@chromium.org ASAP!' % file_path) | 384 ', please ping maruel@chromium.org ASAP!' % file_path) |
400 except EnvironmentError: | 385 except EnvironmentError: |
401 logging.error('Failed to remove %s.' % file_path) | 386 logging.error('Failed to remove %s.' % file_path) |
402 | 387 |
403 try: | 388 try: |
404 # svn revert is so broken we don't even use it. Using | 389 # svn revert is so broken we don't even use it. Using |
405 # "svn up --revision BASE" achieve the same effect. | 390 # "svn up --revision BASE" achieve the same effect. |
406 RunSVNAndGetFileList(options, ['update', '--revision', 'BASE'], path, | 391 self.RunAndGetFileList(options, ['update', '--revision', 'BASE'], path, |
407 file_list) | 392 file_list) |
408 except OSError, e: | 393 except OSError, e: |
409 # Maybe the directory disapeared meanwhile. We don't want it to throw an | 394 # Maybe the directory disapeared meanwhile. We don't want it to throw an |
410 # exception. | 395 # exception. |
411 logging.error('Failed to update:\n%s' % str(e)) | 396 logging.error('Failed to update:\n%s' % str(e)) |
412 | 397 |
413 def revinfo(self, options, args, file_list): | 398 def revinfo(self, options, args, file_list): |
414 """Display revision""" | 399 """Display revision""" |
415 __pychecker__ = 'unusednames=args,file_list,options' | 400 __pychecker__ = 'unusednames=args,file_list,options' |
416 return CaptureSVNHeadRevision(self.url) | 401 return self.CaptureHeadRevision(self.url) |
417 | 402 |
418 def runhooks(self, options, args, file_list): | 403 def runhooks(self, options, args, file_list): |
419 self.status(options, args, file_list) | 404 self.status(options, args, file_list) |
420 | 405 |
421 def status(self, options, args, file_list): | 406 def status(self, options, args, file_list): |
422 """Display status information.""" | 407 """Display status information.""" |
423 path = os.path.join(self._root_dir, self.relpath) | 408 path = os.path.join(self._root_dir, self.relpath) |
424 command = ['status'] | 409 command = ['status'] |
425 command.extend(args) | 410 command.extend(args) |
426 if not os.path.isdir(path): | 411 if not os.path.isdir(path): |
427 # svn status won't work if the directory doesn't exist. | 412 # svn status won't work if the directory doesn't exist. |
428 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " | 413 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " |
429 "does not exist." | 414 "does not exist." |
430 % (' '.join(command), path)) | 415 % (' '.join(command), path)) |
431 # There's no file list to retrieve. | 416 # There's no file list to retrieve. |
432 else: | 417 else: |
433 RunSVNAndGetFileList(options, command, path, file_list) | 418 self.RunAndGetFileList(options, command, path, file_list) |
434 | 419 |
435 def pack(self, options, args, file_list): | 420 def pack(self, options, args, file_list): |
436 """Generates a patch file which can be applied to the root of the | 421 """Generates a patch file which can be applied to the root of the |
437 repository.""" | 422 repository.""" |
438 __pychecker__ = 'unusednames=file_list,options' | 423 __pychecker__ = 'unusednames=file_list,options' |
439 path = os.path.join(self._root_dir, self.relpath) | 424 path = os.path.join(self._root_dir, self.relpath) |
440 command = ['diff'] | 425 command = ['diff'] |
441 command.extend(args) | 426 command.extend(args) |
442 # Simple class which tracks which file is being diffed and | 427 # Simple class which tracks which file is being diffed and |
443 # replaces instances of its file name in the original and | 428 # replaces instances of its file name in the original and |
(...skipping 24 matching lines...) Expand all Loading... |
468 self.SetCurrentFile(line[len(self.index_string):]) | 453 self.SetCurrentFile(line[len(self.index_string):]) |
469 self.ReplaceAndPrint(line) | 454 self.ReplaceAndPrint(line) |
470 else: | 455 else: |
471 if (line.startswith(self.original_prefix) or | 456 if (line.startswith(self.original_prefix) or |
472 line.startswith(self.working_prefix)): | 457 line.startswith(self.working_prefix)): |
473 self.ReplaceAndPrint(line) | 458 self.ReplaceAndPrint(line) |
474 else: | 459 else: |
475 print line | 460 print line |
476 | 461 |
477 filterer = DiffFilterer(self.relpath) | 462 filterer = DiffFilterer(self.relpath) |
478 RunSVNAndFilterOutput(command, path, False, False, filterer.Filter) | 463 self.RunAndFilterOutput(command, path, False, False, filterer.Filter) |
OLD | NEW |