2 # Quick and dirty script to audit font use in a yum package repository
4 # It is slow, it is ugly, and it requires a good network connection
6 # Function declarations
10 Usage: $0 <id> <location>
11 <id>: identifier of the package repository to check
12 <location>: location of the package repository to check
17 $0 rawhide http://example.com/mirrors/fedora.redhat.com/fedora/linux/development/x86_64/os/
23 DATADIR="$(dirname $0)/../private"
25 # Filenames with whitespace or & + makefile = !!!
26 bad_pattern="[[:space:]&\:]"
28 # Tools and humans make mistakes; try to fix some obvious ones
30 sed 's=^file:\(\/*\)=/=' | sed 's=^\(ftp\|http\|https\):\(\/*\)=\1://='
34 fold -s -w $(($(tput cols) - 2)) \
35 | while read line ; do echo " $line" ; done
38 # $1 = CSV file to evaluate
45 rpmsz[$3 "-" $4 "." $5] = $6
56 rpmsize = rpmsize / (1024*1024)
57 filesize = filesize / (1024*1024)
58 print filenumber "|" rpmnumber "|" srpmnumber "|" filesize "|" rpmsize
64 if [ $(cat "$1" | wc -l) -gt 0 ] ; then
65 tally "$1" | awk -F '|' '{ print "⇒ " $1 " file(s) (" $4 " MiB) in " $2 \
66 " package(s) (" $5 " MiB) generated from " $3 " source package(s)." }'\
69 echo "⇒ None!" | pretty_indent
76 # $2 = temporary data file
78 complete_csv_summary() {
79 awk -F '|' -v t_datafile="$2" -v testlabel="$3" \
80 'FILENAME==t_datafile { fail[$1"|"$2"|"$3"|"$4"|"$5"|"$10] = 1 }
81 FILENAME!=t_datafile && FNR==1 {
84 for (i = 2 ; i <= max ; i++) {
85 header = header "|" $i
87 print header testlabel
89 FILENAME!=t_datafile && FNR>1 {
90 line = $1 "|" $2 "|" $3 "|" $4 "|" $5 "|" $6
92 for (i = 2 ; i <= max ; i++) {
93 newline = newline "|" $i
95 print newline fail[line]
99 for ( line in fail ) {
100 if ( ! processed[line] ) {
102 for (i = 7 ; i <= max ; i++) {
103 newline = newline "|"
105 print newline fail[line]
108 }' "$2" "$1" > tmp/tmp.ccs.csv
109 awk 'FNR==1' tmp/tmp.ccs.csv > "$1"
110 awk 'FNR>1' tmp/tmp.ccs.csv | sort -f -t '|' >> "$1"
118 awk -F '|' '{ print $NF }' "$ss_datafile" | sort | uniq \
119 | while read key ; do
121 awk -F '|' -v key="$key" '$NF==key' "$ss_datafile" > tmp/tmp.ss.csv
128 # $1 = CSV file to sum_up
132 summary "$s_datafile"
134 if [ $(cat "$s_datafile" | wc -l) -gt 0 ] ; then
135 (echo "Format|Files|rpm|srpm|Files (MiB)|rpm (MiB)"
136 awk -F '|' '$13 != "" { print $0 "|" $15 }' "$s_datafile" > tmp/tmp.s.csv
137 substats tmp/tmp.s.csv) | column -t -s '|' | pretty_indent
140 (echo "Arch|Files|rpm|srpm|Files (MiB)|rpm (MiB)"
141 awk -F '|' '{ print $0 "|" $5 }' "$s_datafile" > tmp/tmp.s.csv
142 substats tmp/tmp.s.csv)| column -t -s '|' | pretty_indent
150 # $1 = CSV file to sum_up
153 [ $(cat "$1" | wc -l) -gt 0 ] && \
157 if ( $7 == "M" ) { rpm = "[" rpm "]" }
161 n = asorti(total, sorted)
162 for ( i = 1 ; i <= n ; i++ ) {
163 line = line sorted[i] "(" total[sorted[i]] "), "
167 }' "$1" | pretty_indent
171 # Pipe CSV file to sum_up
172 # It is assumed to be of the form
173 # rpm | pattern to match | pattern to display
174 # patterns may include # as separators
182 files[key] = files[key] pat "#" rpm "|"
186 sub("\\|$", "", files[key])
187 total = split(files[key], lines,"|")
188 pb[total] = pb[total] key "|"
190 n = asorti(pb, sorted)
191 for (i = n; i >= 1; i--) {
193 sub("\\|$", "", pb[total])
194 split(pb[total], keys,"|")
195 nk = asort(keys, sortedkeys)
196 for ( k = 1 ; k <= nk ; k++ ) {
198 print gensub("#", ", ", "g", key)
199 split(files[key], lines, "|")
200 nl = asort(lines, sortedlines)
201 for ( l = 1 ; l <= nl ; l++ ) {
202 print " " gensub("#", "\t", "G", lines[l])
211 # $2 = csv file with the results of this test
212 # $3 = csv file that consolidates the results of all tests
215 complete_csv_summary "$3" "$2" "$1"
221 # $1 = csv file with test results
223 if [ $(cat "$1" | wc -l) -gt 1 ] ; then
234 for (i = 1 ; i < (lh-1) ; i++) {
235 if ($i != "") id = id $i "|"
240 for (i = lh ; i <= max ; i++) {
241 score[id"|"i] = score[id"|"i] + $i
242 totalscore[i] = totalscore[i] + $i
246 for (i = lh ; i <= max ; i++) {
247 if ( totalscore[i] ) { headerline = headerline "|" "t" i+1-lh }
251 for (l = 1; l <= n; l++) {
253 for (c = lh ; c <= max ; c++) {
254 if ( totalscore[c] ) {
255 if ( score[fail[l]"|"c] )
256 { newline = newline "|" score[fail[l]"|"c] }
258 { newline = newline "|‧" }
264 for (i = lh ; i <= max ; i++) {
265 if ( totalscore[i] ) { totalline = totalline "|" totalscore[i] }
268 }' "$1" | column -t -s '|'
276 for (i = 1 ; i < (lh-1) ; i++) {
277 if ($i != "") id = id $i "|"
284 print "P#|Maintainer|SRPM|RPM|EVR|Arch"
286 for (l = 1; l <= n; l++) {
289 }' "$1" | column -t -s '|'
292 echo "Test explanation:"
299 for (i = lh ; i <= max ; i++) {
300 legend[i] = i+1-lh "|" $i }
303 for (i = lh ; i <= max ; i++) {
304 totalscore[i] = totalscore[i] + $i
308 for (i = lh ; i <= max ; i++) {
309 if ( totalscore[i] ) { print legend[i] }
311 }' "$1" | while read line ; do
312 testnumber=$(echo $line | awk -F '|' '{ print "t"$1 }')
313 testid=$(echo $line | awk -F '|' '{ print $2 }')
314 echo -n "$testnumber. "
315 "$DATADIR/test-info" $testid title
317 ( "$DATADIR/test-info" $testid help ) | pretty_indent
328 start_time=$(date "+%s")
330 # This is very ugly but the safest syntax to use with any repoquery version
331 FREPOURL=$(echo "$REPOURL" | sed 's=^/=file:///=')
333 echo "Looking for packages:"
334 echo "— with font metadata…"
335 repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
336 --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|M" \
337 --whatprovides "font(*)" --quiet \
339 | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
342 echo "— that include files with common font extensions…"
343 repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
344 --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|E" \
345 -f '*.ttf' -f '*.otf' -f '*.ttc' \
346 -f '*.pfb' -f '*.pfa' \
347 -f '*.pcf.gz' -f '*.pcf' -f '*.bdf' --quiet \
349 | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
352 echo "— that use the core X11 protocol…"
353 repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
354 --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|X" \
355 --whatrequires 'libX11.so*' \
357 | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
360 if [ $(cat "$FPL" "$PWFL" "$XPL" | wc -l) -eq 0 ] ; then
361 echo "Nothing to do!"
365 cat "$FPL" "$PWFL" "$XPL" \
367 { tag[$1 "|" $2 "|" $3 "|" $4 "|" $5] = tag[$1 "|" $2 "|" $3 "|" $4 "|" $5] $6 "," }
370 for (l = 1; l <= n; l++) {
371 sub(",$", "", tag[rpm[l]])
372 print rpm[l] "|" tag[rpm[l]]
377 echo "Inspecting packages:"
381 cat "$FL.1" | while read line ; do
382 rpm=$(echo "$line" | awk -F '|' '{ print $2 "-" $3 "." $4 }')
383 rpmline=$(echo "$line" | awk -F '|' '{ print $1 "|" $2 "|" $3 "|" $4 "|" $5 }')
384 rpmd=$(echo "$rpm" | sed "s+$bad_pattern+_+g")
385 echo "$line" | cut -d "|" -f 6 | grep -q "M" && metadata="M" || metadata=""
389 rpm_loc=$(repoquery --repofrompath=$REPOID,$REPOURL --repoid=$REPOID \
390 --location "$rpm" 2>/dev/null \
392 if $(echo "$rpm_loc" | grep -q -e '^[\./~]') ; then
395 curl -O --silent --show-error --retry 3 --connect-timeout 10 --retry-delay 15 --url "$rpm_loc"
398 rpm2cpio *.rpm > "$rpm.cpio"
400 cat "$rpm.cpio" | cpio --quiet -it > "$rpm.lst"
401 nofont_score=$(cat "$rpm.lst" | sed 's=^\./=/=g' \
402 | grep -viE -e "^/usr/share/fonts" \
403 -e "^/usr/share/fontconfig/conf.avail/" \
404 -e "^/etc/fonts/conf.d/" \
405 -e "^/usr/share/doc/" \
406 -e "^/etc/X11/fontpath.d/" \
407 -e '\.((ttf)|(ttc)|(otf)|(pfa)|(pfb)|(bdf)|(pcf)|(pcf\.gz))$' \
409 echo "$rpmline|$metadata|$nofont_score" > rpm-info.txt
410 if $(echo $line | cut -d "|" -f 6 | grep -q "E") ; then
412 | grep -iE '\.((ttf)|(ttc)|(otf)|(pfa)|(pfb)|(bdf)|(pcf)|(pcf\.gz))$' \
413 | sort > "$rpm.fonts.lst"
415 if $(echo $line | cut -d "|" -f 6 | grep -q "X") ; then
417 | grep -i -e "^./sbin/" \
419 -e "^./usr/kerberos/sbin" \
422 -e "^./usr/kerberos/bin/" \
429 | grep -vi -e "^./usr/bin/dmxwininfo" \
430 -e "^./usr/bin/Xdmx" \
431 -e "^./usr/bin/xfontsel" \
432 -e "^./usr/bin/xlsfonts" \
433 -e "^./usr/bin/Xnest" \
434 -e "^./usr/bin/xprop" \
435 -e "^./usr/bin/xsetroot" \
436 -e "^./usr/bin/xwininfo" \
437 -e "^./usr/bin/x11vnc" \
438 -e "^./usr/bin/x2vnc" \
439 -e "^./usr/lib.*/libXcursor.so" \
440 | sort > "$rpm.bin.lst"
442 touch "$rpm.fonts.lst" "$rpm.bin.lst"
443 cat "$rpm.fonts.lst" "$rpm.bin.lst" | sort | uniq > "$rpm.files.lst"
446 cpio -idm --quiet -E "../$rpm.files.lst" < "../$rpm.cpio"
450 sed 's=^\./==g' "$rpm.fonts.lst" \
451 | while read file; do
453 type=$(file -bzh "src/$file")
454 case $(echo "$type" | sed 's+ (\(.*\)++g' \
455 | sed 's+ `\(.*\)++g' \
456 | sed 's+,\(.*\)++g' \
457 | sed 's+\( \)*$++g' ) in
458 "TrueType font data")
461 "TrueType font collection data")
464 "OpenType font data")
467 "X11 Portable Compiled Font data")
473 # PostScript files are a mess
474 "PostScript Type 1 font text")
477 "PostScript Type 1 font program data")
480 "PostScript document text conforming DSC level 3.0")
484 "PostScript document text"|"8086 relocatable")
487 "symbolic link to"|"broken symbolic link to")
488 target=$(readlink -m "src/$file" | sed "s+^$PWD/src++g")
489 if $(echo "$target" | grep -q "^/usr/share/fonts") ; then
501 if [ "$type" != "ignored" -a ! -h "src/$file" ] ; then
502 mkdir -p $(dirname "tmp/$file")
503 echo "/$file|$type" > "tmp/$file.rfo.fonts.info"
504 if [ "$type" != "TrueType font data" -a \
505 "$type" != "OpenType font data" ] ; then
506 touch "tmp/$file.rfo.unicover"
509 if [ "$type" = "Link" ] ; then
510 echo "/$file|$target" >> font-links.txt
514 sed 's=^\./==g' "$rpm.bin.lst" \
515 | while read file ; do
516 type=$(file -bzh "src/$file")
517 if $(echo "$type" | grep -q -e '^ELF ' -e ' ELF ') ; then
519 mkdir -p $(dirname "tmp/$file")
520 echo "/$file|$type" > "tmp/$file.rfo.core-fonts.info"
529 echo "Analysing files…"
531 find . -type d | grep "$bad_pattern" \
532 | while read dir ; do
533 mkdir -p $(echo "$dir" | sed "s+$bad_pattern+_+g")
536 find . -type f | grep "$bad_pattern" \
537 | while read file ; do
538 mv "$file" $(echo "$file"| sed "s+$bad_pattern+_+g")
541 # There must be a cleaner way to do this
542 parallelism=$(($(cat /proc/cpuinfo | grep processor | wc -l)+1))
543 make -s -r -j $parallelism -f "$DATADIR/repo-font-audit.mk"
545 find . -name "*\.rfo\.fonts" \
546 -o -name "*\.rfo\.core-fonts" \
547 -o -name processed-font-links.txt \
548 | while read datafile ; do
549 cat "$datafile" >> "$FL.2"
553 for rpmlint in */rpmlint.txt ; do
554 mkdir "../data/$(dirname $rpmlint)"
555 mv "$rpmlint" "../data/$rpmlint"
558 for ext in fontlint unicover fc-query ; do
559 find . -name "*\.rfo\.$ext" \
560 | while read file ; do
561 dest=$(echo "$file" \
562 | sed "s+./\([^/]*\)/tmp/\(.*\).rfo.$ext+\1|\2.$ext.txt+" \
563 | sed 's+/+_+g' | sed 's+|+/+g')
564 [ -s "$file" ] && mv "$file" "../data/$dest"
576 echo "Consolidating data…"
578 echo "Maintainer|SRPM|RPM|EVR|Arch|RPM size|RPM metadata|foreign data|\
579 rpmlint score|filename|family name|face name|fixed family name|\
580 fixed face name|format (fontconfig)|format (libmagic)|file size|checksum|\
581 partial scripts|partial blocks|fontlint|symlink target|symlink provider|\
582 core fonts use" > "$FL"
584 if [ -s "tmp/$FL.2" -a -r "tmp/$FL.2" ] ; then
586 # FIXME: make this distro-agnostic
587 cut -d "|" -f 1 "tmp/$FL.2" | sort | uniq \
588 | /usr/bin/fedoradev-pkgowners 2>/dev/null \
590 | awk -F "|" -v file="tmp/$FL.2" '
593 while ((getline < file) > 0) {
594 print owner[$1] "|" $0
596 }' | sort -df -t "|" -k 1 -k 2 -k 3 > "tmp/$FL.3"
599 ($16 != "Link") { source[$10] = $3 "-" $4
601 ($16 == "Link") { link[$0] = $22 }
604 out[line] = line "|" source[link[line]]
607 for (i = 1; i <= n; i++) print out[i]
608 }' "tmp/$FL.3" > "tmp/$FL.4"
611 | sort -df -t "|" -k 1 -k 2 -k 3 -k 4n -k 13 -k 14 -k 10 \
612 | sed 's=$=|=g' | sed 's=|0|=||=g' | sed 's=|0|=||=g' | sed 's=|\+$==g' \
617 echo "Maintainer|SRPM|RPM|EVR|Arch|File" > "$TSUM"
624 echo "Conducting tests:"
629 "$DATADIR/test-info" outside-usr-share-fonts title }
631 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
632 ($10 !~ /^\/usr\/share\/fonts\//)' "$FL" \
633 | sort -df -t "|" > tmp/tmp.csv
636 test_wrapup outside-usr-share-fonts tmp/tmp.csv "$TSUM"
640 "$DATADIR/test-info" without-rpm-metadata title
642 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
644 | sort -df -t "|" > tmp/tmp.csv
647 test_wrapup without-rpm-metadata tmp/tmp.csv "$TSUM"
651 "$DATADIR/test-info" family-mixing title
654 (NR > 1) && ($11 != "") {
655 rpm = $3 "-" $4 "." $5
656 files[rpm] = files[rpm] $0 "#"
657 if ( ! family[rpm] ) {
661 if (family[rpm] != $11) {
668 sub("#$", "", files[rpm])
669 split(files[rpm], lines,"#")
675 | sort -df -t "|" > tmp/tmp.csv
678 test_wrapup family-mixing tmp/tmp.csv "$TSUM"
682 "$DATADIR/test-info" duplicated-file title
685 (NR > 1) && ($24 != "X") && ($16 != "Link") {
686 files[$18] = files[$18] $0 "#"
689 for (checksum in files) {
690 sub("#$", "", files[checksum])
691 count = split(files[checksum], lines,"#")
699 | sort -g -t "|" -k 18 > tmp/tmp.csv
701 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
705 if ( $7 == "M" ) { rpm = "[" rpm "]" }
707 if ( $11 != "" ) { sig = $11 }
709 if ( sig != "" ) { sig = sig ", " }
712 if ( sig != "" ) { sig = "#(" sig ")" }
713 print rpm "|" $18 "|" $10 sig
714 }' tmp/tmp.csv | enum_rpm
716 test_wrapup duplicated-file tmp/tmp.csv "$TSUM"
719 "$DATADIR/test-info" duplicated-face-ext title
722 (NR > 1) && ($11 != "") && ($12 != "") {
724 rpm = $3 "-" $4 "." $5
725 files[face] = files[face] $0 "#"
726 if ( ! loc[face] ) { loc[face] = rpm }
728 if (loc[face] != rpm) {
734 for (face in duplicated) {
735 sub("#$", "", files[face])
736 split(files[face], lines,"#")
742 | sort -df -t "|" -k 11 -k 12 > tmp/tmp.csv
744 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
748 if ( $7 == "M" ) { rpm = "[" rpm "]" }
750 print rpm "|" $11 ", " $12 "|" $10
751 }' tmp/tmp.csv | enum_rpm
753 test_wrapup duplicated-face-ext tmp/tmp.csv "$TSUM"
757 "$DATADIR/test-info" fc-query title
759 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
760 ($15 == "")' "$FL" > tmp/tmp.csv
763 test_wrapup fc-query tmp/tmp.csv "$TSUM"
767 "$DATADIR/test-info" libmagic title
769 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
770 (tolower(" " $16 " ") !~ / font /)' "$FL" > tmp/tmp.csv
773 test_wrapup libmagic tmp/tmp.csv "$TSUM"
777 "$DATADIR/test-info" broken-symlink title
779 awk -F '|' '(NR > 1) && ($16 == "Link") && ($23 == "")' "$FL" > tmp/tmp.csv
781 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
785 if ( $7 == "M" ) { rpm = "[" rpm "]" }
787 print rpm "|" $10 " ↛ " $22
788 }' tmp/tmp.csv | enum_rpm
790 test_wrapup broken-symlink tmp/tmp.csv "$TSUM"
793 "$DATADIR/test-info" rpmlint title
795 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
796 ($9 != "")' "$FL" > tmp/tmp.csv
799 test_wrapup rpmlint tmp/tmp.csv "$TSUM"
803 "$DATADIR/test-info" mixed-with-non-font-data title
805 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
806 ($8 != "")' "$FL" > tmp/tmp.csv
809 test_wrapup mixed-with-non-font-data tmp/tmp.csv "$TSUM"
813 "$DATADIR/test-info" arch-package title
815 awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
816 ($5 != "noarch")' "$FL" > tmp/tmp.csv
819 test_wrapup arch-package tmp/tmp.csv "$TSUM"
823 "$DATADIR/test-info" bad-rpm-naming title
825 awk -F "|" '(NR > 1) && ($16 != "Link") && ($24!="X") && \
826 $3 !~ /^[0-9abcdefghijklmnopqrstuvwxyz\.-]*-fonts$/' "$FL" \
830 test_wrapup bad-rpm-naming tmp/tmp.csv "$TSUM"
834 "$DATADIR/test-info" bad-naming title
836 awk -F '|' '(NR > 1) && \
837 ((tolower($11)!=tolower($13)) || (tolower($12)!=tolower($14)))' \
840 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
844 if ( $7 == "M" ) { rpm = "[" rpm "]" }
846 print rpm "|" $11 ", " $12 " → " $13 ", " $14 "|" $10
847 }' tmp/tmp.csv | enum_rpm
849 test_wrapup bad-naming tmp/tmp.csv "$TSUM"
853 "$DATADIR/test-info" core-fonts title
855 awk -F '|' '(NR > 1) && ($24=="X")' "$FL" > tmp/tmp.csv
858 test_wrapup core-fonts tmp/tmp.csv "$TSUM"
862 "$DATADIR/test-info" font-linking title
864 awk -F '|' '(NR > 1) && ($16=="Link")' "$FL" > tmp/tmp.csv
867 test_wrapup font-linking tmp/tmp.csv "$TSUM"
871 "$DATADIR/test-info" duplicated-face-int title
874 (NR > 1) && ($24!="X") && \
875 ($15 != "PCF") && ($15 != "Type 1") && \
876 ($11 != "") && ($12 != "") {
877 sig = $3 "|" $4 "|" $5 "|" $11 "|" $12
878 files[sig] = files[sig] $0 "#"
882 sub("#$", "", files[sig])
883 n = split(files[sig],lines,"#")
885 for (l in lines) { print lines[l] }
889 | sort -df -t "|" -k 11 -k 12 -k 3 -k 2 > tmp/tmp.csv
891 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
895 if ( $7 == "M" ) { rpm = "[" rpm "]" }
897 print rpm "|" $11 ", " $12 "|" $10
898 }' tmp/tmp.csv | enum_rpm
900 test_wrapup duplicated-face-int tmp/tmp.csv "$TSUM"
904 "$DATADIR/test-info" fontlint title
906 awk -F '|' '(NR > 1) && ($24!="X") && ($21 > 0)' "$FL" > tmp/tmp.csv
909 test_wrapup fontlint tmp/tmp.csv "$TSUM"
913 "$DATADIR/test-info" no-english-metadata title
915 awk -F '|' '(NR > 1) && ($24!="X") && \
916 ($15 != "") && (($11 == "") || ($12 == ""))' "$FL" > tmp/tmp.csv
918 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
921 rpm = $3 "-" $4 "." $5
922 if ( $7 == "M" ) { rpm = "[" rpm "]" }
925 | column -t -s '|' | pretty_indent
927 test_wrapup no-english-metadata tmp/tmp.csv "$TSUM"
931 "$DATADIR/test-info" partial-scripts title
933 awk -F '|' '(NR > 1) && ($24!="X") && ($19 > 0)' "$FL" > tmp/tmp.csv
936 test_wrapup partial-scripts tmp/tmp.csv "$TSUM"
940 "$DATADIR/test-info" partial-blocks title
942 awk -F '|' '(NR > 1) && ($24!="X") && ($20 > 0)' "$FL" > tmp/tmp.csv
945 test_wrapup partial-blocks tmp/tmp.csv "$TSUM"
951 echo "Audit results:"
954 echo "– packages that declare font metadata:"
956 awk -F '|' '(NR > 1) && ($7 == "M") && ($24!="X")' "$FL" > tmp/tmp.csv
959 echo "☛ File size is computed as extracted, while rpm is a compressed \
960 format." | pretty_indent
961 echo "☛ Mid-term, files in legacy PCF or Type1 formats need to be converted \
962 or removed." | pretty_indent
965 echo "– font files in other packages (we should not find any!)"
967 awk -F '|' '(NR > 1) && ($7 != "M") && ($16 != "Link") && ($24!="X")' "$FL" > tmp/tmp.csv
970 [ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
971 echo "☛ Bad packaging may result in arched packages or mixed content." \
972 | pretty_indent && echo ""
974 echo "– errors, warnings and suggestions:"
984 echo "Packing mail data…"
988 for srpm in $(awk -F '|' 'FNR>1 { print $2 }' "$TSUM" | uniq) ; do
989 [ ! -d "tmp/$srpm" ] && mkdir "tmp/$srpm"
990 cp -p report.txt "tmp/$srpm/repo-report.txt"
991 for file in "$FL" "$TSUM" ; do
992 awk 'FNR==1' "$file" > "tmp/$srpm/$file"
993 awk -F '|' -v srpm="$srpm" 'FNR>1 && $2==srpm' "$file" >> "tmp/$srpm/$file"
995 for rpm in $(awk -F '|' 'FNR>1 { print $3 "-" $4 "." $5 }' "tmp/$srpm/$TSUM" | uniq | sed "s+$bad_pattern+_+g") ; do
996 cp -pr "data/$rpm" "tmp/$srpm"
998 cat > tmp/$srpm/message.txt << EOF
1001 At $TIMESTAMP, your “$srpm” package failed one or more of the tests
1002 I was performing on the “$ID” repository located at:
1005 There are three different reasons that may cause this message:
1006 1. your package is including one or more font files, but not packaging
1008 2. your package is including one or more font files, and I've found
1009 issues in some of them;
1010 3. your package is not shipping any font file, but the way it accesses
1011 fonts in other packages is not satisfying.
1013 To stop receiving this message, you need to:
1014 1. drop the font files or fix their packaging;
1015 2. relay the fonts issues to the fonts upstream to get them revised;
1016 3. work with the code upstream to improve the way it accesses font
1017 files (usually by making it use fontconfig through a higher-level
1018 text library such as pango, pango-cairo, harfbuzz, or QT)
1020 You can self-check your packages at any time by:
1021 1. installing createrepo and fontpackages-tools:
1022 # yum install createrepo fontpackages-tools
1023 2. putting your packages and any font package they depends on in a
1025 3. indexing this directory with createrepo:
1026 $ createrepo path-to-test-directory
1027 4. running repo-font-audit:
1028 $ repo-font-audit test absolute-path-to-test-directory
1030 A summary of the issues I detected is appended here. For your
1031 convenience a more comprehensive analysis is also attached to this
1034 Errors, warnings and suggestions:
1036 $(test_score "tmp/$srpm/$TSUM")
1038 Please take the appropriate measures to fix the “$srpm” package.
1039 I will warn you again if it is still necessary next time I am ran.
1041 This report was generated by the repo-font-audit command from:
1042 http://fedoraproject.org/wiki/fontpackages
1044 Please post questions, suggestions, patches or bug reports to:
1045 https://admin.fedoraproject.org/mailman/listinfo/fonts
1046 (subscription required)
1048 Your friendly QA robot,
1054 tar cf "$srpm.tar" "$srpm"
1056 xz -9 "tmp/$srpm.tar"
1057 mv "tmp/$srpm.tar.xz" spam
1059 cat > spam/send-messages.sh << EOF
1061 # Send warnings to problem package owners
1062 # This is a bit distribution-specific, people from other distributions are
1063 # welcome to suggest how to make it more agnostic
1065 #EMAIL="repo-font-audit <your@mail>"
1066 #REPLYTO=another@mail
1068 #export EMAIL REPLYTO
1071 $(awk -F '|' 'FNR>1 { print $2 " \\" }' "$TSUM" | uniq)
1073 tar -xf \$srpm.tar.xz */message.txt -O \\
1074 | mutt -s "[RFA] Your \$srpm $ID package did not pass QA" \\
1075 -a \$srpm.tar.xz -- \$srpm-owner@fedoraproject.org
1080 chmod +x spam/send-messages.sh
1084 echo "Packing result data…"
1089 mkdir -p "$RES/data"
1090 cp "$TSUM" summary.txt report.txt "$FL" "$RES/"
1091 cp -pr data/* "$RES/data" 2>/dev/null
1094 cp "$TSUM" summary.txt report.txt "$SRES/"
1096 for report in "$RES" "$SRES" "$SPAM" ; do
1097 tar cf "$report.tar" "$report"
1099 mv "$report.tar.xz" "$ORIGDIR/"
1103 echo "Audit complete!"
1105 awk 'NR > 1' "$FL" > "tmp/$FL"
1107 end_time=$(date "+%s")
1108 t=$(($end_time-$start_time))
1110 tm=$((($t/60)-(th*60)))
1111 ts=$(($t-(($th*60+$tm)*60)))
1112 [ $th -gt 0 ] && elapsed_time="$th h"
1113 if [ $tm -gt 0 ] ; then
1114 [ "$elapsed_time" != "" ] \
1115 && elapsed_time="$elapsed_time $tm min" \
1116 || elapsed_time="$tm min"
1118 if [ $ts -gt 0 ] ; then
1119 [ "$elapsed_time" != "" ] \
1120 && elapsed_time="$elapsed_time $ts s" \
1121 || elapsed_time="$ts s"
1127 Run time: $elapsed_time.
1128 Number of items processed:
1129 $(summary "tmp/$FL")
1131 1. Extracted data: $ORIGDIR/$RES.tar.xz
1132 2. Short summary: $ORIGDIR/$SRES.tar.xz
1133 3. Mail data: $ORIGDIR/$SPAM.tar.xz
1135 This report was generated by the repo-font-audit command from:
1136 http://fedoraproject.org/wiki/fontpackages
1138 Please post questions, suggestions, patches or bug reports to:
1139 https://admin.fedoraproject.org/mailman/listinfo/fonts
1140 (subscription required)
1146 # End of function declarations
1148 [ "$#" -lt "2" ] && usage
1150 TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ)
1152 REPOID="$1-rfa-$TIMESTAMP"
1153 REPOURL=$(echo "$2" | fix_url)
1156 FPL="font-packages.csv"
1157 PWFL="packages-with-fonts.csv"
1158 XPL="package-using-x11.csv"
1160 FL="consolidated-data.csv"
1161 TSUM="test-summary.csv"
1162 RES="repo-font-audit-$ID-$TIMESTAMP"
1163 SRES="repo-font-audit-$ID-$TIMESTAMP-short"
1164 SPAM="repo-font-audit-$ID-$TIMESTAMP-mail"
1166 TMPDIR=$(mktemp -d --tmpdir=/tmp $RES-XXXXXXXXXX)
1173 analyse | tee report.txt
1174 sum_up | tee summary.txt