diff options
32 files changed, 1528 insertions, 277 deletions
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 345ec8ae..31700648 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -217,7 +217,7 @@ class egg_info(Command): @staticmethod def get_svn_revision(): - return str(svn_utils.parse_revision(os.curdir)) + return str(svn_utils.SvnInfo.load(os.curdir).get_revision()) diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 5cc2139b..e1112ff9 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -8,73 +8,58 @@ from setuptools import svn_utils READMES = ('README', 'README.rst', 'README.txt') -entities = [ - ("<","<"), (">", ">"), (""", '"'), ("'", "'"), - ("&", "&") -] -def unescape(data): - for old,new in entities: - data = data.replace(old,new) - return data +def walk_revctrl(dirname=''): + """Find all files under revision control""" + for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): + for item in ep.load()(dirname): + yield item + + +#TODO will need test case +class re_finder(object): -def re_finder(pattern, postproc=None): - def find(dirname, filename): + def __init__(self, path, pattern, postproc=None): + self.pattern = pattern + self.postproc = postproc + self.path = convert_path(path) + + def _finder(self, dirname, filename): f = open(filename,'rU') - data = f.read() - f.close() - for match in pattern.finditer(data): + try: + data = f.read() + finally: + f.close() + for match in self.pattern.finditer(data): path = match.group(1) if postproc: + #postproc used to be used when the svn finder + #was an re_finder for calling unescape path = postproc(path) - yield joinpath(dirname,path) - return find - -def joinpath(prefix,suffix): - if not prefix: - return suffix - return os.path.join(prefix,suffix) - - - + yield svn_utils.joinpath(dirname,path) + def __call__(self, dirname=''): + path = svn_utils.joinpath(dirname, self.path) - - - - -def walk_revctrl(dirname=''): - """Find all files under revision control""" - for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): - for item in ep.load()(dirname): - yield item - -def _default_revctrl(dirname=''): - for path, finder in finders: - path = joinpath(dirname,path) if os.path.isfile(path): - for path in finder(dirname,path): + for path in self._finder(dirname,path): if os.path.isfile(path): yield path elif os.path.isdir(path): - for item in _default_revctrl(path): + for item in self.find(path): yield item -def entries_externals_finder(dirname, filename): - for record in svn_utils.parse_dir_entries(dirname): - yield joinpath(dirname, record) - - for name in svn_utils.parse_externals(dirname): - yield joinpath(dirname, name) +def _default_revctrl(dirname=''): + 'Primary svn_cvs entry point' + for finder in finders: + for item in finder(dirname): + yield item finders = [ - (convert_path('CVS/Entries'), - re_finder(re.compile(r"^\w?/([^/]+)/", re.M))), - #combined externals due to common interface - #combined externals and enteries due to lack of dir_props in 1.7 - (convert_path('.svn/entries'), entries_externals_finder), + re_finder('CVS/Entries', re.compile(r"^\w?/([^/]+)/", re.M)), + svn_utils.svn_finder, ] @@ -88,6 +73,7 @@ finders = [ + class sdist(_sdist): """Smart sdist that finds anything supported by revision control""" diff --git a/setuptools/compat.py b/setuptools/compat.py index e2f64de2..94fe23e9 100644 --- a/setuptools/compat.py +++ b/setuptools/compat.py @@ -26,6 +26,7 @@ if sys.version_info[0] < 3: reduce = reduce unichr = unichr unicode = unicode + bytes = str from urllib import url2pathname import urllib2 from urllib2 import urlopen, HTTPError, URLError, unquote, splituser @@ -69,6 +70,7 @@ else: from functools import reduce unichr = chr unicode = str + bytes = bytes from urllib.error import HTTPError, URLError import urllib.request as urllib2 from urllib.request import urlopen, url2pathname diff --git a/setuptools/svn_utils.py b/setuptools/svn_utils.py index a4c53f15..09aa5e25 100644 --- a/setuptools/svn_utils.py +++ b/setuptools/svn_utils.py @@ -1,31 +1,22 @@ import os
import re
import sys
-import codecs
from distutils import log
import xml.dom.pulldom
+import shlex
+import locale
+import unicodedata
+from setuptools.compat import unicode, bytes
try:
import urlparse
except ImportError:
import urllib.parse as urlparse
-#requires python >= 2.4
from subprocess import Popen as _Popen, PIPE as _PIPE
-#NOTE: Use of the command line options
-# require SVN 1.3 or newer (December 2005)
-# and SVN 1.3 hsan't been supported by the
-# developers since mid 2008.
-
-
-#svnversion return values (previous implementations return max revision)
-# 4123:4168 mixed revision working copy
-# 4168M modified working copy
-# 4123S switched working copy
-# 4123:4168MS mixed revision, modified, switched working copy
-_SVN_VER_RE = re.compile(r'(?:([\-0-9]+):)?(\d+)([a-z]*)\s*$', re.I)
-
+#NOTE: Use of the command line options require SVN 1.3 or newer (December 2005)
+# and SVN 1.3 hasn't been supported by the developers since mid 2008.
#subprocess is called several times with shell=(sys.platform=='win32')
#see the follow for more information:
@@ -33,27 +24,20 @@ _SVN_VER_RE = re.compile(r'(?:([\-0-9]+):)?(\d+)([a-z]*)\s*$', re.I) # http://stackoverflow.com/questions/5658622/
# python-subprocess-popen-environment-path
def _run_command(args, stdout=_PIPE, stderr=_PIPE):
- #regarding the shell argument, see: http://bugs.python.org/issue8557
- try:
- proc = _Popen(args, stdout=stdout, stderr=stderr,
- shell=(sys.platform == 'win32'))
-
- data = proc.communicate()[0]
- except OSError:
- return 1, ''
-
- #TODO: this is probably NOT always utf-8
- try:
- data = unicode(data, encoding='utf-8')
- except NameError:
- data = str(data, encoding='utf-8')
+ #regarding the shell argument, see: http://bugs.python.org/issue8557
+ try:
+ args = [fsdecode(x) for x in args]
+ proc = _Popen(args, stdout=stdout, stderr=stderr,
+ shell=(sys.platform == 'win32'))
- #communciate calls wait()
- return proc.returncode, data
+ data = proc.communicate()[0]
+ except OSError:
+ return 1, ''
+ data = consoledecode(data)
-def _get_entry_name(entry):
- return entry.getAttribute('path')
+ #communciate calls wait()
+ return proc.returncode, data
def _get_entry_schedule(entry):
@@ -63,105 +47,283 @@ def _get_entry_schedule(entry): if t.nodeType == t.TEXT_NODE])
-def parse_revision(path):
- code, data = _run_command(['svnversion', '-c', path])
+def _get_target_property(target):
+ property_text = target.getElementsByTagName('property')[0]
+ return "".join([t.nodeValue
+ for t in property_text.childNodes
+ if t.nodeType == t.TEXT_NODE])
- if code:
- log.warn("svnversion failed")
- return 0
+
+def _get_xml_data(decoded_str):
+ if sys.version_info < (3, 0):
+ #old versions want an encoded string
+ data = decoded_str.encode('utf-8')
else:
- log.warn('Version: %s' % data.strip())
+ data = decoded_str
+ return data
- parsed = _SVN_VER_RE.match(data)
- if parsed:
- try:
- #No max needed this command summarizes working copy since 1.0
- return int(parsed.group(2))
- except ValueError:
- #This should only happen if the revision is WAY too big.
- pass
- return 0
-
-#TODO: Need to do this with the -R because only root has .svn in 1.7.x
-def parse_dir_entries(path):
- code, data = _run_command(['svn', 'info',
- '--depth', 'immediates', '--xml', path])
-
- if code:
- log.warn("svn info failed")
- return []
- data = codecs.encode(data, 'UTF-8')
+def joinpath(prefix, suffix):
+ if not prefix or prefix == '.':
+ return suffix
+ return os.path.join(prefix, suffix)
+
+
+def fsencode(path):
+ "Path must be unicode or in file system encoding already"
+ encoding = sys.getfilesystemencoding()
+
+ if isinstance(path, unicode):
+ path = path.encode()
+ elif not isinstance(path, bytes):
+ raise TypeError('%s is not a string or byte type'
+ % type(path).__name__)
+
+ #getfilessystemencoding doesn't have the mac-roman issue
+ if encoding == 'utf-8' and sys.platform == 'darwin':
+ path = path.decode('utf-8')
+ path = unicodedata.normalize('NFD', path)
+ path = path.encode('utf-8')
- doc = xml.dom.pulldom.parseString(data)
+ return path
+
+def fsdecode(path):
+ "Path must be unicode or in file system encoding already"
+ encoding = sys.getfilesystemencoding()
+ if isinstance(path, bytes):
+ path = path.decode(encoding)
+ elif not isinstance(path, unicode):
+ raise TypeError('%s is not a byte type'
+ % type(path).__name__)
+
+ return unicodedata.normalize('NFC', path)
+
+def consoledecode(text):
+ encoding = locale.getpreferredencoding()
+ return text.decode(encoding)
+
+
+def parse_dir_entries(decoded_str):
+ '''Parse the entries from a recursive info xml'''
+ doc = xml.dom.pulldom.parseString(_get_xml_data(decoded_str))
entries = list()
+
for event, node in doc:
if event == 'START_ELEMENT' and node.nodeName == 'entry':
doc.expandNode(node)
- entries.append(node)
-
- if entries:
- return [
- _get_entry_name(element)
- for element in entries[1:]
- if _get_entry_schedule(element).lower() != 'deleted'
- ]
- else:
- return []
+ if not _get_entry_schedule(node).startswith('delete'):
+ entries.append((node.getAttribute('path'),
+ node.getAttribute('kind')))
+ return entries[1:] # do not want the root directory
-#--xml wasn't supported until 1.5.x need to do -R
-#TODO: -R looks like directories are seperated by blank lines
-# with dir - prepened to first directory
-# what about directories with spaces?
-# put quotes around them
-# what about the URL's?
-# same
-# convert to UTF-8 and use csv
-# delimiter = space
-#
-#-R without --xml parses a bit funny
-def parse_externals(path):
- try:
- code, lines = _run_command(['svn',
- 'propget', 'svn:externals', path])
- if code:
- log.warn("svn propget failed")
- return []
+def parse_externals_xml(decoded_str, prefix=''):
+ '''Parse a propget svn:externals xml'''
+ prefix = os.path.normpath(prefix)
+
+ doc = xml.dom.pulldom.parseString(_get_xml_data(decoded_str))
+ externals = list()
+
+ for event, node in doc:
+ if event == 'START_ELEMENT' and node.nodeName == 'target':
+ doc.expandNode(node)
+ path = os.path.normpath(node.getAttribute('path'))
+ if os.path.normcase(path).startswith(prefix):
+ path = path[len(prefix)+1:]
- lines = [line for line in lines.splitlines() if line]
- except ValueError:
- lines = []
+ data = _get_target_property(node)
+ for external in parse_external_prop(data):
+ externals.append(joinpath(path, external))
+ return externals # do not want the root directory
+
+
+def parse_external_prop(lines):
+ """
+ Parse the value of a retrieved svn:externals entry.
+
+ possible token setups (with quotng and backscaping in laters versions)
+ URL[@#] EXT_FOLDERNAME
+ [-r#] URL EXT_FOLDERNAME
+ EXT_FOLDERNAME [-r#] URL
+ """
externals = []
- for line in lines:
- line = line.split()
+ for line in lines.splitlines():
+ line = line.lstrip() #there might be a "\ "
if not line:
continue
+ if sys.version_info < (3, 0):
+ #shlex handles NULLs just fine and shlex in 2.7 tries to encode
+ #as ascii automatiically
+ line = line.encode('utf-8')
+ line = shlex.split(line)
+ if sys.version_info < (3, 0):
+ line = [x.decode('utf-8') for x in line]
+
+ #EXT_FOLDERNAME is either the first or last depending on where
+ #the URL falls
if urlparse.urlsplit(line[-1])[0]:
- externals.append(line[0])
+ external = line[0]
else:
- externals.append(line[-1])
+ external = line[-1]
+
+ externals.append(os.path.normpath(external))
return externals
-def get_svn_tool_version():
- _, data = _run_command(['svn', '--version', '--quiet'])
- if data:
- return data.strip()
- else:
- return ''
+class SvnInfo(object):
+ '''
+ Generic svn_info object. No has little knowledge of how to extract
+ information. Use cls.load to instatiate according svn version.
-if __name__ == '__main__':
- def entries_externals_finder(dirname):
- for record in parse_dir_entries(dirname):
- yield os.path.join(dirname, record)
+ Paths are not filesystem encoded.
+ '''
- for name in parse_externals(dirname):
- yield os.path.join(dirname, name)
+ @staticmethod
+ def get_svn_version():
+ code, data = _run_command(['svn', '--version', '--quiet'])
+ if code == 0 and data:
+ return unicode(data).strip()
+ else:
+ return unicode('')
+
+ #svnversion return values (previous implementations return max revision)
+ # 4123:4168 mixed revision working copy
+ # 4168M modified working copy
+ # 4123S switched working copy
+ # 4123:4168MS mixed revision, modified, switched working copy
+ revision_re = re.compile(r'(?:([\-0-9]+):)?(\d+)([a-z]*)\s*$', re.I)
+
+ @classmethod
+ def load(cls, dirname=''):
+ code, data = _run_command(['svn', 'info', os.path.normpath(dirname)])
+ svn_version = tuple(cls.get_svn_version().split('.'))
+ base_svn_version = tuple(int(x) for x in svn_version[:2])
+ if code and base_svn_version:
+ #Not an SVN repository or compatible one
+ return SvnInfo(dirname)
+ elif base_svn_version < (1, 3):
+ log.warn('Insufficent version of SVN found')
+ return SvnInfo(dirname)
+ elif base_svn_version < (1, 5):
+ return Svn13Info(dirname)
+ else:
+ return Svn15Info(dirname)
+
+ def __init__(self, path=''):
+ self.path = path
+ self._entries = None
+ self._externals = None
+
+ def get_revision(self):
+ 'Retrieve the directory revision informatino using svnversion'
+ code, data = _run_command(['svnversion', '-c', self.path])
+ if code:
+ log.warn("svnversion failed")
+ return 0
- for name in entries_externals_finder(sys.argv[1]):
+ parsed = self.revision_re.match(data)
+ if parsed:
+ return int(parsed.group(2))
+ else:
+ return 0
+
+ @property
+ def entries(self):
+ if self._entries is None:
+ self._entries = self.get_entries()
+ return self._entries
+
+ @property
+ def externals(self):
+ if self._externals is None:
+ self._externals = self.get_externals()
+ return self._externals
+
+ def iter_externals(self):
+ '''
+ Iterate over the svn:external references in the repository path.
+ '''
+ for item in self.externals:
+ yield item
+
+ def iter_files(self):
+ '''
+ Iterate over the non-deleted file entries in the repository path
+ '''
+ for item, kind in self.entries:
+ if kind.lower()=='file':
+ yield item
+
+ def iter_dirs(self, include_root=True):
+ '''
+ Iterate over the non-deleted file entries in the repository path
+ '''
+ if include_root:
+ yield self.path
+ for item, kind in self.entries:
+ if kind.lower()=='dir':
+ yield item
+
+ def get_entries(self):
+ return []
+
+ def get_externals(self):
+ return []
+
+class Svn13Info(SvnInfo):
+ def get_entries(self):
+ code, data = _run_command(['svn', 'info', '-R', '--xml', self.path])
+
+ if code:
+ log.debug("svn info failed")
+ return []
+
+ return parse_dir_entries(data)
+
+ def get_externals(self):
+ #Previous to 1.5 --xml was not supported for svn propget and the -R
+ #output format breaks the shlex compatible semantics.
+ cmd = ['svn', 'propget', 'svn:externals']
+ result = []
+ for folder in self.iter_dirs():
+ code, lines = _run_command(cmd + [folder])
+ if code != 0:
+ log.warn("svn propget failed")
+ return []
+ for external in parse_external_prop(lines):
+ if folder:
+ external = os.path.join(folder, external)
+ result.append(os.path.normpath(external))
+
+ return result
+
+
+class Svn15Info(Svn13Info):
+ def get_externals(self):
+ cmd = ['svn', 'propget', 'svn:externals', self.path, '-R', '--xml']
+ code, lines = _run_command(cmd)
+ if code:
+ log.debug("svn propget failed")
+ return []
+ return parse_externals_xml(lines, prefix=os.path.abspath(self.path))
+
+
+def svn_finder(dirname=''):
+ #combined externals due to common interface
+ #combined externals and entries due to lack of dir_props in 1.7
+ info = SvnInfo.load(dirname)
+ for path in info.iter_files():
+ yield fsencode(path)
+
+ for path in info.iter_externals():
+ sub_info = SvnInfo.load(path)
+ for sub_path in sub_info.iter_files():
+ yield fsencode(sub_path)
+
+if __name__ == '__main__':
+ for name in svn_finder(sys.argv[1]):
print(name)
\ No newline at end of file diff --git a/setuptools/tests/environment.py b/setuptools/tests/environment.py new file mode 100644 index 00000000..7c754b8e --- /dev/null +++ b/setuptools/tests/environment.py @@ -0,0 +1,104 @@ +import os +import zipfile +import sys +import tempfile +import unittest +import shutil +import stat + + +def _extract(self, member, path=None, pwd=None): + """for zipfile py2.5 borrowed from cpython""" + if not isinstance(member, zipfile.ZipInfo): + member = self.getinfo(member) + + if path is None: + path = os.getcwd() + + return _extract_member(self, member, path, pwd) + + +def _extract_from_zip(self, name, dest_path): + dest_file = open(dest_path, 'wb') + try: + dest_file.write(self.read(name)) + finally: + dest_file.close() + +def _extract_member(self, member, targetpath, pwd): + """for zipfile py2.5 borrowed from cpython""" + # build the destination pathname, replacing + # forward slashes to platform specific separators. + # Strip trailing path separator, unless it represents the root. + if (targetpath[-1:] in (os.path.sep, os.path.altsep) + and len(os.path.splitdrive(targetpath)[1]) > 1): + targetpath = targetpath[:-1] + + # don't include leading "/" from file name if present + if member.filename[0] == '/': + targetpath = os.path.join(targetpath, member.filename[1:]) + else: + targetpath = os.path.join(targetpath, member.filename) + + targetpath = os.path.normpath(targetpath) + + # Create all upper directories if necessary. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + os.makedirs(upperdirs) + + if member.filename[-1] == '/': + if not os.path.isdir(targetpath): + os.mkdir(targetpath) + return targetpath + + _extract_from_zip(self, member.filename, targetpath) + + return targetpath + + +def _remove_dir(target): + + #on windows this seems to a problem + for dir_path, dirs, files in os.walk(target): + os.chmod(dir_path, stat.S_IWRITE) + for filename in files: + os.chmod(os.path.join(dir_path, filename), stat.S_IWRITE) + shutil.rmtree(target) + + +class ZippedEnvironment(unittest.TestCase): + + datafile = None + dataname = None + old_cwd = None + + def setUp(self): + if not os.path.isfile(self.datafile): + self.old_cwd = None + return + + self.old_cwd = os.getcwd() + + self.temp_dir = tempfile.mkdtemp() + zip_file, source, target = [None, None, None] + try: + zip_file = zipfile.ZipFile(self.datafile) + for files in zip_file.namelist(): + _extract(zip_file, files, self.temp_dir) + finally: + if zip_file: + zip_file.close() + del zip_file + + os.chdir(os.path.join(self.temp_dir, self.dataname)) + + def tearDown(self): + try: + if self.old_cwd: + os.chdir(self.old_cwd) + _remove_dir(self.temp_dir) + except OSError: + #sigh? + pass + diff --git a/setuptools/tests/svn_data/svn13_example.zip b/setuptools/tests/svn_data/svn13_example.zip Binary files differnew file mode 100644 index 00000000..d85fb84f --- /dev/null +++ b/setuptools/tests/svn_data/svn13_example.zip diff --git a/setuptools/tests/svn_data/svn13_ext_list.txt b/setuptools/tests/svn_data/svn13_ext_list.txt new file mode 100644 index 00000000..0bb0f438 --- /dev/null +++ b/setuptools/tests/svn_data/svn13_ext_list.txt @@ -0,0 +1,3 @@ +third_party3 file:///C:/development/svn_example/repos/svn13/extra1
+third_party2 -r3 file:///C:/development/svn_example/repos/svn13/extra1
+third_party -r1 file:///C:/development/svn_example/repos/svn13/extra1
diff --git a/setuptools/tests/svn_data/svn13_ext_list.xml b/setuptools/tests/svn_data/svn13_ext_list.xml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/setuptools/tests/svn_data/svn13_ext_list.xml diff --git a/setuptools/tests/svn_data/svn13_info.xml b/setuptools/tests/svn_data/svn13_info.xml new file mode 100644 index 00000000..5c96520a --- /dev/null +++ b/setuptools/tests/svn_data/svn13_info.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?>
+<info>
+<entry
+ kind="dir"
+ path="svn13_example"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<prop-updated>2013-07-13T15:33:23.187500Z</prop-updated>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:33:28.359375Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn13_example\a file"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main/a%20file</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:33:21.109375Z</text-updated>
+<checksum>a6166e5e98a5a503089cde9bc8031293</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:33:21.312500Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn13_example\to_delete"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main/to_delete</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>delete</schedule>
+<text-updated>2013-07-13T15:33:28.140625Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:33:28.359375Z</date>
+</commit>
+</entry>
+<entry
+ kind="dir"
+ path="svn13_example\folder"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main/folder</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<prop-updated>2013-07-13T15:33:26.187500Z</prop-updated>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:33:26.312500Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn13_example\folder\quest.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main/folder/quest.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:33:20.109375Z</text-updated>
+<checksum>795240c6a830c14f83961e57e07dad12</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:33:20.312500Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn13_example\folder\lalala.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn13/main/folder/lalala.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn13/main</root>
+<uuid>d2996769-47b0-9946-b618-da1aa3eceda3</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:33:19.375000Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:33:19.609375Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/svn_data/svn14_example.zip b/setuptools/tests/svn_data/svn14_example.zip Binary files differnew file mode 100644 index 00000000..57093c0b --- /dev/null +++ b/setuptools/tests/svn_data/svn14_example.zip diff --git a/setuptools/tests/svn_data/svn14_ext_list.txt b/setuptools/tests/svn_data/svn14_ext_list.txt new file mode 100644 index 00000000..800a0965 --- /dev/null +++ b/setuptools/tests/svn_data/svn14_ext_list.txt @@ -0,0 +1,4 @@ +third_party3 file:///C:/development/svn_example/repos/svn13/extra1
+third_party2 -r3 file:///C:/development/svn_example/repos/svn13/extra1
+third_party -r1 file:///C:/development/svn_example/repos/svn13/extra1
+
diff --git a/setuptools/tests/svn_data/svn14_ext_list.xml b/setuptools/tests/svn_data/svn14_ext_list.xml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/setuptools/tests/svn_data/svn14_ext_list.xml diff --git a/setuptools/tests/svn_data/svn14_info.xml b/setuptools/tests/svn_data/svn14_info.xml new file mode 100644 index 00000000..a896a77f --- /dev/null +++ b/setuptools/tests/svn_data/svn14_info.xml @@ -0,0 +1,119 @@ +<?xml version="1.0"?>
+<info>
+<entry
+ kind="dir"
+ path="svn14_example"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:34:14.406250Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn14_example\a file"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main/a%20file</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:34:08.109375Z</text-updated>
+<checksum>a6166e5e98a5a503089cde9bc8031293</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:34:08.390625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn14_example\to_delete"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main/to_delete</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>delete</schedule>
+<text-updated>2013-07-13T15:34:14.125000Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:34:14.406250Z</date>
+</commit>
+</entry>
+<entry
+ kind="dir"
+ path="svn14_example\folder"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main/folder</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:34:12.390625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn14_example\folder\quest.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main/folder/quest.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:34:07.109375Z</text-updated>
+<checksum>795240c6a830c14f83961e57e07dad12</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:34:07.390625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn14_example\folder\lalala.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn14/main/folder/lalala.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn14/main</root>
+<uuid>c75942e5-8b7a-354d-b1cf-73dee23fa94f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<text-updated>2013-07-13T15:34:06.250000Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:34:06.531250Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/svn_data/svn15_example.zip b/setuptools/tests/svn_data/svn15_example.zip Binary files differnew file mode 100644 index 00000000..52a1d45b --- /dev/null +++ b/setuptools/tests/svn_data/svn15_example.zip diff --git a/setuptools/tests/svn_data/svn15_ext_list.txt b/setuptools/tests/svn_data/svn15_ext_list.txt new file mode 100644 index 00000000..75fde4e6 --- /dev/null +++ b/setuptools/tests/svn_data/svn15_ext_list.txt @@ -0,0 +1,4 @@ +third_party3 file:///C:/development/svn_example/repos/svn15/extra1
+-r3 file:///C:/development/svn_example/repos/svn15/extra1 third_party2
+file:///C:/development/svn_example/repos/svn15/extra1@r1 third_party
+
diff --git a/setuptools/tests/svn_data/svn15_ext_list.xml b/setuptools/tests/svn_data/svn15_ext_list.xml new file mode 100644 index 00000000..6950b3c5 --- /dev/null +++ b/setuptools/tests/svn_data/svn15_ext_list.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?>
+<properties>
+<target
+ path="C:/development/svn_example/svn15_example/folder">
+<property
+ name="svn:externals">third_party3 file:///C:/development/svn_example/repos/svn15/extra2
+-r3 file:///C:/development/svn_example/repos/svn15/extra2 third_party2
+file:///C:/development/svn_example/repos/svn15/extra2@r1 third_party大介
+</property>
+</target>
+<target
+ path="C:/development/svn_example/svn15_example">
+<property
+ name="svn:externals">third_party3 file:///C:/development/svn_example/repos/svn15/extra1
+-r3 file:///C:/development/svn_example/repos/svn15/extra1 third_party2
+file:///C:/development/svn_example/repos/svn15/extra1@r1 third_party大介
+</property>
+</target>
+</properties>
diff --git a/setuptools/tests/svn_data/svn15_info.xml b/setuptools/tests/svn_data/svn15_info.xml new file mode 100644 index 00000000..0b3550af --- /dev/null +++ b/setuptools/tests/svn_data/svn15_info.xml @@ -0,0 +1,125 @@ +<?xml version="1.0"?>
+<info>
+<entry
+ kind="dir"
+ path="svn15_example"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:34:49.562500Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn15_example\a file"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main/a%20file</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:34:43.109375Z</text-updated>
+<checksum>a6166e5e98a5a503089cde9bc8031293</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:34:43.484375Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn15_example\to_delete"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main/to_delete</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>delete</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:34:49.125000Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:34:49.562500Z</date>
+</commit>
+</entry>
+<entry
+ kind="dir"
+ path="svn15_example\folder"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main/folder</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:34:47.515625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn15_example\folder\quest.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main/folder/quest.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:34:42.109375Z</text-updated>
+<checksum>795240c6a830c14f83961e57e07dad12</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:34:42.484375Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn15_example\folder\lalala.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn15/main/folder/lalala.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn15/main</root>
+<uuid>4eab6983-54fe-384b-a282-9306f52d948f</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:34:41.375000Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:34:41.734375Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/svn_data/svn16_example.zip b/setuptools/tests/svn_data/svn16_example.zip Binary files differnew file mode 100644 index 00000000..e886b2af --- /dev/null +++ b/setuptools/tests/svn_data/svn16_example.zip diff --git a/setuptools/tests/svn_data/svn16_ext_list.txt b/setuptools/tests/svn_data/svn16_ext_list.txt new file mode 100644 index 00000000..3ca54893 --- /dev/null +++ b/setuptools/tests/svn_data/svn16_ext_list.txt @@ -0,0 +1,4 @@ +"third party3" file:///C:/development/svn_example/repos/svn16/extra1
+'third party3b' file:///C:/development/svn_example/repos/svn16/extra1
+-r3 file:///C:/development/svn_example/repos/svn16/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn16/extra1@r1 third_party
diff --git a/setuptools/tests/svn_data/svn16_ext_list.xml b/setuptools/tests/svn_data/svn16_ext_list.xml new file mode 100644 index 00000000..8ddaed0a --- /dev/null +++ b/setuptools/tests/svn_data/svn16_ext_list.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?>
+<properties>
+<target
+ path="C:/development/svn_example/svn16_example/folder">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn16/extra2
+-r3 file:///C:/development/svn_example/repos/svn16/extra2 third\ party2
+file:///C:/development/svn_example/repos/svn16/extra2@r1 third_party大介
+</property>
+</target>
+<target
+ path="C:/development/svn_example/svn16_example">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn16/extra1
+-r3 file:///C:/development/svn_example/repos/svn16/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn16/extra1@r1 third_party大介
+</property>
+</target>
+</properties>
diff --git a/setuptools/tests/svn_data/svn16_info.xml b/setuptools/tests/svn_data/svn16_info.xml new file mode 100644 index 00000000..745469c9 --- /dev/null +++ b/setuptools/tests/svn_data/svn16_info.xml @@ -0,0 +1,125 @@ +<?xml version="1.0"?>
+<info>
+<entry
+ kind="dir"
+ path="svn16_example"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:17.390625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn16_example\a file"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main/a%20file</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:14.578125Z</text-updated>
+<checksum>a6166e5e98a5a503089cde9bc8031293</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:35:14.906250Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn16_example\to_delete"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main/to_delete</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>delete</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:17.046875Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:17.390625Z</date>
+</commit>
+</entry>
+<entry
+ kind="dir"
+ path="svn16_example\folder"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main/folder</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:35:16.406250Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn16_example\folder\quest.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main/folder/quest.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:14.078125Z</text-updated>
+<checksum>795240c6a830c14f83961e57e07dad12</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:35:14.421875Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn16_example\folder\lalala.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn16/main/folder/lalala.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn16/main</root>
+<uuid>bd8d2cfc-1a74-de45-b166-262010c17c0a</uuid>
+</repository>
+<wc-info>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:12.171875Z</text-updated>
+<checksum>d41d8cd98f00b204e9800998ecf8427e</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:35:13.906250Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/svn_data/svn17_example.zip b/setuptools/tests/svn_data/svn17_example.zip Binary files differnew file mode 100644 index 00000000..ba0e8823 --- /dev/null +++ b/setuptools/tests/svn_data/svn17_example.zip diff --git a/setuptools/tests/svn_data/svn17_ext_list.txt b/setuptools/tests/svn_data/svn17_ext_list.txt new file mode 100644 index 00000000..a8b832a8 --- /dev/null +++ b/setuptools/tests/svn_data/svn17_ext_list.txt @@ -0,0 +1,4 @@ +"third party3" file:///C:/development/svn_example/repos/svn17/extra1
+'third party3b' file:///C:/development/svn_example/repos/svn17/extra1
+-r3 file:///C:/development/svn_example/repos/svn17/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn17/extra1@r1 third_party
diff --git a/setuptools/tests/svn_data/svn17_ext_list.xml b/setuptools/tests/svn_data/svn17_ext_list.xml new file mode 100644 index 00000000..2879bb65 --- /dev/null +++ b/setuptools/tests/svn_data/svn17_ext_list.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<properties>
+<target
+ path="C:/development/svn_example/svn17_example">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn16/extra1
+-r3 file:///C:/development/svn_example/repos/svn16/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn16/extra1@r1 third_party大介
+</property>
+</target>
+<target
+ path="C:/development/svn_example/svn17_example/folder">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn17/extra2
+-r3 file:///C:/development/svn_example/repos/svn17/extra2 third\ party2
+file:///C:/development/svn_example/repos/svn17/extra2@r1 third_party大介
+</property>
+</target>
+</properties>
diff --git a/setuptools/tests/svn_data/svn17_info.xml b/setuptools/tests/svn_data/svn17_info.xml new file mode 100644 index 00000000..6cffeffd --- /dev/null +++ b/setuptools/tests/svn_data/svn17_info.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<info>
+<entry
+ kind="dir"
+ path="svn17_example"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn17/main</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:36.171875Z</date>
+</commit>
+</entry>
+<entry
+ path="svn17_example\folder"
+ revision="6"
+ kind="dir">
+<url>file:///C:/development/svn_example/repos/svn17/main/folder</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:35:34.859375Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn17_example\folder\quest.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn17/main/folder/quest.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:32.812500Z</text-updated>
+<checksum>bc80eba9e7a10c0a571a4678c520bc9683f3bac2</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:35:33.109375Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn17_example\folder\lalala.txt"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn17/main/folder/lalala.txt</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:32.343750Z</text-updated>
+<checksum>da39a3ee5e6b4b0d3255bfef95601890afd80709</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:35:32.687500Z</date>
+</commit>
+</entry>
+<entry
+ path="svn17_example\a file"
+ revision="6"
+ kind="file">
+<url>file:///C:/development/svn_example/repos/svn17/main/a%20file</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:33.187500Z</text-updated>
+<checksum>43785ab4b1816b49f242990883292813cd4f486c</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:35:33.515625Z</date>
+</commit>
+</entry>
+<entry
+ path="svn17_example\to_delete"
+ revision="6"
+ kind="file">
+<url>file:///C:/development/svn_example/repos/svn17/main/to_delete</url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn17/main</root>
+<uuid>5ba45434-5197-164e-afab-81923f4744f5</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn17_example</wcroot-abspath>
+<schedule>delete</schedule>
+<depth>infinity</depth>
+<checksum>da39a3ee5e6b4b0d3255bfef95601890afd80709</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:36.171875Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/svn_data/svn18_example.zip b/setuptools/tests/svn_data/svn18_example.zip Binary files differnew file mode 100644 index 00000000..4362f8e9 --- /dev/null +++ b/setuptools/tests/svn_data/svn18_example.zip diff --git a/setuptools/tests/svn_data/svn18_ext_list.txt b/setuptools/tests/svn_data/svn18_ext_list.txt new file mode 100644 index 00000000..c90a5f11 --- /dev/null +++ b/setuptools/tests/svn_data/svn18_ext_list.txt @@ -0,0 +1,4 @@ +"third party3" file:///C:/development/svn_example/repos/svn18/extra1
+'third party3b' file:///C:/development/svn_example/repos/svn18/extra1
+-r3 file:///C:/development/svn_example/repos/svn18/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn18/extra1@r1 third_party
diff --git a/setuptools/tests/svn_data/svn18_ext_list.xml b/setuptools/tests/svn_data/svn18_ext_list.xml new file mode 100644 index 00000000..9b5e9e96 --- /dev/null +++ b/setuptools/tests/svn_data/svn18_ext_list.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<properties>
+<target
+ path="C:/development/svn_example/svn18_example">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn16/extra1
+-r3 file:///C:/development/svn_example/repos/svn16/extra1 third\ party2
+file:///C:/development/svn_example/repos/svn16/extra1@r1 third_party大介
+</property>
+</target>
+<target
+ path="C:/development/svn_example/svn18_example/folder">
+<property
+ name="svn:externals">"third party3" file:///C:/development/svn_example/repos/svn18/extra2
+-r3 file:///C:/development/svn_example/repos/svn18/extra2 third\ party2
+file:///C:/development/svn_example/repos/svn18/extra2@r1 third_party大介
+</property>
+</target>
+</properties>
diff --git a/setuptools/tests/svn_data/svn18_info.xml b/setuptools/tests/svn_data/svn18_info.xml new file mode 100644 index 00000000..7ca55995 --- /dev/null +++ b/setuptools/tests/svn_data/svn18_info.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<info>
+<entry
+ path="svn18_example"
+ revision="6"
+ kind="dir">
+<url>file:///C:/development/svn_example/repos/svn18/main</url>
+<relative-url>^/</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:57.796875Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn18_example\a file"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn18/main/a%20file</url>
+<relative-url>^/a%20file</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:54.906250Z</text-updated>
+<checksum>43785ab4b1816b49f242990883292813cd4f486c</checksum>
+</wc-info>
+<commit
+ revision="3">
+<author>ptt</author>
+<date>2013-07-13T15:35:55.265625Z</date>
+</commit>
+</entry>
+<entry
+ kind="file"
+ path="svn18_example\to_delete"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn18/main/to_delete</url>
+<relative-url>^/to_delete</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>delete</schedule>
+<depth>infinity</depth>
+<checksum>da39a3ee5e6b4b0d3255bfef95601890afd80709</checksum>
+</wc-info>
+<commit
+ revision="6">
+<author>ptt</author>
+<date>2013-07-13T15:35:57.796875Z</date>
+</commit>
+</entry>
+<entry
+ kind="dir"
+ path="svn18_example\folder"
+ revision="6">
+<url>file:///C:/development/svn_example/repos/svn18/main/folder</url>
+<relative-url>^/folder</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+</wc-info>
+<commit
+ revision="5">
+<author>ptt</author>
+<date>2013-07-13T15:35:56.750000Z</date>
+</commit>
+</entry>
+<entry
+ path="svn18_example\folder\quest.txt"
+ revision="6"
+ kind="file">
+<url>file:///C:/development/svn_example/repos/svn18/main/folder/quest.txt</url>
+<relative-url>^/folder/quest.txt</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:54.484375Z</text-updated>
+<checksum>bc80eba9e7a10c0a571a4678c520bc9683f3bac2</checksum>
+</wc-info>
+<commit
+ revision="2">
+<author>ptt</author>
+<date>2013-07-13T15:35:54.843750Z</date>
+</commit>
+</entry>
+<entry
+ path="svn18_example\folder\lalala.txt"
+ revision="6"
+ kind="file">
+<url>file:///C:/development/svn_example/repos/svn18/main/folder/lalala.txt</url>
+<relative-url>^/folder/lalala.txt</relative-url>
+<repository>
+<root>file:///C:/development/svn_example/repos/svn18/main</root>
+<uuid>3c5e3929-c92b-7045-9ba9-5e65d3dd1ee9</uuid>
+</repository>
+<wc-info>
+<wcroot-abspath>C:/development/svn_example/svn18_example</wcroot-abspath>
+<schedule>normal</schedule>
+<depth>infinity</depth>
+<text-updated>2013-07-13T15:35:54.015625Z</text-updated>
+<checksum>da39a3ee5e6b4b0d3255bfef95601890afd80709</checksum>
+</wc-info>
+<commit
+ revision="1">
+<author>ptt</author>
+<date>2013-07-13T15:35:54.375000Z</date>
+</commit>
+</entry>
+</info>
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index f26a1f51..95667b69 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -1,10 +1,12 @@ import os +import sys import tempfile import shutil import unittest import pkg_resources from setuptools.command import egg_info +from setuptools import svn_utils ENTRIES_V10 = pkg_resources.resource_string(__name__, 'entries-v10') "An entries file generated with svn 1.6.17 against the legacy Setuptools repo" @@ -31,6 +33,17 @@ class TestEggInfo(unittest.TestCase): def test_version_10_format(self): """ """ + #keeping this set for 1.6 is a good check on the get_svn_revision + #to ensure I return using svnversion what would had been returned + version_str = svn_utils.SvnInfo.get_svn_version() + version = [int(x) for x in version_str.split('.')[:2]] + if version != [1,6]: + if hasattr(self, 'skipTest'): + self.skipTest('') + else: + sys.stderr.write('\n Skipping due to SVN Version\n') + return + self._write_entries(ENTRIES_V10) rev = egg_info.egg_info.get_svn_revision() self.assertEqual(rev, '89000') diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 438f7ced..8d6aff19 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -8,12 +8,14 @@ import sys import tempfile import unittest import unicodedata +from setuptools.tests import environment from setuptools.compat import StringIO, unicode -from setuptools.command.sdist import sdist +from setuptools.command.sdist import sdist, walk_revctrl from setuptools.command.egg_info import manifest_maker from setuptools.dist import Distribution - +from setuptools import svn_utils +from setuptools.svn_utils import fsencode SETUP_ATTRS = { 'name': 'sdist_test', @@ -395,6 +397,64 @@ class TestSdistTest(unittest.TestCase): self.assertTrue(filename in cmd.filelist.files) +class TestSvn(environment.ZippedEnvironment): + + def setUp(self): + version = svn_utils.SvnInfo.get_svn_version() + self.base_version = tuple([int(x) for x in version.split('.')][:2]) + + if not self.base_version: + raise ValueError('No SVN tools installed') + elif self.base_version < (1,3): + raise ValueError('Insufficient SVN Version %s' % version) + elif self.base_version >= (1,9): + #trying the latest version + self.base_version = (1,8) + + self.dataname = "svn%i%i_example" % self.base_version + self.datafile = os.path.join('setuptools', 'tests', + 'svn_data', self.dataname + ".zip") + super(TestSvn, self).setUp() + + def test_walksvn(self): + if self.base_version >= (1,6): + folder2 = 'third party2' + folder3 = 'third party3' + else: + folder2 = 'third_party2' + folder3 = 'third_party3' + + #TODO is this right + expected = set([ + os.path.join('a file'), + os.path.join(folder2, 'Changes.txt'), + os.path.join(folder2, 'MD5SUMS'), + os.path.join(folder2, 'README.txt'), + os.path.join(folder3, 'Changes.txt'), + os.path.join(folder3, 'MD5SUMS'), + os.path.join(folder3, 'README.txt'), + os.path.join(folder3, 'TODO.txt'), + os.path.join(folder3, 'fin'), + os.path.join('third_party', 'README.txt'), + os.path.join('folder', folder2, 'Changes.txt'), + os.path.join('folder', folder2, 'MD5SUMS'), + os.path.join('folder', folder2, 'WatashiNiYomimasu.txt'), + os.path.join( 'folder', folder3, 'Changes.txt'), + os.path.join('folder', folder3, 'fin'), + os.path.join('folder', folder3, 'MD5SUMS'), + os.path.join('folder', folder3, 'oops'), + os.path.join('folder', folder3, 'WatashiNiYomimasu.txt'), + os.path.join('folder', folder3, 'ZuMachen.txt'), + os.path.join('folder', 'third_party', 'WatashiNiYomimasu.txt'), + os.path.join('folder', 'lalala.txt'), + os.path.join('folder', 'quest.txt'), + #The example will have a deleted file (or should) but shouldn't return it + ]) + expected = set(fsencode(x) for x in expected) + self.assertEqual(set(x for x in walk_revctrl()), expected) + + + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) diff --git a/setuptools/tests/test_svn.py b/setuptools/tests/test_svn.py index 6036f85c..4a6e7eff 100644 --- a/setuptools/tests/test_svn.py +++ b/setuptools/tests/test_svn.py @@ -3,77 +3,20 @@ import os -import zipfile import sys -import tempfile import unittest -import shutil -import stat +import codecs +from setuptools.tests import environment +from setuptools.svn_utils import fsencode +from setuptools.compat import unicode, unichr from setuptools import svn_utils -from setuptools.command import egg_info -from setuptools.command import sdist #requires python >= 2.4 from subprocess import call as _call -def _extract(self, member, path=None, pwd=None): - """for zipfile py2.5 borrowed from cpython""" - if not isinstance(member, zipfile.ZipInfo): - member = self.getinfo(member) +from distutils import log - if path is None: - path = os.getcwd() - - return _extract_member(self, member, path, pwd) - -def _extract_from_zip(self, name, dest_path): - dest_file = open(dest_path, 'wb') - try: - dest_file.write(self.read(name)) - finally: - dest_file.close() - -def _extract_member(self, member, targetpath, pwd): - """for zipfile py2.5 borrowed from cpython""" - # build the destination pathname, replacing - # forward slashes to platform specific separators. - # Strip trailing path separator, unless it represents the root. - if (targetpath[-1:] in (os.path.sep, os.path.altsep) - and len(os.path.splitdrive(targetpath)[1]) > 1): - targetpath = targetpath[:-1] - - # don't include leading "/" from file name if present - if member.filename[0] == '/': - targetpath = os.path.join(targetpath, member.filename[1:]) - else: - targetpath = os.path.join(targetpath, member.filename) - - targetpath = os.path.normpath(targetpath) - - # Create all upper directories if necessary. - upperdirs = os.path.dirname(targetpath) - if upperdirs and not os.path.exists(upperdirs): - os.makedirs(upperdirs) - - if member.filename[-1] == '/': - if not os.path.isdir(targetpath): - os.mkdir(targetpath) - return targetpath - - _extract_from_zip(self, member.filename, targetpath) - - return targetpath - - -def _remove_dir(target): - - #on windows this seems to a problem - for dir_path, dirs, files in os.walk(target): - os.chmod(dir_path, stat.S_IWRITE) - for filename in files: - os.chmod(os.path.join(dir_path, filename), stat.S_IWRITE) - shutil.rmtree(target) class TestSvnVersion(unittest.TestCase): @@ -90,81 +33,207 @@ class TestSvnVersion(unittest.TestCase): old_path = os.environ[path_variable] os.environ[path_variable] = '' try: - version = svn_utils.get_svn_tool_version() + version = svn_utils.SvnInfo.get_svn_version() self.assertEqual(version, '') finally: os.environ[path_variable] = old_path def test_svn_should_exist(self): - version = svn_utils.get_svn_tool_version() + version = svn_utils.SvnInfo.get_svn_version() self.assertNotEqual(version, '') +def _read_utf8_file(path): + fileobj = None + try: + fileobj = codecs.open(path, 'r', 'utf-8') + data = fileobj.read() + return data + finally: + if fileobj: + fileobj.close() -class TestSvn_1_7(unittest.TestCase): - def setUp(self): - version = svn_utils.get_svn_tool_version() - ver_list = [int(x) for x in version.split('.')] - if ver_list < [1,7,0]: - self.version_err = 'Insufficent Subversion (%s)' % version +class ParserInfoXML(unittest.TestCase): + + def parse_tester(self, svn_name, ext_spaces): + path = os.path.join('setuptools', 'tests', + 'svn_data', svn_name + '_info.xml') + #Remember these are pre-generated to test XML parsing + # so these paths might not valid on your system + example_base = "%s_example" % svn_name + + data = _read_utf8_file(path) + + if ext_spaces: + folder2 = 'third party2' + folder3 = 'third party3' else: - self.version_err = None + folder2 = 'third_party2' + folder3 = 'third_party3' + expected = set([ + ("\\".join((example_base, 'a file')), 'file'), + ("\\".join((example_base, 'folder')), 'dir'), + ("\\".join((example_base, 'folder', 'lalala.txt')), 'file'), + ("\\".join((example_base, 'folder', 'quest.txt')), 'file'), + ]) + self.assertEqual(set(x for x in svn_utils.parse_dir_entries(data)), + expected) - self.temp_dir = tempfile.mkdtemp() - zip_file, source, target = [None, None, None] - try: - zip_file = zipfile.ZipFile(os.path.join('setuptools', 'tests', - 'svn17_example.zip')) - for files in zip_file.namelist(): - _extract(zip_file, files, self.temp_dir) - finally: - if zip_file: - zip_file.close() - del zip_file + def test_svn13(self): + self.parse_tester('svn13', False) - self.old_cwd = os.getcwd() - os.chdir(os.path.join(self.temp_dir, 'svn17_example')) + def test_svn14(self): + self.parse_tester('svn14', False) - def tearDown(self): - try: - os.chdir(self.old_cwd) - _remove_dir(self.temp_dir) - except OSError: - #sigh? - pass - - def _chk_skip(self): - if self.version_err is not None: - if hasattr(self, 'skipTest'): - self.skipTest(self.version_err) - else: - sys.stderr.write(self.version_error + "\n") - return True - return False - - def test_egg_info(self): - if self._chk_skip: - return - - rev = egg_info.egg_info.get_svn_revision() - self.assertEqual(rev, '4') - - def test_iterator(self): - if self._chk_skip: - return + def test_svn15(self): + self.parse_tester('svn15', False) + + def test_svn16(self): + self.parse_tester('svn16', True) + + def test_svn17(self): + self.parse_tester('svn17', True) + + def test_svn18(self): + self.parse_tester('svn18', True) + +class ParserExternalXML(unittest.TestCase): + + def parse_tester(self, svn_name, ext_spaces): + path = os.path.join('setuptools', 'tests', + 'svn_data', svn_name + '_ext_list.xml') + example_base = svn_name + '_example' + data = _read_utf8_file(path) + + if ext_spaces: + folder2 = 'third party2' + folder3 = 'third party3' + else: + folder2 = 'third_party2' + folder3 = 'third_party3' expected = set([ - os.path.join('.', 'readme.txt'), - os.path.join('.', 'other'), - os.path.join('.', 'third_party'), - os.path.join('.', 'third_party2'), - os.path.join('.', 'third_party3'), + "\\".join((example_base, folder2)), + "\\".join((example_base, folder3)), + #third_party大介 + "\\".join((example_base, + unicode('third_party') + + unichr(0x5927) + unichr(0x4ecb))), + "\\".join((example_base, 'folder', folder2)), + "\\".join((example_base, 'folder', folder3)), + "\\".join((example_base, 'folder', + unicode('third_party') + + unichr(0x5927) + unichr(0x4ecb))), ]) - self.assertEqual(set(x for x - in sdist.entries_externals_finder('.', '')), + + dir_base = r'c:\development\svn_example' + self.assertEqual(set(x for x \ + in svn_utils.parse_externals_xml(data, dir_base)), expected) + + def test_svn15(self): + self.parse_tester('svn15', False) + + def test_svn16(self): + self.parse_tester('svn16', True) + + def test_svn17(self): + self.parse_tester('svn17', True) + + def test_svn18(self): + self.parse_tester('svn18', True) + + +class ParseExternal(unittest.TestCase): + + def parse_tester(self, svn_name, ext_spaces): + path = os.path.join('setuptools', 'tests', + 'svn_data', svn_name + '_ext_list.txt') + example_base = svn_name + '_example' + data = _read_utf8_file(path) + + if ext_spaces: + expected = set(['third party2', 'third party3', + 'third party3b', 'third_party']) + else: + expected = set(['third_party2', 'third_party3', 'third_party']) + + self.assertEqual(set(x for x in svn_utils.parse_external_prop(data)), expected) + def test_svn13(self): + self.parse_tester('svn13', False) + + def test_svn14(self): + self.parse_tester('svn14', False) + + def test_svn15(self): + self.parse_tester('svn15', False) + + def test_svn16(self): + self.parse_tester('svn16', True) + + def test_svn17(self): + self.parse_tester('svn17', True) + + def test_svn18(self): + self.parse_tester('svn18', True) + + +class TestSvn(environment.ZippedEnvironment): + + def setUp(self): + version = svn_utils.SvnInfo.get_svn_version() + self.base_version = tuple([int(x) for x in version.split('.')[:2]]) + + if not self.base_version: + raise ValueError('No SVN tools installed') + elif self.base_version < (1,3): + raise ValueError('Insufficient SVN Version %s' % version) + elif self.base_version >= (1,9): + #trying the latest version + self.base_version = (1,8) + + self.dataname = "svn%i%i_example" % self.base_version + self.datafile = os.path.join('setuptools', 'tests', + 'svn_data', self.dataname + ".zip") + super(TestSvn, self).setUp() + + def test_revision(self): + rev = svn_utils.SvnInfo.load('.').get_revision() + self.assertEqual(rev, 6) + + def test_entries(self): + expected = set([ + (os.path.join('a file'), 'file'), + (os.path.join('folder'), 'dir'), + (os.path.join('folder', 'lalala.txt'), 'file'), + (os.path.join('folder', 'quest.txt'), 'file'), + #The example will have a deleted file (or should) + #but shouldn't return it + ]) + info = svn_utils.SvnInfo.load('.') + self.assertEqual(set(x for x in info.entries), expected) + + def test_externals(self): + if self.base_version >= (1,6): + folder2 = 'third party2' + folder3 = 'third party3' + else: + folder2 = 'third_party2' + folder3 = 'third_party3' + + expected = set([ + os.path.join(folder2), + os.path.join(folder3), + os.path.join('third_party'), + os.path.join('folder', folder2), + os.path.join('folder', folder3), + os.path.join('folder', 'third_party'), + ]) + info = svn_utils.SvnInfo.load('.') + self.assertEqual(set([x for x in info.externals]), expected) + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) |