From 363d3843ebf4da81c4aca40d8c2f47412c27cf83 Mon Sep 17 00:00:00 2001 From: Holger Levsen Date: Sun, 12 Oct 2014 11:21:02 +0200 Subject: reproducible: create pages for issues too, refactor --- bin/reproducible_stats.sh | 441 ++++++++++++++++++++++++++++------------------ 1 file changed, 270 insertions(+), 171 deletions(-) diff --git a/bin/reproducible_stats.sh b/bin/reproducible_stats.sh index ae41ba15..6ec1912b 100755 --- a/bin/reproducible_stats.sh +++ b/bin/reproducible_stats.sh @@ -28,6 +28,8 @@ LAST48="AND build_date > datetime('now', '-48 hours') " SUITE=sid AMOUNT=$(sqlite3 -init $INIT $PACKAGES_DB "SELECT amount FROM source_stats WHERE suite = \"$SUITE\"" | xargs echo) ALLSTATES="reproducible FTBR_with_buildinfo FTBR FTBFS 404 not_for_us blacklisted" +MAINVIEW="all_abc" +ALLVIEWS="last_24h last_48h all_abc" GOOD["all"]=$(sqlite3 -init $INIT $PACKAGES_DB "SELECT name FROM source_packages WHERE status = \"reproducible\" ORDER BY build_date DESC" | xargs echo) GOOD["last_24h"]=$(sqlite3 -init $INIT $PACKAGES_DB "SELECT name FROM source_packages WHERE status = \"reproducible\" $LAST24 ORDER BY build_date DESC" | xargs echo) GOOD["last_48h"]=$(sqlite3 -init $INIT $PACKAGES_DB "SELECT name FROM source_packages WHERE status = \"reproducible\" $LAST48 ORDER BY build_date DESC" | xargs echo) @@ -64,6 +66,7 @@ SPOKENTARGET["last_48h"]="packages tested in the last 48h" SPOKENTARGET["all_abc"]="all tested packages (sorted alphabetically)" SPOKENTARGET["dd-list"]="maintainers of unreproducible packages" SPOKENTARGET["notes"]="packages with notes" +SPOKENTARGET["issues"]="known issues related to reproducible builds" SPOKENTARGET["reproducible"]="packages which built reproducibly" SPOKENTARGET["FTBR"]="packages which failed to build reproducibly and don't create a .buildinfo file" SPOKENTARGET["FTBR_with_buildinfo"]="packages which failed to build reproducibly and create a .buildinfo file" @@ -89,7 +92,8 @@ cd $WORKSPACE PACKAGES_YML=/var/lib/jenkins/notes.git/packages.yml ISSUES_YML=/var/lib/jenkins/notes.git/issues.yml NOTES_PATH=/var/lib/jenkins/userContent/notes -mkdir -p $NOTES_PATH +ISSUES_PATH=/var/lib/jenkins/userContent/issues +mkdir -p $NOTES_PATH $ISSUES_PATH declare -A NOTES_PACKAGE declare -A NOTES_VERSION @@ -114,26 +118,6 @@ show_multi_values() { rm $TMPFILE } -parse_issues() { - ISSUES=$(cat ${ISSUES_YML} | /srv/jenkins/bin/shyaml keys) - for ISSUE in ${ISSUES} ; do - echo " Issue = ${ISSUE}" - for PROPERTY in url description ; do - VALUE="$(cat ${ISSUES_YML} | /srv/jenkins/bin/shyaml get-value ${ISSUE}.${PROPERTY} )" - if [ "$VALUE" != "" ] ; then - case $PROPERTY in - url) ISSUES_URL[${ISSUE}]=$VALUE - echo " $PROPERTY = $VALUE" - ;; - description) ISSUES_DESCRIPTION[${ISSUE}]=$VALUE - show_multi_values "$VALUE" - ;; - esac - fi - done - done -} - tag_property_loop() { BEFORE=$1 shift @@ -147,7 +131,7 @@ tag_property_loop() { elif [ "${p:0:2}" = "- " ] ; then p="${p:2}" fi - echo "$BEFORE" >> ${NOTE} + write_page "$BEFORE" if $BUG ; then # turn bugs into links p="#$p" @@ -155,8 +139,8 @@ tag_property_loop() { # turn URLs into links p="$(echo $p |sed -e 's|http[s:]*//[^ ]*|\0|g')" fi - echo "$p" >> ${NOTE} - echo "$AFTER" >> ${NOTE} + write_page "$p" + write_page "$AFTER" done < $TMPFILE unset IFS rm $TMPFILE @@ -165,87 +149,149 @@ tag_property_loop() { issues_loop() { TTMPFILE=$(mktemp) echo "$@" > $TTMPFILE - FIRST=true while IFS= read -r p ; do if [ "${p:0:2}" = "- " ] ; then p="${p:2}" fi - if ! $FIRST ; then - echo " " >> ${NOTE} - fi - FIRST=false + write_page "" if [ "${ISSUES_URL[$p]}" != "" ] ; then - echo "" + fi + if [ "${ISSUES_DESCRIPTION[$p]}" != "" ] ; then + write_page "" fi - tag_property_loop "" "
" "${ISSUES_DESCRIPTION[$p]}" - echo "" >> ${NOTE} + write_page "
Identifier:$p
$p" >> ${NOTE} - else - echo "$p" >> ${NOTE} + write_page "
URL${ISSUES_URL[$p]}
Description" + tag_property_loop "" "
" "${ISSUES_DESCRIPTION[$p]}" + write_page "
" done < $TTMPFILE unset IFS rm $TTMPFILE } create_pkg_note() { - echo "" > ${NOTE} - echo "" >> ${NOTE} - echo "Notes for $1" >> ${NOTE} - echo "" >> ${NOTE} - - echo "" >> ${NOTE} BUG=false + rm -f $PAGE + # write_page_header() is not used as it contains the

tag... + write_page "" + write_page "" + write_page "" + write_page "Notes for $1" + write_page "
" + write_page "

Version annotated:${NOTES_VERSION[$1]}
" + + write_page "" if [ "${NOTES_ISSUES[$1]}" != "" ] ; then - echo "" >> ${NOTE} + write_page "" fi + BUG=true if [ "${NOTES_BUGS[$1]}" != "" ] ; then - echo "" >> ${NOTE} - echo "" + write_page "" >> ${NOTE} + write_page "" fi BUG=false + if [ "${NOTES_COMMENTS[$1]}" != "" ] ; then - echo "" >> ${NOTE} - echo "" + write_page "" >> ${NOTE} + write_page "" fi - echo "" >> ${NOTE} - echo "" >> ${NOTE} - echo "
Version annotated:${NOTES_VERSION[$1]}
Identified issues:
Identified issues:" issues_loop "${NOTES_ISSUES[$1]}" + write_page "
Bugs noted:
 " >> ${NOTE} + write_page "
Bugs noted:" tag_property_loop "" "
" "${NOTES_BUGS[$1]}" - echo "
Comments:
 " >> ${NOTE} + write_page "
Comments:" tag_property_loop "" "
" "${NOTES_COMMENTS[$1]}" - echo "
 
" >> ${NOTE} - echo "Notes are stored in notes.git." >> ${NOTE} - echo "
" >> ${NOTE} + write_page " " + write_page "" + write_page "Notes are stored in notes.git." + write_page "" + write_page_footer } -parse_notes() { - touch $NOTES_PATH/stamp - PACKAGES_WITH_NOTES=$(cat ${PACKAGES_YML} | /srv/jenkins/bin/shyaml keys) +create_issue() { + BUG=false + write_page_header "" "Notes about issue '$1'" + write_page "" + + write_page "" + + if [ "${ISSUES_URL[$1]}" != "" ] ; then + write_page "" + fi + if [ "${ISSUES_DESCRIPTION[$1]}" != "" ] ; then + write_page "" + write_page "" + fi + + write_page "" + write_page "" + write_page "
Identifier:$1
URL:${ISSUES_URL[$1]}
Description:" + tag_property_loop "" "
" "${ISSUES_DESCRIPTION[$1]}" + write_page "
Packages known to be affected by this issue:" for PKG in $PACKAGES_WITH_NOTES ; do - echo " Package = ${PKG}" - NOTES_PACKAGE[${PKG}]=" notes " - for PROPERTY in version issues bugs comments ; do - VALUE="$(cat ${PACKAGES_YML} | /srv/jenkins/bin/shyaml get-value ${PKG}.${PROPERTY} )" + if [ "${NOTES_ISSUES[$PKG]}" != "" ] ; then + TTMPFILE=$(mktemp) + echo "${NOTES_ISSUES[$PKG]}" > $TTMPFILE + while IFS= read -r p ; do + if [ "${p:0:2}" = "- " ] ; then + p="${p:2}" + fi + if [ "$p" = "$1" ] ; then + write_page " ${LINKTARGET[$PKG]} " + fi + done < $TTMPFILE + unset IFS + rm $TTMPFILE + fi + done + write_page "
 
" + write_page "Notes are stored in notes.git." + write_page "
" + write_page_footer +} + +write_issues() { + touch $ISSUES_PATH/stamp + for ISSUE in ${ISSUES} ; do + PAGE=$ISSUES_PATH/${ISSUE}_issue.html + create_issue $ISSUE + done + cd $ISSUES_PATH + for FILE in *.html ; do + # if issue is older than stamp file... + if [ $FILE -ot stamp ] ; then + rm $FILE + fi + done + rm stamp + cd - > /dev/null +} + +parse_issues() { + ISSUES=$(cat ${ISSUES_YML} | /srv/jenkins/bin/shyaml keys) + for ISSUE in ${ISSUES} ; do + echo " Issue = ${ISSUE}" + for PROPERTY in url description ; do + VALUE="$(cat ${ISSUES_YML} | /srv/jenkins/bin/shyaml get-value ${ISSUE}.${PROPERTY} )" if [ "$VALUE" != "" ] ; then case $PROPERTY in - version) NOTES_VERSION[${PKG}]=$VALUE + url) ISSUES_URL[${ISSUE}]=$VALUE echo " $PROPERTY = $VALUE" ;; - issues) NOTES_ISSUES[${PKG}]=$VALUE - show_multi_values "$VALUE" - ;; - bugs) NOTES_BUGS[${PKG}]=$VALUE - show_multi_values "$VALUE" - ;; - comments) NOTES_COMMENTS[${PKG}]=$VALUE + description) ISSUES_DESCRIPTION[${ISSUE}]=$VALUE show_multi_values "$VALUE" ;; esac fi done - NOTE=$NOTES_PATH/${PKG}_note.html + done +} + +write_notes() { + touch $NOTES_PATH/stamp + for PKG in $PACKAGES_WITH_NOTES ; do + PAGE=$NOTES_PATH/${PKG}_note.html create_pkg_note $PKG done cd $NOTES_PATH @@ -266,6 +312,33 @@ parse_notes() { cd - > /dev/null } +parse_notes() { + PACKAGES_WITH_NOTES=$(cat ${PACKAGES_YML} | /srv/jenkins/bin/shyaml keys) + for PKG in $PACKAGES_WITH_NOTES ; do + echo " Package = ${PKG}" + NOTES_PACKAGE[${PKG}]=" notes " + for PROPERTY in version issues bugs comments ; do + VALUE="$(cat ${PACKAGES_YML} | /srv/jenkins/bin/shyaml get-value ${PKG}.${PROPERTY} )" + if [ "$VALUE" != "" ] ; then + case $PROPERTY in + version) NOTES_VERSION[${PKG}]=$VALUE + echo " $PROPERTY = $VALUE" + ;; + issues) NOTES_ISSUES[${PKG}]=$VALUE + show_multi_values "$VALUE" + ;; + bugs) NOTES_BUGS[${PKG}]=$VALUE + show_multi_values "$VALUE" + ;; + comments) NOTES_COMMENTS[${PKG}]=$VALUE + show_multi_values "$VALUE" + ;; + esac + fi + done + done +} + validate_yaml() { VALID_YAML=true set +e @@ -276,25 +349,13 @@ validate_yaml() { } # -# actually parse the notes -# -validate_yaml ${ISSUES_YML} -validate_yaml ${PACKAGES_YML} -if $VALID_YAML ; then - parse_issues - parse_notes -else - echo "Warning: ${ISSUES_YML} or ${PACKAGES_YML} contains invalid yaml, please fix." -fi - -# -# end note parsing +# end note parsing functions... # mkdir -p /var/lib/jenkins/userContent/rb-pkg/ -write_summary() { - echo "$1" >> $SUMMARY +write_page() { + echo "$1" >> $PAGE } set_icon() { @@ -418,144 +479,157 @@ force_package_targets() { link_packages() { for PKG in $@ ; do - write_summary " ${LINKTARGET[$PKG]} " + write_page " ${LINKTARGET[$PKG]} " done } -write_summary_header() { - rm -f $SUMMARY - write_summary "" - write_summary "" - write_summary "" - write_summary "$2" - write_summary "

$2

" +write_page_header() { + rm -f $PAGE + write_page "" + write_page "" + write_page "" + write_page "$2" + write_page "

$2

" if [ "$1" = "$MAINVIEW" ] ; then - write_summary "

These pages are updated every six hours. Results are obtained from several jobs running on jenkins.debian.net. Thanks to Profitbricks for donating the virtual machine it's running on!

" + write_page "

These pages are updated every six hours. Results are obtained from several jobs running on jenkins.debian.net. Thanks to Profitbricks for donating the virtual machine it's running on!

" fi - write_summary "

$COUNT_TOTAL packages have been attempted to be build so far, that's $PERCENT_TOTAL% of $AMOUNT source packages in Debian $SUITE currently. Out of these, $PERCENT_GOOD% were successful, so quite wildly guessing this roughy means about $GUESS_GOOD packages should be reproducibly buildable!" + write_page "

$COUNT_TOTAL packages have been attempted to be build so far, that's $PERCENT_TOTAL% of $AMOUNT source packages in Debian $SUITE currently. Out of these, $PERCENT_GOOD% were successful, so quite wildly guessing this roughy means about $GUESS_GOOD packages should be reproducibly buildable!" if [ "${1:0:3}" = "all" ] || [ "$1" = "dd-list" ] ; then - write_summary " Join #debian-reproducible on OFTC to get support for making sure your packages build reproducibly too!" + write_page " Join #debian-reproducible on OFTC to get support for making sure your packages build reproducibly too!" fi - write_summary "

" - write_summary "
  • Other views for these build results:
  • " + write_page "

    " + write_page "
    • Other views for these build results:
    • " for MY_STATE in $ALLSTATES ; do WITH="" if [ "$MY_STATE" = "FTBR_with_buildinfo" ] ; then WITH="YES" fi set_icon $MY_STATE $WITH # sets ICON and STATE_TARGET_NAME - write_summary "
    • \"${STATE_TARGET_NAME}
    • " + write_page "
    • \"${STATE_TARGET_NAME}
    • " done - for TARGET in notes $ALLVIEWS dd-list ; do + for TARGET in issues notes $ALLVIEWS dd-list ; do if [ "$TARGET" = "$1" ] ; then continue + elif [ "$TARGET" = "issues" ] ; then + SPOKEN_TARGET="issues" + else + SPOKEN_TARGET=${SPOKENTARGET[$TARGET]} fi - write_summary "
    • ${SPOKENTARGET[$TARGET]}
    • " + write_page "
    • ${SPOKEN_TARGET}
    • " done - write_summary "
    " - write_summary "
" + write_page "" + write_page "
" } -write_summary_footer() { - write_summary "

There is more information about jenkins.debian.net and about reproducible builds of Debian available elsewhere. Last update: $(date +'%Y-%m-%d %H:%M %Z'). Copyright 2014 Holger Levsen, GPL-2 licensed. The weather icons are public domain and have been taken from the Tango Icon Library.

" - write_summary "" +write_page_footer() { + write_page "

There is more information about jenkins.debian.net and about reproducible builds of Debian available elsewhere. Last update: $(date +'%Y-%m-%d %H:%M %Z'). Copyright 2014 Holger Levsen, GPL-2 licensed. The weather icons are public domain and have been taken from the Tango Icon Library.

" + write_page "" } -write_summary_beta_sign() { - write_summary "

A β sign after a package which is unreproducible indicates that a .buildinfo file was generated." - write_summary "This means the basics for building packages reproducibly are covered :-)

" +write_page_beta_sign() { + write_page "

A β sign after a package which is unreproducible indicates that a .buildinfo file was generated." + write_page "This means the basics for building packages reproducibly are covered :-)

