| Software Liste | Dokumentationen | Demos | Artikel |
IzzySoft Release Framework: Software Release einfach gemacht
Um was es geht
Wer ein oder mehrere Software-Projekte verwaltet und überdies auch für die "File Releases" verantwortlich zeichnet, weiß, was mit dieser Aufgabe verbunden ist – und genau für sie/ihn ist dieses Framework gedacht. Bei jedem Release muss der/die Verantwortliche …
relman in Aktion (zum Vergrößern anklicken)
- die Sourcen kompilieren
- einen Tarball erstellen
*.deb/*.rpmPakete generieren- den Tarball und/oder die Pakete zu einem/mehreren Server(n) hochladen
- Repositories und/oder Download Seiten aktualisieren
- die Verfügbarkeit einer neuen Version bekanntgeben
Und dann immer im Blick haben, was sich wo befindet: Lokale Verzeichnisse,
Verzeichnisse auf den Servern. Nicht vergessen, die Links für die Downloads
bzw. die Versionsnummern zu aktualisieren, usw. usf.. Wäre es da nicht
praktisch, einen "Release Manager" zur Hand zu haben - dem man einfach sagt:
relman MeinProg NeueVersion, und er erledigt alles nötige automatisch?
Nachdem das hier beschriebene "Release Framework" einmal installiert und
richtig konfiguriert ist, hat man genau das! Alle *.tar.gz Archive und Debian
bzw. RPM Pakete sind nach diesem Kommando nicht nur erstellt, sondern auch
bereits auf den jeweiligen Servern abgelegt. Auch das "ChangeLog" liegt dann
schon dort vor, und stellt auf magische Weise die gerade fertiggestellten
Pakete zum Download an. Nur das "Announcement" in den entsprechenden Foren o.ä.
steht noch offen. …
Dies sind die drei Programme, die an diesem Framework beteiligt sind:
- relman ist die "Schaltzentrale" und das "Verteilzentrum". In seiner Konfigurationsdatei sind alle relevanten Daten der Projekte abgelegt. Darauf basierend ruft relman seinen "Kompagnon" pkgmake auf (um die Pakete und den Tarball zu erstellen), und verteilt dann alles, je nach Konfiguration, auf die angegebenen Server. Optional können auch zusätzliche Skripte in den Verschiedenen Stadien (vorher, nachher, vor dem Build, nach dem Build aber vor dem Verteilen) aufgerufen werden – z.B. um das Repository auf dem Server nach dem Verteilen der Pakete zu aktualisieren.
- pkgmake erstellt das Tar-Archiv und/oder die
*.deb/*.rpmPakete, basierend auf den von relman auf der Kommandozeile übergebenen Parametern sowie einer RPM .spec Template-Datei. - histview ist auf dem Webserver installiert, und erkennt alte und neue Releases automatisch anhand der "ChangeLog" Datei (welche relman ja ebenfalls verteilt hat) – die Liste der Änderungen steht also zusammen mit den Download-Links bereit.
Feuer gefangen? Auf den folgenden Seiten gibt es die Einzelheiten:
Inhalt
relman
Als diejenige Komponente, die die Verteilung der Software auf die verschiedenen Server übernimmt, kann man relman sicher als "Verteilerzentrum" ansprechen. Aber es ist mehr – es ist die "Schaltzentrale" des gesamten Frameworks: Hier werden alle relevanten Details zu den Projekten gespeichert, nur dieses Programm wird direkt aufgerufen und kümmert sich um alles nötige.
Auch wenn relman selbst nur ein "einfaches Shell Skript" ist, welches die Daten einer Konfigurationsdatei ausliest, sie interpretiert, und darauf basierend die entsprechenden Tools aufruft – es ist ein leistungsfähiges Werkzeug. Dank seiner flexiblen Konfiguration erlaubt es u.a. auch die Definition von Skripten, die in den verschiedenen Stadien des Prozesses (zu Anfang, vor der Paketerstellung, vor der Verteilung bzw. zum Abschluss), verschiedene Arten des Bezugs der Sources (vom einfachen Kopieren bis zum Export aus CVS bzw. SVN), sowie das Kopieren des entsprechend formatierten "ChangeLogs" zum Einsatz mit HistView. Nur Kaffeekochen kann es leider noch nicht …
Dokumentation
Die eigentliche Dokumentation (abgesehen von diesem Artikel) kommt in Form von
"Man pages" – eine unter Unix/Linux durchaus verbreitete Form. Durch Eingabe
von man relman an der Kommandozeile (gefolgt von "Enter" ;) erhält der
Anwender eine Übersicht über die passenden Parameter und deren Einsatz.
Gleiches gilt für man relman.conf hinsichtlich des Aufbaus und der
verfügbaren Optionen in der Konfigurationsdatei. Da an diesen beiden Stellen
alle Details beschrieben sind, konzentriert sich dieser Artikel auf das
Wesentliche – um in überschaubarem Rahmen einen Einblick zu ermöglichen.
Konfiguration
Allgemein
Die Konfiguration – eine einfache "ASCII" Textdatei – lässt sich grob in zwei
Sektionen einteilen: Die "globalen", sowie die projektspezifischen Einstellungen.
In vielen Fällen gilt es hier lediglich, die Werte 0 (für ein deaktiviertes
Feature) bzw. 1 (aktivierte Funktion) zuzuweisen. Die verbleibenden Einstellungen
Extract from config file (click to enlarge)
betreffen überwiegend Verzeichnis- und Serverangaben. Da die meisten "globalen
Einstellungen" gleichzeit als "Defaults" für projektspezifische Settings dienen,
kann die Erstellung eines Projektes im Minimalfall mit zwei Zeilen auskommen:
Dem Namen des Projektes sowie dem Verzeichnis, in welchem sich der zugehörige
Sourcecode befindet. Selbstverständlich lassen sich jedoch einige oder gar alle
"Defaults" hier durch spezifische Einstellungen "überschreiben". Auf diese Weise
bleiben die Angaben für "einfache Projekte" überschaubar – während für
"spezielle Projekte" die volle Flexibilität gewahrt bleibt.
Die einzigen ausschließlich "globalen" Einstellungen sind das Verzeichnis des
"Build Environments" (gewöhnlich /usr/src/debian, sofern bereits
pkgmake installiert ist – was der Fall sein sollte, und zwar
automatisch sofern die Installation von relman über ein *.deb/*.rpm Paket
erfolgte, da relman auf pkgmake aufsetzt), sowie das zu verwendende pkgmake
"Executable". Bei Installation basierend auf einem *.deb/*.rpm Paket sind
hier keine Anpassungen nötig.
Alle anderen Einstellungen sind die bereits genannten "Defaults" (Voreinstellungen) für die später zu definierenden Projekte. Konkret bedeutet dies, dass man z.B. generell die Erstellung von RPM Paketen aktivieren, sie aber für einzelne Projekte gezielt abschalten kann – oder auch umgekehrt. Je besser diese Voreinstellungen auf den Großteil der Projekte passen, desto weniger ist für jene später explizit zu definieren. Die Beispiel-Konfiguration, welche mit relman ausgeliefert wird, demonstriert dies anhand der Projekte "small" und "medium" – sowie die "volle Flexibilität" anhand des Projektes "LongJohn".
Sind die "globalen Einstellungen" festgelegt, kann man zur Definition der
Projekte fortschreiten. Projekteinstellungen sind zweifelsfrei an ihrem Präfix
zu erkennen (und dem jeweiligen Projekt zuzuordnen). Diese lassen sich für
jedes Projekt möglichst kurz halten, um Tipparbeit zu sparen. Um ein "dummes"
Beispiel zu geben, nehmen wir uns ein Projekt und nennen es
"verylongprojectname". Alle "Releases" sollen natürlich den vollen Namen
verwenden (also z. B. verylongprojectname-0.1.2.tar.gz) – aber wir wollen das
natürlich nicht jedes Mal eingeben müssen. Also nehmen wir uns stattdessen als
Kürzel vlpn_ her:
vlpn_name=verylongprojectname
vlpn_srcdir=/usr/local/source/vlpn
usw.. Für eine Release können wir uns auf das Projekt unter dem Kürzel "vlpn"
beziehen: relman vlpn 0.1.2.
Für jedes Projekt lassen sich separate "Distribution Targets" (also Ziele, zu denen die erstellten Archive/Pakete transferriert werden sollen) definieren, sowie welche Pakete (nicht) erstellt werden sollen, und, und, und. Sobald die nötigen Einstellungen jedoch mit den "Defaults" übereinstimmen, brauchen wir sie hier jedoch nicht explizit aufzuführen.
Pakete
Mit einfachen "booleschen" Variablen lässt sich festlegen, welche Pakete
erstellt werden sollen. Während der "Tarball" generell dazu gehören sollte
(mktar=1), sofern man etwas aus den Sourcen erstellen will (da dieser sowohl
für RPM als auch Debian Pakete als Grundlage genommen wird), kann die
Entscheidung hinsichtlich Debian (mkdeb) und RPM (mkrpm) Paketen
differenzierter ausfallen. Die Variablen group und section legen hier die
von pkgmake zu verwendende RPM Paketgruppe bzw. Debian Sektion fest. Und soll
pkgmake noch etwas mitgeteilt werden, für dass relman (noch?) kein Keyword
bereit hält, kann dies über pkgmakeparms geschehen.
Weiter oben wurden einige Variablen bereits im Rahmen der "globalen"
Einstellungen und "Defaults" angesprochen. Bis auf die beiden genannten
Spezialfälle gilt: Stellt man den Projekt-Präfix (in unserem Beispiel "vlpn_")
voran, wird daraus eine projektspezifische Einstellung. Beispiel: mkdeb=1 -
generell sollen Debian Pakete erstellt werden, vlpn_mkdeb=0 - für unser
verylongprojectname jedoch nicht.
Paketdienst
Die Verteilung der Software erfolgt über FTP und SCP (je nachdem, was konfiguriert wurde). Die Ziele können für jedes Projekt separat definiert werden, aber selbstverständlich sind auch hier globale Werte möglich. Ein klassisches Beispiel wäre ein Upload der Software in den "incoming" Ordner bei Sourceforge:
tarftp=upload.sourceforge.net
tarftpdir=incoming
In diesem Fall haben wir das global für alle *.tar.gz Archive mit zwei Zeilen
für FTP definiert: Den Server sowie das Verzeichnis separat. Für SCP wäre dies
nur eine Zeile: [user[/password]@]server:/path/to[/filename.ext].
Wird der Dateiname nicht extra angegeben, heißt die Datei auf dem Zielsystem
exakt so wie nach der Paketerstellung lokal (das gilt übrigens generell für
FTP). Lässt man das Passwort weg, wird ggf. danach gefragt. Den Usernamen
ebenfalls entfallen lassen kann man, wenn auf der Gegenseite der selbe
Verwendung findet. Bei FTP erfolgt die Authentifizierung übrigens anhand einer
netrc Datei – näheres bringt man netrc zum Vorschein.
Diese *ftp[dir] und/oder *scp Einstellungen sind für jeden Dateityp separat
vorzunehmen (kann ja auch alles zu ganz verschiedenen Zielen kopiert werden
[müssen]) – d. h. für deb, rpm, tar, und - ein spezieller Fall - hist, welches
das "History File" für Histview bezeichnet.
Skripte Bereits in der genannt wurden diverse Skripte, die zu
verschiedenen Stadien des Prozesses "laufen gelassen" werden können. Also sollen an dieser Stelle auch gleich ein paar mögliche Einsatzgebiete her, um deren Einsatz zu veranschaulichen:
Bevor wir irgend etwas "releasen", wollen wir die aktuelle Arbeit noch in das
entsprechende Repository einchecken. Dafür eignet sich das prerun Skript, da dies
zu allererst läuft: vlpn_prerun="cd /usr/local/source/vlpn && cvs ci".
Dann wollen wir sicherstellen, dass die Versionsnummer in einer speziellen Datei
auch die richtige ist - ohne dass wir dieser Datei eine neue CVS-Version verpassen:
vlpn_prebuild="echo \"version=%v\" >%b/version". So, diese beiden
Dinge können wir jetzt nie mehr vergessen. Damit nach dem Hochladen des aktuellen
Debian Paketes auch das Repository aktualisiert wird, gleich noch ein
postrun="ssh unser.server ~/bin/update-repo" – jawollja, global,
damit es immer passiert.
Quellen
Wer mehr über relman erfahren will, kann sich noch an folgenden Stellen umsehen:
- Relman Homepage
- Relman Projectseite bei Freshmeat
- Relman ChangeLog und Download-Verzeichnis
- Die Software Liste dieser Site
pkgmake
Haben wir relman als "Schaltzentrale" und "Verteilerzentrum" kennengelernt, so ist pkgmake eigentlich nur ein "Backend" dazu – aber immerhin ein wichtiges: Ohne das, was der "Packager" erstellt, hätte relman nichts zu tun: pkgmake zeichnet verantwortlich für das Erstellen der Tar Archive sowie Debian und RPM Pakete – je nachdem, was konfiguriert wurde.
Anders als relman, der hauptsächlich über seine Konfigurationsdatei gesteuert wird und im Allgemeinen mit zwei Kommandozeilen- Parametern ausreichend bedient ist, verlangt ein Aufruf von pkgmake gleich eine ganze Kette von Parametern. Daher bietet sich auch die Verwendung von relman als "Frontend" an, sodass wir uns darüber nicht wirklich Sorgen machen müssen. Aber wir dürfen es natürlich, wenn wir darauf bestehen: pkgmake kann durchaus auch "Stand-Alone" verwendet werden.
Dokumentation
Wie bereits bezüglich relman erwähnt,
kommt auch hier die Dokumentation wieder hauptsächlich in Form von "Man Pages"
daher. Nur ist es hier gleich eine mehr: man pkgmake gibt Auskunft
über die zahlreichen Kommandozeilen-Parameter, man pkgmake.conf
hinsichtlich der Optionen in der Konfigurationsdatei, und "man pkgmake.tpl"
ist zuständig für die Details in den Template Dateien.
Konfiguration
Die Konfigurationsdatei
Konfigurationsdatei (zum Vergrößern anklicken)
Wie bereits gesagt, kann pkgmake durchaus auch (sinnvoll) "Stand-Alone" eingesetzt
werden – also verfügt es auch über eine eigene Konfigurationsdatei. Wie auch
bereits bei relman, handelt es sich hier um eine einfache (ASCII) Textdatei nach
Konventionen der Unix Shell "Bash", sodass die Einstellungen aus "Variable=Wert"
Paaren bestehen. Alle hier getroffenen Einstellungen stellen "Defaults" dar, welche
mittels Kommandozeilen-Parametern überschrieben werden können. Dies heißt wiederum:
Je genauer diese Einstellungen mit denen eines Projektes übereinstimmen, desto
weniger Parameter braucht man für selbiges anzugeben. Doch genaugenommen
interessiert uns das ja eigentlich gar nicht, da sich ja relman um diese Dinge
kümmert …
Doch selbst wenn relman zum Einsatz kommt, sollten einige Einstellungen in der
Konfiguration von pkgman getroffen sein. Dies betrifft in erster Linie die
Angabe des Packers (also desjenigen, der für die Erstellung der Pakete
verantwortlich zeichnet), sowie des Vendors (also des "Herstellers" der
Software). Zumindest ersterer ist i. d. R. konstant, auch wenn "Fremdsoftware"
verarbeitet wird – was sicher eher die Ausnahme ist, sodass auch der "Vendor"
überwiegend gleich bleibt. Die Lizenzen der Software können voneinander
abweichen, aber auch hier gibt es meist einen Schwerpunkt, der an dieser Stelle
konfiguriert werden sollte. Auf jeden Fall stellen die verwendeten
"Executables" (ausführbaren Programme) zur Erstellung von Debian (DEBBUILD)
und RPM (RPMBUILD) Pakete eine Konstante dar, sowie das "Build Environment"
(Verzeichnis, in welchem die Pakete und Tar-Archive abgelegt werden). Für
zumindest diese Dinge sollten hier Voreinstellungen getroffen werden.
Nebenbei: Wie auch bei relman, werden bei pkgmake zwei Verzeichnisse
auf Konfigurationsdateien geprüft, und selbige dann sequentiell eingelesen:
Globale Einstellungen aus der Datei /etc/pkgmake.conf werden mit
denen aus der "persönlichen" Datei ~/.pkgmake/pkgmake.conf
überschrieben – in letzterer lassen sich also von ersterer abweichende
Einstellungen treffen, während man alle anderen hier auskommentiert. So
ergänzen sich beide wunderbar, wenn sich z. B. mehrere Entwickler einen Server
zur Paketerstellung teilen.
Die Template Datei(en)
Template-Datei (zum Vergrößern anklicken)
pkgmake benutzt RPM .spec Dateien als Konfiguration zur Erstellung von RPM
und Debian Paketen. Dabei können im Grunde genommen beide Pakettypen aus der
gleichen .spec Datei generiert werden. Der "kleine Unterschied" liegt hier in
der Definition der Paketgruppe: Die bei RPM verwendeten Gruppen stimmen nämlich
mit den bei Debian zum einsatz kommenden "Sektionen" ganz und gar nicht
überein. Dennoch käme es deshalb nicht zu einem Installationsfehler – obwohl es
zwei gute Gründe gibt, diesen Konflikt zu beheben: 1) Ein Debian-Paket mit
einer RPM Gruppe ist einfach nicht 100% konform, und 2) sorgt es beim Anwender
dafür, dass dieser in seiner Paketverwaltung letztendlich zahlreiche
zusätzliche "Gruppen" hat, die jeweils nur ein oder zwei Pakete enthalten. Um
dieses Problem zu umgehen, lassen sich bei pkgmake eine Gruppe und eine Sektion
definieren, wobei letztere dann speziell für die Debian Pakete zum Einsatz
kommt. Solange niemand die Gruppe im Template "hardcoded" hat, sondern brav der
Platzhalter Verwendung findet.
Wie (üppig) Platzhalter in der Template-Datei zum einsatz kommen (können),
zeigt die Abbildung (links): Fas die ganze Datei kann sich aus solchen
zusammensetzen. Je weniger man ohne Platzhalter auskommt, desto flexibler wird
die Handhabung der Template-Datei: Im Idealfall ließe sich ein solches Template
gleich für mehrere Projekte nutzen - woran oftmals nur die %files Sektion
hinderlich ist …
Niemand ist dazu gezwungen, Platzhalter zu verwenden - jedoch macht pkgmake ohne diese einfach weniger Sinn. In der Praxis gilt es daher nicht abzuwägen, ob, sondern welche Platzhalter zum Einsatz kommen sollen. Nicht alles kann mit ihnen abgedeckt werden, und nicht immer macht jeder Platzhalter auch wirklich Sinn. Die Flexibilität ist jedoch gegeben, und der Einsatz mag bei verschiedenen Projekten halt unterschiedlich ausfallen. Wie obiges Beispiel zeigt, sollte jedoch zumindest die "Group:" als Platzhalter realisiert sein, damit sowohl konforme RPM als auch Debian-Pakete erstellt werden können.
Quellen
Mehr Informationen zu pkgmake finden sich:
- pkgmake Homepage
- pkgmake Projectseite bei Freshmeat
- pkgmake ChangeLog und Download-Verzeichnis
- Die Software Liste dieser Site
HistView
Das Release ist gemacht, das Projekt hat seine "Website", die Dateien sind hochgeladen, und (potentielle) Benutzer sollen über die neue Version sowie die gemachten Änderungen informiert werden – hier kommt Histview ins Spiel. Die PHP Klasse lässt sich nutzen, um das "ChangeLog" des Projekts auf benutzerfreundliche Weise anzuzeigen – und dabei für jedes Release auch die zugehörigen Dateien zum Download anzubieten.
Dokumentation
Histview in Aktion (zum Vergrößern anklicken)
Anders als bei den Kommandozeilen-Tools relman pkgmake,
kommt die Dokumentation hier im HTML-Format daher. Die Pakete (und auch der
"Tarball") enthalten eine Api Referenz in Form einzelner HTML Dateien, die sich
im Verzeichnis doc/ (Tar-Archiv) bzw. /usr/share/doc/histview (RPM/Debian
Paket) befinden. Beispiele für die Anwendung finden sich im Programmverzeichnis
(/usr/share/histview bei Installation aus Paketquellen).
Damit Histview ein ChangeLog analysieren kann, muss dieses in einem bestimmten Format vorliegen – wobei dies in den meisten Fällen "von Natur aus" so ist, da das Format sich recht intuitiv darstellt:
Eine mit v0.0.0 beginnende Zeile wird als "Version" interpretiert – wobei die
"0.0.0" natürlich durch die entsprechende Versionsnummer zu ersetzen ist. Dieser
Zeile folgt meist eine "Unterstreichung" (-----). Alles vor der ersten
Versionsnummer wird genau so ignoriert, wie leere oder mit einem Hash (#)
beginnende Zeilen. Für neue Features beginnt die Zeile mit einem +, gefolgt
von mindestens einem Leerzeichen (braucht man mehrere Zeilen für die
Beschreibung, sind die Folgezeilen entsprechend einzurücken). Ein *
bezeichnet eine Änderung, ! einen Bugfix und - den Wegfall einer "Sache".
Für die meisten Projekte sollte also entweder keine oder nur geringe Änderungen am Format des ChangeLog nötig sein, damit Histview dieses verarbeiten kann.
Konfiguration
Histview
Skript-Datei (zum Vergrößern anklicken)
Die Konfiguration findet hier in der aufrufenden PHP Skript Datei statt. Da
Histview als PHP Klasse bereit gestellt wird, lässt sich das "Drum herum" auf
diese Weise frei gestalten – wobei die bereitgestellten Beispieldateien
durchaus als Grundlage dienen können.
Im Grunde genommen gibt es da auch nicht viel zu tun: Es muss eine Instanz der
Klasse angelegt werden, wobei der Name der zu analysierenden ChangeLog Datei
und, optional, der "Basisname" für die zum Download zu verlinkenden Dateien
(für gewöhnlich der Projektname in Kleinbuchstaben –z.B. "histview" für
histview-0.1.4.tar.gz, histview_0.1.4-izzy1_all.deb, etc.pp.) als Parameter
übergeben werden. Dann lässt sich – wiederum optional – durch den Aufruf der
Methode use_dlclass() die Benutzung der Download-Klasse aktivieren (siehe
Beispielskript). Auf jeden Fall sollten wir Histview mitteilen, wo es die
Download-Dateien für die jeweiligen Typen (tar, rpm, deb) finden kann – hierfür
steht die Methode set_basedir(). Sollen Debian/RPM Pakete angezeigt werden,
sollte auch mittels der Methode set_relname() der Release-Prefix angegeben
werden, sofern einer zum einsatz kommt (im obigen "histview" Beispiel wäre das
"izzy"). Das war's im Wesentlichen (wie immer, gibt es noch mehr, was man
machen kann, aber nicht muss) – und Histview kann mit der process()
Methode angewiesen werden, das angegebene ChangeLog zu analysieren – um dann
mittels der Methode out() den resultierenden HTML-Code zurück zu liefern,
damit er im aufrufenden Skript verarbeitet (ausgegeben) werden kann.
Als weitere "Nice-to-Have" Dinge, die man noch tun kann, steht z.B. die Angabe anderer Icons für die Download-Dateien zur Verfügung, um nur eine Sache beim Namen zu nennen. Doch diese Details lassen sich alle der bereits weiter oben genannten Api Referenz entnehmen.
Die Download-Klasse
Weiter oben wurde sie bereits erwähnt, da die Histview-Klasse sie optional verwenden kann. Wozu man dies tun sollte, war dort jedoch nicht beschrieben. Nun, die Download-Klasse bietet – auch über die Einbindung in Histview selbst – einige nette Funktionen: In Histview eingebunden, lassen sich damit die Download Verzeichnisse selbst verstecken (es taucht nur noch der Dateiname auf). Darüber hinaus können auch (im Zusammenspiel mit einer MySQL Datenbank) Download-Statistiken erstellt werden. Eine weitere Möglichkeit ist das Erstellen von Verzeichnislisten für den Download.
Weitaus interessanter dürfte jedoch die Möglichkeit sein, sich mittels der
Download-Klasse einen "Alias" zum Herunterladen der jeweils aktuellsten Version
zu erstellen. Man kann dann für den Download einfach eine feste URL, z. B.
"project_release.php", angeben – und wer diese URL ansteuert, erhält immer die
jeweils neueste Version, ohne dass wir erneut Hand angelegt hätten. Die Methode
send_latest() stellt dazu den Schlüssel dar. Anhand dreier Parameter
(Basisname der Datei, Typ ["tar","deb","rpm"], sowie Verzeichnis) ermittelt sie
die so spezifizierte Datei mit der höchsten Versionsnummer, und schickt diese
an den "Anforderer".
Quellen
Wer mehr über Histview erfahren möchte, schaut bitte hier:
- Histview Homepage
- Histview Projectseite bei Freshmeat
- Histview ChangeLog und Download-Verzeichnis
- Die Software Liste dieser Site
