1 patch for repository davidsarah@dev.allmydata.org:/home/darcs/tahoe/trunk: Fri Jan 21 05:36:10 GMT Standard Time 2011 david-sarah@jacaranda.org * Refactor _auto_deps.py and __init__.py, adding more robust checking of dependency versions, and not trusting pkg_resources to get the versions right. refs #1258, #1287 New patches: [Refactor _auto_deps.py and __init__.py, adding more robust checking of dependency versions, and not trusting pkg_resources to get the versions right. refs #1258, #1287 david-sarah@jacaranda.org**20110121053610 Ignore-this: b36d03e725ea9eb3362417e322019ebe ] { hunk ./src/allmydata/__init__.py 7 community web site: U{http://tahoe-lafs.org/} """ -# We want to call require_auto_deps() before other imports, because the setuptools -# docs claim that if a distribution is installed with --multi-version, it might not -# be importable until after pkg_resources.require() has been called for it. We don't -# have an example of this happening at this time. It is possible that require() isn't -# actually needed because we set __requires__ in the generated startup script, but -# that would be an undocumented property of the setuptools implementation. - -from allmydata import _auto_deps -_auto_deps.require_auto_deps() - -# This is just to suppress DeprecationWarnings from nevow and twisted. -# See http://allmydata.org/trac/tahoe/ticket/859 and -# http://divmod.org/trac/ticket/2994 . -import warnings -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="the sha module is deprecated; use the hashlib module instead", - append=True) -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="object.__new__\(\) takes no parameters", - append=True) -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="The popen2 module is deprecated. Use the subprocess module.", - append=True) -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="the md5 module is deprecated; use hashlib instead", - append=True) -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="twisted.web.error.NoResource is deprecated since Twisted 9.0. See twisted.web.resource.NoResource.", - append=True) -try: - import nevow - from twisted.persisted import sob - from twisted.python import filepath - hush_pyflakes = (nevow, sob, filepath) - del hush_pyflakes -finally: - warnings.filters.pop() - warnings.filters.pop() - warnings.filters.pop() - warnings.filters.pop() - # Don't pop the filter for the sha module warning because it is also generated - # by pycrypto (which we don't want to import unless needed). - # warnings.filters.pop() - -# This warning is generated by twisted, PyRex, and possibly other packages, -# but can happen at any time, not only when they are imported. See -# http://tahoe-lafs.org/trac/tahoe-lafs/ticket/1129 . -warnings.filterwarnings("ignore", category=DeprecationWarning, - message="BaseException.message has been deprecated as of Python 2.6", - append=True) +class PackagingError(EnvironmentError): + """ + Raised when there is an error in packaging of Tahoe-LAFS or its + dependencies which makes it impossible to proceed safely. + """ + pass __version__ = "unknown" try: hunk ./src/allmydata/__init__.py 134 else: return platform.platform() -def get_package_versions_from_setuptools(): - import pkg_resources - return dict([(p.project_name, (p.version, p.location)) for p in pkg_resources.require(__appname__)]) hunk ./src/allmydata/__init__.py 135 -def package_dir(srcfile): - return os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile)))) +from allmydata.util import verlib +def normalized_version(verstr): + return verlib.NormalizedVersion(verlib.suggest_normalized_version(verstr)) + def get_package_versions_and_locations(): hunk ./src/allmydata/__init__.py 141 - # because there are a few dependencies that are outside setuptools's ken - # (Python and platform, and sqlite3 if you are on Python >= 2.5), and - # because setuptools might fail to find something even though import - # finds it: - import OpenSSL, allmydata, foolscap.api, nevow, platform, pycryptopp, setuptools, simplejson, twisted, zfec, zope.interface - pysqlitever = None - pysqlitefile = None - sqlitever = None + import warnings + from _auto_deps import package_imports, deprecation_messages, deprecation_imports + + def package_dir(srcfile): + return os.path.dirname(os.path.dirname(os.path.normcase(os.path.realpath(srcfile)))) + + # pkg_resources.require returns the distribution that pkg_resources attempted to put + # on sys.path, which can differ from the one that we actually import due to #1258, + # or any other bug that causes sys.path to be set up incorrectly. Therefore we + # must import the packages in order to check their versions and paths. + + # This warning is generated by twisted, PyRex, and possibly other packages, + # but can happen at any time, not only when they are imported. See + # http://tahoe-lafs.org/trac/tahoe-lafs/ticket/1129 . + warnings.filterwarnings("ignore", category=DeprecationWarning, + message="BaseException.message has been deprecated as of Python 2.6", + append=True) + + # This is to suppress various DeprecationWarnings that occur when modules are imported. + # See http://allmydata.org/trac/tahoe/ticket/859 and http://divmod.org/trac/ticket/2994 . + + for msg in deprecation_messages: + warnings.filterwarnings("ignore", category=DeprecationWarning, message=msg, append=True) try: hunk ./src/allmydata/__init__.py 165 - import sqlite3 - except ImportError: - try: - from pysqlite2 import dbapi2 - except ImportError: - pass + for modulename in deprecation_imports: + try: + __import__(modulename) + except ImportError: + pass + finally: + for ign in deprecation_messages: + warnings.filters.pop() + + packages = [] + + def get_version(module, attr): + return str(getattr(module, attr, 'unknown')) + + for pkgname, modulename in [(__appname__, 'allmydata')] + package_imports: + if modulename: + try: + __import__(modulename) + module = sys.modules[modulename] + except ImportError: + packages.append((pkgname, (None, modulename))) + else: + if 'sqlite' in pkgname: + packages.append( (pkgname, (get_version(module, 'version'), package_dir(module.__file__))) ) + packages.append( ('sqlite', (get_version(module, 'sqlite_version'), package_dir(module.__file__))) ) + else: + packages.append( (pkgname, (get_version(module, '__version__'), package_dir(module.__file__))) ) + elif pkgname == 'python': + packages.append( (pkgname, (platform.python_version(), sys.executable)) ) + elif pkgname == 'platform': + packages.append( (pkgname, (get_platform(), None)) ) + + return packages + + +def check_requirement(req, vers_and_locs): + # TODO: check [] options + # We support only disjunctions of >= and == + + reqlist = req.split(',') + name = reqlist[0].split('>=')[0].split('==')[0].strip(' ').split('[')[0] + if name not in vers_and_locs: + raise PackagingError("no version info for %s" % (name,)) + if req.strip(' ') == name: + return + (actual, location) = vers_and_locs[name] + if actual is None: + raise ImportError("could not import %r for requirement %r" % (location, req)) + if actual == 'unknown': + return + actualver = normalized_version(actual) + + for r in reqlist: + s = r.split('>=') + if len(s) == 2: + required = s[1].strip(' ') + if actualver >= normalized_version(required): + return # minimum requirement met else: hunk ./src/allmydata/__init__.py 224 - pysqlitever = dbapi2.version - pysqlitefile = package_dir(dbapi2.__file__) - sqlitever = dbapi2.sqlite_version - else: - pysqlitever = sqlite3.version - pysqlitefile = package_dir(sqlite3.__file__) - sqlitever = sqlite3.sqlite_version + s = r.split('==') + if len(s) == 2: + required = s[1].strip(' ') + if actualver == normalized_version(required): + return # exact requirement met + else: + raise PackagingError("no version info or could not understand requirement %r" % (req,)) + + msg = ("We require %s, but could only find version %s.\n" % (req, actual)) + if location and location != 'unknown': + msg += "The version we found is from %r.\n" % (location,) + msg += ("To resolve this problem, uninstall that version, either using your\n" + "operating system's package manager or by moving aside the directory.") + raise PackagingError(msg) + + +_vers_and_locs_list = get_package_versions_and_locations() hunk ./src/allmydata/__init__.py 242 - d1 = { - 'pyOpenSSL': (OpenSSL.__version__, package_dir(OpenSSL.__file__)), - __appname__: (allmydata.__version__, package_dir(allmydata.__file__)), - 'foolscap': (foolscap.api.__version__, package_dir(foolscap.__file__)), - 'Nevow': (nevow.__version__, package_dir(nevow.__file__)), - 'pycryptopp': (pycryptopp.__version__, package_dir(pycryptopp.__file__)), - 'setuptools': (setuptools.__version__, package_dir(setuptools.__file__)), - 'simplejson': (simplejson.__version__, package_dir(simplejson.__file__)), - 'pysqlite': (pysqlitever, pysqlitefile), - 'sqlite': (sqlitever, 'unknown'), - 'zope.interface': ('unknown', package_dir(zope.interface.__file__)), - 'Twisted': (twisted.__version__, package_dir(twisted.__file__)), - 'zfec': (zfec.__version__, package_dir(zfec.__file__)), - 'python': (platform.python_version(), sys.executable), - 'platform': (get_platform(), None), - } + +def cross_check_pkg_resources_versus_import(): + """This function returns a list of errors due to any failed cross-checks.""" hunk ./src/allmydata/__init__.py 246 - # But we prefer to get all the dependencies as known by setuptools: import pkg_resources hunk ./src/allmydata/__init__.py 247 - try: - d2 = get_package_versions_from_setuptools() - except pkg_resources.DistributionNotFound: - # See docstring in _auto_deps.require_auto_deps() to explain why it makes sense to ignore this exception. - pass + from _auto_deps import install_requires + + errors = [] + not_pkg_resourceable = set(['sqlite', 'sqlite3', 'python', 'platform', __appname__.lower()]) + not_import_versionable = set(['zope.interface', 'mock', 'pyasn1']) + ignorable = set(['argparse', 'pyutil', 'zbase32']) + + pkg_resources_vers_and_locs = dict([(p.project_name.lower(), (str(p.version), p.location)) + for p in pkg_resources.require(install_requires)]) + + for name, (imp_ver, imp_loc) in _vers_and_locs_list: + name = name.lower() + if name not in not_pkg_resourceable: + if name not in pkg_resources_vers_and_locs: + errors.append("Warning: dependency %s (version %s imported from %r) was not found by pkg_resources." + % (name, imp_ver, imp_loc)) + + pr_ver, pr_loc = pkg_resources_vers_and_locs[name] + try: + pr_normver = normalized_version(pr_ver) + except Exception, e: + errors.append("Warning: version number %s found for dependency %s by pkg_resources could not be parsed. " + "The version found by import was %s from %r. " + "pkg_resources thought it should be found at %r. " + "The exception was %s: %s" + % (pr_ver, name, imp_ver, imp_loc, pr_loc, e.__class__.name, e)) + else: + if imp_ver == 'unknown': + if name not in not_import_versionable: + errors.append("Warning: unexpectedly could not find a version number for dependency %s imported from %r. " + "pkg_resources thought it should be version %s at %r." + % (name, imp_loc, pr_ver, pr_loc)) + else: + try: + imp_normver = normalized_version(imp_ver) + except Exception, e: + errors.append("Warning: version number %s found for dependency %s (imported from %r) could not be parsed. " + "pkg_resources thought it should be version %s at %r. " + "The exception was %s: %s" + % (imp_ver, name, imp_loc, pr_ver, pr_loc, e.__class__.name, e)) + else: + if pr_ver == 'unknown' or (pr_normver != imp_normver): + if not os.path.normpath(os.path.realpath(pr_loc)) == os.path.normpath(os.path.realpath(imp_loc)): + errors.append("Warning: dependency %s found to have version number %s (normalized to %s, from %r) " + "by pkg_resources, but version %s (normalized to %s, from %r) by import." + % (name, pr_ver, str(pr_normver), pr_loc, imp_ver, str(imp_normver), imp_loc)) + + imported_packages = set([p.lower() for (p, _) in _vers_and_locs_list]) + for pr_name, (pr_ver, pr_loc) in pkg_resources_vers_and_locs.iteritems(): + if pr_name not in imported_packages and pr_name not in ignorable: + errors.append("Warning: dependency %s (version %s) found by pkg_resources not found by import." + % (pr_name, pr_ver)) + + return errors + + +def get_error_string(errors): + from allmydata._auto_deps import install_requires + + return ("\n%s\n\n" + "For debugging purposes, the PYTHONPATH was\n" + " %r\n" + "install_requires was\n" + " %r\n" + "sys.path after importing pkg_resources was\n" + " %s\n" + % ("\n".join(errors), os.environ.get('PYTHONPATH'), install_requires, (os.pathsep+"\n ").join(sys.path)) ) + +def check_all_requirements(): + """This function returns a list of errors due to any failed checks.""" + + from allmydata._auto_deps import install_requires + + errors = [] + + # we require 2.4.4 on non-UCS-2, non-Redhat builds to avoid + # we require 2.4.3 on non-UCS-2 Redhat, because 2.4.3 is common on Redhat-based distros and will have patched the above bug + # we require at least 2.4.2 in any case to avoid a bug in the base64 module: + if sys.maxunicode == 65535: + if sys.version_info < (2, 4, 2) or sys.version_info[0] > 2: + errors.append("Tahoe-LAFS current requires Python v2.4.2 or greater " + "for a UCS-2 build (but less than v3), not %r" % + (sys.version_info,)) + elif platform.platform().lower().find('redhat') >= 0: + if sys.version_info < (2, 4, 3) or sys.version_info[0] > 2: + errors.append("Tahoe-LAFS current requires Python v2.4.3 or greater " + "on Redhat-based distributions (but less than v3), not %r" % + (sys.version_info,)) else: hunk ./src/allmydata/__init__.py 336 - d1.update(d2) + if sys.version_info < (2, 4, 4) or sys.version_info[0] > 2: + errors.append("Tahoe-LAFS current requires Python v2.4.4 or greater " + "for a non-UCS-2 build (but less than v3), not %r" % + (sys.version_info,)) + + vers_and_locs = dict(_vers_and_locs_list) + for requirement in install_requires: + try: + check_requirement(requirement, vers_and_locs) + except Exception, e: + errors.append("%s: %s" % (e.__class__.__name__, e)) + + if errors: + raise PackagingError(get_error_string(errors)) + +check_all_requirements() hunk ./src/allmydata/__init__.py 353 - return d1 def get_package_versions(): hunk ./src/allmydata/__init__.py 355 - return dict([(k, v) for k, (v, l) in get_package_versions_and_locations().iteritems()]) + return dict([(k, v) for k, (v, l) in _vers_and_locs_list]) def get_package_locations(): hunk ./src/allmydata/__init__.py 358 - return dict([(k, l) for k, (v, l) in get_package_versions_and_locations().iteritems()]) + return dict([(k, l) for k, (v, l) in _vers_and_locs_list]) def get_package_versions_string(show_paths=False): hunk ./src/allmydata/__init__.py 361 - vers_and_locs = get_package_versions_and_locations() res = [] hunk ./src/allmydata/__init__.py 362 - for p in [__appname__, "foolscap", "pycryptopp", "zfec", "Twisted", "Nevow", "zope.interface", "python", "platform"]: - (ver, loc) = vers_and_locs.get(p, ('UNKNOWN', 'UNKNOWN')) - info = str(p) + ": " + str(ver) - if show_paths: - info = info + " (%s)" % str(loc) - res.append(info) - if vers_and_locs.has_key(p): - del vers_and_locs[p] - - for p, (v, loc) in vers_and_locs.iteritems(): + for p, (v, loc) in _vers_and_locs_list: info = str(p) + ": " + str(v) if show_paths: info = info + " (%s)" % str(loc) hunk ./src/allmydata/__init__.py 367 res.append(info) - return ', '.join(res) + + output = ",\n".join(res) + "\n" + + if not hasattr(sys, 'frozen'): + errors = cross_check_pkg_resources_versus_import() + if errors: + output += get_error_string(errors) + + return output hunk ./src/allmydata/_auto_deps.py 1 -# Note: do not import any module from Tahoe-LAFS itself in this -# file. Also please avoid importing modules from other packages than -# the Python Standard Library if at all possible (exception: we rely -# on importing pkg_resources, which is provided by setuptools, -# zetuptoolz, distribute, and perhaps in the future distutils2, for -# the require_auto_deps() function.) +# Note: please minimize imports in this file. In particular, do not import +# any module from Tahoe-LAFS or its dependencies, and do not import any +# modules at all at global level. That includes setuptools and pkg_resources. +# It is ok to import modules from the Python Standard Library if they are +# always available, or the import is protected by try...except ImportError. hunk ./src/allmydata/_auto_deps.py 7 -install_requires=[ - # we require newer versions of setuptools (actually - # zetuptoolz) to build, but can handle older versions to run - "setuptools >= 0.6c6", +install_requires = [ + "zfec >= 1.1.0", hunk ./src/allmydata/_auto_deps.py 10 - "zfec >= 1.1.0", + # Feisty has simplejson 1.4 + "simplejson >= 1.4", hunk ./src/allmydata/_auto_deps.py 13 - # Feisty has simplejson 1.4 - "simplejson >= 1.4", + "zope.interface", hunk ./src/allmydata/_auto_deps.py 15 - "zope.interface", - "Twisted >= 2.4.0", + "Twisted >= 2.4.0", hunk ./src/allmydata/_auto_deps.py 17 - # foolscap < 0.5.1 had a performance bug which spent - # O(N**2) CPU for transferring large mutable files - # of size N. - # foolscap < 0.6 is incompatible with Twisted 10.2.0. - # foolscap 0.6.1 quiets a DeprecationWarning. - "foolscap[secure_connections] >= 0.6.1", - "Nevow >= 0.6.0", + # foolscap < 0.5.1 had a performance bug which spent + # O(N**2) CPU for transferring large mutable files + # of size N. + # foolscap < 0.6 is incompatible with Twisted 10.2.0. + # foolscap 0.6.1 quiets a DeprecationWarning. + "foolscap[secure_connections] >= 0.6.1", hunk ./src/allmydata/_auto_deps.py 24 - # Needed for SFTP. pyasn1 is needed by twisted.conch in Twisted >= 9.0. - # pycrypto 2.2 doesn't work due to https://bugs.launchpad.net/pycrypto/+bug/620253 - "pycrypto == 2.0.1, == 2.1, >= 2.3", - "pyasn1 >= 0.0.8a", + "Nevow >= 0.6.0", hunk ./src/allmydata/_auto_deps.py 26 - # http://www.voidspace.org.uk/python/mock/ - "mock", + # Needed for SFTP. pyasn1 is needed by twisted.conch in Twisted >= 9.0. + # pycrypto 2.2 doesn't work due to https://bugs.launchpad.net/pycrypto/+bug/620253 + "pycrypto == 2.0.1, == 2.1.0, >= 2.3", + "pyasn1 >= 0.0.8a", hunk ./src/allmydata/_auto_deps.py 31 - # Will be needed to test web apps, but not yet. See #1001. - #"windmill >= 1.3", - ] + # http://www.voidspace.org.uk/python/mock/ + "mock", hunk ./src/allmydata/_auto_deps.py 34 -import platform -if platform.machine().lower() in ['i386', 'x86_64', 'amd64', 'x86', '']: - # pycryptopp v0.5.20 fixes bugs in SHA-256 and AES on x86 or amd64 - # (from Crypto++ revisions 470, 471, 480, 492). The '' is there - # in case platform.machine is broken and this is actually an x86 - # or amd64 machine. - install_requires.append("pycryptopp >= 0.5.20") -else: - # pycryptopp v0.5.13 had a new bundled version of Crypto++ - # (v5.6.0) and a new bundled version of setuptools (although that - # shouldn't make any different to users of pycryptopp). - install_requires.append("pycryptopp >= 0.5.14") + # Will be needed to test web apps, but not yet. See #1001. + #"windmill >= 1.3", +] hunk ./src/allmydata/_auto_deps.py 38 +# Includes some indirect dependencies, but does not include allmydata. +# These are in the order they should be listed by --version, etc. +package_imports = [ + # package name module name + ('foolscap', 'foolscap'), + ('pycryptopp', 'pycryptopp'), + ('zfec', 'zfec'), + ('Twisted', 'twisted'), + ('Nevow', 'nevow'), + ('zope.interface', 'zope.interface'), + ('python', None), + ('platform', None), + ('pyOpenSSL', 'OpenSSL'), + ('simplejson', 'simplejson'), + ('pycrypto', 'Crypto'), + ('pyasn1', 'pyasn1'), + ('mock', 'mock'), +] hunk ./src/allmydata/_auto_deps.py 57 -# Sqlite comes built into Python >= 2.5, and is provided by the "pysqlite" -# distribution for Python 2.4. -import sys -if sys.version_info < (2, 5): - # pysqlite v2.0.5 was shipped in Ubuntu 6.06 LTS "dapper" and Nexenta NCP 1. - install_requires.append("pysqlite >= 2.0.5") +def require_more(): + import platform, sys hunk ./src/allmydata/_auto_deps.py 60 -if hasattr(sys, 'frozen'): # for py2exe - install_requires=[] -del sys # clean up namespace + if platform.machine().lower() in ['i386', 'x86_64', 'amd64', 'x86', '']: + # pycryptopp v0.5.20 fixes bugs in SHA-256 and AES on x86 or amd64 + # (from Crypto++ revisions 470, 471, 480, 492). The '' is there + # in case platform.machine is broken and this is actually an x86 + # or amd64 machine. + install_requires.append("pycryptopp >= 0.5.20") + else: + # pycryptopp v0.5.13 had a new bundled version of Crypto++ + # (v5.6.0) and a new bundled version of setuptools (although that + # shouldn't make any difference to users of pycryptopp). + install_requires.append("pycryptopp >= 0.5.14") hunk ./src/allmydata/_auto_deps.py 72 -def require_python_version(): - import sys, platform + # Sqlite comes built into Python >= 2.5, and is provided by the "pysqlite" + # distribution for Python 2.4. + try: + import sqlite3 + sqlite3 # hush pyflakes + package_imports.append(('sqlite3', 'sqlite3')) + except ImportError: + # pysqlite v2.0.5 was shipped in Ubuntu 6.06 LTS "dapper" and Nexenta NCP 1. + install_requires.append("pysqlite >= 2.0.5") + package_imports.append(('pysqlite', 'pysqlite.dbapi2')) hunk ./src/allmydata/_auto_deps.py 83 - # we require 2.4.4 on non-UCS-2, non-Redhat builds to avoid - # we require 2.4.3 on non-UCS-2 Redhat, because 2.4.3 is common on Redhat-based distros and will have patched the above bug - # we require at least 2.4.2 in any case to avoid a bug in the base64 module: - if sys.maxunicode == 65535: - if sys.version_info < (2, 4, 2) or sys.version_info[0] > 2: - raise NotImplementedError("Tahoe-LAFS current requires Python v2.4.2 or greater " - "for a UCS-2 build (but less than v3), not %r" % - (sys.version_info,)) - elif platform.platform().lower().find('redhat') >= 0: - if sys.version_info < (2, 4, 3) or sys.version_info[0] > 2: - raise NotImplementedError("Tahoe-LAFS current requires Python v2.4.3 or greater " - "on Redhat-based distributions (but less than v3), not %r" % - (sys.version_info,)) - else: - if sys.version_info < (2, 4, 4) or sys.version_info[0] > 2: - raise NotImplementedError("Tahoe-LAFS current requires Python v2.4.4 or greater " - "for a non-UCS-2 build (but less than v3), not %r" % - (sys.version_info,)) + if not hasattr(sys, 'frozen'): + # we require newer versions of setuptools (actually + # zetuptoolz) to build, but can handle older versions to run + install_requires.append("setuptools >= 0.6c6") + package_imports.append(('setuptools', 'setuptools')) + +require_more() hunk ./src/allmydata/_auto_deps.py 91 -def require_auto_deps(): - """ - The purpose of this function is to raise a pkg_resources exception if any of the - requirements can't be imported. This is just to give earlier and more explicit error - messages, as opposed to waiting until the source code tries to import some module from one - of these packages and gets an ImportError. This function gets called from - src/allmydata/__init__.py . - """ - require_python_version() +deprecation_messages = [ + "the sha module is deprecated; use the hashlib module instead", + "object.__new__\(\) takes no parameters", + "The popen2 module is deprecated. Use the subprocess module.", + "the md5 module is deprecated; use hashlib instead", + "twisted.web.error.NoResource is deprecated since Twisted 9.0. See twisted.web.resource.NoResource.", + "the sets module is deprecated", +] hunk ./src/allmydata/_auto_deps.py 100 - import pkg_resources - for requirement in install_requires: - try: - pkg_resources.require(requirement) - except pkg_resources.DistributionNotFound: - # there is no .egg-info present for this requirement, which - # either means that it isn't installed, or it is installed in a - # way that pkg_resources can't find it (but regular python - # might). There are several older Linux distributions which - # provide our dependencies just fine, but they don't ship - # .egg-info files. Note that if there *is* an .egg-info file, - # but it shows a too-old version, then we'll get a - # VersionConflict error instead of DistributionNotFound. - pass +deprecation_imports = [ + 'nevow', + 'twisted.persisted.sob', + 'twisted.python.filepath', + 'Crypto.Hash.SHA', +] addfile ./src/allmydata/test/test_version.py hunk ./src/allmydata/test/test_version.py 1 + +from twisted.trial import unittest + +from allmydata import check_requirement, PackagingError +from allmydata.util.verlib import NormalizedVersion as V, \ + IrrationalVersionError, \ + suggest_normalized_version as suggest + + +class CheckRequirement(unittest.TestCase): + def test_check_requirement(self): + check_requirement("setuptools >= 0.6c6", {"setuptools": ("0.6", "")}) + check_requirement("pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.1.0", "")}) + check_requirement("pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.4.0", "")}) + + check_requirement("zope.interface", {"zope.interface": ("unknown", "")}) + check_requirement("mock", {"mock": ("0.6.0", "")}) + check_requirement("foo >= 1.0", {"foo": ("1.0", ""), "bar": ("2.0", "")}) + + check_requirement("foolscap[secure_connections] >= 0.6.0", {"foolscap": ("0.7.0", "")}) + + self.failUnlessRaises(PackagingError, check_requirement, + "foolscap[secure_connections] >= 0.6.0", {"foolscap": ("0.5.1", "")}) + self.failUnlessRaises(PackagingError, check_requirement, + "pycrypto == 2.0.1, == 2.1, >= 2.3", {"pycrypto": ("2.2.0", "")}) + self.failUnlessRaises(PackagingError, check_requirement, + "foo >= 1.0", {}) + + +# based on https://bitbucket.org/tarek/distutilsversion/src/17df9a7d96ef/test_verlib.py + +class VersionTestCase(unittest.TestCase): + versions = ((V('1.0'), '1.0'), + (V('1.1'), '1.1'), + (V('1.2.3'), '1.2.3'), + (V('1.2'), '1.2'), + (V('1.2.3a4'), '1.2.3a4'), + (V('1.2c4'), '1.2c4'), + (V('1.2.3.4'), '1.2.3.4'), + (V('1.2.3.4.0b3'), '1.2.3.4b3'), + (V('1.2.0.0.0'), '1.2'), + (V('1.0.dev345'), '1.0.dev345'), + (V('1.0.post456.dev623'), '1.0.post456.dev623')) + + def test_basic_versions(self): + for v, s in self.versions: + self.failUnlessEqual(str(v), s) + + def test_from_parts(self): + for v, s in self.versions: + parts = v.parts + v2 = V.from_parts(*parts) + self.failUnlessEqual(v, v2) + self.failUnlessEqual(str(v), str(v2)) + + def test_irrational_versions(self): + irrational = ('1', '1.2a', '1.2.3b', '1.02', '1.2a03', + '1.2a3.04', '1.2.dev.2', '1.2dev', '1.2.dev', + '1.2.dev2.post2', '1.2.post2.dev3.post4') + + for s in irrational: + self.failUnlessRaises(IrrationalVersionError, V, s) + + def test_comparison(self): + self.failUnlessRaises(TypeError, lambda: V('1.2.0') == '1.2') + + self.failUnlessEqual(V('1.2.0'), V('1.2')) + self.failIfEqual(V('1.2.0'), V('1.2.3')) + self.failUnless(V('1.2.0') < V('1.2.3')) + self.failUnless(V('1.0') > V('1.0b2')) + self.failUnless(V('1.0') > V('1.0c2') > V('1.0c1') > V('1.0b2') > V('1.0b1') + > V('1.0a2') > V('1.0a1')) + self.failUnless(V('1.0.0') > V('1.0.0c2') > V('1.0.0c1') > V('1.0.0b2') > V('1.0.0b1') + > V('1.0.0a2') > V('1.0.0a1')) + + self.failUnless(V('1.0') < V('1.0.post456.dev623')) + self.failUnless(V('1.0.post456.dev623') < V('1.0.post456') < V('1.0.post1234')) + + self.failUnless(V('1.0a1') + < V('1.0a2.dev456') + < V('1.0a2') + < V('1.0a2.1.dev456') # e.g. need to do a quick post release on 1.0a2 + < V('1.0a2.1') + < V('1.0b1.dev456') + < V('1.0b2') + < V('1.0c1') + < V('1.0c2.dev456') + < V('1.0c2') + < V('1.0.dev7') + < V('1.0.dev18') + < V('1.0.dev456') + < V('1.0.dev1234') + < V('1.0') + < V('1.0.post456.dev623') # development version of a post release + < V('1.0.post456')) + + def test_suggest_normalized_version(self): + self.failUnlessEqual(suggest('1.0'), '1.0') + self.failUnlessEqual(suggest('1.0-alpha1'), '1.0a1') + self.failUnlessEqual(suggest('1.0c2'), '1.0c2') + self.failUnlessEqual(suggest('walla walla washington'), None) + self.failUnlessEqual(suggest('2.4c1'), '2.4c1') + + # from setuptools + self.failUnlessEqual(suggest('0.4a1.r10'), '0.4a1.post10') + self.failUnlessEqual(suggest('0.7a1dev-r66608'), '0.7a1.dev66608') + self.failUnlessEqual(suggest('0.6a9.dev-r41475'), '0.6a9.dev41475') + self.failUnlessEqual(suggest('2.4preview1'), '2.4c1') + self.failUnlessEqual(suggest('2.4pre1') , '2.4c1') + self.failUnlessEqual(suggest('2.1-rc2'), '2.1c2') + + # from pypi + self.failUnlessEqual(suggest('0.1dev'), '0.1.dev0') + self.failUnlessEqual(suggest('0.1.dev'), '0.1.dev0') + + # we want to be able to parse Twisted + # development versions are like post releases in Twisted + self.failUnlessEqual(suggest('9.0.0+r2363'), '9.0.0.post2363') + + # pre-releases are using markers like "pre1" + self.failUnlessEqual(suggest('9.0.0pre1'), '9.0.0c1') + + # we want to be able to parse Tcl-TK + # they us "p1" "p2" for post releases + self.failUnlessEqual(suggest('1.4p1'), '1.4.post1') + + # from darcsver + self.failUnlessEqual(suggest('1.8.1-r4956'), '1.8.1.post4956') + + # zetuptoolz + self.failUnlessEqual(suggest('0.6c16dev3'), '0.6c16.dev3') } Context: [src/allmydata/util/iputil.py: loosen regexps and ensure that 'LANG=en_US.UTF-8' is set in the environment, to minimize problems with localized output of IP-address-finding tools. refs #1274 david-sarah@jacaranda.org**20110120084827 Ignore-this: da04b1d780915ecfe492b671fdc2727e ] [Eliminate dependencies on pywin32, even via Twisted. refs #1274 david-sarah@jacaranda.org**20110120043238 Ignore-this: 96a2c30ea71a897472d704e905d3cb13 ] [Makefile: consistently use TAHOE macro to run bin/tahoe. Use '$(TAHOE) debug repl' instead of $(RUNPP) -p. refs #1296 david-sarah@jacaranda.org**20110119234429 Ignore-this: 1c339126c6cdb6cd7d60a95a2f0db0a2 ] [Makefile: consistently use 'tahoe debug trial' to run tests. refs #1296 david-sarah@jacaranda.org**20110119233737 Ignore-this: 4b6b5a13fcf767c23e5f983f92f2c053 ] [setup.py: add descriptions for some of the setup commands. ref #1306 david-sarah@jacaranda.org**20110119233305 Ignore-this: 8759eb5c3ee4b717bba5580622d76c6b ] [setup.py: create bin/tahoe.pyscript on Unix as well as Windows for consistency, and to reduce conditional code. ref #1306 david-sarah@jacaranda.org**20110119233145 Ignore-this: d1a7e66b3a2244fb4523ab3ef4057e5f ] [src/allmydata/test/test_runner.py: add test_import_from_repl, which checks that we are running the right code in a bin/tahoe subprocess. refs #1258 david-sarah@jacaranda.org**20110119082145 Ignore-this: c53a76827b47446df9e7b0128a2cb2c5 ] [docs/frontends/CLI.rst, src/allmydata/test/trialtest.py: add trailing newlines. refs #1296 david-sarah@jacaranda.org**20110119081955 Ignore-this: 1d19fad753ff17febf9b99bb2f5b7df7 ] [Eliminate direct dependencies of Tahoe-LAFS on pywin32 (rebased to trunk). refs #1274 david-sarah@jacaranda.org**20110119075911 Ignore-this: 8f31d1188daa382ec694908a68a19194 ] [trivial: add comment in scripts/debug.py about trial option parsing. refs #1296 david-sarah@jacaranda.org**20110119060808 Ignore-this: 3cda9b574d1fbc1cac683ed31c826051 ] [Update foolscap requirement to >= 0.6.1. fixes #1329 david-sarah@jacaranda.org**20110119060639 Ignore-this: 47908e13d1c79e74b9ebb9df934b3cf1 ] [Add support to bin/tahoe for invoking a runner command prefixed with @, with the Tahoe libraries on the PYTHONPATH. This is documented in 'tahoe debug --help'. david-sarah@jacaranda.org**20110119051137 Ignore-this: 65fd13a23670aea3825a706f45a7019f ] [bin/tahoe-script.template, src/windows/fixups.py: simplify the method of stripping initial arguments in sys.argv on Windows. This helps with bb-freeze and running tahoe via 'coverage'. Also includes some wording changes and minor refactoring of bin/tahoe-script.template. refs #585, #1303 david-sarah@jacaranda.org**20110119045324 Ignore-this: 756e83c5eae7dabac31290b98a0e5a99 ] [Change misc/build_helpers/test-with-fake-pkg to use 'setup.py trial'. refs #1296 david-sarah@jacaranda.org**20110119042401 Ignore-this: e1518b6f43becf47d5a956bb710a9dcb ] [Makefile: update 'make clean' to delete the setuptools_trial egg(s). david-sarah@jacaranda.org**20110119025053 Ignore-this: ec373228f3a169c7070633e3b89ec1d ] [Change 'setup.py trial' and 'setup.py test' to use 'bin/tahoe debug trial'. refs #1296 david-sarah@jacaranda.org**20110119024532 Ignore-this: 43df1a50435c794cfa60ecca71a46b10 ] [src/allmydata/test/test_cli.py: add test for 'tahoe debug trial' options help. refs #1296 david-sarah@jacaranda.org**20110119024224 Ignore-this: e9f7a67724b60c11a34efbce9a83a5cb ] [Makefile: update 'make clean' to avoid deleting the setuptools_darcs egg. david-sarah@jacaranda.org**20110119021958 Ignore-this: 908673ddd30ab88db5af8c8d80a74eb1 ] [Add src/allmydata/test/trialtest.py needed by tests for 'tahoe debug trial'. refs #1296 david-sarah@jacaranda.org**20110119020239 Ignore-this: 58d468dbd869c2e6c85552710ed47ffe ] [Tests for 'tahoe debug trial' (rebased and fixed to work with Twisted 10.2). refs #1296 david-sarah@jacaranda.org**20110119013859 Ignore-this: bb2ea70e5c3c841713ae38744b80980f ] [Documentation for 'tahoe debug trial' (rebased for trunk). refs #1296 david-sarah@jacaranda.org**20110118205729 Ignore-this: 3a4a4c2d23864851cb24c32a5b7962b4 ] [Make 'mock' a run-time rather than setup-time dependency. This is necessary in order for 'tahoe debug trial' to work. refs #1296 david-sarah@jacaranda.org**20110118205114 Ignore-this: 256c4fcd259eda02dd86ed163afc6497 ] [src/allmydata/scripts/debug.py: add 'tahoe debug trial' command (rebased for trunk). refs #1296 david-sarah@jacaranda.org**20110118204659 Ignore-this: 19e5f96d15c14625d5969ca4ae10a3cc ] [Remove setuptools_trial egg. david-sarah@jacaranda.org**20110110063306 Ignore-this: 329f5062db0c7914464c547a3957c596 ] [src/allmydata/webish.py: clean-ups and correction to a comment. Also change an open and write to use fileutil.write. See ref #1286 comment 13. david-sarah@jacaranda.org**20110117233152 Ignore-this: c4aa2f4286ad8a9fba9827d428f7fbe5 ] [setup: load the setuptools_darcs-1.2.12.egg that is bundled in the root of the source tree at setup.py time, and setup_require it. This is in order to make sure that its 'find all package data' plugin works to inform setuptools of all files which are under revision control, so that setuptools can include them in a distribution. By the way, this is ugly and horrible. refs #1054 david-sarah@jacaranda.org**20110118065445 Ignore-this: b4b9d3798a9beb9c44943daf2722a51 ] [setup: bundle a copy of setuptools_darcs-1.2.12 zooko@zooko.com**20110118062521 Ignore-this: 47e240417e0ff57a66d2f02f416a78fe This is to work-around https://bitbucket.org/tarek/distribute/issue/55/revision-control-plugin-automatically-installed-as-a-build-dependency-is-not-present-when-another-build-dependency-is-being . refs #1054. ] [NEWS: default reserved_space for new storage nodes is 1 GiB. refs #1208 david-sarah@jacaranda.org**20110117235930 Ignore-this: 81c898890f51400b7229b4b6de69eb30 ] ['tahoe debug catalog-shares': sort SIs and shnums Brian Warner **20110117095932 Ignore-this: f2c60da422178dfba6d03ff4957cf80c Without this, SIs or shnums could be emitted in random order, depending upon what the filesystem happens to return. ] [CLI: tests for ref #1305 (v2, remove spurious extra arg to create-alias in test) david-sarah@jacaranda.org**20110114040327 Ignore-this: 770b7117e66b04ced293b7b740b4a27f ] [CLI: make 'tahoe create-alias' and 'tahoe add-alias' accept a trailing colon on the new alias name (v2, minor change not to rely on implicit Unicode conversion). Includes doc changes and news; tests in a separate patch. fixes #1305 david-sarah@jacaranda.org**20110114034414 Ignore-this: 97e8e88d8b0f7c628b77db3adb67fa1b ] [Improve 'tahoe ln' help text. Patch by David-Sarah. Closes #1230. Brian Warner **20110117081421 Ignore-this: ae0ab1525fd39c95500535d6d015e706 ] [Tolerate Twisted-10.2's endpoints, patch by David-Sarah. Closes #1286. Brian Warner **20110117074751 Ignore-this: 8875749e4cab0e444a8452e290647bb6 The service generated by strports.service() changed in 10.2, and the ugly private-attribute-reading hack we used to glean a kernel-allocated port number (e.g. when using "tcp:0", especially during unit tests) broke, causing Tahoe to be completely unusable with Twisted-10.2 . The new ugly private-attribute-reading hack starts by figuring out what sort of service was generated, then reads different attributes accordingly. This also hushes a warning when using schemeless strports strings like "0" or "3456", by quietly prepending a "tcp:" scheme, since 10.2 complains about those. It also adds getURL() and getPortnum() accessors to the "webish" service, rather than having unit tests dig through _url and _portnum and such to find out what they are. ] [debian/control: add python-twisted-conch to dependencies. Closes #1095. Brian Warner **20110117071206 Ignore-this: 74714eeb8bd324d6124824f119468ab5 ] [Test changes to take account of ref #1311. david-sarah@jacaranda.org**20110117060540 Ignore-this: d787405b00a05d98abb34e5133a88b36 ] [create_node.py: add comments to default tahoe.cfg to clarify the meaning of each section. fixes #1311 david-sarah@jacaranda.org**20110117052419 Ignore-this: a2b0bba6b347bb0b0247782ee9ea9419 ] [Undo the temporary hack to check the foolscap version. refs #1246 david-sarah@jacaranda.org**20110117052042 Ignore-this: c58a8a5b91355a15d02b60c20a44bbd9 ] [misc/build_helpers/run_trial.py: fix pyflakes warning. david-sarah@jacaranda.org**20110115080456 Ignore-this: 95760a442fc397526a5d921510ec3843 ] [Set "reserved_space=1G" in newly-created storage nodes. Closes #1208. Brian Warner **20110116205822 Ignore-this: 2aac3dbb46e181ce7ae5e0af07bbb3bb ] [Temporary hack to investigate whether we are getting the right version of foolscap on trunk. refs #1258 david-sarah@jacaranda.org**20110116044959 Ignore-this: 4760970f9235dde07472ca980c24f75b ] [Makefile: allow tarball upload when either BB_BRANCH=='trunk' or BB_BRANCH==''. david-sarah@jacaranda.org**20110115212211 Ignore-this: 358822b25e69bfe9651a561ec387ca7a ] [misc/build_helpers/test-with-fake-dists.py: clean up directories and files only if they exist. david-sarah@jacaranda.org**20110115053011 Ignore-this: 7aa8fec370e12c62d9b56afcd55d17f ] [misc/build_helpers/test-with-fake-dists.py: wrong arguments in comment. david-sarah@jacaranda.org**20110115045325 Ignore-this: 89322306ed4fb478af4988675fd4c968 ] [Attempt to fix test-with-fake-dist build step. david-sarah@jacaranda.org**20110115022651 Ignore-this: 9d7195dca59b79f93a5f527b1ae9e79e ] [bin/tahoe-script.template: improve the error message if we end up running under Python 3. refs #1302 david-sarah@jacaranda.org**20110112211628 Ignore-this: ee78f8e4bbd197e620cb0cc6b995ac46 ] [Makefile: Fix uploading of tarballs on trunk builds. david-sarah@jacaranda.org**20110109065851 Ignore-this: 864b06e39103f46dbb6ccb74e1e333d3 ] [docs/frontends/CLI.rst: fix the rst syntax to be as actually intended :-) david-sarah@jacaranda.org**20110109014057 Ignore-this: c11331670ba89d8601ba3782ffc4f32c ] [docs/frontends/CLI.rst: really fix rst syntax error this time. david-sarah@jacaranda.org**20110109013914 Ignore-this: 59550154c9ab41488ddfdee8938d7bda ] [docs/frontends/CLI.rst: fix rst syntax error. david-sarah@jacaranda.org**20110109010943 Ignore-this: 427444f5572115059c75fa1bd8371d51 ] [docs/frontends/CLI.rst: discuss commandline/output quoting issues and wildcards. refs #1135 david-sarah@jacaranda.org**20110109010119 Ignore-this: 533938d89be878b404a8540aebdf68ad ] [setup.py: add Python 2.7 trove classifier. david-sarah@jacaranda.org**20110108211212 Ignore-this: b479c0a1adf9b7a2d1fdc54abc6582e6 ] [docs/FTP-and-SFTP.rst: document issue in ref #1297. Remove known issue #1045 which is fixed. Also some cosmetic changes. david-sarah@jacaranda.org**20110108061038 Ignore-this: 8d9aa2e33f1054545f7bed47bf0e647d ] [misc/build_helpers/show-tool-versions.py: remove attempts to show stdout.encoding and stderr.encoding that always printed None due to redirection. Also remove code to show os.path.supports_unicode_filenames which is not useful. refs #1251 david-sarah@jacaranda.org**20110103015144 Ignore-this: 45e11431f7e2e0cebcb58e1841485cf8 ] [NEWS: 'top' for node processes, WUI formatting, removal of GUI apps, documentation updates, foolscap dependency. refs #174, #1219, #1225 david-sarah@jacaranda.org**20110106005727 Ignore-this: f61ac58b4d10e635feb6f7391b1b48fe ] [Makefile: update 'clean' target for files in bin/ david-sarah@jacaranda.org**20110103052738 Ignore-this: 2bdbc4a50e13e508b66d0f65718c79b2 ] [docs: update performance.rst to describe the difference between already-uploaded and not-already-uploaded, to parameterize segment size, and to use "~A" to mean "approximately A" zooko@zooko.com**20110104065455 Ignore-this: 8df0d79a062ee19854c0211bd202f606 ] [bin/tahoe-script.template: On non-Windows, invoke support/bin/tahoe directly as a script (rather than via python), so that 'top' for example will show it as 'tahoe'. On Windows, simplify some code that set argv[0], which is never used. fixes #174 david-sarah@jacaranda.org**20101127232650 Ignore-this: 42a86f3eecfdc1ea7b76a7cc68626898 ] [test_runner: avoid unnecessary use of non-ASCII. david-sarah@jacaranda.org**20110101100101 Ignore-this: e2ff40dce6bb3b021306f2913d4e75df ] [docs/quickstart.html: fix redundant, badly nested tag. refs #1284 david-sarah@jacaranda.org**20110102175159 Ignore-this: 2ae9cc0b47d2e87b9eb64a0f517c4eef ] [docs/quickstart.html: information about 'troublesome dependencies' and 'verified systems' de-emphasized by smaller italic font. Re-wrap so that the HTML source is readable (just about) as text. Minor wording tweaks. Improve organization by adding 'Windows Caveats' subsection. fixes #1284 david-sarah@jacaranda.org**20110102174212 Ignore-this: e9dc57983974478200856651c5318fee ] [NEWS: update entry for removal of Mac and Windows apps. refs #1282 david-sarah@jacaranda.org**20101226042245 Ignore-this: c8099bc6e8235718d042c9a13c1e2425 ] [Move dependency imports from windows/depends.py (which has gone away) into src/allmydata/windows/tahoesvc.py. Also fix a pyflakes warning, and change the service display name from 'Allmydata Tahoe Node' to 'Tahoe-LAFS node'. refs #1282 david-sarah@jacaranda.org**20101226042100 Ignore-this: ee45f324934e1251380206dbee6346d0 ] [Remove unmaintained Windows GUI app, except for windows/tahoesvc.py which is moved to src/allmydata/windows. refs #1282 david-sarah@jacaranda.org**20101226040237 Ignore-this: cae37b6622a7dd5940acc7d3e6a98b90 ] [Remove the Makefile targets relating to the Mac GUI app. refs #1282 david-sarah@jacaranda.org**20101226025859 Ignore-this: 75303be783974b41138744ec62b07965 ] [NEWS: remove unmaintained Mac GUI app. refs #1282 david-sarah@jacaranda.org**20101226020858 Ignore-this: 40474a07f4a550b48563d35350be7ab5 ] [Remove unmaintained Mac GUI app. fixes #1282 david-sarah@jacaranda.org**20101226020508 Ignore-this: b3613bf1abfd284d542bf7c753ec557a ] [Remove src/allmydata/util/find_exe.py which is no longer used. fixes #1150 david-sarah@jacaranda.org**20101226023206 Ignore-this: 7436c9b53bf210aed34a1a973cd9cace ] [status_web_pages_review.darcs.patch freestorm77@gmail.com**20110102034214 Ignore-this: 29f1ecb36177f10f3f846b3d56b313b2 I make some changes on status web pages status.xhtml: - Delete unused webform_css link - Align tables on the left tahoe-css: - Do some minor changes on code synthax - changes table.status-download-events style to look like other tables status.py: - Align table on the left - Changes table header - Add heading tags - Modify google api graph: add image border, calculate height to feet data signed-off-by: zooko@zooko.com fixes #1219 ] [test_storage.py: fix a pyflakes unused import warning. david-sarah@jacaranda.org**20101231220756 Ignore-this: df08231540cb7dff9d2b038e47ab30ee ] [test_storage.py: leave at least 512 MiB free when running test_large_share. refs #1195 david-sarah@jacaranda.org**20101231203215 Ignore-this: b2144c0341c3452b5d4ba219e284ea0e ] [storage: use fileutil's version of get_disk_stats() and get_available_space(), use mockery/fakery in tests, enable large share test on platforms with sparse files and if > 4 GiB of disk space is currently available zooko@zooko.com**20100910173629 Ignore-this: 1304f1164c661de6d5304f993eb9b27b ] [fileutil: copy in the get_disk_stats() and get_available_space() functions from storage/server.py zooko@zooko.com**20100910173520 Ignore-this: 8b15569715f710f4fc5092f7ca109253 ] [Update foolscap version requirement to 0.6.0, to address http://foolscap.lothar.com/trac/ticket/167 david-sarah@jacaranda.org**20101231060039 Ignore-this: 98d2b8086a1a500b9f4565bca5a3810 ] [docs/webapi.rst: typos. david-sarah@jacaranda.org**20101230034422 Ignore-this: d1f5166d72cc711f7e0d9981eac9105e ] [docs/webapi.rst: capitalization, formatting of section on URL character encoding, and a correction about Internet Explorer. david-sarah@jacaranda.org**20101230034049 Ignore-this: b3b9819d2fb264b4cdc5c8afd4e8c48d ] [docs: corrections and clarifications. david-sarah@jacaranda.org**20101227051056 Ignore-this: e33202858c7644c58f3f924b164294b6 ] [docs: more formatting cleanups and corrections. Spell webapi and wapi as web-API. david-sarah@jacaranda.org**20101227050533 Ignore-this: 18b23cbfb780df585d8a722a1ec63e94 ] [docs/debian.rst: bring description of building dependencies from source up-to-date, and change hostname from allmydata.com to tahoe-lafs.org. david-sarah@jacaranda.org**20101212222912 Ignore-this: f38462afc88b4475195610385a28391c ] [docs/architecture.rst: correct rst syntax. david-sarah@jacaranda.org**20101212202003 Ignore-this: 3fbe12feb28bec6f1c63aedbc79aad21 ] [docs/architecture.rst: formatting. david-sarah@jacaranda.org**20101212201719 Ignore-this: 305fa5dfc2939355eaf6d0d2161eb1ff ] [docs: linkification, wording improvements. david-sarah@jacaranda.org**20101212201234 Ignore-this: 4e67287f527a8bc728cfbd93255d2aae ] [docs: formatting. david-sarah@jacaranda.org**20101212201115 Ignore-this: 2e0ed394ac7726651d3a4f2c4b0d3798 ] [docs/configuration.rst: more formatting tweaks; which -> that. david-sarah@jacaranda.org**20101212195522 Ignore-this: a7becb7021854ca5a90edd892b36fdd7 ] [docs/configuration.rst: more changes to formatting. david-sarah@jacaranda.org**20101212194511 Ignore-this: 491aac33e5f5268d224359f1447d10be ] [docs/configuration.rst: changes to formatting (mainly putting commands and filenames in monospace). david-sarah@jacaranda.org**20101212181828 Ignore-this: 8a1480e2d5f43bee678476424615b50f ] [scripts/backupdb.py: more accurate comment about path field. david-sarah@jacaranda.org**20101212170320 Ignore-this: 50e47a2228a85207bbcd188a78a0d4e6 ] [scripts/cli.py: fix missing 'put' in usage example for 'tahoe put'. david-sarah@jacaranda.org**20101212170207 Ignore-this: 2cbadf066fff611fc03d3c0ff97ce6ec ] [docs/frontends/CLI.rst: changes to formatting (mainly putting commands and filenames in monospace), and to command syntax to reflect that DIRCAP/... is accepted. Clarify the syntax of 'tahoe put' and other minor corrections. Tahoe -> Tahoe-LAFS. david-sarah@jacaranda.org**20101212165800 Ignore-this: a123ef6b564aa8624d1e79c97068ea12 ] [docs/frontends/CLI.rst: Unicode arguments to 'tahoe' work on Windows as of v1.7.1. david-sarah@jacaranda.org**20101212063740 Ignore-this: 3977a99dfa86ac33a44171deaf43aaab ] [docs/known_issues.rst: fix title and linkify another URL. refs #1225 david-sarah@jacaranda.org**20101212062817 Ignore-this: cc91287f7fb51c23440b3d2fe79c449c ] [docs/known_issues.rst: fix an external link. refs #1225 david-sarah@jacaranda.org**20101212062435 Ignore-this: b8cbf12f353131756c358965c48060ec ] [Fix a link from uri.rst to dirnodes.rst. refs #1225 david-sarah@jacaranda.org**20101212054502 Ignore-this: af6205299f5c9a33229cab259c00f9d5 ] [Fix a link from webapi.rst to FTP-and-SFTP.rst. refs #1225 david-sarah@jacaranda.org**20101212053435 Ignore-this: 2b9f88678c3447ea860d6b61e8799858 ] [More specific hyperlink to architecture.rst from helper.rst. refs #1225 david-sarah@jacaranda.org**20101212052607 Ignore-this: 50424c768fca481252fabf58424852dc ] [Update hyperlinks between docs, and linkify some external references. refs #1225 david-sarah@jacaranda.org**20101212051459 Ignore-this: cd43a4c3d3de1f832abfa88d5fc4ace1 ] [docs/specifications/dirnodes.rst: fix references to mutable.rst. refs #1225 david-sarah@jacaranda.org**20101212012720 Ignore-this: 6819b4b4e06e947ee48b365e840db37d ] [docs/specifications/mutable.rst: correct the magic string for v1 mutable containers. refs #1225 david-sarah@jacaranda.org**20101212011400 Ignore-this: 99a5fcdd40cef83dbb08f323f6cdaaca ] [Move .txt files in docs/frontends and docs/specifications to .rst. refs #1225 david-sarah@jacaranda.org**20101212010251 Ignore-this: 8796d35d928370f7dc6ad2dafdc1c0fe ] [Convert docs/frontends and docs/specifications to reStructuredText format (not including file moves). david-sarah@jacaranda.org**20101212004632 Ignore-this: e3ceb2d832d73875abe48624ddbb5622 ] [scripts/cli.py: remove the disclaimer in the help for 'tahoe cp' that it does not handle non-ASCII filenames well. (At least, we intend to handle them.) david-sarah@jacaranda.org**20101130002145 Ignore-this: 94c003efaa20b9eb4a83503d79844ca ] [relnotes.txt: fifth -> sixth labor-of-love release zooko@zooko.com**20101129045647 Ignore-this: 21c245015268b38916e3a138d256c09d ] [Makefile: BB_BRANCH is set to the empty string for trunk, not the string 'trunk'. david-sarah@jacaranda.org**20101128233512 Ignore-this: 5a7ef8eb10475636d21b91e25b56c369 ] [relnotes.txt: eleventh -> twelfth release. david-sarah@jacaranda.org**20101128223321 Ignore-this: 1e26410156a665271c1170803dea2c0d ] [relnotes.tst: point to known_issues.rst, not known_issues.txt. david-sarah@jacaranda.org**20101128222918 Ignore-this: 60194eb4544cac446fe4f60b3e34b887 ] [quickstart.html: fix link to point to allmydata-tahoe-1.8.1.zip. david-sarah@jacaranda.org**20101128221728 Ignore-this: 7b3ee86f8256aa12f5d862f689f3ee29 ] [TAG allmydata-tahoe-1.8.1 david-sarah@jacaranda.org**20101128212336 Ignore-this: 9c18bdeaef4822f590d2a0d879e00621 ] Patch bundle hash: 2a5436643847f4294061f1182d078ec52424df11