!/usr/bin/env python import argparse import re import sys import knittingneedles as knit
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(
"--patches", nargs='+', help="The patches to knit together with the tutorial"
) args = parser.parse_args() tutorial_contents = args.tutorial.read().split(“n”) chunks = []
# load patches diffs = [] for patch in args.patches:
with open(patch, "r") as handle:
data = handle.readlines()
subject = [x for x in data[0:5] if x.startswith('Subject:')]
if len(subject) != 1:
commit = "MISSING"
else:
if subject[0].count(": ") >= 2:
commit = subject[0].split(": ")[2]
else:
commit = "MISSING"
indexindex = [idx for (idx, x) in enumerate(data) if x.startswith('index ')]
if len(indexindex) == 0:
# take a guess, it's our format?
data = [x.rstrip("\n") for x in data[5:-3]]
else:
# If 'index ' then we start at the next line
data = [x.rstrip("\n") for x in data[indexindex[0] + 1:-3]]
diffs.append((commit, data))
current = None diff_idx = 0 prev_line = None for line, text in enumerate(tutorial_contents):
m = re.match(knit.BOXES, text)
if m:
depth = m.group(1).count(">")
else:
depth = 0
(unprefixed, prefix) = knit.stripN(text, depth)
m0 = re.match(knit.BOX_PREFIX, unprefixed)
m1 = re.match(knit.BOX_OPEN, unprefixed)
m2 = re.match(knit.BOX_CLOSE, unprefixed)
if m0:
current = []
if m1 and current is None:
current = []
if current is not None:
current.append(unprefixed)
else:
chunks.append(text)
if current and len(current) > 2 and (current[-2].strip() == "```") and not m2:
chunks.extend([prefix + x for x in current])
# chunks.append('REJECT)')
current = None
if m2 and current and len(current) > 0:
(amount, _) = knit.removeWhitespacePrefix(current)
prefix_text = prefix + (amount * " ")
from_patch = diffs[diff_idx]
# Compare the diff messages
obs_msg = knit.extractCommitMsg(current).strip()
exp_msg = from_patch[0].strip()
obs_extra = m2.groups()[1]
if obs_msg != exp_msg:
# Most just got truncated
if exp_msg not in obs_msg:
print(f"WARNING: Diff messages do NOT line up: {obs_msg} != {exp_msg}")
# Replace with current message
exp_msg = obs_msg
# Knit it anyway
new_diff = from_patch[1]
chunks.append(prefix_text + "{% raw %}")
chunks.append(prefix_text + "```diff")
chunks.extend([f'{prefix}{amount * " "}{line}' for line in new_diff])
chunks.append(prefix_text + "{% endraw %}")
chunks.append(prefix_text + "```")
chunks.append(prefix_text + '{: data-commit="%s"%s}' % (exp_msg, obs_extra))
diff_idx += 1
current = None
prev_line = text
# Overwrite the original tutorial args.tutorial.seek(0) args.tutorial.truncate(0) # The last chunk is a newline for some reason. for c in chunks:
args.tutorial.write(c + "\n")
args.tutorial.close()