<commit_before>#!/usr/bin/env python3
from distutils.version import StrictVersion
import os
import re
import requests
import subprocess
import sys
import tempfile

from client.api import assignment
from client.utils import auth

GITHUB_TOKEN_FILE = '.github-token'
GITHUB_REPO = 'Cal-CS-61A-Staff/ok-client'
OK_SERVER_URL = 'https://okpy.org'

def abort(message=None):
    if message:
        print('ERROR:', message, file=sys.stderr)
    sys.exit(1)

def shell(command, capture_output=False):
    kwargs = dict(shell=True, check=True)
    if capture_output:
        kwargs.update(stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    else:
        print('>', command)
    try:
        output = subprocess.run(command, **kwargs)
    except subprocess.CalledProcessError as e:
        print(str(e), file=sys.stderr)
        if capture_output:
            print(e.stderr.decode('utf-8'), file=sys.stderr)
        abort()
    if capture_output:
        return output.stdout.decode('utf-8').strip()

def edit(text):
    # from Mercurial sources:
    # https://selenic.com/repo/hg-stable/file/2770d03ae49f/mercurial/ui.py#l318
    (fd, name) = tempfile.mkstemp(
        prefix='ok-client-release-', suffix='.txt', text=True)
    try:
        f = os.fdopen(fd, 'w')
        f.write(text)
        f.close()

        editor = os.environ.get('EDITOR', 'vi')
        shell('{} \"{}\"'.format(editor, name))
        f = open(name)
        t = f.read()
        f.close()
    finally:
        os.unlink(name)
    return t

def post_request(url, *args, **kwargs):
    try:
        print('POST', url)
        r = requests.post(url, *args, **kwargs)
        r.raise_for_status()
    except Exception as e:
        abort(str(e))
    return r.json()

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Usage: {} NEW_VERSION'.format(sys.argv[0]), file=sys.stderr)
        abort()
    new_release = sys.argv[1]

    # change to directory that script is in; should be root of project
    os.chdir(os.path.dirname(os.path.realpath(__file__)))

    # read GitHub token
    try:
        with open(GITHUB_TOKEN_FILE, 'r') as f:
            github_token = f.read().strip()
    except (OSError, IOError) as e:
        print('No GitHub access token found.', file=sys.stderr)
        print('Generate an access token with the "repo" scope as per', file=sys.stderr)
        print('https://help.github.com/articles/creating-an-access-token-for-command-line-use/', file=sys.stderr)
        print('and paste the token into a file named "{}".'.format(GITHUB_TOKEN_FILE), file=sys.stderr)
        abort()

    if new_release[:1] != 'v':
        abort("Version must start with 'v'")
    if shell('git rev-parse --abbrev-ref HEAD', capture_output=True) != 'master':
        abort('You must be on master to release a new version')
    shell('git pull --ff-only')

    # find latest release
    latest_release = shell('git describe --tags --abbrev=0', capture_output=True)
    latest_release_commit = shell('git rev-list -n 1 {}'.format(latest_release),
        capture_output=True)

    print('Latest version: {} ({})'.format(latest_release, latest_release_commit[:7]))
    print('New version: {}'.format(new_release))

    # run tests
    shell('nosetests tests')

    # check that release numbers are sane
    try:
        latest_version = StrictVersion(latest_release[1:])
        new_version = StrictVersion(new_release[1:])
    except ValueError as e:
        abort(str(e))
    if latest_version >= new_version:
        abort('Version numbers must be increasing')
    elif new_version.version[0] > latest_version.version[0] + 1:
        abort('Major version number cannot increase by more than one')

    # edit changelog message
    log = shell('git log --pretty=format:"- %s" {}..HEAD'.format(latest_release),
        capture_output=True)
    changelog = edit('\n'.join([
        'Changelog',
        log,
        '',
        '# Please enter a changelog since the latest release. Lines starting',
        "# with '#' will be ignored, and an empty message aborts the release.",
    ]))
    log_lines = [line for line in changelog.splitlines() if line[:1] != '#']
    changelog = '\n'.join(log_lines).strip()
    if not changelog:
        abort('Empty changelog, aborting')<commit_msg>Add a colon to the changelog<commit_after>#!/usr/bin/env python3
from distutils.version import StrictVersion
import os
import re
import requests
import subprocess
import sys
import tempfile

from client.api import assignment
from client.utils import auth

GITHUB_TOKEN_FILE = '.github-token'
GITHUB_REPO = 'Cal-CS-61A-Staff/ok-client'
OK_SERVER_URL = 'https://okpy.org'

def abort(message=None):
    if message:
        print('ERROR:', message, file=sys.stderr)
    sys.exit(1)

def shell(command, capture_output=False):
    kwargs = dict(shell=True, check=True)
    if capture_output:
        kwargs.update(stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    else:
        print('>', command)
    try:
        output = subprocess.run(command, **kwargs)
    except subprocess.CalledProcessError as e:
        print(str(e), file=sys.stderr)
        if capture_output:
            print(e.stderr.decode('utf-8'), file=sys.stderr)
        abort()
    if capture_output:
        return output.stdout.decode('utf-8').strip()

def edit(text):
    # from Mercurial sources:
    # https://selenic.com/repo/hg-stable/file/2770d03ae49f/mercurial/ui.py#l318
    (fd, name) = tempfile.mkstemp(
        prefix='ok-client-release-', suffix='.txt', text=True)
    try:
        f = os.fdopen(fd, 'w')
        f.write(text)
        f.close()

        editor = os.environ.get('EDITOR', 'vi')
        shell('{} \"{}\"'.format(editor, name))
        f = open(name)
        t = f.read()
        f.close()
    finally:
        os.unlink(name)
    return t

def post_request(url, *args, **kwargs):
    try:
        print('POST', url)
        r = requests.post(url, *args, **kwargs)
        r.raise_for_status()
    except Exception as e:
        abort(str(e))
    return r.json()

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Usage: {} NEW_VERSION'.format(sys.argv[0]), file=sys.stderr)
        abort()
    new_release = sys.argv[1]

    # change to directory that script is in; should be root of project
    os.chdir(os.path.dirname(os.path.realpath(__file__)))

    # read GitHub token
    try:
        with open(GITHUB_TOKEN_FILE, 'r') as f:
            github_token = f.read().strip()
    except (OSError, IOError) as e:
        print('No GitHub access token found.', file=sys.stderr)
        print('Generate an access token with the "repo" scope as per', file=sys.stderr)
        print('https://help.github.com/articles/creating-an-access-token-for-command-line-use/', file=sys.stderr)
        print('and paste the token into a file named "{}".'.format(GITHUB_TOKEN_FILE), file=sys.stderr)
        abort()

    if new_release[:1] != 'v':
        abort("Version must start with 'v'")
    if shell('git rev-parse --abbrev-ref HEAD', capture_output=True) != 'master':
        abort('You must be on master to release a new version')
    shell('git pull --ff-only')

    # find latest release
    latest_release = shell('git describe --tags --abbrev=0', capture_output=True)
    latest_release_commit = shell('git rev-list -n 1 {}'.format(latest_release),
        capture_output=True)

    print('Latest version: {} ({})'.format(latest_release, latest_release_commit[:7]))
    print('New version: {}'.format(new_release))

    # run tests
    shell('nosetests tests')

    # check that release numbers are sane
    try:
        latest_version = StrictVersion(latest_release[1:])
        new_version = StrictVersion(new_release[1:])
    except ValueError as e:
        abort(str(e))
    if latest_version >= new_version:
        abort('Version numbers must be increasing')
    elif new_version.version[0] > latest_version.version[0] + 1:
        abort('Major version number cannot increase by more than one')

    # edit changelog message
    log = shell('git log --pretty=format:"- %s" {}..HEAD'.format(latest_release),
        capture_output=True)
    changelog = edit('\n'.join([
        'Changelog:',
        log,
        '',
        '# Please enter a changelog since the latest release. Lines starting',
        "# with '#' will be ignored, and an empty message aborts the release.",
    ]))
    log_lines = [line for line in changelog.splitlines() if line[:1] != '#']
    changelog = '\n'.join(log_lines).strip()
    if not changelog:
        abort('Empty changelog, aborting')
{'fraction_non_alphanumeric': 0.13792700046794573, 'fraction_numerical': 0.0070191857744501636, 'mean_word_length': 2.9000912408759123, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1393349', 'n_tokens_mistral': 2761, 'n_tokens_neox': 2726, 'n_words': 682}