[PATCH v3] Change test suite to read file properties in XML format
Michael Haggerty <[email protected]>
| Newsgroups | gmane.comp.version-control.subversion.cvs2svn.devel |
|---|---|
| Message-ID | <[email protected]> |
Thanks, everybody, for the feedback.
James Abbatiello wrote:
> Sorry, it still doesn't work.
>>>> svntest.tree.get_props(["svntest"])
> {u'svntest': {u'svn:ignore': u'*.pyc\r\n*.o\r\n*~\r\n.*~\r\n\r\n'}}
>
> You do the folding at the top of the function. As you noted,
> wait_on_pipe() already does basically the same thing so that by the
> time the strings get to you they end with " \n". And rstrip isn't
> going to match against encoded XML entities. You're either going to
> have to match against " \n" at the end of the line (ick) or wait
> until after the XML parser has had a shot at it and adjust the line
> endings then.
Yes, of course you are right again.
This time I hand-tested against the output that you listed in your
previous email, and it seems to work. Third time's the charm?
Julian Foad wrote:
> Please state the main goal of making this part of the test suite
> compatible with the output of pre-1.6 svn, and the cvs2svn project's
> interest in this. And this change doesn't really make it shorter if you
> ignore the blank lines.
Suggestion incorporated.
Hyrum K. Wright wrote:
>> I don't think there is anything precluding the use of "svn proplist
>> > --xml" for svntest's property-checking functions.
>
> Julian Foad wrote
> Nor do I, just as long as we make sure to still test the "standard"
> output somewhere in the testsuite.
I just intentionally broke the code for "svn proplist -v" (without
--xml) and several test cases in prop_test.py broke. So there is at
least some level of testing aside from tree.get_props().
David Glasser wrote:
> The Python versions we support ship with an XML parser, right?
The xml.dom.minidom parser (which I'm using) was added in Python 2.0.
Michael
[[[
Read svn properties in XML rather than text format in test suite.
This makes the routine more robust to strange property values. It also
makes it immune to changes in the text output format, as happened
between svn 1.5 and 1.6. (This is useful for the cvs2svn project,
which uses the svntest infrastructure but doesn't want to care what
version of svn the user has installed.)
* subversion/tests/cmdline/svntest/tree.py
(get_props): Read svn properties via "svn proplist -v" using the
"--xml" option.
]]]
------------------------------------------------------
http://cvs2svn.tigris.org/ds/viewMessage.do?dsForumId=1667&dsMessageId=2376240
To unsubscribe from this discussion, e-mail: [[email protected]].
proplist-xml-3.diff
(text/x-diff, 3.5 KB)
Index: subversion/tests/cmdline/svntest/tree.py
===================================================================
--- subversion/tests/cmdline/svntest/tree.py (revision 38480)
+++ subversion/tests/cmdline/svntest/tree.py (working copy)
@@ -32,6 +32,8 @@
else:
# Python <3.0
from StringIO import StringIO
+from xml.dom.minidom import parseString
+import base64
import svntest
@@ -487,6 +489,7 @@
return root_node
+eol_re = re.compile(r'(\r\n|\r)')
# helper for build_tree_from_wc()
def get_props(paths):
@@ -499,47 +502,47 @@
# respecting the black-box paradigm.
files = {}
- filename = None
exit_code, output, errput = svntest.main.run_svn(1,
"proplist",
"--verbose",
+ "--xml",
*paths)
- properties_on_re = re.compile("^Properties on '(.+)':$")
+ output = (line for line in output if not line.startswith('DBG:'))
+ dom = parseString(''.join(output))
+ target_nodes = dom.getElementsByTagName('target')
+ for target_node in target_nodes:
+ filename = target_node.attributes['path'].nodeValue
+ file_props = {}
+ for property_node in target_node.getElementsByTagName('property'):
+ name = property_node.attributes['name'].nodeValue
+ if property_node.hasChildNodes():
+ text_node = property_node.firstChild
+ value = text_node.nodeValue
+ else:
+ value = ''
+ try:
+ encoding = property_node.attributes['encoding'].nodeValue
+ if encoding == 'base64':
+ value = base64.b64decode(value)
+ else:
+ raise Exception("Unknown encoding '%s' for file '%s' property '%s'"
+ % (encoding, filename, name,))
+ except KeyError:
+ pass
+ # If the property value contained a CR, or if under Windows an
+ # "svn:*" property contains a newline, then the XML output
+ # contains a CR character XML-encoded as ' '. The XML
+ # parser converts it back into a CR character. So again convert
+ # all end-of-line variants into a single LF:
+ value = eol_re.sub('\n', value)
+ file_props[name] = value
+ files[filename] = file_props
- # Parse the output
- for line in output:
- if line.startswith('DBG:'):
- continue
- line = line.rstrip('\r\n') # ignore stdout's EOL sequence
+ dom.unlink()
+ return files
- match = properties_on_re.match(line)
- if match:
- filename = match.group(1)
- elif line.startswith(' '):
- # It's (part of) the value (strip the indentation)
- if filename is None:
- raise Exception("Missing 'Properties on' line: '"+line+"'")
- files.setdefault(filename, {})[name] += line[4:] + '\n'
-
- elif line.startswith(' '):
- # It's the name
- name = line[2:] # strip the indentation
- if filename is None:
- raise Exception("Missing 'Properties on' line: '"+line+"'")
- files.setdefault(filename, {})[name] = ''
-
- else:
- raise Exception("Malformed line from proplist: '"+line+"'")
-
- # Strip, from each property value, the final new-line that we added
- for filename in files:
- for name in files[filename]:
- files[filename][name] = files[filename][name][:-1]
-
- return files
-
### ridiculous function. callers should do this one line themselves.
def get_text(path):
"Return a string with the textual contents of a file at PATH."