Repository: buildbot/buildbot

Issue:
0.9.1 release notes
This also contains merge commit of the 0.9.0 tag to master, which I forgot to push as well as cleanup of pycparse no binary which was inefficient anyway




Discussion:

Resolving patch:
diff --git a/www/buildbot_www.py b/www/buildbot_www.py
--- a/www/buildbot_www.py
+++ b/www/buildbot_www.py
@@ -22,36 +22,18 @@
 def sibpath(*elts):
     return os.path.join(os.path.dirname(__file__), *elts)
 
-# (see comments in setup.py about contexts)
-#
-# this script never runs in the SDIST state, so if src/ is missing,
-# then we're INSTALLED
-src_exists = os.path.isdir(sibpath('src'))
-built_exists = os.path.isdir(sibpath('built'))
-if src_exists:
-    if not built_exists:
-        context = 'SRC'
-    else:
-        context = 'BUILT'
-else:
-    context = 'INSTALLED'
 
 class Application(object):
     def __init__(self):
         self.description = "Buildbot UI"
-
-        # the rest depends on the context we're executing in
-        if context == 'SRC':
-            raise Exception("cannot run in source mode! you need to first call grunt dev.")
-        elif context == 'BUILT':
-            self.version = 'source'
-            self.static_dir = os.path.abspath(sibpath('built'))
-        else: # context == 'INSTALLED'
-            instdir = os.path.join(sys.prefix, 'share', 'buildbot', 'dist')
-            verfile = os.path.join(instdir, 'buildbot-version.txt')
-            self.version = open(verfile).read().strip()
-            self.static_dir = instdir
-
+        # VERSION's location differs depending on whether we're installed
+        for f in sibpath('VERSION'), sibpath('buildbot_www', 'VERSION'):
+            if os.path.exists(f):
+                self.version = open(f).read().strip()
+                break
+        else:
+            self.version = '<unknown>'
+        self.static_dir = os.path.abspath(sibpath('buildbot_www'))
         self.resource = static.File(self.static_dir)
 
 
diff --git a/www/setup.py b/www/setup.py
--- a/www/setup.py
+++ b/www/setup.py
@@ -15,71 +15,211 @@
 #
 # Copyright Buildbot Team Members
 
-import os, sys
+import os
+import subprocess
 from setuptools import setup
+import setuptools.command.sdist
+import setuptools.command.install
+from distutils.core import Command
 
-# this script executes in a few contexts:
-#
-# 'SRC'     - from a new git working directory (python setup.py develop)
-# 'BUILT'   - from build.sh in a git working directory, after the build
-# 'SDIST'   - from an sdist tarball during installation
-#
-# distinguish these by which directories exist: src only, both, and built only,
-# respectively
-
-src_exists = os.path.isdir('src')
-built_exists = os.path.isdir('built')
-if src_exists:
-    if not built_exists:
-        context = 'SRC'
-    else:
-        context = 'BUILT'
+# This script can run either in a source checkout (e.g., to 'setup.py sdist')
+# or in an sdist tarball (to install)
+MODE = 'SRC' if os.path.isdir('src') else 'SDIST'
+
+if MODE == 'SRC':
+    # if we're in a source tree, use master's __init__ to determine the
+    # version, and update the version file as a by-product
+    master_init = os.path.abspath("../master/buildbot/__init__.py")
+    globals = { "__file__" :  master_init }
+    execfile(master_init, globals)
+    version = globals['version']
+    open('VERSION', 'w').write(version + '\n')
 else:
