Automatic Buildout Updates
==========================

When a buildout is run, one of the first steps performed is to check
for updates to either zc.buildout or setuptools.  To demonstrate this,
we've creates some "new releases" of buildout and setuptools in a
new_releases folder:

    >>> ls(new_releases)
    d  setuptools
    -  setuptools-99.99-py2.4.egg
    d  zc.buildout
    -  zc.buildout-99.99-py2.4.egg

Let's update the sample buildout.cfg to look in this area:

    >>> write(sample_buildout, 'buildout.cfg',
    ... """
    ... [buildout]
    ... find-links = %(new_releases)s
    ... index = %(new_releases)s
    ... parts = show-versions
    ... develop = showversions
    ... 
    ... [show-versions]
    ... recipe = showversions
    ... """ % dict(new_releases=new_releases))

We'll also include a recipe that echos the versions of setuptools and
zc.buildout used:

    >>> mkdir(sample_buildout, 'showversions')

    >>> write(sample_buildout, 'showversions', 'showversions.py', 
    ... """
    ... import pkg_resources
    ...
    ... class Recipe:
    ...
    ...     def __init__(self, buildout, name, options):
    ...         pass
    ...
    ...     def install(self):
    ...         for project in 'zc.buildout', 'setuptools':
    ...             req = pkg_resources.Requirement.parse(project)
    ...             print project, pkg_resources.working_set.find(req).version
    ...         return ()
    ...     update = install
    ... """)


    >>> write(sample_buildout, 'showversions', 'setup.py',
    ... """
    ... from setuptools import setup
    ... 
    ... setup(
    ...     name = "showversions",
    ...     entry_points = {'zc.buildout': ['default = showversions:Recipe']},
    ...     )
    ... """)


Now if we run the buildout, the buildout will upgrade itself to the
new versions found in new releases:

    >>> print system(buildout),
    Getting distribution for 'zc.buildout'.
    Got zc.buildout 99.99.
    Getting distribution for 'setuptools'.
    Got setuptools 99.99.
    Upgraded:
      zc.buildout version 99.99,
      setuptools version 99.99;
    restarting.
    Generated script '/sample-buildout/bin/buildout'.
    Develop: '/sample-buildout/showversions'
    Installing show-versions.
    zc.buildout 99.99
    setuptools 99.99

Our buildout script has been updated to use the new eggs:

    >>> cat(sample_buildout, 'bin', 'buildout') 
    #!/usr/local/bin/python2.4
    <BLANKLINE>
    import sys
    sys.path[0:0] = [
      '/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
      '/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
      ]
    <BLANKLINE>
    import zc.buildout.buildout
    <BLANKLINE>
    if __name__ == '__main__':
        zc.buildout.buildout.main()

There are a number of cases in which the updates don't happen.
Let's recreate the sample buildout. One case is the one in which we
specify versions of zc.buildout and setuptools for which the don't
match. If we update out configuration file to specify an older
version:

    >>> write(sample_buildout, 'buildout.cfg',
    ... """
    ... [buildout]
    ... find-links = %(new_releases)s
    ... index = %(new_releases)s
    ... parts = show-versions
    ... develop = showversions
    ... zc.buildout-version = < 99
    ... setuptools-version = < 99
    ... 
    ... [show-versions]
    ... recipe = showversions
    ... """ % dict(new_releases=new_releases))

We'll actually "upgrade" to an earlier version.

    >>> print system(buildout),
    Upgraded:
      zc.buildout version 1.0.0,
      setuptools version 0.6;
    restarting.
    Generated script '/sample-buildout/bin/buildout'.
    Develop: '/sample-buildout/showversions'
    Updating show-versions.
    zc.buildout 1.0.0
    setuptools 0.6

We won't upgrade in offline mode:

    >>> write(sample_buildout, 'buildout.cfg',
    ... """
    ... [buildout]
    ... find-links = %(new_releases)s
    ... index = %(new_releases)s
    ... parts = show-versions
    ... develop = showversions
    ... 
    ... [show-versions]
    ... recipe = showversions
    ... """ % dict(new_releases=new_releases))

    >>> print system(buildout+' -o'),
    Develop: '/sample-buildout/showversions'
    Updating show-versions.
    zc.buildout 1.0.0
    setuptools 0.6

Or in non-newest mode:

    >>> print system(buildout+' -N'),
    Develop: '/sample-buildout/showversions'
    Updating show-versions.
    zc.buildout 1.0.0
    setuptools 0.6

We also won't upgrade if the buildout script bing run isn't in the
buildouts bin directory.  To see this we'll create a new buildout
directory:

    >>> sample_buildout2 = tmpdir('sample_buildout2')
    >>> write(sample_buildout2, 'buildout.cfg',
    ... """
    ... [buildout]
    ... find-links = %(new_releases)s
    ... index = %(new_releases)s
    ... parts = 
    ... """ % dict(new_releases=new_releases))
    
    >>> cd(sample_buildout2)
    >>> print system(buildout),
    Creating directory '/sample_buildout2/bin'.
    Creating directory '/sample_buildout2/parts'.
    Creating directory '/sample_buildout2/eggs'.
    Creating directory '/sample_buildout2/develop-eggs'.
    Getting distribution for 'zc.buildout'.
    Got zc.buildout 99.99.
    Getting distribution for 'setuptools'.
    Got setuptools 99.99.
    Not upgrading because not running a local buildout command.

    >>> ls('bin')
