1#!/bin/bash
2
3# usage:
4#   cd xen.git
5#   docs/support-matrix-generate [-D]                               \
6#       refs/remotes/origin/master                                  \
7#           https://xenbits.xen.org/docs/unstable/SUPPORT.html      \
8#       refs/remotes/origin/stable-NN                               \
9#           https://xenbits.xen.org/docs/NN-testing/SUPPORT.html    \
10#
11# NN is a *literal* in the above rune!  It will be substituted with
12# the appropriate version number.
13#
14# The idea is that we use staging's version of this script, and it
15# looks into the git history and various git remote tracking refs to
16# find the various versions of SUPPORT.md.
17#
18# The arguments specify the git refs to look in, and also the URLs for
19# the SUPPORT.html (which are needed so that we can make
20# cross-reference links).  We provide the ref and url (i) for unstable
21# (ii) in template form for all previous versions.
22
23# Algorithm:
24#
25# We start with `refs/remotes/origin/master' and process its
26# SUPPORT.md into json.
27#
28# Then we try to find the next previous revision.  This is done by
29# extracting the current version number from xen/Makefile.  (We make
30# some slight assumption about how xen/Makefile's variables are
31# written, because we want to be able to do this without checking out
32# the whole tree for the version in question.)  Then we use git log on
33# xen/Makefile to try to find a commit where the version changed.
34# This gives us the previous version number, NN.
35#
36# That is substituted into the `refs/remotes/origin/stable-NN'
37# argument to get the tip of the relevant branch.  That in turns
38# contains another SUPPORT.md.  We keep going until either the ref
39# itself is missing, or we get to a ref with no SUPPORT.md.
40
41set -e
42set -o posix
43set -o pipefail
44
45fail () { echo >&2 "$0: $1"; exit 12; }
46
47args=()
48
49case "$1" in
50    -D) args+=("$1"); shift ;;
51    -*) fail 'bad usage' ;;
52    --) shift; break ;;
53esac
54
55case "$#" in
56    4) ;;
57    *) fail 'bad usage' ;;
58esac
59
60current_ref=$1
61current_url=$2
62pattern_ref=$3
63pattern_url=$4
64
65tmp_prefix="docs/tmp.support-matrix"
66tmp_mdfile="$tmp_prefix.md"
67tmp_revisions="$tmp_prefix.revisions.html"
68
69versionfile=xen/Makefile
70tmp_versionfile="$tmp_prefix.xen.make"
71
72cat docs/misc/support-matrix-head.html
73
74debug () {
75    echo "<!-- $* -->"
76}
77
78select_commitish () {
79    commitish=$1
80    debug "select_commitish $commitish"
81    obj="$(printf "%s:SUPPORT.md" "$commitish")"
82    exists="$(printf "%s" "$obj" | git cat-file --batch-check)"
83    >"$tmp_mdfile"
84    case "$exists" in
85        *' missing')
86            rm "$tmp_mdfile"
87            ;;
88        *' blob '*)
89            git cat-file blob "$obj" >"$tmp_mdfile"
90            ;;
91        *) fail "?? $current_url $exists ?";;
92    esac
93}
94
95commitish_version () {
96    case "$commitish" in
97        refs/*)
98            # this is how to find out if a ref exists
99            local gfer=$(git for-each-ref "[r]${commitish#r}")
100            if [ "x$gfer" = x ]; then return; fi
101            ;;
102    esac
103
104    git cat-file blob "$commitish:$versionfile" >"$tmp_versionfile"
105
106    local maj=$(sed -n 's/.*XEN_VERSION.*= \([0-9]\+\)/\1/p' < "$tmp_versionfile")
107    local min=$(sed -n 's/.*XEN_SUBVERSION.*= \([0-9]\+\)/\1/p' < "$tmp_versionfile")
108
109    if [ -z $maj ] || [ -z $min ];
110    then
111        fail "Unable to identify Xen version for $commitish";
112    fi
113
114    printf "%d.%d\n" "$maj" "$min"
115}
116
117exec 4>"$tmp_revisions"
118
119while true; do
120    select_commitish "$current_ref"
121    current_version=$(commitish_version)
122    debug "current_version=$current_version"
123
124    if ! [ -e "$tmp_mdfile" ]; then break; fi
125
126    cat >&4 <<END
127<tr>
128<td align="center">$current_version</td>
129END
130    git >&4 log -n1 --pretty=tformat:'
131<td><code>%ci</code></td>
132<td><code>%H</code></td>
133' "$current_ref"
134    cat >&4 <<END
135</tr>
136END
137
138    current_jsonfile="$tmp_prefix.$current_version.json"
139    pandoc -t json <"$tmp_mdfile" >"$current_jsonfile"
140
141    args+=("$current_jsonfile" "$current_url")
142
143    # find previous version
144    search_commit="$current_ref"
145    while true; do
146        search_commit=$(git log --pretty=format:%H -n1 \
147                        -G 'XEN.*VERSION' $search_commit -- $versionfile)
148        if ! [ "$search_commit" ]; then search_version=''; break; fi
149
150        search_commit="$search_commit~"
151        select_commitish "$search_commit"
152        search_version=$(commitish_version)
153        debug "search_version=$search_version"
154        if [ "x$search_version" != "x$current_version" ]; then break; fi
155    done
156
157    if [ "x$search_version" = x ]; then break; fi
158
159    # have found the previous version
160    current_ref=${pattern_ref/NN/$search_version}
161    current_url=${pattern_url/NN/$search_version}
162done
163
164debug "${args[*]}"
165docs/parse-support-md "${args[@]}"
166
167cat <<END
168    <h2>Source materials</h2>
169      Generated from xen.git
170      by docs/support-matrix-generate and docs/parse-support-md.
171      <p>
172      Input revisions of SUPPORT.md used:
173    <table>
174    <tr>
175      <th>Version</th>
176      <th align="left">Commit date</th>
177      <th align="left">Git commit</th>
178END
179
180cat "$tmp_revisions"
181
182generated=$(TZ=UTC date --iso-8601=minutes)
183
184cat <<END
185    </table>
186    <p>
187    Last checked/updated/regenerated: ${generated/T/ }
188  </body>
189</html>
190END
191