|
|
@ -1,23 +1,13 @@ |
|
|
|
#!/usr/bin/env python |
|
|
|
#!/usr/bin/env python |
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
make-release |
|
|
|
|
|
|
|
~~~~~~~~~~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Helper script that performs a release. Does pretty much everything |
|
|
|
|
|
|
|
automatically for us. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:copyright: (c) 2015 by Armin Ronacher. |
|
|
|
|
|
|
|
:license: BSD, see LICENSE for more details. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
from __future__ import print_function |
|
|
|
from __future__ import print_function |
|
|
|
import sys |
|
|
|
|
|
|
|
import os |
|
|
|
import os |
|
|
|
import re |
|
|
|
import re |
|
|
|
from datetime import datetime, date |
|
|
|
import sys |
|
|
|
from subprocess import Popen, PIPE |
|
|
|
from datetime import date, datetime |
|
|
|
|
|
|
|
from subprocess import PIPE, Popen |
|
|
|
|
|
|
|
|
|
|
|
_date_clean_re = re.compile(r'(\d+)(st|nd|rd|th)') |
|
|
|
_date_strip_re = re.compile(r'(?<=\d)(st|nd|rd|th)') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_changelog(): |
|
|
|
def parse_changelog(): |
|
|
@ -25,18 +15,27 @@ def parse_changelog(): |
|
|
|
lineiter = iter(f) |
|
|
|
lineiter = iter(f) |
|
|
|
for line in lineiter: |
|
|
|
for line in lineiter: |
|
|
|
match = re.search('^Version\s+(.*)', line.strip()) |
|
|
|
match = re.search('^Version\s+(.*)', line.strip()) |
|
|
|
|
|
|
|
|
|
|
|
if match is None: |
|
|
|
if match is None: |
|
|
|
continue |
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
version = match.group(1).strip() |
|
|
|
version = match.group(1).strip() |
|
|
|
if lineiter.next().count('-') != len(match.group(0)): |
|
|
|
|
|
|
|
|
|
|
|
if next(lineiter).count('-') != len(match.group(0)): |
|
|
|
continue |
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
while 1: |
|
|
|
while 1: |
|
|
|
change_info = lineiter.next().strip() |
|
|
|
change_info = next(lineiter).strip() |
|
|
|
|
|
|
|
|
|
|
|
if change_info: |
|
|
|
if change_info: |
|
|
|
break |
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
match = re.search(r'released on (\w+\s+\d+\w+\s+\d+)' |
|
|
|
match = re.search( |
|
|
|
r'(?:, codename (.*))?(?i)', change_info) |
|
|
|
r'released on (\w+\s+\d+\w+\s+\d+)(?:, codename (.*))?', |
|
|
|
|
|
|
|
change_info, |
|
|
|
|
|
|
|
flags=re.IGNORECASE |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
if match is None: |
|
|
|
if match is None: |
|
|
|
continue |
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
@ -46,15 +45,16 @@ def parse_changelog(): |
|
|
|
|
|
|
|
|
|
|
|
def bump_version(version): |
|
|
|
def bump_version(version): |
|
|
|
try: |
|
|
|
try: |
|
|
|
parts = map(int, version.split('.')) |
|
|
|
parts = [int(i) for i in version.split('.')] |
|
|
|
except ValueError: |
|
|
|
except ValueError: |
|
|
|
fail('Current version is not numeric') |
|
|
|
fail('Current version is not numeric') |
|
|
|
|
|
|
|
|
|
|
|
parts[-1] += 1 |
|
|
|
parts[-1] += 1 |
|
|
|
return '.'.join(map(str, parts)) |
|
|
|
return '.'.join(map(str, parts)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_date(string): |
|
|
|
def parse_date(string): |
|
|
|
string = _date_clean_re.sub(r'\1', string) |
|
|
|
string = _date_strip_re.sub('', string) |
|
|
|
return datetime.strptime(string, '%B %d %Y') |
|
|
|
return datetime.strptime(string, '%B %d %Y') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -65,9 +65,13 @@ def set_filename_version(filename, version_number, pattern): |
|
|
|
before, old, after = match.groups() |
|
|
|
before, old, after = match.groups() |
|
|
|
changed.append(True) |
|
|
|
changed.append(True) |
|
|
|
return before + version_number + after |
|
|
|
return before + version_number + after |
|
|
|
|
|
|
|
|
|
|
|
with open(filename) as f: |
|
|
|
with open(filename) as f: |
|
|
|
contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern, |
|
|
|
contents = re.sub( |
|
|
|
inject_version, f.read()) |
|
|
|
r"^(\s*%s\s*=\s*')(.+?)(')" % pattern, |
|
|
|
|
|
|
|
inject_version, f.read(), |
|
|
|
|
|
|
|
flags=re.DOTALL | re.MULTILINE |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
if not changed: |
|
|
|
if not changed: |
|
|
|
fail('Could not find %s in %s', pattern, filename) |
|
|
|
fail('Could not find %s in %s', pattern, filename) |
|
|
@ -81,8 +85,9 @@ def set_init_version(version): |
|
|
|
set_filename_version('flask/__init__.py', version, '__version__') |
|
|
|
set_filename_version('flask/__init__.py', version, '__version__') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_and_upload(): |
|
|
|
def build(): |
|
|
|
Popen([sys.executable, 'setup.py', 'release', 'sdist', 'bdist_wheel', 'upload']).wait() |
|
|
|
cmd = [sys.executable, 'setup.py', 'sdist', 'bdist_wheel'] |
|
|
|
|
|
|
|
Popen(cmd).wait() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fail(message, *args): |
|
|
|
def fail(message, *args): |
|
|
@ -95,7 +100,9 @@ def info(message, *args): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_git_tags(): |
|
|
|
def get_git_tags(): |
|
|
|
return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines()) |
|
|
|
return set( |
|
|
|
|
|
|
|
Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines() |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def git_is_clean(): |
|
|
|
def git_is_clean(): |
|
|
@ -116,29 +123,40 @@ def main(): |
|
|
|
os.chdir(os.path.join(os.path.dirname(__file__), '..')) |
|
|
|
os.chdir(os.path.join(os.path.dirname(__file__), '..')) |
|
|
|
|
|
|
|
|
|
|
|
rv = parse_changelog() |
|
|
|
rv = parse_changelog() |
|
|
|
|
|
|
|
|
|
|
|
if rv is None: |
|
|
|
if rv is None: |
|
|
|
fail('Could not parse changelog') |
|
|
|
fail('Could not parse changelog') |
|
|
|
|
|
|
|
|
|
|
|
version, release_date, codename = rv |
|
|
|
version, release_date, codename = rv |
|
|
|
dev_version = bump_version(version) + '-dev' |
|
|
|
dev_version = bump_version(version) + '.dev' |
|
|
|
|
|
|
|
|
|
|
|
info('Releasing %s (codename %s, release date %s)', |
|
|
|
info( |
|
|
|
version, codename, release_date.strftime('%d/%m/%Y')) |
|
|
|
'Releasing %s (codename %s, release date %s)', |
|
|
|
|
|
|
|
version, codename, release_date.strftime('%d/%m/%Y') |
|
|
|
|
|
|
|
) |
|
|
|
tags = get_git_tags() |
|
|
|
tags = get_git_tags() |
|
|
|
|
|
|
|
|
|
|
|
if version in tags: |
|
|
|
if version in tags: |
|
|
|
fail('Version "%s" is already tagged', version) |
|
|
|
fail('Version "%s" is already tagged', version) |
|
|
|
|
|
|
|
|
|
|
|
if release_date.date() != date.today(): |
|
|
|
if release_date.date() != date.today(): |
|
|
|
fail('Release date is not today (%s != %s)', |
|
|
|
fail( |
|
|
|
release_date.date(), date.today()) |
|
|
|
'Release date is not today (%s != %s)', |
|
|
|
|
|
|
|
release_date.date(), date.today() |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
if not git_is_clean(): |
|
|
|
if not git_is_clean(): |
|
|
|
fail('You have uncommitted changes in git') |
|
|
|
fail('You have uncommitted changes in git') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
import wheel # noqa: F401 |
|
|
|
|
|
|
|
except ImportError: |
|
|
|
|
|
|
|
fail('You need to install the wheel package.') |
|
|
|
|
|
|
|
|
|
|
|
set_init_version(version) |
|
|
|
set_init_version(version) |
|
|
|
make_git_commit('Bump version number to %s', version) |
|
|
|
make_git_commit('Bump version number to %s', version) |
|
|
|
make_git_tag(version) |
|
|
|
make_git_tag(version) |
|
|
|
build_and_upload() |
|
|
|
build() |
|
|
|
set_init_version(dev_version) |
|
|
|
set_init_version(dev_version) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|