Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: scm.py

Issue 6799021: Switch from xml.dom.minidom to xml.etree (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """SCM-specific utility classes.""" 5 """SCM-specific utility classes."""
6 6
7 import cStringIO 7 import cStringIO
8 import glob 8 import glob
9 import logging 9 import logging
10 import os 10 import os
11 import re 11 import re
12 import shutil 12 import shutil
13 import subprocess 13 import subprocess
14 import sys 14 import sys
15 import tempfile 15 import tempfile
16 import time 16 import time
17 import xml.dom.minidom 17 from xml.etree import ElementTree
18 18
19 import gclient_utils 19 import gclient_utils
20 import subprocess2 20 import subprocess2
21 21
22 22
23 def ValidateEmail(email): 23 def ValidateEmail(email):
24 return (re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email) 24 return (re.match(r"^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", email)
25 is not None) 25 is not None)
26 26
27 27
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 time.sleep(backoff_time) 505 time.sleep(backoff_time)
506 backoff_time *= 1.3 506 backoff_time *= 1.3
507 continue 507 continue
508 break 508 break
509 509
510 @staticmethod 510 @staticmethod
511 def CaptureInfo(cwd): 511 def CaptureInfo(cwd):
512 """Returns a dictionary from the svn info output for the given file. 512 """Returns a dictionary from the svn info output for the given file.
513 513
514 Throws an exception if svn info fails.""" 514 Throws an exception if svn info fails."""
515 result = {}
515 output = SVN.Capture(['info', '--xml', cwd]) 516 output = SVN.Capture(['info', '--xml', cwd])
516 dom = gclient_utils.ParseXML(output) 517 info = ElementTree.XML(output)
517 result = {} 518 if info is None:
518 if dom: 519 return result
519 GetNamedNodeText = gclient_utils.GetNamedNodeText 520 entry = info.find('entry')
520 GetNodeNamedAttributeText = gclient_utils.GetNodeNamedAttributeText 521
521 def C(item, f): 522 # Use .text when the item is not optional.
522 if item is not None: 523 result['Path'] = entry.attrib['path']
523 return f(item) 524 result['Revision'] = int(entry.attrib['revision'])
524 # /info/entry/ 525 result['Node Kind'] = entry.attrib['kind']
525 # url 526 # Differs across versions.
526 # reposityory/(root|uuid) 527 if result['Node Kind'] == 'dir':
527 # wc-info/(schedule|depth) 528 result['Node Kind'] = 'directory'
528 # commit/(author|date) 529 result['URL'] = entry.find('url').text
529 # str() the results because they may be returned as Unicode, which 530 repository = entry.find('repository')
530 # interferes with the higher layers matching up things in the deps 531 result['Repository Root'] = repository.find('root').text
531 # dictionary. 532 result['UUID'] = repository.find('uuid')
532 result['Repository Root'] = C(GetNamedNodeText(dom, 'root'), str) 533 wc_info = entry.find('wc-info')
533 result['URL'] = C(GetNamedNodeText(dom, 'url'), str) 534 result['Schedule'] = wc_info.find('schedule').text
534 result['UUID'] = C(GetNamedNodeText(dom, 'uuid'), str) 535 result['Copied From URL'] = wc_info.find('copy-from-url')
535 result['Revision'] = C(GetNodeNamedAttributeText(dom, 'entry', 536 result['Copied From Rev'] = wc_info.find('copy-from-rev')
536 'revision'), 537 for key in result.keys():
537 int) 538 if isinstance(result[key], unicode):
538 result['Node Kind'] = C(GetNodeNamedAttributeText(dom, 'entry', 'kind'), 539 # Unicode results interferes with the higher layers matching up things
539 str) 540 # in the deps dictionary.
540 # Differs across versions. 541 result[key] = result[key].encode()
541 if result['Node Kind'] == 'dir': 542 # Automatic conversion of optional parameters.
542 result['Node Kind'] = 'directory' 543 result[key] = getattr(result[key], 'text', result[key])
543 result['Schedule'] = C(GetNamedNodeText(dom, 'schedule'), str)
544 result['Path'] = C(GetNodeNamedAttributeText(dom, 'entry', 'path'), str)
545 result['Copied From URL'] = C(GetNamedNodeText(dom, 'copy-from-url'), str)
546 result['Copied From Rev'] = C(GetNamedNodeText(dom, 'copy-from-rev'), str)
547 return result 544 return result
548 545
549 @staticmethod 546 @staticmethod
550 def CaptureRevision(cwd): 547 def CaptureRevision(cwd):
551 """Get the base revision of a SVN repository. 548 """Get the base revision of a SVN repository.
552 549
553 Returns: 550 Returns:
554 Int base revision 551 Int base revision
555 """ 552 """
556 info = SVN.Capture(['info', '--xml'], cwd=cwd) 553 return SVN.CaptureInfo(cwd).get('Revision')
557 dom = xml.dom.minidom.parseString(info)
558 return dom.getElementsByTagName('entry')[0].getAttribute('revision')
559 554
560 @staticmethod 555 @staticmethod
561 def CaptureStatus(files): 556 def CaptureStatus(files):
562 """Returns the svn 1.5 svn status emulated output. 557 """Returns the svn 1.5 svn status emulated output.
563 558
564 @files can be a string (one file) or a list of files. 559 @files can be a string (one file) or a list of files.
565 560
566 Returns an array of (status, file) tuples.""" 561 Returns an array of (status, file) tuples."""
567 command = ["status", "--xml"] 562 command = ["status", "--xml"]
568 if not files: 563 if not files:
(...skipping 14 matching lines...) Expand all
583 'incomplete': '!', 578 'incomplete': '!',
584 'merged': 'G', 579 'merged': 'G',
585 'missing': '!', 580 'missing': '!',
586 'modified': 'M', 581 'modified': 'M',
587 'none': ' ', 582 'none': ' ',
588 'normal': ' ', 583 'normal': ' ',
589 'obstructed': '~', 584 'obstructed': '~',
590 'replaced': 'R', 585 'replaced': 'R',
591 'unversioned': '?', 586 'unversioned': '?',
592 } 587 }
593 dom = gclient_utils.ParseXML(SVN.Capture(command)) 588 dom = ElementTree.XML(SVN.Capture(command))
594 results = [] 589 results = []
595 if dom: 590 if dom is None:
596 # /status/target/entry/(wc-status|commit|author|date) 591 return results
597 for target in dom.getElementsByTagName('target'): 592 # /status/target/entry/(wc-status|commit|author|date)
598 #base_path = target.getAttribute('path') 593 for target in dom.findall('target'):
599 for entry in target.getElementsByTagName('entry'): 594 for entry in target.findall('entry'):
600 file_path = entry.getAttribute('path') 595 file_path = entry.attrib['path']
601 wc_status = entry.getElementsByTagName('wc-status') 596 wc_status = entry.find('wc-status')
602 assert len(wc_status) == 1 597 # Emulate svn 1.5 status ouput...
603 # Emulate svn 1.5 status ouput... 598 statuses = [' '] * 7
604 statuses = [' '] * 7 599 # Col 0
605 # Col 0 600 xml_item_status = wc_status.attrib['item']
606 xml_item_status = wc_status[0].getAttribute('item') 601 if xml_item_status in status_letter:
607 if xml_item_status in status_letter: 602 statuses[0] = status_letter[xml_item_status]
608 statuses[0] = status_letter[xml_item_status] 603 else:
609 else: 604 raise gclient_utils.Error(
610 raise gclient_utils.Error( 605 'Unknown item status "%s"; please implement me!' %
611 'Unknown item status "%s"; please implement me!' % 606 xml_item_status)
612 xml_item_status) 607 # Col 1
613 # Col 1 608 xml_props_status = wc_status.attrib['props']
614 xml_props_status = wc_status[0].getAttribute('props') 609 if xml_props_status == 'modified':
615 if xml_props_status == 'modified': 610 statuses[1] = 'M'
616 statuses[1] = 'M' 611 elif xml_props_status == 'conflicted':
617 elif xml_props_status == 'conflicted': 612 statuses[1] = 'C'
618 statuses[1] = 'C' 613 elif (not xml_props_status or xml_props_status == 'none' or
619 elif (not xml_props_status or xml_props_status == 'none' or 614 xml_props_status == 'normal'):
620 xml_props_status == 'normal'): 615 pass
621 pass 616 else:
622 else: 617 raise gclient_utils.Error(
623 raise gclient_utils.Error( 618 'Unknown props status "%s"; please implement me!' %
624 'Unknown props status "%s"; please implement me!' % 619 xml_props_status)
625 xml_props_status) 620 # Col 2
626 # Col 2 621 if wc_status.attrib.get('wc-locked') == 'true':
627 if wc_status[0].getAttribute('wc-locked') == 'true': 622 statuses[2] = 'L'
628 statuses[2] = 'L' 623 # Col 3
629 # Col 3 624 if wc_status.attrib.get('copied') == 'true':
630 if wc_status[0].getAttribute('copied') == 'true': 625 statuses[3] = '+'
631 statuses[3] = '+' 626 # Col 4
632 # Col 4 627 if wc_status.attrib.get('switched') == 'true':
633 if wc_status[0].getAttribute('switched') == 'true': 628 statuses[4] = 'S'
634 statuses[4] = 'S' 629 # TODO(maruel): Col 5 and 6
635 # TODO(maruel): Col 5 and 6 630 item = (''.join(statuses), file_path)
636 item = (''.join(statuses), file_path) 631 results.append(item)
637 results.append(item)
638 return results 632 return results
639 633
640 @staticmethod 634 @staticmethod
641 def IsMoved(filename): 635 def IsMoved(filename):
642 """Determine if a file has been added through svn mv""" 636 """Determine if a file has been added through svn mv"""
643 return SVN.IsMovedInfo(SVN.CaptureInfo(filename)) 637 return SVN.IsMovedInfo(SVN.CaptureInfo(filename))
644 638
645 @staticmethod 639 @staticmethod
646 def IsMovedInfo(info): 640 def IsMovedInfo(info):
647 """Determine if a file has been added through svn mv""" 641 """Determine if a file has been added through svn mv"""
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 if (file_status[0][0] in ('D', 'A', '!') or 976 if (file_status[0][0] in ('D', 'A', '!') or
983 not file_status[0][1:].isspace()): 977 not file_status[0][1:].isspace()):
984 # Added, deleted file requires manual intervention and require calling 978 # Added, deleted file requires manual intervention and require calling
985 # revert, like for properties. 979 # revert, like for properties.
986 try: 980 try:
987 SVN.Capture(['revert', file_status[1]], cwd=repo_root) 981 SVN.Capture(['revert', file_status[1]], cwd=repo_root)
988 except gclient_utils.CheckCallError: 982 except gclient_utils.CheckCallError:
989 if not os.path.exists(file_path): 983 if not os.path.exists(file_path):
990 continue 984 continue
991 raise 985 raise
OLDNEW
« rietveld.py ('K') | « rietveld.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698