| 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 |