OLD | NEW |
1 # Copyright 2009 Google Inc. All Rights Reserved. | 1 # Copyright 2009 Google Inc. All Rights Reserved. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with 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 | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 command, self.scm_name)) | 89 command, self.scm_name)) |
90 | 90 |
91 return getattr(self, command)(options, args, file_list) | 91 return getattr(self, command)(options, args, file_list) |
92 | 92 |
93 | 93 |
94 class GitWrapper(SCMWrapper): | 94 class GitWrapper(SCMWrapper): |
95 """Wrapper for Git""" | 95 """Wrapper for Git""" |
96 | 96 |
97 def cleanup(self, options, args, file_list): | 97 def cleanup(self, options, args, file_list): |
98 """Cleanup working copy.""" | 98 """Cleanup working copy.""" |
| 99 __pychecker__ = 'unusednames=args,file_list,options' |
99 self._RunGit(['prune'], redirect_stdout=False) | 100 self._RunGit(['prune'], redirect_stdout=False) |
100 self._RunGit(['fsck'], redirect_stdout=False) | 101 self._RunGit(['fsck'], redirect_stdout=False) |
101 self._RunGit(['gc'], redirect_stdout=False) | 102 self._RunGit(['gc'], redirect_stdout=False) |
102 | 103 |
103 def diff(self, options, args, file_list): | 104 def diff(self, options, args, file_list): |
104 # NOTE: This function does not currently modify file_list. | 105 __pychecker__ = 'unusednames=args,file_list,options' |
105 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 106 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) |
106 self._RunGit(['diff', merge_base], redirect_stdout=False) | 107 self._RunGit(['diff', merge_base], redirect_stdout=False) |
107 | 108 |
108 def export(self, options, args, file_list): | 109 def export(self, options, args, file_list): |
| 110 __pychecker__ = 'unusednames=file_list,options' |
109 assert len(args) == 1 | 111 assert len(args) == 1 |
110 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 112 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
111 if not os.path.exists(export_path): | 113 if not os.path.exists(export_path): |
112 os.makedirs(export_path) | 114 os.makedirs(export_path) |
113 self._RunGit(['checkout-index', '-a', '--prefix=%s/' % export_path], | 115 self._RunGit(['checkout-index', '-a', '--prefix=%s/' % export_path], |
114 redirect_stdout=False) | 116 redirect_stdout=False) |
115 | 117 |
116 def update(self, options, args, file_list): | 118 def update(self, options, args, file_list): |
117 """Runs git to update or transparently checkout the working copy. | 119 """Runs git to update or transparently checkout the working copy. |
118 | 120 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 files = self._RunGit(['diff', new_base, '--name-only']).split() | 162 files = self._RunGit(['diff', new_base, '--name-only']).split() |
161 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 163 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
162 self._RunGit(['rebase', '-v', new_base], redirect_stdout=False) | 164 self._RunGit(['rebase', '-v', new_base], redirect_stdout=False) |
163 print "Checked out revision %s." % self.revinfo(options, (), None) | 165 print "Checked out revision %s." % self.revinfo(options, (), None) |
164 | 166 |
165 def revert(self, options, args, file_list): | 167 def revert(self, options, args, file_list): |
166 """Reverts local modifications. | 168 """Reverts local modifications. |
167 | 169 |
168 All reverted files will be appended to file_list. | 170 All reverted files will be appended to file_list. |
169 """ | 171 """ |
| 172 __pychecker__ = 'unusednames=args' |
170 path = os.path.join(self._root_dir, self.relpath) | 173 path = os.path.join(self._root_dir, self.relpath) |
171 if not os.path.isdir(path): | 174 if not os.path.isdir(path): |
172 # revert won't work if the directory doesn't exist. It needs to | 175 # revert won't work if the directory doesn't exist. It needs to |
173 # checkout instead. | 176 # checkout instead. |
174 print("\n_____ %s is missing, synching instead" % self.relpath) | 177 print("\n_____ %s is missing, synching instead" % self.relpath) |
175 # Don't reuse the args. | 178 # Don't reuse the args. |
176 return self.update(options, [], file_list) | 179 return self.update(options, [], file_list) |
177 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 180 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) |
178 files = self._RunGit(['diff', merge_base, '--name-only']).split() | 181 files = self._RunGit(['diff', merge_base, '--name-only']).split() |
179 self._RunGit(['reset', '--hard', merge_base], redirect_stdout=False) | 182 self._RunGit(['reset', '--hard', merge_base], redirect_stdout=False) |
180 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 183 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
181 | 184 |
182 def revinfo(self, options, args, file_list): | 185 def revinfo(self, options, args, file_list): |
183 """Display revision""" | 186 """Display revision""" |
| 187 __pychecker__ = 'unusednames=args,file_list,options' |
184 return self._RunGit(['rev-parse', 'HEAD']) | 188 return self._RunGit(['rev-parse', 'HEAD']) |
185 | 189 |
186 def runhooks(self, options, args, file_list): | 190 def runhooks(self, options, args, file_list): |
187 self.status(options, args, file_list) | 191 self.status(options, args, file_list) |
188 | 192 |
189 def status(self, options, args, file_list): | 193 def status(self, options, args, file_list): |
190 """Display status information.""" | 194 """Display status information.""" |
| 195 __pychecker__ = 'unusednames=args,options' |
191 if not os.path.isdir(self.checkout_path): | 196 if not os.path.isdir(self.checkout_path): |
192 print('\n________ couldn\'t run status in %s:\nThe directory ' | 197 print('\n________ couldn\'t run status in %s:\nThe directory ' |
193 'does not exist.' % checkout_path) | 198 'does not exist.' % self.checkout_path) |
194 else: | 199 else: |
195 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) | 200 merge_base = self._RunGit(['merge-base', 'HEAD', 'origin']) |
196 self._RunGit(['diff', '--name-status', merge_base], redirect_stdout=False) | 201 self._RunGit(['diff', '--name-status', merge_base], redirect_stdout=False) |
197 files = self._RunGit(['diff', '--name-only', merge_base]).split() | 202 files = self._RunGit(['diff', '--name-only', merge_base]).split() |
198 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) | 203 file_list.extend([os.path.join(self.checkout_path, f) for f in files]) |
199 | 204 |
200 def _RunGit(self, args, cwd=None, checkrc=True, redirect_stdout=True): | 205 def _RunGit(self, args, cwd=None, checkrc=True, redirect_stdout=True): |
201 stdout=None | 206 stdout=None |
202 if redirect_stdout: | 207 if redirect_stdout: |
203 stdout=subprocess.PIPE | 208 stdout=subprocess.PIPE |
204 if cwd == None: | 209 if cwd == None: |
205 cwd = self.checkout_path | 210 cwd = self.checkout_path |
206 cmd = ['git'] | 211 cmd = ['git'] |
207 cmd.extend(args) | 212 cmd.extend(args) |
208 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) | 213 sp = subprocess.Popen(cmd, cwd=cwd, stdout=stdout) |
209 if checkrc and sp.returncode: | 214 if checkrc and sp.returncode: |
210 raise gclient_utils.Error('git command %s returned %d' % | 215 raise gclient_utils.Error('git command %s returned %d' % |
211 (args[0], sp.returncode)) | 216 (args[0], sp.returncode)) |
212 output = sp.communicate()[0] | 217 output = sp.communicate()[0] |
213 if output != None: | 218 if output != None: |
214 return output.strip() | 219 return output.strip() |
215 | 220 |
216 | 221 |
217 class SVNWrapper(SCMWrapper): | 222 class SVNWrapper(SCMWrapper): |
218 """ Wrapper for SVN """ | 223 """ Wrapper for SVN """ |
219 | 224 |
220 def cleanup(self, options, args, file_list): | 225 def cleanup(self, options, args, file_list): |
221 """Cleanup working copy.""" | 226 """Cleanup working copy.""" |
| 227 __pychecker__ = 'unusednames=file_list,options' |
222 command = ['cleanup'] | 228 command = ['cleanup'] |
223 command.extend(args) | 229 command.extend(args) |
224 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 230 RunSVN(command, os.path.join(self._root_dir, self.relpath)) |
225 | 231 |
226 def diff(self, options, args, file_list): | 232 def diff(self, options, args, file_list): |
227 # NOTE: This function does not currently modify file_list. | 233 # NOTE: This function does not currently modify file_list. |
| 234 __pychecker__ = 'unusednames=file_list,options' |
228 command = ['diff'] | 235 command = ['diff'] |
229 command.extend(args) | 236 command.extend(args) |
230 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 237 RunSVN(command, os.path.join(self._root_dir, self.relpath)) |
231 | 238 |
232 def export(self, options, args, file_list): | 239 def export(self, options, args, file_list): |
| 240 __pychecker__ = 'unusednames=file_list,options' |
233 assert len(args) == 1 | 241 assert len(args) == 1 |
234 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) | 242 export_path = os.path.abspath(os.path.join(args[0], self.relpath)) |
235 try: | 243 try: |
236 os.makedirs(export_path) | 244 os.makedirs(export_path) |
237 except OSError: | 245 except OSError: |
238 pass | 246 pass |
239 assert os.path.exists(export_path) | 247 assert os.path.exists(export_path) |
240 command = ['export', '--force', '.'] | 248 command = ['export', '--force', '.'] |
241 command.append(export_path) | 249 command.append(export_path) |
242 RunSVN(command, os.path.join(self._root_dir, self.relpath)) | 250 RunSVN(command, os.path.join(self._root_dir, self.relpath)) |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 if revision: | 362 if revision: |
355 command.extend(['--revision', str(revision)]) | 363 command.extend(['--revision', str(revision)]) |
356 RunSVNAndGetFileList(options, command, self._root_dir, file_list) | 364 RunSVNAndGetFileList(options, command, self._root_dir, file_list) |
357 | 365 |
358 def revert(self, options, args, file_list): | 366 def revert(self, options, args, file_list): |
359 """Reverts local modifications. Subversion specific. | 367 """Reverts local modifications. Subversion specific. |
360 | 368 |
361 All reverted files will be appended to file_list, even if Subversion | 369 All reverted files will be appended to file_list, even if Subversion |
362 doesn't know about them. | 370 doesn't know about them. |
363 """ | 371 """ |
| 372 __pychecker__ = 'unusednames=args' |
364 path = os.path.join(self._root_dir, self.relpath) | 373 path = os.path.join(self._root_dir, self.relpath) |
365 if not os.path.isdir(path): | 374 if not os.path.isdir(path): |
366 # svn revert won't work if the directory doesn't exist. It needs to | 375 # svn revert won't work if the directory doesn't exist. It needs to |
367 # checkout instead. | 376 # checkout instead. |
368 print("\n_____ %s is missing, synching instead" % self.relpath) | 377 print("\n_____ %s is missing, synching instead" % self.relpath) |
369 # Don't reuse the args. | 378 # Don't reuse the args. |
370 return self.update(options, [], file_list) | 379 return self.update(options, [], file_list) |
371 | 380 |
372 for file in CaptureSVNStatus(path): | 381 for file_status in CaptureSVNStatus(path): |
373 file_path = os.path.join(path, file[1]) | 382 file_path = os.path.join(path, file_status[1]) |
374 if file[0][0] == 'X': | 383 if file_status[0][0] == 'X': |
375 # Ignore externals. | 384 # Ignore externals. |
376 logging.info('Ignoring external %s' % file_path) | 385 logging.info('Ignoring external %s' % file_path) |
377 continue | 386 continue |
378 | 387 |
379 if logging.getLogger().isEnabledFor(logging.INFO): | 388 if logging.getLogger().isEnabledFor(logging.INFO): |
380 logging.info('%s%s' % (file[0], file[1])) | 389 logging.info('%s%s' % (file[0], file[1])) |
381 else: | 390 else: |
382 print(file_path) | 391 print(file_path) |
383 if file[0].isspace(): | 392 if file_status[0].isspace(): |
384 logging.error('No idea what is the status of %s.\n' | 393 logging.error('No idea what is the status of %s.\n' |
385 'You just found a bug in gclient, please ping ' | 394 'You just found a bug in gclient, please ping ' |
386 'maruel@chromium.org ASAP!' % file_path) | 395 'maruel@chromium.org ASAP!' % file_path) |
387 # svn revert is really stupid. It fails on inconsistent line-endings, | 396 # svn revert is really stupid. It fails on inconsistent line-endings, |
388 # on switched directories, etc. So take no chance and delete everything! | 397 # on switched directories, etc. So take no chance and delete everything! |
389 try: | 398 try: |
390 if not os.path.exists(file_path): | 399 if not os.path.exists(file_path): |
391 pass | 400 pass |
392 elif os.path.isfile(file_path): | 401 elif os.path.isfile(file_path): |
393 logging.info('os.remove(%s)' % file_path) | 402 logging.info('os.remove(%s)' % file_path) |
(...skipping 12 matching lines...) Expand all Loading... |
406 # "svn up --revision BASE" achieve the same effect. | 415 # "svn up --revision BASE" achieve the same effect. |
407 RunSVNAndGetFileList(options, ['update', '--revision', 'BASE'], path, | 416 RunSVNAndGetFileList(options, ['update', '--revision', 'BASE'], path, |
408 file_list) | 417 file_list) |
409 except OSError, e: | 418 except OSError, e: |
410 # Maybe the directory disapeared meanwhile. We don't want it to throw an | 419 # Maybe the directory disapeared meanwhile. We don't want it to throw an |
411 # exception. | 420 # exception. |
412 logging.error('Failed to update:\n%s' % str(e)) | 421 logging.error('Failed to update:\n%s' % str(e)) |
413 | 422 |
414 def revinfo(self, options, args, file_list): | 423 def revinfo(self, options, args, file_list): |
415 """Display revision""" | 424 """Display revision""" |
| 425 __pychecker__ = 'unusednames=args,file_list,options' |
416 return CaptureSVNHeadRevision(self.url) | 426 return CaptureSVNHeadRevision(self.url) |
417 | 427 |
418 def runhooks(self, options, args, file_list): | 428 def runhooks(self, options, args, file_list): |
419 self.status(options, args, file_list) | 429 self.status(options, args, file_list) |
420 | 430 |
421 def status(self, options, args, file_list): | 431 def status(self, options, args, file_list): |
422 """Display status information.""" | 432 """Display status information.""" |
423 path = os.path.join(self._root_dir, self.relpath) | 433 path = os.path.join(self._root_dir, self.relpath) |
424 command = ['status'] | 434 command = ['status'] |
425 command.extend(args) | 435 command.extend(args) |
426 if not os.path.isdir(path): | 436 if not os.path.isdir(path): |
427 # svn status won't work if the directory doesn't exist. | 437 # svn status won't work if the directory doesn't exist. |
428 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " | 438 print("\n________ couldn't run \'%s\' in \'%s\':\nThe directory " |
429 "does not exist." | 439 "does not exist." |
430 % (' '.join(command), path)) | 440 % (' '.join(command), path)) |
431 # There's no file list to retrieve. | 441 # There's no file list to retrieve. |
432 else: | 442 else: |
433 RunSVNAndGetFileList(options, command, path, file_list) | 443 RunSVNAndGetFileList(options, command, path, file_list) |
434 | 444 |
435 def pack(self, options, args, file_list): | 445 def pack(self, options, args, file_list): |
436 """Generates a patch file which can be applied to the root of the | 446 """Generates a patch file which can be applied to the root of the |
437 repository.""" | 447 repository.""" |
| 448 __pychecker__ = 'unusednames=file_list,options' |
438 path = os.path.join(self._root_dir, self.relpath) | 449 path = os.path.join(self._root_dir, self.relpath) |
439 command = ['diff'] | 450 command = ['diff'] |
440 command.extend(args) | 451 command.extend(args) |
441 # Simple class which tracks which file is being diffed and | 452 # Simple class which tracks which file is being diffed and |
442 # replaces instances of its file name in the original and | 453 # replaces instances of its file name in the original and |
443 # working copy lines of the svn diff output. | 454 # working copy lines of the svn diff output. |
444 class DiffFilterer(object): | 455 class DiffFilterer(object): |
445 index_string = "Index: " | 456 index_string = "Index: " |
446 original_prefix = "--- " | 457 original_prefix = "--- " |
447 working_prefix = "+++ " | 458 working_prefix = "+++ " |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 'normal': ' ', | 761 'normal': ' ', |
751 'obstructed': '~', | 762 'obstructed': '~', |
752 'replaced': 'R', | 763 'replaced': 'R', |
753 'unversioned': '?', | 764 'unversioned': '?', |
754 } | 765 } |
755 dom = gclient_utils.ParseXML(CaptureSVN(command)) | 766 dom = gclient_utils.ParseXML(CaptureSVN(command)) |
756 results = [] | 767 results = [] |
757 if dom: | 768 if dom: |
758 # /status/target/entry/(wc-status|commit|author|date) | 769 # /status/target/entry/(wc-status|commit|author|date) |
759 for target in dom.getElementsByTagName('target'): | 770 for target in dom.getElementsByTagName('target'): |
760 base_path = target.getAttribute('path') | |
761 for entry in target.getElementsByTagName('entry'): | 771 for entry in target.getElementsByTagName('entry'): |
762 file = entry.getAttribute('path') | 772 file_path = entry.getAttribute('path') |
763 wc_status = entry.getElementsByTagName('wc-status') | 773 wc_status = entry.getElementsByTagName('wc-status') |
764 assert len(wc_status) == 1 | 774 assert len(wc_status) == 1 |
765 # Emulate svn 1.5 status ouput... | 775 # Emulate svn 1.5 status ouput... |
766 statuses = [' ' for i in range(7)] | 776 statuses = [' '] * 7 |
767 # Col 0 | 777 # Col 0 |
768 xml_item_status = wc_status[0].getAttribute('item') | 778 xml_item_status = wc_status[0].getAttribute('item') |
769 if xml_item_status in status_letter: | 779 if xml_item_status in status_letter: |
770 statuses[0] = status_letter[xml_item_status] | 780 statuses[0] = status_letter[xml_item_status] |
771 else: | 781 else: |
772 raise Exception('Unknown item status "%s"; please implement me!' % | 782 raise Exception('Unknown item status "%s"; please implement me!' % |
773 xml_item_status) | 783 xml_item_status) |
774 # Col 1 | 784 # Col 1 |
775 xml_props_status = wc_status[0].getAttribute('props') | 785 xml_props_status = wc_status[0].getAttribute('props') |
776 if xml_props_status == 'modified': | 786 if xml_props_status == 'modified': |
777 statuses[1] = 'M' | 787 statuses[1] = 'M' |
778 elif xml_props_status == 'conflicted': | 788 elif xml_props_status == 'conflicted': |
779 statuses[1] = 'C' | 789 statuses[1] = 'C' |
780 elif (not xml_props_status or xml_props_status == 'none' or | 790 elif (not xml_props_status or xml_props_status == 'none' or |
781 xml_props_status == 'normal'): | 791 xml_props_status == 'normal'): |
782 pass | 792 pass |
783 else: | 793 else: |
784 raise Exception('Unknown props status "%s"; please implement me!' % | 794 raise Exception('Unknown props status "%s"; please implement me!' % |
785 xml_props_status) | 795 xml_props_status) |
786 # Col 2 | 796 # Col 2 |
787 if wc_status[0].getAttribute('wc-locked') == 'true': | 797 if wc_status[0].getAttribute('wc-locked') == 'true': |
788 statuses[2] = 'L' | 798 statuses[2] = 'L' |
789 # Col 3 | 799 # Col 3 |
790 if wc_status[0].getAttribute('copied') == 'true': | 800 if wc_status[0].getAttribute('copied') == 'true': |
791 statuses[3] = '+' | 801 statuses[3] = '+' |
792 # Col 4 | 802 # Col 4 |
793 if wc_status[0].getAttribute('switched') == 'true': | 803 if wc_status[0].getAttribute('switched') == 'true': |
794 statuses[4] = 'S' | 804 statuses[4] = 'S' |
795 # TODO(maruel): Col 5 and 6 | 805 # TODO(maruel): Col 5 and 6 |
796 item = (''.join(statuses), file) | 806 item = (''.join(statuses), file_path) |
797 results.append(item) | 807 results.append(item) |
798 return results | 808 return results |
OLD | NEW |