" } + publish_summary() { - cp $SUMMARY /var/lib/jenkins/userContent/ + cp $PAGE /var/lib/jenkins/userContent/ if [ "$VIEW" = "$MAINVIEW" ] ; then - cp $SUMMARY /var/lib/jenkins/userContent/reproducible.html + cp $PAGE /var/lib/jenkins/userContent/reproducible.html fi - rm $SUMMARY + rm $PAGE } +# +# actually parse the notes +# +validate_yaml ${ISSUES_YML} +validate_yaml ${PACKAGES_YML} +if $VALID_YAML ; then + parse_issues + parse_notes + process_packages ${PACKAGES_WITH_NOTES} + write_issues + write_notes +else + echo "Warning: ${ISSUES_YML} or ${PACKAGES_YML} contains invalid yaml, please fix." +fi + +# +# actually build the package pages +# echo "Processing $COUNT_TOTAL packages... this will take a while." -process_packages ${PACKAGES_WITH_NOTES} BUILDINFO_SIGNS=true process_packages ${BAD["all"]} BUILDINFO_SIGNS=false process_packages ${UGLY["all"]} ${GOOD["all"]} ${SOURCELESS["all"]} ${NOTFORUS["all"]} $BLACKLISTED -MAINVIEW="all_abc" -ALLVIEWS="last_24h last_48h all_abc" for VIEW in $ALLVIEWS ; do - SUMMARY=index_${VIEW}.html - echo "Starting to write $SUMMARY page." - write_summary_header $VIEW "Overview of reproducible builds of ${SPOKENTARGET[$VIEW]}" + PAGE=index_${VIEW}.html + echo "Starting to write $PAGE page." + write_page_header $VIEW "Overview of reproducible builds of ${SPOKENTARGET[$VIEW]}" if [ "${VIEW:0:3}" = "all" ] ; then FINISH=":" else SHORTER_SPOKENTARGET=$(echo ${SPOKENTARGET[$VIEW]} | cut -d "(" -f1) FINISH=", from $SHORTER_SPOKENTARGET these were:" fi - write_summary "

$COUNT_BAD packages ($PERCENT_BAD% of $COUNT_TOTAL) failed to built reproducibly in total$FINISH " + write_page "

$COUNT_BAD packages ($PERCENT_BAD% of $COUNT_TOTAL) failed to built reproducibly in total$FINISH " link_packages ${BAD[$VIEW]} - write_summary "

" - write_summary - write_summary "

$COUNT_UGLY packages ($PERCENT_UGLY%) failed to build from source in total$FINISH " + write_page "

" + write_page + write_page "

$COUNT_UGLY packages ($PERCENT_UGLY%) failed to build from source in total$FINISH " link_packages ${UGLY[$VIEW]} - write_summary "

" + write_page "

" if [ "${VIEW:0:3}" = "all" ] && [ $COUNT_SOURCELESS -gt 0 ] ; then - write_summary "

For $COUNT_SOURCELESS ($PERCENT_SOURCELESS%) packages in total sources could not be downloaded: ${SOURCELESS[$VIEW]}

" + write_page "

For $COUNT_SOURCELESS ($PERCENT_SOURCELESS%) packages in total sources could not be downloaded: ${SOURCELESS[$VIEW]}

" fi if [ "${VIEW:0:3}" = "all" ] && [ $COUNT_NOTFORUS -gt 0 ] ; then - write_summary "

In total there were $COUNT_NOTFORUS ($PERCENT_NOTFORUS%) packages which are neither Architecture: 'any' nor 'all' nor 'amd64' nor 'linux-any' nor 'linux-amd64': ${NOTFORUS[$VIEW]}

" + write_page "

In total there were $COUNT_NOTFORUS ($PERCENT_NOTFORUS%) packages which are neither Architecture: 'any' nor 'all' nor 'amd64' nor 'linux-any' nor 'linux-amd64': ${NOTFORUS[$VIEW]}

" fi if [ "${VIEW:0:3}" = "all" ] && [ $COUNT_BLACKLISTED -gt 0 ] ; then - write_summary "

$COUNT_BLACKLISTED packages are blacklisted and will never be tested here: $BLACKLISTED

" + write_page "

$COUNT_BLACKLISTED packages are blacklisted and will never be tested here: $BLACKLISTED

" fi - write_summary "

$COUNT_GOOD packages ($PERCENT_GOOD%) successfully built reproducibly$FINISH " + write_page "

$COUNT_GOOD packages ($PERCENT_GOOD%) successfully built reproducibly$FINISH " link_packages ${GOOD[$VIEW]} - write_summary "

" - write_summary_beta_sign - write_summary_footer + write_page "

" + write_page_beta_sign + write_page_footer publish_summary done -VIEW=dd-list -SUMMARY=index_${VIEW}.html -echo "Starting to write $SUMMARY page." -write_summary_header $VIEW "Overview of ${SPOKENTARGET[$VIEW]}" -TMPFILE=$(mktemp) -echo "${BAD["all"]}" | dd-list -i > $TMPFILE -write_summary "

The following maintainers and uploaders are listed for packages which have built unreproducibly:

"
-while IFS= read -r LINE ; do
-	if [ "${LINE:0:3}" = "   " ] ; then
-		PACKAGE=$(echo "${LINE:3}" | cut -d " " -f1)
-		UPLOADERS=$(echo "${LINE:3}" | cut -d " " -f2-)
-		if [ "$UPLOADERS" = "$PACKAGE" ] ; then
-			UPLOADERS=""
-		fi
-		write_summary "   $PACKAGE $UPLOADERS"
-	else
-		LINE="$(echo $LINE | sed 's#&#\&#g ; s#<#\<#g ; s#>#\>#g')"
-		write_summary "$LINE"
-	fi
-done < $TMPFILE
-write_summary "

" -rm $TMPFILE -write_summary_footer -publish_summary - VIEW=notes -SUMMARY=index_${VIEW}.html -echo "Starting to write $SUMMARY page." -write_summary_header $VIEW "Overview of ${SPOKENTARGET[$VIEW]}" +PAGE=index_${VIEW}.html +echo "Starting to write $PAGE page." +write_page_header $VIEW "Overview of ${SPOKENTARGET[$VIEW]}" if $VALID_YAML ; then - write_summary "

Packages which have notes: " + write_page "

Packages which have notes: " force_package_targets $PACKAGES_WITH_NOTES PACKAGES_WITH_NOTES=$(echo $PACKAGES_WITH_NOTES | sed -s "s# #\n#g" | sort | xargs echo) link_packages $PACKAGES_WITH_NOTES - write_summary "

" + write_page "

" +else + write_page "

Broken .yaml files in notes.git could not be parsed, please investigate and fix!

" +fi +write_page "

Notes are stored in notes.git.

" +write_page_footer +publish_summary + +VIEW=issues +PAGE=index_${VIEW}.html +echo "Starting to write $PAGE page." +write_page_header $VIEW "Overview of ${SPOKENTARGET[$VIEW]}" +if $VALID_YAML ; then + write_page "" + ISSUES=$(echo ${ISSUES} | sed -s "s# #\n#g" | sort | xargs echo) + for ISSUE in ${ISSUES} ; do + write_page "" + done + write_page "
${ISSUE}
" else - write_summary "

Broken .yaml files in notes.git could not be parsed, please investigate and fix!

" + write_page "

Broken .yaml files in notes.git could not be parsed, please investigate and fix!

" fi -write_summary "

Notes are stored in notes.git.

" -write_summary_footer +write_page "

Notes are stored in notes.git.

" +write_page_footer publish_summary count_packages() { @@ -564,9 +638,9 @@ count_packages() { } for STATE in $ALLSTATES ; do - SUMMARY=index_${STATE}.html - echo "Starting to write $SUMMARY page." - write_summary_header $STATE "Overview of ${SPOKENTARGET[$STATE]}" + PAGE=index_${STATE}.html + echo "Starting to write $PAGE page." + write_page_header $STATE "Overview of ${SPOKENTARGET[$STATE]}" WITH="" case "$STATE" in reproducible) PACKAGES=${GOOD["all"]} @@ -598,18 +672,43 @@ for STATE in $ALLSTATES ; do ;; esac count_packages ${PACKAGES} - write_summary "

$COUNT ($PERCENT%)" + write_page "

$COUNT ($PERCENT%)" set_icon $STATE $WITH # sets ICON and STATE_TARGET_NAME - write_summary "\"${STATE_TARGET_NAME}" - write_summary " ${SPOKENTARGET[$STATE]}:" + write_page "\"${STATE_TARGET_NAME}" + write_page " ${SPOKENTARGET[$STATE]}:" link_packages ${PACKAGES} - write_summary "

" - write_summary + write_page "

" + write_page if [ "${STATE:0:4}" = "FTBR" ] ; then - write_summary_beta_sign + write_page_beta_sign fi - write_summary_footer + write_page_footer publish_summary done +VIEW=dd-list +PAGE=index_${VIEW}.html +echo "Starting to write $PAGE page." +write_page_header $VIEW "Overview of ${SPOKENTARGET[$VIEW]}" +TMPFILE=$(mktemp) +echo "${BAD["all"]}" | dd-list -i > $TMPFILE +write_page "

The following maintainers and uploaders are listed for packages which have built unreproducibly:

"
+while IFS= read -r LINE ; do
+	if [ "${LINE:0:3}" = "   " ] ; then
+		PACKAGE=$(echo "${LINE:3}" | cut -d " " -f1)
+		UPLOADERS=$(echo "${LINE:3}" | cut -d " " -f2-)
+		if [ "$UPLOADERS" = "$PACKAGE" ] ; then
+			UPLOADERS=""
+		fi
+		write_page "   $PACKAGE $UPLOADERS"
+	else
+		LINE="$(echo $LINE | sed 's#&#\&#g ; s#<#\<#g ; s#>#\>#g')"
+		write_page "$LINE"
+	fi
+done < $TMPFILE
+write_page "

" +rm $TMPFILE +write_page_footer +publish_summary + echo "Enjoy $JENKINS_URL/userContent/reproducible.html" -- cgit v1.2.3-70-g09d2