| Index: revert.py
|
| diff --git a/revert.py b/revert.py
|
| index 1bc7421d2c90bd8e74c08dfcc9d56d5207f23766..19d924e2c1e5221247f767047a2bf5c0f9a45801 100755
|
| --- a/revert.py
|
| +++ b/revert.py
|
| @@ -24,32 +24,6 @@ class OutsideOfCheckout(exceptions.Exception):
|
| pass
|
|
|
|
|
| -def getTexts(nodelist):
|
| - """Return a list of texts in the children of a list of DOM nodes."""
|
| - rc = []
|
| - for node in nodelist:
|
| - if node.nodeType == node.TEXT_NODE:
|
| - rc.append(node.data)
|
| - else:
|
| - rc.extend(getTexts(node.childNodes))
|
| - return rc
|
| -
|
| -
|
| -def RunShellXML(command, print_output=False, keys=None):
|
| - output = gcl.RunShell(command, print_output)
|
| - try:
|
| - dom = xml.dom.minidom.parseString(output)
|
| - if not keys:
|
| - return dom
|
| - result = {}
|
| - for key in keys:
|
| - result[key] = getTexts(dom.getElementsByTagName(key))
|
| - except xml.parsers.expat.ExpatError:
|
| - print "Failed to parse output:\n%s" % output
|
| - raise
|
| - return result
|
| -
|
| -
|
| def UniqueFast(list):
|
| list = [item for item in set(list)]
|
| list.sort()
|
| @@ -58,9 +32,9 @@ def UniqueFast(list):
|
|
|
| def GetRepoBase():
|
| """Returns the repository base of the root local checkout."""
|
| - xml_data = RunShellXML(['svn', 'info', '.', '--xml'], keys=['root', 'url'])
|
| - root = xml_data['root'][0]
|
| - url = xml_data['url'][0]
|
| + info = gclient.CaptureSVNInfo('.')
|
| + root = info['Repository Root']
|
| + url = info['URL']
|
| if not root or not url:
|
| raise exceptions.Exception("I'm confused by your checkout")
|
| if not url.startswith(root):
|
| @@ -68,6 +42,38 @@ def GetRepoBase():
|
| return url[len(root):] + '/'
|
|
|
|
|
| +def CaptureSVNLog(args):
|
| + command = ['log', '--xml']
|
| + if args:
|
| + command += args
|
| + output = gclient.CaptureSVN(command)
|
| + dom = gclient.ParseXML(output)
|
| + entries = []
|
| + if dom:
|
| + # /log/logentry/
|
| + # @revision
|
| + # author|date
|
| + # paths/
|
| + # path (@kind&@action)
|
| + for node in dom.getElementsByTagName('logentry'):
|
| + paths = []
|
| + for path in node.getElementsByTagName('path'):
|
| + item = {
|
| + 'kind': path.getAttribute('kind'),
|
| + 'action': path.getAttribute('action'),
|
| + 'path': path.firstChild.nodeValue,
|
| + }
|
| + paths.append(item)
|
| + entry = {
|
| + 'revision': int(node.getAttribute('revision')),
|
| + 'author': gclient.GetNamedNodeText(node, 'author'),
|
| + 'date': gclient.GetNamedNodeText(node, 'date'),
|
| + 'paths': paths,
|
| + }
|
| + entries.append(entry)
|
| + return entries
|
| +
|
| +
|
| def Revert(revisions, force=False, commit=True, send_email=True, message=None,
|
| reviewers=None):
|
| """Reverts many revisions in one change list.
|
| @@ -91,20 +97,23 @@ def Revert(revisions, force=False, commit=True, send_email=True, message=None,
|
| revisions_string = ",".join([str(rev) for rev in revisions])
|
| revisions_string_rev = ",".join([str(-rev) for rev in revisions])
|
|
|
| - repo_base = GetRepoBase()
|
| - files = []
|
| - blames = []
|
| # Get all the modified files by the revision. We'll use this list to optimize
|
| # the svn merge.
|
| + logs = []
|
| for revision in revisions:
|
| - log = RunShellXML(["svn", "log", "-r", str(revision), "-v", "--xml"],
|
| - keys=['path', 'author'])
|
| - for file in log['path']:
|
| + logs.extend(CaptureSVNLog(["-r", str(revision), "-v"]))
|
| +
|
| + files = []
|
| + blames = []
|
| + repo_base = GetRepoBase()
|
| + for log in logs:
|
| + for file in log['paths']:
|
| + file_name = file['path']
|
| # Remove the /trunk/src/ part. The + 1 is for the last slash.
|
| - if not file.startswith(repo_base):
|
| - raise OutsideOfCheckout(file)
|
| - files.append(file[len(repo_base):])
|
| - blames.extend(log['author'])
|
| + if not file_name.startswith(repo_base):
|
| + raise OutsideOfCheckout(file_name)
|
| + files.append(file_name[len(repo_base):])
|
| + blames.append(log['author'])
|
|
|
| # On Windows, we need to fix the slashes once they got the url part removed.
|
| if sys.platform == 'win32':
|
| @@ -178,7 +187,6 @@ def Revert(revisions, force=False, commit=True, send_email=True, message=None,
|
| print 'svn up . -N failed in %s/.' % root
|
| return retcode
|
|
|
| - # TODO(maruel): BUG WITH ONLY ONE FILE.
|
| command = ["svn", "merge", "-c", revisions_string_rev]
|
| command.extend(file_list)
|
| (output, retcode) = gcl.RunShellWithReturnCode(command, print_output=True)
|
|
|