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