^src/Crypto/build($|/)
^_test_memory($|/)
+# version.py is generated at build time, and never checked in
+^src/allmydata/version\.py$
+
.PHONY: build
build: build-zfec build-Crypto build-foolscap
+ $(PYTHON) misc/make-version.py
$(PP) $(PYTHON) ./setup.py $(EXTRA_SETUP_ARGS) install --prefix="." --root="$(INSTDIR)" --install-lib="lib" --install-scripts="bin"
build-zfec:
# DEBIAN PACKAGING
-VER=$(shell python -c "import os,re;print re.search(\"verstr=['\\\"](.*?)['\\\"]\", open(os.path.join('src', 'allmydata', '__init__.py')).readline()).group(1)")
-DEBSTRING=$(VER)-T`date +%s`
+VER=$(shell $(PYTHON) misc/get-version.py)
DEBCOMMENTS="'make deb' build"
-show:
+show-version:
@echo $(VER)
- @echo $(DEBSTRING)
.PHONY: setup-dapper setup-sid setup-edgy setup-feisty
.PHONY: deb-dapper deb-sid deb-edgy deb-feisty
echo "The newly built .deb packages are in the parent directory from here."
increment-deb-version:
- debchange --newversion $(DEBSTRING) $(DEBCOMMENTS)
+ debchange --newversion $(VER) $(DEBCOMMENTS)
deb-dapper-head: setup-dapper increment-deb-version
fakeroot debian/rules binary
deb-sid-head: setup-sid increment-deb-version
--- /dev/null
+#! /usr/bin/python
+
+"""Determine the version number of the current tree.
+
+This should be run *after* make-version.py . It will emit a single line of
+text to stdout, either of the form '0.2.0' if this is a release tree (i.e. no
+patches have been added since the last release tag), or '0.2.0-34' (if 34
+patches have been added since the last release tag). If the tree does not
+have a well-formed version number, this will emit 'unknown'.
+
+The version string thus calculated should exactly match the version string
+determined by setup.py (when it creates eggs and source tarballs) and also
+the version available in the code image when you do:
+
+ from allmydata import __version__
+
+"""
+
+import os.path, re
+
+def get_version():
+ VERSIONFILE = "src/allmydata/version.py"
+ verstr = "unknown"
+ if os.path.exists(VERSIONFILE):
+ VSRE = re.compile("^verstr = ['\"]([^'\"]*)['\"]", re.M)
+ verstrline = open(VERSIONFILE, "rt").read()
+ mo = VSRE.search(verstrline)
+ if mo:
+ verstr = mo.group(1)
+ else:
+ raise RuntimeError("if version.py exists, it must be well-formed")
+
+ return verstr
+
+if __name__ == '__main__':
+ verstr = get_version()
+ print verstr
+
--- /dev/null
+#! /usr/bin/python
+
+"""
+Create src/allmydata/version.py, based upon the latest darcs release tag.
+
+If your source tree is coming from darcs (i.e. there exists a _darcs
+directory), this tool will determine the most recent release tag, count the
+patches that have been applied since then, and compute a version number to be
+written into version.py . This version number will be available by doing:
+
+ from allmydata import __version__
+
+Source trees that do not come from darcs (release tarballs, nightly tarballs)
+do not have a _darcs directory. Instead, they should have a version.py that
+was generated before the tarball was produced. In this case, this script will
+quietly exit without modifying the existing version.py .
+
+FYI, src/allmydata/__init__.py will attempt to import version.py and use the
+version number therein. If it cannot, it will announce a version of
+'UNKNOWN'. This should only happen if someone manages to get hold of a
+non-_darcs/ source tree.
+
+'release tags' are tags in the tahoe source tree that match the following
+regexp:
+
+ ^allmydata-tahoe-\d+\.\d+\.\d+\w*$
+
+This excludes zfec tags (which start with 'zfec '). It also excludes
+'developer convenience tags', which look like 'hoping to fix bug -warner'.
+(the original goal was to use release tags that lacked the 'allmydata-tahoe-'
+prefix, but it turns out to be more efficient to keep it in, because I can't
+get 'darcs changes --from-tag=' to accept real regexps).
+
+"""
+
+import os, sys, commands, re
+import xml.dom.minidom
+
+def get_text(nodelist):
+ rc = ""
+ for node in nodelist:
+ if node.nodeType == node.TEXT_NODE:
+ rc = rc + node.data
+ return rc
+
+VERSION_BODY = '''
+from util.version import Version
+
+# This is the version of this tree, as created by misc/make-version.py from
+# the Darcs patch information: the main version number is taken from the most
+# recent release tag. If some patches have been added since the last release,
+# this will have a -NN "build number" suffix. Please see
+# allmydata.util.version for a description of what the different fields mean.
+
+verstr = "%s"
+__version__ = Version(verstr)
+'''
+
+def write_version_py(verstr):
+ f = open("src/allmydata/version.py", "wt")
+ f.write(VERSION_BODY % (verstr,))
+ f.close()
+
+def update():
+ if not os.path.exists("_darcs") or not os.path.isdir("_darcs"):
+ if os.path.exists("src/allmydata/version.py"):
+ print "no _darcs/ and version.py exists, leaving it alone"
+ return 0
+ print "no _darcs/ but no version.py either: how did you get this tree?"
+ return 0
+ cmd = "darcs changes --from-tag=^allmydata-tahoe --xml-output"
+ (rc, output) = commands.getstatusoutput(cmd)
+ if rc != 0:
+ print "unable to run 'darcs changes':"
+ print output
+ print "so I'm leaving version.py alone"
+ return 0
+
+ try:
+ doc = xml.dom.minidom.parseString(output)
+ except xml.parsers.expat.ExpatError:
+ print "unable to parse darcs XML output:"
+ print output
+ raise
+ changelog = doc.getElementsByTagName("changelog")[0]
+ patches = changelog.getElementsByTagName("patch")
+ count = 0
+ version_re = re.compile("^TAG allmydata-tahoe-(\d+\.\d+\.\d+\w*)$")
+ for patch in patches:
+ name = get_text(patch.getElementsByTagName("name")[0].childNodes)
+ m = version_re.match(name)
+ if m:
+ last_tag = m.group(1)
+ last_tag = last_tag.encode("ascii")
+ break
+ count += 1
+ else:
+ print "unable to find a matching tag"
+ print output
+ print "so I'm leaving version.py alone"
+ return 0
+
+ if count:
+ # this is an interim version
+ verstr = "%s-%d" % (last_tag, count)
+ else:
+ # this is a release
+ verstr = last_tag
+
+ write_version_py(verstr)
+ print "wrote '%s' into src/allmydata/version.py" % (verstr,)
+ return 0
+
+if __name__ == '__main__':
+ rc = update()
+ sys.exit(rc)
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
+import re, os.path
from distutils.core import Extension, setup
trove_classifiers=[
"Topic :: System :: Archiving",
]
-import re
-VSRE=re.compile("verstr=['\"]([^'\"]*)['\"]")
-verstrline=open("src/allmydata/__init__.py").readline()
-mo = VSRE.search(verstrline)
-verstr = mo.group(1)
+
+VERSIONFILE = "src/allmydata/version.py"
+verstr = "unknown"
+if os.path.exists(VERSIONFILE):
+ VSRE = re.compile("^verstr = ['\"]([^'\"]*)['\"]", re.M)
+ verstrline = open(VERSIONFILE, "rt").read()
+ mo = VSRE.search(verstrline)
+ if mo:
+ verstr = mo.group(1)
+ else:
+ print "unable to find version in version.py"
+ raise RuntimeError("if version.py exists, it must be well-formed")
setup(name='allmydata-tahoe',
version=verstr,
-verstr="0.2.0-0-UNSTABLE"
-# The line is placed above so that it can be easily read by build scripts.
"""
Decentralized storage grid.
community web site: U{http://allmydata.org/}
"""
-from util.version import Version
+__version__ = "unknown"
+try:
+ from allmydata.version import __version__
+except ImportError:
+ # we're running in a tree that hasn't run misc/make-version.py, so we
+ # don't know what our version is. This should not happen very often.
+ pass
-# For an explanation of what the parts of the version string mean,
-# please see pyutil.version.
-__version__ = Version(verstr)
-
-# Please put a URL or other note here which shows where to get the branch of
-# development from which this version grew.
-__sources__ = ["http://allmydata.org/source/tahoe",]
+hush_pyflakes = __version__
+del hush_pyflakes