diff --git a/Scripts/changelog_generator.py b/Scripts/changelog_generator.py new file mode 100755 index 000000000..9bde2ffa6 --- /dev/null +++ b/Scripts/changelog_generator.py @@ -0,0 +1,56 @@ +#!/bin/env python3 +import sys + +import fileinput +import re + +# Handles the following formats: +# +# -> goes in Misc category +# : -> Goes in +# /: -> Goes in / + +Meta = { } +for line in sys.stdin.readlines(): + if detailed := re.findall("^([A-Za-z0-9]+)/([A-Za-z0-9]+):(.+)$", line): + detailed = detailed[0] + meta = detailed[0].strip() + "/" + detailed[1].strip() + if meta not in Meta: + Meta[meta] = [] + Meta[meta].append(detailed[2].strip()) + elif category := re.findall("(^[A-Za-z0-9]+):(.+)$", line): + category = category[0] + if category[0].strip() not in Meta: + Meta[category[0].strip()] = [] + Meta[category[0].strip()].append(category[1].strip()) + else: + if "_Misc" not in Meta: + Meta["_Misc"] = [] + Meta["_Misc"].append(line.strip()) + +print(sys.argv[1]) + +Category = "" +Tag = "" +for item in sorted(Meta.items()): + if item[0] == "_Misc": + tag = "Misc" + else: + tag = item[0] + + category = tag.split("/")[0] + if category != Category: + Category = category + Tag = "" + print("") + print("- " + category) + if Tag != tag and tag != category: + Tag = tag + print("") + print(" - " + tag.split("/")[1]) + + for change in item[1]: + if Tag == "": + print(" - " + change) + else: + print(" - " + change) diff --git a/Scripts/doc_outline_generator.py b/Scripts/doc_outline_generator.py new file mode 100755 index 000000000..501a5e2df --- /dev/null +++ b/Scripts/doc_outline_generator.py @@ -0,0 +1,134 @@ +#!/usr/bin/python3 + +# Tag Format +# $info$ +# glossary: ~ (Optional, registers or replaces a glossary entry) +# glossary: IR ~ Intermidiate Representation, a of storage for our high-level opcode representation +# glossary: SSA ~ Single Static Assignment, a form of representing IR in memory +# glossary: Basic Block ~ A block of instructions with no control flow, terminated by control flow +# glossary: Fragment ~ A Collection of basic blocks, possible an entire guest function or a fraction of it +# category: ~ (Optional, registers or replaces a category description) +# category: backend ~ Concerns itself with generating binary code from (optimized) IR +# meta: ~ (Optional, registers or replaces a meta, aka tag, description) +# meta: backend|arm64 ~ Arm64 Splatter backend +# tags: [, , ...] (Required if info tag exists) +# tags: backend|arm64 +# desc: (Optional) +# desc: Main glue logic of the arm64 splatter backend +# $end_info$ + +import re +from pathlib import Path +import sys + +if (len(sys.argv) != 4): + print("doc_outline_generator GIT_DIR SRC_DIR LINK_PREFIX") + sys.exit(-2) + +Base = Path(sys.argv[1]) +Root = Path(sys.argv[2]) +Prefix = sys.argv[3] + +Paths = [] + +for path in Root.rglob('*.c'): + Paths.append(path) + +for path in Root.rglob('*.cpp'): + Paths.append(path) + +for path in Root.rglob('*.cc'): + Paths.append(path) + +for path in Root.rglob('*.h'): + Paths.append(path) + +for path in Root.rglob('*.hpp'): + Paths.append(path) + +CategoryLabels = { } +MetaLabels = { } +GlossaryLabels = { } + +Meta = { } +Desc = { } + +for path in Paths: + with path.open() as file: + txt = file.read() + x = re.findall("\$info\$([^\$]*)\$end_info\$", txt) + if x: + for entry in x[0].strip().split("\n"): + name = entry.split(":", 1)[0].strip(); + val = entry.split(":", 1)[1].strip(); + if name == "category": + cat_name = val.split("~", 1)[0].strip(); + cat_val = val.split("~", 1)[1].strip(); + CategoryLabels[cat_name] = cat_val + elif name == "meta": + meta_name = val.split("~", 1)[0].strip(); + meta_val = val.split("~", 1)[1].strip(); + MetaLabels[meta_name] = meta_val + elif name == "glossary": + glossary_name = val.split("~", 1)[0].strip(); + glossary_val = val.split("~", 1)[1].strip(); + GlossaryLabels[glossary_name] = glossary_val + elif name == "tags": + for meta_name in val.split(","): + if meta_name.strip() not in Meta: + Meta[meta_name.strip()] = [] + Meta[meta_name.strip()].append(path) + elif name == "desc": + Desc[path] = val; + else: + print("Error") + sys.exit(-1) + + +Readme = None +if (Root / "README.md").is_file(): + Readme = Root / "README.md" + +if (Root / "Readme.md").is_file(): + Readme = Root / "Readme.md" + +print("## " + Root.relative_to(Base).as_posix()) + +if Readme: + print("See [" + Root.name + "/" + Readme.name + "](" + Prefix + Readme.relative_to(Base).as_posix() + ") for more details") + +print("") + +if (GlossaryLabels): + print ("### Glossary") + print("") + for item in GlossaryLabels.items(): + print("- " + item[0] + ": " + item[1]) + print("") + print("") + +Category = "" +for item in sorted(Meta.items()): + meta = item[0] + category = meta.split("|")[0] + topic = meta.split("|")[1] + if Category != category: + if Category != "": + print("") + print("") + Category = category + print("### " + Category) + if Category in CategoryLabels: + print(CategoryLabels[Category]) + print("") + + print("#### " + topic) + if meta in MetaLabels: + print(MetaLabels[meta]) + + for path in sorted(item[1]): + if path in Desc: + print("- [" + path.name + "](" + Prefix + path.relative_to(Base).as_posix() + ")" + ": " + Desc[path]) + else: + print("- [" + path.name + "](" + Prefix + path.relative_to(Base).as_posix() + ")") + print("") diff --git a/Scripts/generate_changelog.sh b/Scripts/generate_changelog.sh new file mode 100755 index 000000000..49cb400a4 --- /dev/null +++ b/Scripts/generate_changelog.sh @@ -0,0 +1,7 @@ +#!/bin/env bash +if [ "$#" -ne 2 ]; +then +echo "$0: " +exit -1 +fi +git log "$1..HEAD" --pretty="%b (%h)" --abbrev-commit --merges | Scripts/changelog_generator.py "$2" diff --git a/Scripts/generate_doc_outline.sh b/Scripts/generate_doc_outline.sh new file mode 100755 index 000000000..4328ee6d1 --- /dev/null +++ b/Scripts/generate_doc_outline.sh @@ -0,0 +1,13 @@ +#!/bin/env bash +echo \# `git describe --always` +echo + +./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/External/FEXCore" "../" +./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/ThunkLibs" "../" +./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/Source/Tests" "../" +./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/unittests" "../" + +# These don't have useful documentation at this point +#./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/Scripts" "../" +#./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/Source/Common" "../" +#./Scripts/doc_outline_generator.py "`pwd`" "`pwd`/Source/CommonCore" "../" \ No newline at end of file diff --git a/Scripts/generate_release.sh b/Scripts/generate_release.sh new file mode 100755 index 000000000..612c84e4e --- /dev/null +++ b/Scripts/generate_release.sh @@ -0,0 +1,21 @@ +#!/bin/env bash + +if [ "$#" -ne 2 ]; +then +echo "$0: " +exit -1 +fi + + +echo "Tagging FEX-$2, previous release FEX-$1" +echo "Press cltr-c to cancel within 10 seconds" +sleep 10 + +git tag FEX-$2 -a -m "temporary" +Scripts/generate_doc_outline.sh > docs/SourceOutline.md +git commit docs/SourceOutline.md -m "Docs: Update for release FEX-$2" +git tad -d FEX-$2 +git tag FEX-$2 -a -m "$(Scripts/generate_changelog.sh FEX-$1 FEX-$2)" --edit + +echo "Inspect if everything went smoothly via 'git log -6 FEX-$2' " +echo "if all is good, do 'git push FEX-$2:FEX-$2'"