#!/usr/bin/env python import shutil import os import argparse import re import sys import knittingneedles as knit

# read in a tutorial, and check the structure of it. parser = argparse.ArgumentParser(

description="Extract specially formatted diffs from tutorials as a series of patches to apply"

) parser.add_argument(“tutorial”, type=argparse.FileType(“r”), help=“Input tutorial”) parser.add_argument(

"prefix", help="Some prefix for the output commit files to keep them separate"

) args = parser.parse_args()

fnparts = args.tutorial.name.split('/') fn_topic = fnparts[fnparts.index('tutorials') - 1] fn_tutorial = fnparts[fnparts.index('tutorials') + 1]

diffs = [] current = None currentCmd = None currentTest = None for line, text in enumerate(args.tutorial.read().split(“n”)):

m = re.match(knit.BOXES, text)
if m:
    depth = m.group(1).count(">")
else:
    depth = 0

(unprefixed, prefix) = knit.stripN(text, depth)
m1 = re.match(knit.BOX_OPEN, unprefixed)
m2 = re.match(knit.BOX_CLOSE, unprefixed)
c1 = re.match(knit.CMD_OPEN, unprefixed)
c2 = re.match(knit.CMD_CLOSE, unprefixed)
t1 = re.match(knit.TEST_OPEN, unprefixed)
t2 = re.match(knit.TEST_CLOSE, unprefixed)

if m1:
    if current is not None:
        diffs.append(current)
    current = []
elif current is not None:
    current.append(unprefixed)

if c1:
    if currentCmd is not None:
        diffs.append(currentCmd)
    currentCmd = []
elif currentCmd is not None:
    currentCmd.append(unprefixed)

if t1:
    if currentTest is not None:
        diffs.append(currentTest)
    currentTest = []
elif currentTest is not None:
    currentTest.append(unprefixed)

if current and len(current) > 2 and current[-2].strip() == "```" and not m2:
    current = None

if currentCmd and len(currentCmd) > 2 and currentCmd[-2].strip() == "```" and not c2:
    currentCmd = None

if currentTest and len(currentTest) > 2 and currentTest[-2].strip() == "```" and not t2:
    currentTest = None

# Tests are known short, same with commands. If we haven't exited by now, it's an issue..
if currentTest and len(currentTest) > 4:
    currentTest = None

# interesting = (t1, t2, currentCmd, currentTest)
# if any([x is not None for x in interesting]):
    # print(*interesting)

if m2:
    diffs.append(current)
    current = None

if c2:
    diffs.append(currentCmd)
    currentCmd = None

if t2:
    diffs.append(currentTest)
    currentTest = None

postfix = [“–”, “2.25.1”, “”, “”]

# import sys; sys.exit()

GITGAT = os.path.dirname(args.prefix) BASE = os.path.basename(args.prefix) BASE_PARTS = BASE.split('-')

cmdhandle = open(f“{GITGAT}/.scripts/{BASE}-run.sh”, 'w') cmdhandle.write(“#!/bin/bashn”) cmdhandle.write(“set -exnn”) cmdhandle.write(“# Install dependencies before changing commitsn”) cmdhandle.write(f“find .scripts -name requirements.txt | xargs –no-run-if-empty -n 1 pip install -rn”) cmdhandle.write('cat hosts | sed “s/^gat.*/$(hostname -f) ansible_connection=local ansible_user=$(whoami)/g” > ~/.hostsn')

cmdhandle.write('export GALAXY_HOSTNAME=“$(hostname -f)”n') cmdhandle.write('export GALAXY_API_KEY=adminkeyn') cmdhandle.write(“## The students should use a random password, we override with 'password' for reproducibilityn”) cmdhandle.write(“echo 'password' > ~/.vault-password.txt;n”) cmdhandle.write(“## And one in this directory, it can contain garbagen”) cmdhandle.write(“echo 'garbage' > ./.vault-password.txt;n”) # If it's after the ansible-galaxy tutorial if int(BASE_PARTS) > 10:

cmdhandle.write("## Ensure the galaxy user is setup\n")
cmdhandle.write("sudo -u galaxy /srv/galaxy/venv/bin/python /usr/bin/galaxy-create-user -c /srv/galaxy/config/galaxy.yml --user admin@example.org --password password --key adminkey --username admin\n")

lastCommit = None for idx, diff in enumerate(diffs):

if 'data-commit' in diff[-1]:
    commit_msg = knit.extractCommitMsg(diff)
    safe_commit = re.sub("[^a-z0-9-]", "-", commit_msg.lower())

    prefix = [
        "From: The Galaxy Training Network <galaxytrainingnetwork@gmail.com>",
        "Date: Mon, 15 Feb 2021 14:06:56 +0100",
        f"Subject: {fn_topic}/{fn_tutorial}/{idx:04d}: {commit_msg}",
        "",
        "",
    ]

    lastCommit = f"{fn_topic}/{fn_tutorial}/{idx:04d}"

    (_, diff) = knit.removeWhitespacePrefix(diff)

    patch_id = diff[-1]
    # Remove patch id, ```
    diff = diff[0:-2]
    if diff[-1] == "{% endraw %}":
        diff = diff[0:-1]

    fn = f"{args.prefix}-commit-{idx:04d}-{safe_commit}.patch"
    with open(fn, "w") as handle:
        print(fn)
        handle.write("\n".join(prefix + diff + postfix))
elif 'data-cmd' in diff[-1]:
    cmdhandle.write("\n# CMD\n")
    if lastCommit is not None:
        cmdhandle.write(f'## Checkout\ngit checkout $(git log main --pretty=oneline | grep "{lastCommit}" | cut -c1-40)\n')
    for line in diff[0:-2]:
        cmdhandle.write("## Run command\n")
        if 'ansible-playbook' in line:
            cmdhandle.write("if [[ -z ${GALAXY_VERSION} ]]; then\n")
            cmdhandle.write(line.strip() + " -i ~/.hosts --vault-password-file ~/.vault-password.txt\n")
            cmdhandle.write("else\n")
            cmdhandle.write(line.strip() + " -i ~/.hosts --vault-password-file ~/.vault-password.txt -e galaxy_commit_id=${GALAXY_VERSION}\n")
            cmdhandle.write("fi\n")
        else:
            line = line.strip()
            line = line.replace('https://your-galaxy', 'https://$(hostname -f)')
            line = line.replace('https://galaxy.example.org', 'https://$(hostname -f)')
            line = line.replace('<api-key>', 'adminkey')
            cmdhandle.write(line + "\n")
elif 'data-test' in diff[-1]:
    cmdhandle.write("\n# TEST\n")
    if lastCommit is not None:
        cmdhandle.write(f'## Checkout\ngit checkout $(git log main --pretty=oneline | grep "{lastCommit}" | cut -c1-40)\n')
    for line in diff[0:-2]:
        testdir = f"topics/{fn_topic}/tutorials/{fn_tutorial}/tests"
        gittestdir = f"{GITGAT}/.scripts/{BASE}-test"
        if os.path.exists(testdir) and not os.path.exists(gittestdir):
            shutil.copytree(testdir, gittestdir)

        cmdhandle.write("## Run test case\n")
        cmdhandle.write(f"./.scripts/{BASE}-test/{line.strip()}\n")
else:
    print("Unknown!")

cmdhandle.write(“# Done!ngit checkout mainn”)