diff --git a/Makefile b/Makefile index 3905a8de06..4e8ac9f675 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,28 @@ build: $(PYTHON) setup.py build touch .built +# build OS X pkg packages +.PHONY: build-osx-pkg +build-osx-pkg: make-version + $(PYTHON) setup.py build_for_package + touch .built + +# create component pkg + pkgbuild --root $(shell pwd) \ + --identifier com.leastauthority.tahoe \ + --version $(shell $(PYTHON) ./setup.py --version) \ + --ownership recommended \ + --install-location /Applications/tahoe.app \ + --scripts $(shell pwd)/misc/build_helpers/osx/scripts \ + tahoe-lafs.pkg + +# create product archive + productbuild --distribution $(shell pwd)/misc/build_helpers/osx/Distribution.xml \ + --package-path . \ + tahoe-lafs-osx.pkg + +# remove intermediate pkg + rm -f tahoe-lafs.pkg # TESTING @@ -236,6 +258,7 @@ clean: rm -rf misc/dependencies/build misc/dependencies/temp rm -rf misc/dependencies/tahoe_deps.egg-info rm -f bin/tahoe bin/tahoe.pyscript + rm -f *.pkg .PHONY: distclean distclean: clean diff --git a/misc/build_helpers/test_mac_pkg.py b/misc/build_helpers/test_mac_pkg.py new file mode 100644 index 0000000000..3b15033bff --- /dev/null +++ b/misc/build_helpers/test_mac_pkg.py @@ -0,0 +1,74 @@ +# This script uses hdiutil to attach a dmg (whose name is derived from the +# appname and the version number passed in), asserts that it attached as +# expected, cd's into the mounted filesystem, executes "$appname +# --version-and-path", and checks whether the output of --version-and-path is +# right. + +# If all of the paths listed therein are loaded from within the current PWD +# then it exits with code 0. + +# If anything goes wrong then it exits with non-zero (failure). This is to +# check that the Mac OS "DMG" (disk image) package that gets built is correctly +# loading all of its packages from inside the image. + +# Here is an example output from --version-and-path: + +# allmydata-tahoe: 1.4.1-r3916 (/home/zooko/playground/allmydata/tahoe/trunk/trunk/src), foolscap: 0.4.1 (/usr/local/lib/python2.6/dist-packages/foolscap-0.4.1-py2.6.egg), pycryptopp: 0.5.10 (/home/zooko/playground/allmydata/tahoe/trunk/trunk/support/lib/python2.6/site-packages/pycryptopp-0.5.10-py2.6-linux-x86_64.egg), zfec: 1.4.2 (/usr/local/lib/python2.6/dist-packages/zfec-1.4.2-py2.6-linux-x86_64.egg), Twisted: 8.2.0-r26987 (/usr/local/lib/python2.6/dist-packages/Twisted-8.2.0_r26987-py2.6-linux-x86_64.egg), Nevow: 0.9.32 (/home/zooko/playground/allmydata/tahoe/trunk/trunk/support/lib/python2.6/site-packages/Nevow-0.9.32-py2.6.egg), zope.interface: 3.4.0 (/usr/lib/python2.6/dist-packages), python: 2.6.2 (/usr/bin/python), platform: Linux-Ubuntu_9.04-x86_64-64bit_ELF (None), sqlite: 3.6.10 (unknown), simplejson: 2.0.1 (/usr/local/lib/python2.6/dist-packages/simplejson-2.0.1-py2.6-linux-x86_64.egg), argparse: 0.8.0 (/usr/local/lib/python2.6/dist-packages/argparse-0.8.0-py2.6.egg), pyOpenSSL: 0.7 (/home/zooko/playground/allmydata/tahoe/trunk/trunk/support/lib/python2.6/site-packages/pyOpenSSL-0.7-py2.6-linux-x86_64.egg), pyutil: 1.3.30 (/usr/local/lib/python2.6/dist-packages/pyutil-1.3.30-py2.6.egg), zbase32: 1.1.1 (/usr/local/lib/python2.6/dist-packages/zbase32-1.1.1-py2.6.egg), setuptools: 0.6c12dev (/home/zooko/playground/allmydata/tahoe/trunk/trunk/support/lib/python2.6/site-packages/setuptools-0.6c12dev.egg), pysqlite: 2.4.1 (/usr/lib/python2.6/sqlite3) + +import os, re, subprocess, time, tempfile, shutil + +def test_mac_pkg(appname, version): + """ Return True on success, raise exception on failure. """ + assert isinstance(appname, basestring), appname + assert isinstance(version, basestring), version + PKGNAME='mac/'+appname+'-'+version+'.pkg' + + d = tempfile.mkdtemp(dir='/tmp') + # xar -C /tmp/tmpdir -xf PKGNAME + cmd = ['xar', '-C', d, '-xf', PKGNAME] + extractit = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + rc = extractit.wait() + if rc != 0: + raise Exception("FAIL: xar returned non-zero exit code: %r from command: %r" % (rc, cmd,)) + + stderrtxt = extractit.stderr.read() + if stderrtxt: + raise Exception("FAIL: xar said something on stderr: %r" % (stderrtxt,)) + + # cd /tmp/tmpXXX/tahoe-lafs.pkg + os.chdir(d + '/tahoe-lafs.pkg') + + # cat Payload | gunzip -dc | cpio -i + cat_process = subprocess.Popen(['cat', 'Payload'], stdout=subprocess.PIPE) + gunzip_process = subprocess.Popen(['gunzip', '-dc'], + stdin=cat_process.stdout, + stdout=subprocess.PIPE) + cpio_process = subprocess.Popen(['cpio', '-i'], + stdin=gunzip_process.stdout, + stdout=subprocess.PIPE) + cpio_process.communicate() + + callitpid = None + try: + basedir = os.getcwd() + cmd = ['bin/' + appname, '--version-and-path'] + callit = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + callitpid = callit.pid + assert callitpid + + time.sleep(5) + stdouttxt = callit.stdout.read() + + PKG_VER_PATH_RE=re.compile("(\S+): (\S+) \((.+?)\)", re.UNICODE) + + for mo in PKG_VER_PATH_RE.finditer(stdouttxt): + if not mo.group(3).startswith(basedir): + # the following packages are provided by the OS X default installation itself + if not mo.group(1) in ['zope.interface', 'python', 'platform', 'pyOpenSSL']: + raise Exception("FAIL: found package not loaded from basedir (%s); package was: %s" % (basedir, mo.groups(),)) + return True # success! + finally: + shutil.rmtree(d) + if callitpid: + os.kill(callitpid, 9) + os.waitpid(callitpid, 0) diff --git a/setup.cfg b/setup.cfg index ac312c9d2b..6099fbf874 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,6 +34,7 @@ find_links=misc/dependencies tahoe-deps ../tahoe-deps [aliases] build = update_version develop --prefix=support make_executable build +build_for_package = update_version make_executable build test = update_version develop --prefix=support make_executable build trial sdist = update_version sdist install = update_version install