1 contributor
#!/bin/bash
fgaddon_url=https://sourceforge.net/p/flightgear/fgaddon/HEAD/tree/trunk/Aircraft
fgaddon_svn=https://svn.code.sf.net/p/flightgear/fgaddon/trunk/Aircraft
fgaddon_path=$HOME/.fgfs/flightgear-addons/Aircraft
attribute_regex='s/^.*id="l[0-9]+" class="code_block">.*<span class="nt"><__attribute__><.span>(.+)<span class="nt"><.__attribute__><.span>.*$/\1/p'
aircrafts=$(mktemp --dry-run /dev/shm/Aircraft-XXXXXXXXX)
aircraft=$(mktemp --dry-run /dev/shm/aircraft-XXXXXXX)
setxml=$(mktemp --dry-run /dev/shm/setxml-XXXXXXXX)
in_ram_database=$(mktemp --dry-run /dev/shm/XXXXXXX)
database=${DB:-$0.db}
attributes=(description long_description author flight_model)
function get_attribute () {
eval "unset $1"
result=$(sed -rn "${attribute_regex//__attribute__/${1//_/-}}" $setxml)
eval "$1=\$\"$result\""
}
function sqlite_request () {
sqlite3 "$in_ram_database" <<< "$1"
}
function trap_exit () {
echo "updating installation status"
for ac in $(sqlite_request 'select printf("%i:%s/%s", aircrafts.id, aircrafts.name, setxml.file) from aircrafts inner join setxml where aircrafts.id = setxml.variantof;'); do
ac_path=${ac#*:}
test ! -e $fgaddon_path/$ac_path
installed=$?
sqlite_request "update setxml set installed = $installed where file = '${ac_path#*/}' and variantof = ${ac%:*}"
done
if test -r "$database" && md5sum $in_ram_database | sed "s,$in_ram_database,$database," | md5sum --status -c -; then
rm -f $in_ram_database
echo "no changes in $database"
elif test -w "$database"; then
mv -f $in_ram_database "$database"
echo "database $database updated"
elif ! test -e "$database"; then
mv $in_ram_database "$database"
echo "database $database created"
else
rm -f $in_ram_database
echo "nothing can be done with $database !"
fi
rm -f $aircrafts $aircraft $setxml
}
update_database () {
let progress++
echo "[ ${progress}${total:+/$total} ] $ac"
dbupdate=$(sqlite_request "select revision from aircrafts where name is '$ac'")
if test -z "$dbupdate"; then
sqlite_request "insert into aircrafts (name, revision, date, author) values ('$ac', $revision, $revdate, '$revauthor')"
elif test $dbupdate -lt $revision; then
sqlite_request "update aircrafts set revision = $revision, author = '$revauthor' where name is '$ac'"
fi
id=$(sqlite_request "select id from aircrafts where name is '$ac'")
wget -qO- $fgaddon_url/$ac > $aircraft
for sx in $(sed -rn 's/<a class="icon" href="(.+-set.xml)" title=".+"><i class="fa fa-file-o">.+$/\1/p' $aircraft); do
echo " -> ${sx/-set.xml}"
wget -qO- $fgaddon_url/$ac/$sx > $setxml
for attribute in ${attributes[@]}; do
get_attribute $attribute
done
if test -n "$description" -a -z "$flight_model"; then
grep -qi 'jsbsim' <<< "$description" && flight_model='jsb'
grep -qi 'yasim' <<< "$description" && flight_model='yasim'
fi
known=$(sqlite_request "select variantof from setxml where file is '$sx'")
if test -n "$known"; then
for attribute in ${attributes[@]}; do
dbvalue=$(sqlite_request "select $attribute from setxml where file is '$sx'")
eval "wgvalue=\$$attribute"
if test "$dbvalue" != "$wgvalue"; then
sqlite_request "update setxml set $attribute = '$wgvalue' where file is '$sx'"
fi
done
else
test ! -e $fgaddon_path/$ac/$sx
installed=$?
sqlite_request "insert into setxml values ('$sx', $id, '$description', '$long_description', '$author', '$type', '$flight_model', $installed)"
fi
done
}
xmlgetnext () {
local IFS='>'
read -d '<' TAG VALUE
}
trap trap_exit EXIT
test -e $database && cp $database $in_ram_database
sqlite_request "create table if not exists aircrafts (id integer primary key, name text, revision integer, date integer, author text)"
sqlite_request "create table if not exists setxml (file text, variantof integer, description text, long_description text, author text, type text, flight_model text, installed integer)"
test -z "$1" && echo "mode RSS"
case ${1:-rss} in
'full')
echo "downloading the FGADDON list"
wget -qO- $fgaddon_url | sed -n '/<table>/,/<\/table>/p' > $aircrafts
total=$(grep -c '<a class="icon" href=".*class="fa fa-folder".*i> ' $aircrafts)
while xmlgetnext; do
case "$TAG" in
'tr')
unset ac revision revauthor
;;
'a class="icon" href='*)
eval $(echo "${TAG#* }")
ac=$href
;;
'span title='*)
eval $(echo "${TAG#* }")
revdate=$(date +%s -d "$title")
;;
'a href="/p/flightgear/fgaddon/'*)
eval $(echo "${TAG#* }")
revision=$(tr -cd '[:digit:]' <<< $href)
;;
'span class="icon emboss x16" style="text-align:center;" title="User"'*)
user=1
;;
'/span')
test -n "$user" && revauthor=$(tr -cd '[:alnum:]' <<< $VALUE) && unset user
;;
'/tr')
test -n "$revision" -a -n "$revauthor" -a -n "$ac" -a -n "$revdate" && update_database
;;
esac
done < $aircrafts
;;
'rss')
get_updates_from_rss () {
while xmlgetnext; do
case "$TAG" in
'item')
let entry++
unset link revdate revauthor revision title;;
'link')
link="$VALUE";;
'title')
title="$VALUE";;
'dc:creator'*)
revauthor="$VALUE";;
'guid isPermaLink="false"')
revision=$(sed -r 's,^.+/([0-9]+)/$,\1,' <<< $VALUE)
if test $revision -eq ${latest_revision:-0}; then
test $entry -eq 1 && echo "no new updates" >&2
break
fi
;;
'pubDate')
revdate=$(date +%s -d "$VALUE")
;;
'/item')
echo "$revision ($(date +"%d %B" -d@$revdate), $revauthor): $title" >&2
wget -qO- "$link" | awk -v data="revision=$revision revdate=$revdate revauthor=$revauthor" '
/>\/trunk\/Aircraft\/.+</ {
ac[gensub("^.+>/trunk/Aircraft/([^/]+).+<.*$", "ac=\\1", "1", $0)]++
}
END {
for (i in ac) print data " " i
}'
;;
'/channel')
if test ${latest_revision:-0} -lt $revision; then
echo "WARNING: $(( ($revision - ${latest_revision:-0}) )) revisions between the oldest RSS entry and last DB entry" >&2
echo "a \`$0 full' may be useful" >&2
fi
;;
esac
done < $aircrafts | awk '
{
if (a[$4] == "") a[$4]=$0
}
END {
for (i in a) {
total++
command = command a[i] " update_database;"
}
printf("total=%i;%s", total, command)
}'
}
latest_revision=$(sqlite_request "select max(revision) from aircrafts")
wget -qO- https://sourceforge.net/p/flightgear/fgaddon/feed > $aircrafts
eval "$(get_updates_from_rss)"
;;
*)
echo "usage: [DB=path/to/database] $0 [rss|full]"
echo
echo "rss: updates only last repo changes"
echo "full: updates from all repo"
exit 1
;;
esac