view gub/versiondb.py @ 6512:ccc20ae889ca default tip guix

mingw::guile-2.0.7 builds.
author Jan Nieuwenhuizen <janneke@gnu.org>
date Thu, 24 Mar 2016 08:03:39 +0100
parents eb85697e7f2a
children
line wrap: on
line source

#!/usr/bin/env python

"""
    Copyright (c) 2005--2007
    Jan Nieuwenhuizen <janneke@gnu.org>
    Han-Wen Nienhuys <hanwen@xs4all.nl>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write toth e Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""

import re
import urllib
import string
import pickle
import optparse
import os
import sys
#
from gub import misc
from gub.syntax import printf

def get_url_versions (url):
    printf (url)
    opener = urllib.URLopener ()
    index = opener.open (url).read ()

    versions = []
    def note_version (m):
        name = m.group (2)
        version = tuple (map (int,  m.group (3).split ('.')))
        build = 0
        build_url = url + re.sub ("(HREF|href)=", '', m.group (0))
        build_url = build_url.replace ('"', "")

        # disregard buildnumber for src tarball.
        if m.group (4):
            build = int (m.group (5))

        versions.append ((name, version, build, build_url))

        return ''

    # [^0-9] is to force that version no is not swalled by name. Check this for cygwin libfoo3
    # packages
    re.sub (r'(HREF|href)="(.*[^0-9])-([0-9.]+)(-([0-9]+))?\.[0-9a-z-]+\.[.0-9a-z-]+"', note_version, index)

    return versions

class VersionDataBase:
    def __init__ (self, file_name):
        self._db = {}
        self.file_name = file_name
        self.platforms = list ()
        if os.path.exists (file_name):
            self.read ()

    def get_sources_from_url (self, url):

        ## ugh: should follow urls in the index.
        directories = ['v0.0', 'v0.1', 'v1.0', 'v1.1', 'v1.2', 'v1.3',
                       'v1.4', 'v1.5', 'v1.6', 'v1.7', 'v1.8', 'v1.9',
                       'v2.0', 'v2.1', 'v2.2', 'v2.3', 'v2.4', 'v2.5',
                       'v2.6', 'v2.7', 'v2.8', 'v2.9', 'v2.10', 'v2.11',
                       'v2.12','v2.13',]

        sources = []
        for d in directories:
            # FIXME: this / is necessary to prevent 301 redirection
            u = '%(url)ssources/%(d)s/' % locals ()
            sources += get_url_versions (u)
        self._db['source'] = sources

    def get_binaries_from_url (self, url):
        package = os.path.basename (os.path.splitext (self.file_name)[0])
        for p in self.platforms:
            if p == 'source':
                continue

            u = '%(url)sbinaries/%(p)s/' % locals ()

            if p == 'cygwin':
                u += 'release/%(package)s/' % locals ()

            try:
                self._db[p] = get_url_versions (u)
            except:
                t, v, b = sys.exc_info ()
                if t == IOError:
                    printf ('problem loading', u)
                    sys.path.insert (0, 'gub')
                    # FIXME: do want to be inside gub framework or not?
                    printf (misc.exception_string (v))
                    continue
                raise

    def write (self):
        open (self.file_name, 'wb').write (pickle.dumps ((self.platforms,
                                                          self._db),
                                                         protocol=2))

    def read (self):
        (self.platforms,
         self._db) = pickle.loads (open (self.file_name, 'rb').read ())

    ## UI functions:
    def get_next_build_number (self, version_tuple):
        assert (type (version_tuple) == type (()))
        sub_db = {}
        for platform in self.platforms:
            sub_db[platform] = [0]
            if platform in self._db:
                sub_db[platform] = [buildnum
                                    for (name, version, buildnum, url)
                                    in self._db[platform]
                                    if version == version_tuple]
        return max ([max (bs + [0]) for (p, bs) in list (sub_db.items ())] + [-1]) + 1

    def get_last_release (self, platform, version_tuple):
        candidates = [(v, b, url) for (name, v, b, url) in  self._db[platform]
                      if v[:len (version_tuple)] == version_tuple]
        candidates.append ( ((0,0,0), 0, '/dev/null' ))
        candidates.sort ()
        return candidates[-1]

def get_cli_parser ():
    p = optparse.OptionParser ()

    p.usage='''versiondb.py  [OPTION]... COMMAND [PACKAGE]...

Inspect lilypond.org download area, and write pickle of all version numbers.

'''
    p.description='Grand Unified Builder.  Specify --package-version to set build version'

    p.add_option ('--version-db', action='store',
                  dest='version_db',
                  help='Pickle of version dict',
                  default='versiondb/lilypond.versions')

    p.add_option ('--url', action='store',
                  dest='url',
                  default='http://lilypond.org/download/',
                  help='download url')

    p.add_option ('--download', action='store_true',
                  dest='download',
                  default=False,
                  help='download new versions')

    p.add_option ('--no-sources', action='store_false',
                  dest='do_sources',
                  default=True,
                  help='do not look for versions of sources')

    p.add_option ('--build-for', action='store',
                  dest='version',
                  default='',
                  help='print build number for version')

    p.add_option ('--test', action='store_true',
                  dest='test',
                  default=False,
                  help='self test')

    p.add_option ('--platforms', action='store',
                  dest='platforms',
                  default='',
                  help='platforms to inspect; space separated')

    return p

def main ():
    cli_parser = get_cli_parser ()
    (options, files) = cli_parser.parse_args ()

    if options.url and not options.url.endswith ('/'):
        options.url += "/"

    options.platforms = re.sub ('[, ]+', ' ', options.platforms)
    if not options.platforms:
        sys.stderr.write ("need --platforms definition")
        sys.exit (1)

    db = VersionDataBase (options.version_db)
    db.platforms = options.platforms.split (' ')

    if options.test:
        printf ('2.9.28:', db.get_next_build_number ((2,9,28)))
        printf ('2.8.2:', db.get_next_build_number ((2,8,2)))
        printf ('2.9.28:', db.get_next_build_number ((2,9,28)))
        printf ('2.8.2:', db.get_next_build_number ((2,8,2)))
        printf ('2.10.0 next:', db.get_next_build_number ((2,10,0)))

        printf ('last mingw 2.9.26:', db.get_last_release ('mingw', (2,9,26)))
        printf ('last mingw 2.9:', db.get_last_release ('mingw', (2,9)))
        printf ('last mingw 2.9:', db.get_last_release ('mingw', (2,)))
        printf ('last source:', db.get_last_release ('source', ()))
        return

    if options.download:

        ##ugh
        if options.do_sources:
            db.get_sources_from_url (options.url)

        db.get_binaries_from_url (options.url)
        db.write ()

    if options.version:
        v = tuple (map (int, options.version.split ('.')))
        printf (db.get_next_build_number (v))


if __name__ == '__main__':
    main ()