| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 | #!/usr/bin/env pythonfrom __future__ import absolute_import, unicode_literalsimport errnoimport osimport reimport shleximport subprocessimport sysfrom contextlib import contextmanagerfrom tempfile import NamedTemporaryFilestr_t = str if sys.version_info[0] >= 3 else basestringdef rq(s):    return s.strip("\"'")def cmd(*args):    return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]@contextmanagerdef no_enoent():    try:        yield    except OSError as exc:        if exc.errno != errno.ENOENT:            raiseclass StringVersion(object):    def decode(self, s):        s = rq(s)        text = ''        major, minor, release = s.split('.')        if not release.isdigit():            pos = release.index(re.split('\d+', release)[1][0])            release, text = release[:pos], release[pos:]        return int(major), int(minor), int(release), text    def encode(self, v):        return '.'.join(map(str, v[:3])) + v[3]to_str = StringVersion().encodefrom_str = StringVersion().decodeclass TupleVersion(object):    def decode(self, s):        v = list(map(rq, s.split(', ')))        return (tuple(map(int, v[0:3])) +                tuple([''.join(v[3:])]))    def encode(self, v):        v = list(v)        def quote(lit):            if isinstance(lit, str_t):                return '"{0}"'.format(lit)            return str(lit)        if not v[-1]:            v.pop()        return ', '.join(map(quote, v))class VersionFile(object):    def __init__(self, filename):        self.filename = filename        self._kept = None    def _as_orig(self, version):        return self.wb.format(version=self.type.encode(version),                              kept=self._kept)    def write(self, version):        pattern = self.regex        with no_enoent():            with NamedTemporaryFile() as dest:                with open(self.filename) as orig:                    for line in orig:                        if pattern.match(line):                            dest.write(self._as_orig(version))                        else:                            dest.write(line)                os.rename(dest.name, self.filename)    def parse(self):        pattern = self.regex        gpos = 0        with open(self.filename) as fh:            for line in fh:                m = pattern.match(line)                if m:                    if '?P<keep>' in pattern.pattern:                        self._kept, gpos = m.groupdict()['keep'], 1                    return self.type.decode(m.groups()[gpos])class PyVersion(VersionFile):    regex = re.compile(r'^VERSION\s*=\s*\((.+?)\)')    wb = 'VERSION = ({version})\n'    type = TupleVersion()class SphinxVersion(VersionFile):    regex = re.compile(r'^:[Vv]ersion:\s*(.+?)$')    wb = ':Version: {version}\n'    type = StringVersion()class CPPVersion(VersionFile):    regex = re.compile(r'^\#\s*define\s*(?P<keep>\w*)VERSION\s+(.+)')    wb = '#define {kept}VERSION "{version}"\n'    type = StringVersion()_filetype_to_type = {'py': PyVersion,                     'rst': SphinxVersion,                     'txt': SphinxVersion,                     'c': CPPVersion,                     'h': CPPVersion}def filetype_to_type(filename):    _, _, suffix = filename.rpartition('.')    return _filetype_to_type[suffix](filename)def bump(*files, **kwargs):    version = kwargs.get('version')    before_commit = kwargs.get('before_commit')    files = [filetype_to_type(f) for f in files]    versions = [v.parse() for v in files]    current = list(reversed(sorted(versions)))[0]  # find highest    current = current.split()[0]  # only first sentence    if version:        next = from_str(version)    else:        major, minor, release, text = current        if text:            raise Exception("Can't bump alpha releases")        next = (major, minor, release + 1, text)    print('Bump version from {0} -> {1}'.format(to_str(current), to_str(next)))    for v in files:        print('  writing {0.filename!r}...'.format(v))        v.write(next)    if before_commit:        cmd(*shlex.split(before_commit))    print(cmd('git', 'commit', '-m', 'Bumps version to {0}'.format(        to_str(next)), *[f.filename for f in files]))    print(cmd('git', 'tag', 'v{0}'.format(to_str(next))))def main(argv=sys.argv, version=None, before_commit=None):    if not len(argv) > 1:        print('Usage: distdir [docfile] -- <custom version>')        sys.exit(0)    args = []    for arg in argv:        if arg.startswith('--before-commit='):            _, before_commit = arg.split('=')        else:            args.append(arg)    if '--' in args:        c = args.index('--')        version = args[c + 1]        argv = args[:c]    bump(*args[1:], version=version, before_commit=before_commit)if __name__ == '__main__':    main()
 |