-    context = 'SDIST'
-
-def make_data_files():
-    # hack to build the app automatically on setup.py develop
-    if src_exists:
-        if os.system("npm install"):
-            raise Exception("to setup this app, you need node and npm installed in your system")
-        grunt_target = "prod"
-        if "develop" in sys.argv:
-            grunt_target="default"
-        os.system("./node_modules/.bin/grunt "+grunt_target)
-
-# use the list of data files build.sh created, and generate filenames
-    # to end up under "{sys.prefix}/share/buildbot"
-    by_dir = {}
-    for root, dirs, files in os.walk('built'):
-        for name in files:
-            fn = os.path.join(root, name)
-            dirname = os.path.join('share', 'buildbot', os.path.dirname(fn))
-            dirlist = by_dir.setdefault(dirname, [])
-            dirlist.append(fn)
-    print by_dir
-    return by_dir.items()
-
-def get_version():
-    if context in ('SRC', 'BUILT'):
-        # if we're in a source tree, use master's __init__ to determine the
-        # version
-        master_init = os.path.abspath("../master/buildbot/__init__.py")
-        globals = { "__file__" :  master_init }
-        execfile(master_init, globals)
-        return globals['version']
-    else:
-        # otherwise, use what build.sh left us
-        return open('built/buildbot-version.txt').read().strip()
-
-setup(name='buildbot-www',
-    version=get_version(),
+    # otherwise, use what the build left us
+    version = open('VERSION').read().strip()
+
+package_json = """\
+{
+    "name": "buildbot-www",
+    "version": "VERSION",
+    "author": {
+        "name": "Pierre Tardy",
+        "email": "tardyp@gmail.com",
+        "url": "https://github.com/tardyp"
+    },
+    "description": "Buildbot UI",
+    "contributors": [
+        {
+        "name": "David Bochenski",
+        "email": "david@bochenski.co.uk",
+        "url": "https://github.com/Bochenski"
+        },
+        {
+        "name": "Cary Landholt",
+        "email": "cary@landholt.com",
+        "url": "https://github.com/CaryLandholt"
+        }
+    ],
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/buildbot/buildbot"
+    },
+    "dependencies": {
+        "grunt": "~0.3.17",
+        "grunt-hustler": "~0.7.4",
+        "grunt-reload": "~0.2.0",
+        "grunt-jade": "~0.3.9"
+    },
+    "devDependencies": {
+        "coffee-script": "~1.4.0",
+        "testacular": "~0.5.5"
+    },
+    "engines": {
+        "node": "0.8.x",
+        "npm": "1.1.x"
+    }
+}
+""".replace('VERSION', version)
+
+## command classes
+
+cmdclass = {}
+class npm_install(Command):
+    """
+    Run 'npm install' to install all of the relevant npm modules
+    """
+
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        open("package.json", "w").write(package_json)
+        self.spawn(['npm', 'install'])
+
+cmdclass['npm_install'] = npm_install
+
+
+class grunt(Command):
+    """
+    Run grunt to update buildbot_www/
+    """
+
+    user_options = [
+        ('devel', 'd',
+         "Do not minify JS")
+        ]
+
+    sub_commands = [
+        ('npm_install', None)
+    ]
+
+    def initialize_options(self):
+        self.devel = False
+        self.bindir = None
+
+    def finalize_options(self):
+        pass
+
+    def get_bindir(self):
+        if not self.bindir:
+            p = subprocess.Popen(["npm", "bin"], stdout=subprocess.PIPE)
+            self.bindir = p.communicate()[0].strip()
+        return self.bindir
+
+    def run(self):
+        # bail out if we're not in SRC mode, since grunt won't work from
+        # an sdist tarball
+        if MODE != 'SRC':
+            return
+
+        for command in self.get_sub_commands():
+            self.run_command(command)
+
+        args = ['default'] if self.devel else ['prod']
+        bindir = self.get_bindir()
+        self.spawn([os.path.abspath(os.path.join(bindir, 'grunt'))] + args)
+
+cmdclass['grunt'] = grunt
+
+
+class install_www(Command):
+
+    description = "install WWW files"
+
+    user_options = [
+        ('install-dir=', 'd',
+         "base directory for installing WWW files "
+         "(default: `$install_lib/buildbot_www`)"),
+        ]
+
+    boolean_options = ['force']
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.outfiles = []
+
+    def finalize_options(self):
+        if not self.install_dir:
+            cmd = self.get_finalized_command('install')
+            self.install_dir = os.path.join(cmd.install_lib, 'buildbot_www')
+
+    def run(self):
+        out = self.copy_tree('buildbot_www', self.install_dir)
+        self.outfiles.extend(out)
+        (out, _) = self.copy_file('VERSION', self.install_dir)
+        self.outfiles.append(out)
+
+    def get_outputs(self):
+        return self.outfiles
+
+cmdclass['install_www'] = install_www
+
+
+class sdist(setuptools.command.sdist.sdist):
+    """
+    Customize sdist to run grunt first
+    """
+
+    def run(self):
+        if MODE == 'SRC':
+            self.run_command('grunt')
+        setuptools.command.sdist.sdist.run(self)
+
+cmdclass['sdist'] = sdist
+
+
+class install(setuptools.command.install.install):
+    """
+    Customize install to run grunt first, and to run install_js after.
+    """
+
+    sub_commands = setuptools.command.install.install.sub_commands + [
+        ('install_www', None)
+    ]
+
+    def run(self):
+        if MODE == 'SRC':
+            self.run_command('grunt')
+        setuptools.command.install.install.run(self)
+
+cmdclass['install'] = install
+
+
+setup(
+    name='buildbot-www',
+    version=version,
     description='Buildbot UI',
     author=u'Pierre Tardy',
     author_email=u'tardyp@gmail.com',
     url='http://buildbot.net/',
     license='GNU GPL',
     py_modules=['buildbot_www'],
-    data_files=make_data_files(),
+    cmdclass=cmdclass,
     entry_points="""
         [buildbot.www]
         base = buildbot_www:ep


Test patch: