1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
#!/usr/bin/env bash
set -eEuo pipefail
sort_authors() {
# Unify author aliases.
sed -e 's/^dibyendumajumdar <mobile@majumdar\.org\.uk>$/Dibyendu Majumdar <mobile@majumdar.org.uk>/g' \
-e 's/^Dibyendu Majumdar <dibyendumajumdar@users\.noreply\.github\.com>$/Dibyendu Majumdar <mobile@majumdar.org.uk>/g' |
# Rank by number of commits.
sort | uniq -c | sort -nr | sed -E 's/^ *[0-9]+ //'
}
IFS=$'\n'
mkdir linear
cd linear
git init -q -b main
repo=..
last_committer_date='0 +0000'
git -C "$repo" ls-tree HEAD --name-only | grep '^chapter' |
while read -r chapter; do
echo "Processing $chapter"
chapter_number="$(sed 's/^chapter0*//' <<< "$chapter")"
if [[ ! -f "$repo/$chapter/README.md" ]]; then
echo "Missing $chapter/READMD.md" >&2
echo "# Chapter $chapter_number" > "$repo/$chapter/README.md"
fi
chapter_title="$(grep '^#' "$repo/$chapter/README.md" | head -n1 | sed 's/^#* //')"
# Extract the authors for this chapter from commit authors and the
# Co-authored-by trailer.
authors="$(git -C "$repo" log --format='%an <%ae>' --no-merges "$chapter")"
co_authors="$(git -C "$repo" log --format=%B --no-merges "$chapter" |
tr -d $'\r' | sed -n 's/^ *Co-authored-by: //p')"
first_author="$(sort_authors <<< "$authors" | head -n1)"
all_authors="$(sort_authors <<< "$authors"$'\n'"$co_authors")"
message="$chapter_title"$'\n\n'
while read -r author; do
if [[ "$author" != "$first_author" ]]; then
message+="Co-authored-by: $author"$'\n'
fi
done <<< "$all_authors"
# Get the first and last dates this chapter was modified.
root_files=(README.md LICENSE pom.xml .gitignore .dir-locals.el transpile-tests graph print isa build-support)
author_root_files=()
if [[ $chapter = chapter01 ]]; then
# Only include the commit date of the root files for chapter01.
author_root_files+=("${root_files[@]}")
fi
author_date="$(git -C "$repo" log --format=%ad --date=raw "$chapter" "${author_root_files[@]}" | tail -n1)"
committer_date="$(git -C "$repo" log --format=%ad --date=raw -1 "$chapter" "${root_files[@]}")"
if [[ $committer_date < $last_committer_date ]]; then
committer_date="$last_committer_date"
else
last_committer_date="$committer_date"
fi
# Add the files for the chapter.
git rm -qr --ignore-unmatch .
cp -R "$repo/$chapter/." .
mkdir -p docs
mv README.md docs/
mv docs chapter_docs
rm pom.xml || :
git add .
# Add the shared files in the root, except for README.md and pom.xml.
root_files=(LICENSE .gitignore .dir-locals.el transpile-tests graph print isa build-support)
cp -R "${root_files[@]/#/"$repo/"}" .
git add "${root_files[@]}"
# Fix README.md, docs/chapter??/README.md, and pom.xml.
if git rev-parse HEAD >/dev/null 2>/dev/null; then
# Restore the documentation and pom.xml from the previous chapter.
git diff --staged --diff-filter=D --name-only -- docs README.md pom.xml | xargs git checkout -q HEAD
else
# This is the first commit; setup shared files.
cp "$repo"/{README.md,pom.xml} .
mkdir docs
# Shared type-domain illustrations are referenced from chapter READMEs.
cp "$repo"/docs/type-*.svg docs/
git add docs/type-*.svg
# Remove links to chapters.
sed -Ei 's,\[Chapter ([0-9]+[a-z]?)\]\(chapter0?\1/README\.md\),Chapter \1,' README.md
# Change to a JAR and delete the modules, for a single-project structure.
sed -i -e 's,<packaging>pom</packaging>,<packaging>jar</packaging>,' \
-e '/<modules>/,/^$/d' pom.xml
fi
# ISA sources enter the standalone Maven build with instruction encoding.
if [[ "$chapter_number" == 21 ]]; then
sed -i '/<source>${simple.print.directory}\/src\/main\/java<\/source>/a\ <source>${project.basedir}/isa/src/main/java</source>' pom.xml
sed -i '/<\/executions>/i\ <execution>\
<id>shared-isa-test-sources</id>\
<phase>generate-test-sources</phase>\
<goals><goal>add-test-source</goal></goals>\
<configuration><sources>\
<source>${project.basedir}/isa/src/test-support/java</source>\
</sources></configuration>\
</execution>' pom.xml
fi
git mv chapter_docs "docs/$chapter"
# Restore the link to this chapter.
sed -Ei "s,^\* Chapter $chapter_number: ,* [Chapter $chapter_number](docs/$chapter/README.md): ," README.md
# Repair links for this chapter.
sed -Ei 's,\bdocs/,,' "docs/$chapter/README.md"
sed -Ei 's,\(\.\./isa/,(../../isa/,g' "docs/$chapter/README.md"
# Source links are chapter-relative in the main tree; sources live at the
# repository root in a standalone chapter checkout.
sed -Ei 's,\((\./)?src/,(../../src/,g' "docs/$chapter/README.md"
git add README.md "docs/$chapter/README.md" pom.xml
# Create a commit for the chapter, using the metadata.
if [[ ! "$first_author" =~ ^(.*)\ \<(.*)\>$ ]]; then
echo "First author does not match pattern" >&2
exit 1
fi
name="${BASH_REMATCH[1]}"
email="${BASH_REMATCH[2]}"
GIT_AUTHOR_NAME="$name" GIT_AUTHOR_EMAIL="$email" GIT_AUTHOR_DATE="$author_date" \
GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" GIT_COMMITTER_DATE="$committer_date" \
git commit -q -m "$message"
# Tag the chapter, so it can be stably linked.
git tag "linear-$chapter"
done
echo 'Done!'
|