Development

Aus TuxboxWIKI
Wechseln zu: Navigation, Suche

Development

Dieser Artikel versucht interessierten Entwicklern oder die jenigen die zur Verbesserung der Tuxbox- bzw. auf NeutrinoHD basierender Software beitragen wollen, Informationen über den Entwicklungsprozess zu geben und Fragen von neuen Entwicklern zu beantworten. Wenn Du beim Programmieren helfen willst, aber noch nicht die notwendigen Kenntnisse hast, dürfte dies eine gute Anlaufstelle sein. Bei Fragen hierzu bitte auch die Supportforen oder Mailinglisten nutzen.

Inhaltsverzeichnis


Source-Code

Build Documentation

Programmiersprachen

Vorwiegend wird C/C++ verwendet. Für diverse Software oder Tools, die nicht direkt mit der Software oder Treibern für die unterstützen Receivertypen zu tun haben, kann natürlich jede nach Bedarf benötige Sprache verwendet werden. Dies würde beispielsweise einige Tools betreffen, die unter Hostapps im CVS abgelegt worden sind.


Codingstyle

Der Sourcecode von Neutrino ist inzwischen in die Jahre gekommen. Viele Programmierer haben Hand am Source angelegt. Da es nie Maintainer oder besondere Sourcecode Formatierungsregeln gab, ist der Quellcode von Neutrino, und auch der daraus entstandene Quellcode von Neutrino-HD, in unterschiedlichster Weise formatiert. Dies ist für die Lesbarkeit und für das Verständnis des Quellcodes nicht von Vorteil.

Zustand

Der Source der Neutrino Quellen ist zum größten Teil in C bzw C++ geschrieben. Da teilweise viele Personen an ein und derselben Datei gearbeitet haben kann es innerhalb ein und der selben Datei die unterschiedlichsten Formatierungen geben.
In den sonstigen Dateien wiederum (Shellscripte z.B.) gibt es keine besonderen Unterschiede in den Styles und Formatierungen.

Strukturierung

Für das Formatieren von C/C++ gibt es leicht unterschiedliche Einrückungsstile. Um die Lesbarkeit des Quellcodes zu verbessern sollten Programmierer die in den diversen Dateien arbeiten sich an bestimmte Standards halten. Dies ist kein absolutes Muss, ist aber sehr zuträglich für das Projekt. In anderen GNU Projekten ist die Einhaltung projektspezifischer Standards wegen der Größe dieser Projekte wiederum Pflicht. So zum Beispiel bei der Linuxkernelentwicklung oder beim KDE Projekt.

Modelines

Mit sogenannten Modelines kann man dem Editor seiner Wahl Bearbeitungsoptionen und Anzeigeoptionen mitgeben, sofern dieser dieses Feature unterstützt. Diese Modelines müssen entweder direkt in den bis zu ersten drei Zeilen oder in der letzten Zeile vorhanden sein, allgemein üblich ist am Beginn der Datei. Da historisch bedingt die ersten Editoren reine Text basierende Programme waren bezieht sich der Syntax in der Regel auf Vi/Vim. Eine Modeline (im Beispiel nur in der ersten Zeile) sieht dann z.B. so aus.

// vim:filetype=c:ai:expandtab:tabstop=4:textwidth=72:
//
// file foo.cpp
// The file foo.cpp implements various helper functions.
//
// include <iostream>
// ...
Erläuterung zu den Modeline Angaben
Modelineargument Erklärung
vim: Start der Modelineanweisungen
filetype=c Angabe des Dateityp, hier C Quelletxt
ai autointend, bei Zeilenumbruch automatisierte Einrückung (funktioniert je nach Editor nicht automatisch)
expandtab automatische Erweiterung von Tabulatoranschlägen mit Leerzeichen
tabstop=4 Anzahl von Zeichen die beim benutzen der Tabulatortaste benutzt werden
textwidth=72 automatisierter Umbruch nach dem 72. Zeichen (Tabs werden aufgelöst)

Die Anweisungen der Modeline beginnen im Beispiel mit vim: und werden immer mit einem Doppelpunkt oder auch Leerzeichen getrennt. Zwischen den Kommentarzeichen und dem Beginn der Modeline muss mindestens ein Leerzeichen sich befinden. Genaueres zum Aufbau der Modelines findet man im Wiki vom Vim.

Quelltextformatierungen

Da an Neutrino wohl fast nur Freiwillige arbeiten, ist so eine Forderung nur schwer umzusetzen. Man kann so etwas aber sehr wohl als erstrebenswertes Optimum ansehen und jeder der mitarbeitet, sollte sich so weit es geht an solche Wunschvorgaben halten.

Als ein guter Kompromiss zwischen Lesbarkeit und Platzbedarf hat sich der Stil 1TBS/K&C („One True Brace Style“ von Kernighan und Ritchie) erwiesen. Kurz und kompakt bedeutet das folgendes:

Beispiel Funktionsdeklaration

  • Die öffnende Klammer einer Funktion steht immer an einem Zeilenanfang.
void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
{
...
}
  • Bei vielen Funktionsübergabeparametern sollten an diesen jeweils möglichst die Zeile umgebrochen werden. Eine Zeile sollte nicht mehr wie 72 Zeichen enthalten.
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
	unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
	unsigned int *offset, enum xfer_buf_dir dir)
{
...
}

Beispiel Schleifen

  • Schleifen können genauso eingefasst werden. Dies kostet aber relativ viel Platz bei zahlreichen einfachen Aktionen, darum folgende Empfehlung die öffnenden Klammer direkt nach der Bedingung von Schleifen, if...then...else...-Steuerpaaren usw. zu setzen mit der schließenden Klammer vor der nächsten Bedingung. Dieser Stil wird auch in der Kernelentwicklung angewandt und ist sehr gebräuchlich.
if(( hp = gethostbyname( host )) != NULL ) {
	memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
	taddr->sin_port = 0;
	taddr->sin_family = AF_INET;
} else if ( inet_aton( host, &taddr->sin_addr ) == 0 ) {
	return -1;
}
  • Das Gegenstück dazu ist, jede Klammer separat in eine Zeile zu setzen was zwar nicht platz sparend ist, aber die Lesbarkeit des Quellcodes welcher logisch zusammen gehört, wird dabei erhöht. Der selbe Quellcode würde dann so aussehen.
if(( hp = gethostbyname( host )) != NULL )
{
	memmove( &taddr->sin_addr, hp->h_addr_list[0], sizeof( taddr->sin_addr ));
	taddr->sin_port = 0;
	taddr->sin_family = AF_INET;
}
else if( inet_aton( host, &taddr->sin_addr ) == 0 )
{
	return -1;
}
  • Letztendlich gilt aber auch hier: Benutzt den Stil den Ihr in der Datei vorfindet!
  • Die Einrückungstiefe (Tabulator) sollte aus vier Zeichen bestehen. Acht Zeichen sind allerdings auch o.k. Innerhalb einer Datei sollte aber immer die selbe Einrückungstiefe benutzt werden.
  • Hier ist zu beachten das je nach verwendeten Editor und dessen Einstellungen unterschiedliche Effekte auftreten können. Die meisten Editoren bieten an eine Tabeinrückung mit der entsprechenden Leerzeichenanzahl aufzufüllen . Kontrolliert Eure Einstellung im Editor.
  • Massives oder sogar vollständiges Verändern von Dateien, nur um die obigen Punkte zu erreichen (z.B. durch Tools wie astyle), sind daher grundsätzlich zu vermeiden! Dadurch geht die komplette Historie zu dieser Datei zwar nicht verloren, wird aber stark beeinträchtigt, so dass z.B. Blame-Tools unter Umständen wenig oder keine brauchbaren Daten liefern könnten. Die Historie ist aber bei der Einkreisung von Programmierfehlern teilweise sehr hilfreich! Es sollten daher nur die Stellen vereinzelt nebenher verändert werden, an denen man gerade Veränderungen durchführen will.

Kommentare

Kommentare sind wichtige Bestandteile des Quellcodes! Nutzt diese Möglichkeit der Informationsweitergabe.

Gemessen an vielen C++ Projekten wie sie zB. auf Ohloh analysiert werden, sind 22% aller Quellcode-Zeilen Kommentare. Für Neutrino-HD, ist diese Zahl nur 13% und hat damit eine der niedrigsten Quoten, die offiziell bestätigt sind.

Eine hohe Anzahl von Kommentaren könnte darauf hindeuten, dass der Code gut dokumentiert und organisiert ist, und könnte ein Zeichen für teamfähige Mitglieder, ein hilfreiches und diszipliniertes Entwicklungsteam sein.

Leider sind Kommentare in Neutrino und Neutrino-HD aktuell in der Tat sehr spärlich im Code. Es muss nicht jede Subroutine erklärt werden, aber ein Kommentar zu einer Funktion, der Funktionsweise und deren Rückgabewerte sollte aber selbstverständlich sein.

  • In internationalen Projekten sind Kommentare in Landessprache des Entwickler verpönt! Üblich und eine von jeden Programmierer verstandene Sprache ist Englisch, also bitte alle Kommentare in Englisch verfassen.
  • Kommentare über mehr wie eine Zeile sollten mit /* ... */ eingefasst und einzeilige Kommentare können mit // begonnen werden, üblich ist aber auch wieder die Einfassung mit /* ... */. Kommentare sollten entweder der einzige Inhalt einer Zeile sein oder am Ende einer Codezeile stehen aber niemals mitten im Code (was theoretisch auch geht).
/*
 * draw_line
 * 
 * args:
 * x1    StartCol
 * y1    StartRow
 * x2    EndCol
 * y1    EndRow
 * state LCD_PIXEL_OFF/LCD_PIXEL_ON/LCD_PIXEL_INV
 * 
 */

oder

if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
	perror("LCD (" LCD_DEVICE ")"); //giving out an error message
...

folgendes ist auch gebräuchlich

if ((fd = open(LCD_DEVICE, O_RDWR)) < 0) {
	perror("LCD (" LCD_DEVICE ")"); /* giving out an error message */
...

Debugausgaben

Ausgabe von Debugmeldungen sind ein wichtiges Hilfsmittel bei der Entwicklung. Für den normalen Betrieb sind diese Debugausgaben jedoch auf die wichtigsten Meldungen zu minimieren. Gerade hier kann Neutrino-HD noch deutlich verbessert werden. Einfache printf Ausgaben sind für die eigene Entwicklung o.k. sollten aber nicht in ein Versionsverwaltungssystem eingecheckt werden.


Bugtracking

Commit Messages

Was sind gute Commit Messages und warum man diese erstellen sollte.

  • Commit Messages sollen anderen Beteiligten an einem Projekt mitteilen, was Du in Deinem Commit getan hast. Damit diese Info effizient und auch elektronisch verwertbar sind (z.B. zur Aufbereitung eines whats_changend.txt) gibt es ein paar Regeln die beachtet werden sollten.
  • Gute Commit Messages ersparen anderen Beteiligten eine aufwendige Suche und steigern die Effektivität.
  • Aussagekräftige Commit Messages sind ebenfalls der Baustein für ein treffsicheres Suchen zu späterer Zeit. Dies ist zum Beispiel wichtig wenn man eine Fehlersuche betreiben muss, und dies üblicher Weise basieren auf den Commit Nachrichten tätigt.
  • Der Zeitaufwand für das Schreiben einer aussagekräftigen Message beläuft sich auf geschätzt höchstens 3-5min. Aber dadurch wird das spätere Suchen in der History oder im Sourcecode wesentlich effizienter und der Entwickler kann sich seiner eigentlichen Beschäftigung, dem Programmieren, widmen. Wenn Ihr bisher noch nicht so gearbeitet habt, lest folgende Hinweise und fragt Euch dann ob es nicht besser wäre so zu arbeiten.

Aufbau einer Commit Message

  • Die erste Zeile eines Commits besteht immer aus einer kurzen Zusammenfassung Deines Commits bestehend aus Zahlen und Buchstaben, jedoch ohne Anführungspunkte. Diese sollte nicht mehr wie 50 Zeichen umfassen. Die üblichen Editoren helfen mit einer farblichen Hervorhebung beim Verfassen der Commit Message.
  • Es ist gute Praxis die Funktion, die logische Einheit oder auch eine Bugnummer gefolgt von einem Doppelpunkt der kurzen Zusammenfassung voran zustellen.
  • Hast Du nun noch mehr mitzuteilen, das wird fast immer der Fall sein, dann beachte folgendes.
    Die zweite Zeile bleibt prinzipiell leer!
  • Ab der dritten Zeile beginnt Deine ausführlichere Darstellung Deines Commits. Aber auch hier sollte man sich daran halten das alle Zeilen nicht länger wie 72 Zeichen sein sollen. Für die Strukturierung Deiner Punkte kannst Du z.B. diverse Anführungspunkte benutzen wie z.B. *, -, #. Schreibe Deine Nachricht in der gegenwartsbezogenen Verlaufsform!

Ein Beispiel aus der Linuxkernelentwicklung. [1]

loop: export module parameters

Export 'max_loop' and 'max_part' parameters to sysfs so user can know
that how many devices are allowed and how many partitions are supported.

If 'max_loop' is 0, there is no restriction on the number of loop devices.
User can create/use the devices as many as minor numbers available. If
'max_part' is 0, it means simply the device doesn't support partitioning.

Also note that 'max_part' can be adjusted to power of 2 minus 1 form if
needed. User should check this value after the module loading if he/she
want to use that number correctly (i.e. fdisk, mknod, etc.).


Stop hand.png HINWEIS:

Im Vi bzw. VIM lässt sich die maximale Textbreite mit

set textwidth=72

schnell und einfach auf 72 Zeichen setzen! Ein Eintrag dieser Anweisung in die ~/.vimrc veranlasst Vi bzw. VIM bei jedem Start diese Textbreite zu benutzen. Siehe auch Beispiel einer .vimrc

Tipps für Gute Commits

Ein Commit sollte nie die Buildfähigkeit brechen!

Als eine goldene Regel für das Committen gilt, dass ein Commit niemals die Funktionalität des Projektes beeinträchtigen sollte. Dies bedeutet, dass jeder andere, der am Projekt mit arbeitet im Stande sein sollte, das Projekt auch mit Deinem Commit noch Bauen können muss. Prüfe Deine Arbeit daraufhin bevor Du etwas committen willst!

Du bist nichts besonderes!

Jeder denkt, dass er gute Messages schreibt. In den meisten Fällen ist dies auch so. Aber jeder, auch Du, wird nachlässig nach einer gewissen Zeit! Wenn Du denkst, dass Du außergewöhnliche Commits schreibst dann schau kritisch über die letzten 100 Commits, wie viele von denen würdest Du wirklich "außergewöhnlich" bezeichnen? Nur so aus Spaß, probiere es einmal.

Mache einfache Commits!

Dies kann man fast wörtlich nehmen, auch komplexen Sachen lassen sich in der Regel in Einzelcommits erledigen. Ein Commit soll nach Möglichkeit ein Problem lösen bzw. eine Neuigkeit einbinden etc. Ein Commit sollte eine logische Einheit bilden. Es kann sich später heraus stellen das genau dieser Commit revertet werden muss, dann soll dies auch mit dem reverten dieses einzelnen Commits möglich sein und nicht durch verschiedenste Commits verteilt sein! Dies kommt besonders zum tragen wenn man mit git bisect automatisierte Fehlersuche betreibt. Und dies hilft auch beim Erstellen der Commit Messages.
Beachte dies wenn Du eine Commit Message erstellst! Es gibt auch das Gegenteil, eine zu lange Nachricht. Sollte Deine Commit Nachricht lang sein frage Dich ob Du Deinen Commit nicht weiter aufsplittest.

Sei spezifisch und genau! Hilf es einfach zu finden!

Folgende Message hat sicherlich jeder schon gesehen oder gar selber verfasst, die schlechteste aller möglichen Messages!

fixed some bugs

Wow, wer hätte das gedacht!

fix foo id

Na toll, aber welche! Muss ich jetzt den Code durchforsten...

Im Moment des Commits sind für den Autor der Message die Fakten sicher bekannt und die Jenigen, die das Problem verfolgt haben, dürften ebenfalls bescheid wissen, aber ein simpler Hinweis oder eine einfacher Link auf ein Post in einem Board oder eine Mailinglist, wo das Problem behandelt wurde, wäre ein gewisser Mindestaufwand, den man hier betreiben sollte. Naturgemäß hat niemand wirklich Lust drauf, erst den Code durchzufosrten und auch der Autor schaut unter Umständen nach Jahren dumm aus der Wäsche, wenn er seine eigene Message nicht versteht.

Grundsätzlich gibt es sicherlich niemanden, der absichtlich Bugs einbaut! Natürlich wird Dein Commit dazu da sein, um vorhandene Fehler zu beseitigen!
Wenn Du eine größere Menge an Fehlern gefunden und beseitigt hast, dann schreibe dies auch bitte! Erkläre was Du wo warum gemacht hast. Auch Du wirst später mal nach etwas suchen was du nur noch inhaltlich weist, und genau dann ist eine Suche in den Commit Messages Dein Vorteil. Besser wäre eine Commit Message wie:

Fixed bad allocations in image processing routines

Wie schon erwähnt wird das Finden von Commits auch erheblich vereinfacht wenn man gewisse thematische Markierungen benutzt, indem man den Commit entsprechend einleitet. Dies könnte z.B. der Name eines Moduls (Funktion), eines Branches, Maketarget, Scriptes o.ä. sein. Siehe auch obiges Beispiel aus der Linuxkernelentwicklung.

modulX: Fixed bad allocations in image processing routines

oder um es auf einen bestimmten Vorgang einzugrenzen:

modulX clean up: removed unused variables. 

So wird man nach Jahren wieder erkennen, dass hier jemand am ModulXY aufgeräumt hat und kann die Änderung sofort zuordnen.

Sehr nützlich kann es sein, wenn man z.B. lokal viel in Branches arbeitet und hier naturgemäß kleinere Commits macht, diese mit dem Branchnamen markiert.

Branch_cleanups modulX: removed unused variables in ...

So fällt es leichter die Commits auch noch ohne großes darauf schauen, einem Branch zuzuordnen. Wenn der Branchname auch noch ein Thema darstellt, kann man sogar nach einem Merge in den Master-Branch Rückschlüsse auf die Herkunft ziehen, ohne die Historie genauer zu studieren.

Es wird so schnell klar, sich hierbei Gedanken um etwas Organisation zu machen. Das ist noch nicht mal viel Aufwand. Man ist zumindest sich selbst dankbar und froh darüber, ohne großen Aufwand, irgendwann mal einen Commit zu finden, der genau zu einem Problem oder Vorgang passt. Schaue Dir andere Commits an vergleiche diese mit Deinen.

Erkläre nicht Deinen Code, erkläre warum Du es genau so implementiert hast!

Deinen Code kann jeder sehen und lesen, deshalb ist es unnütz zu erklären was Du programmiert hast. Wenn Du überzeugst bist von Deinem Code, und das bist Du doch sicher, erkläre warum Du die Funktionalität genau so aufgebaut hast.

Teile Auffälligkeiten und Besonderheiten mit!

Du hast etwas schönes Neues für Dein Projekt, aber da es noch so neu ist und Du nicht alle Varianten prüfen konntest oder wolltest dann teile dies mit!

Adding a special GUI Option for the new entry XY

Dies beschreibt zwar Deine Arbeit, dies aber auch nur halb. Besser ist es zu mindestens noch mitzuteilen was funktioniert und wo es noch Probleme geben könnte.

Tested a seperate GUI entry, it works for the common way,
but the function() for coloring may not working for the old models

Unterlasse unnötige Interjektion

Sorry, aber das geht garnicht!

Solche Messages sind völlig unbrauchbar und eher peinlich, oder was will uns diese Nachricht sagen? Und welchen Eindruck hinterlässt so eine Message in einem automatisch generiertem Changelog, wenn das ein interessierter User oder Kollege liest.

Messages, die im Eifer des Gefechts entstehen sind sicher kein Problem, solange aus der Message ersichtlich ist, warum man so formuliert, schließlich kann man sich immer mal vertun und einen fehlerhaften Commit übermitteln und schnell korrigieren, aber ein ergänzender Hinweis wäre hier sicher nicht zu viel verlangt.

Stelle keine anderen Mitglieder bloß!

Du hast Code gefunden der nur so vor Fehlern strotzte? Korrigiere ihn einfach. Du warst auch mal Anfänger!

Fixed up heavy wrong typo, created by Beginner

Diese Mitteilung ist nicht besonders hilfreich. Hilfestellungen und Diskussionen sollten in einer Mailingliste oder Forum stattfinden. Folgendes wäre besser.

Fixed wrong typo in function() that come with Revision XYZ

Script zum Erstellen einer ChangeLog

Wenn man die Punkte von oben beachtet kann man mit diesem kleinen Script relativ schnell eine ChanLog Datei erstellen. Das Script ist recht rudimentär und ist sicherlich ausbaufähig und z.B. nur den ChangeLog zwischen zwei Commits oder Tags zu produzieren.

#!/bin/sh
# changelog.sh
# Convert git log to GNU-style ChangeLog file.
# (C) Chris
if test -d ".git"; then
    git log --date-order --date=short | \
    sed -e '/^commit.*$/d' | \
    awk '/^Author/ {sub(/\\$/,""); getline t; print $0 t; next}; 1' | \
    sed -e 's/^Author: //g' | \
    sed -e 's/>Date:   \([0-9]*-[0-9]*-[0-9]*\)/>\t\1/g' | \
#    sed -e ‘s/\(.*\)>Date: \([0-9]*-[0-9]*-[0-9]*\)/\2 \1>/g’ | \
    sed -e 's/^\(.*\) \(\)\t\(.*\)/\3    \1    \2/g' > ChangeLog
    exit 0
else
    echo "No git repository present."
    exit 1
fi

Das ergibt dann einen solchen Output:

8< ---
Carsten Schoenert <c.schoenert_at_t-online_dot_de>     2011-07-10

   openvpn: fixing wrong position of patch call in the target
   
   ups, a poor copy paste error :-(
   
   And one forgotten warning!
   You should't use your STB as a VPN Gateway from/to the Internet!
   Every process on the box is running the root previleges, so if someone
   has taken your box he will full access to your local lan!

Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de>        2011-07-09

   improve nfsd init script to check exports syntax

Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de>        2011-07-09

   glibc-pkg: add libnsl to package (needed by samba)

Carsten Schoenert <c.schoenert_at_t-online_dot_de>     2011-07-10

   openvpn: new target for *the* open source VPN software
   
   In the between times some people from the dark side there some quicker
   than I and make a usable make target for openvpn. I made some little
   modification for using it in my buildsystem. I added also the opkg build
   to the target.
   
   The opkg package may be usable, i did not tested it realy! The
   start/stop functionality is yet completely not implemented! So if you
   have some ideas for the correct implementation feel free to build it.
   
   So there is to copy the client.conf.example to /etc/openvpn, or even
   testing if there is some config, the loaded kernelmodul and so on.
   
   Remind:
   !!! You need the tun.ko kernelmodul to get proper working openvpn !!!

Stefan Seyfried <seife_at_tuxbox-git_dot_slipkontur_dot_de>        2011-07-03

   add debian-on-coolstream documentation
--->8

Code Changes/Source code Repositories

Aktuelle Änderungen lassen sich in den jeweiligen Mailinglisten verfolgen oder in den Logs der jeweiligen Repositories (siehe Listen).

Buildsysteme

Erstellung von USB- u. Flash-Images, OPKG-Paketierung für diverse Platformen

Nur Coolstream Flash-Image

Neutrino-HD

Libs

Multiplatform


Coolstream

Driver

Coolstream


Tuxbox-SD

Dokumentation

Die Dokumentation, die vor allem dem Benutzer die Funktionsweise der Betriebssoftware vermitteln soll, findet sinnvollerweise im TuxboxWIKI statt.


Jeder Entwickler ist daher angehalten, entsprechende Änderungen, Ergänzungen usw. zeitnah zu den eingetragenen Änderungen zu dokumentieren, oder zumindest einem TuxboxWIKI-Autor oder Sysop mitzuteilen, damit diese den Weg auch zum Benutzer findet und keine Lücken entstehen!.

Die Quellcode-Dokumentation sollte direkt im Sourcecode-erfolgen. Dies ist in der Vergangenheit leider nicht immer in dem Maße erfolgt, wie man es gerne gehabt hätte, so dass es hier leider nicht immer so einfach ist, möglichst schnell einzusteigen. Einen wesentlichen Schritt zur Verbesserung im dBox2-Bereich trug die Einführung von Newmake bei, wodurch zumindest der Aufbau einer Entwicklungsumgebung besser gelingen sollte. Im Coolstream-Bereich wurde zumindest im Bereich der Buildsysteme gute Arbeit geleistet. Im Bereich Neutrino-HD gibt es Nachholbedarf.

GIT Zugang


Stop hand.png Bitte beachten!
Bei den Git-Repositories sind Anfragen zu Schreibzugängen nicht zwingend notwendig, da man dort dank der dezentralen Struktur von Git, üblicherweise formatierte Patche erzeugt oder in bestimmten Fällen Pull-Requests macht, welche man direkt dem Maintainer der jeweiligen Repos oder einem Entwickler per EMail zukommen lassen kann. Bei Gitorious gibt es diese Funktion direkt auf der Web-Oberfläche bzw. kann seine Änderungen direkt per E-Mail dorthin verschicken! Nähere Informationen, wie man solche Patch-E-Mails erstellt findest Du hier. Aus diesem Grund ist es unter anderem üblich, dass sich jeder Entwickler mit gültige EMail-Adresse und realen Namen in seinen Commits zu erkennen gibt. Fake-Adressen oder Aliaseinträge sind eher schlechter Stil [2]'

Coolstream-GIT

GIT-Buildsysteme:

GIT-Novatux

Patch einreichen

Wer einen Patch zur Verfügung stellen möchte, kann dies natürlich gerne tun. Hierfür kannst du die Anhangsfunktion in den Boards, Mailinglisten oder Upload-Server nutzen. Da als Revisionscontrollsystem nun durchgängig auf Git gesetzt wird ist es ebenfalls möglich und erwünscht bei größeren Patchserien einen Pullrequest in einer der Mailinglisten oder auch im den Boards kund zu tun (unter Angabe des Remote Repository natürlich).

Die Benamung der Patches erfolgt beim Git eigenen Kommando automatisch, ebenso ergibt sich dadurch auch eine Reihenfolge in der die Patche später gegebenenfalls wieder applied werden müssen.

Einige IDE's oder auch SCM-UI's bieten die Möglichkeit an, passende Namen erzeugen zu lassen. Man kann sich auch eigene Scripte dafür anfertigen, die dies übernehmen. Dies bitte aber nur im Ausnahmefall.

Aktuell werden vorwiegend für die Multiplattform als auch für das bisherige Tuxbox-cvs auf Basis von GIT Patche erzeugt und angewendet.

Wer einen Patch bereitstellen möchte, kann mit Git speziell importierbare Patchfiles erstellen. Die nötigen Funktionen werden durch Git ohne Zusatzsoftware zur Verfügung gestellt. Zusätzliche Tools wie diff und patch werden nicht benötigt.

Durch diese Git Eigenheit wird das Arbeiten mit Git auch für die Entwickler deutlich vereinfacht. Anders als CVS oder auch SVN unterscheidet Git zwischen Committer und Autor des Patches. Dies hat unter Anderem auch zur Folge, das durch einen mit Git formatierter Patch, sofern er korrekt erzeugt und angewendet wurde, auch der Autor in die Historie des Repostories aufgeführt wird.

Da mit Git formatierte Patche in der Regel auf lokale Commits des Autors basieren, werden auch die darin bereits vorhandenen Commit Messages übernommen. Sofern diese auch den Patch erklären, ist es für den Entwickler, der den Patch erhält auch schneller nachvollziebar, worum es bei diesem oder jenem Patch geht und braucht sich nicht selbst um die Commit Message zu kümmern. Andererseits kann der Autor vor der Überführung in das Remote-Repo und auch Dank der vorhandenen Autordaten im Repo später um Nachbesserung gebeten werden.


Vorbereitung

Sicherstellen das ein gültiger Authorname und eine gültige Emailadresse hinterlegt ist. Wenn nicht, dies global für alle Git Repositories nachholen.

git config --global user.name "Firstname Lastname"
git config --global user.email "your_email@youremail.com"

Oder nur für das lokale Git Repository.

cd /Pfad/zum/Repository 
git config user.name "Firstname Lastname"
git config user.email "your_email@youremail.com"


Stop hand.png HINWEIS:

Es ist übrigens unangemessen ungültige, falsche, keine oder gar sinnlose Angaben zu machen und zeugt gegenüber anderen Entwicklern und Contributoren eher von schlechtem Stil und ist deshalb nicht gern gesehen!

Quellcode verändern

Diese Schritt ist genauso wie bei anderen SCM-Systemen. Man verändert den Quellcode mit den eigenen gewünschten Veränderungen.

git pull
# adding some modifications

Patch erstellen

Patche werden unter Git üblicherweise aus Commits erstellt und lassen sich somit entwicklerfreundlich weitergeben. Patche, die herkömmlich ohne Commits erzeugt werden (git diff), sind lediglich ein Mittel für Schnelltests. Auch wenn man dies evtl. von früheren zentralen Versionskontrollsystemen so gewohnt ist, sollte man beim Arbeiten mit Git davon absehen, unformatierte bzw. rohe Patches an Entwickler zu übergeben. Der Aufwand hierfür geht im Verhältnis gegenüber alten Methoden gegen Null, wenn man bedenkt, dass mehr als nur ein einfacher Patch dabei herauskommt. Diese Arbeitsweise scheint vor allem für Umsteiger ein Problem zu sein, aber dies ist auch eine Frage des Teamworks innerhalb des Projektes und diese unter Git übliche Vorgehensweise wird man sehr schnell schätzen lernen.

Grundlage: Commit erzeugen

Um seine Änderungen weitergeben zu können, müssen die Quellcodeveränderungen zunächst committet werden. Wenn Ihr wirklich nur die Dateien verändert habt, die zum Commit gehören, kann einfach dieses Kommando verwendet werden.

git commit -a

Wenn nicht per

git add <Datei1> <Datei2> ...

die relevanten Dateien selektiv hinzufügen und abschließend

git commit

aufrufen. Hier im Beispiel eine einfache Veränderung der neutrino.cpp.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ vi src/neutrino.cpp
user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git commit -a
[tuxbox-port 5756abf] neutrino.cpp: changing debug output to use macro dprintf
1 files changed, 2 insertions(+), 2 deletions(-)

Nun liegen die Veränderungen im lokalen Git Repo und können mit

git format-patch -s [BRANCH]

als Patch ausgegeben werden. Der Parameter -s bewirkt ein SignOff im Patch, also eine Art Unterschrift das Du/Ihr den Patch auch geprüft habt. Dies hilft Irritationen zu vermeiden wenn es mal Diskussionen über einen Patch gibt und wer nun eigentlich den Patch auf sachlich richtig geprüft hat. Es gibt noch weitere Arten einen Patch zu kommentieren, sehr bekannt und üblich sind die Flags "Acked-by:", "Tested-by:" und "Reviewed-by:". Für diese Flags gibt es aber keinen Switch innerhalb git format-patch. Diese müssen manuell oder per Alias eingefügt werden.

Stop hand.png HINWEIS:

Spätestens jetzt sollte man erkennen, dass man für seine lokalen Änderungen, die man für eine bestimmte Aufgabe abarbeitet immer mit Branches arbeiten sollte und darin seine Commits klein und nachvollziehbar hält. Möchte man später trotzdem mehrere Commits zu einem oder weniger Commits zusammenfassen, kann man das über git rebase -i nachholen.

Im Beispiel wurde die neutrino.cpp vom Branch tuxbox-hd/tuxbox-port verändert. Daher dann auch der git-format-patch Befehl gegen diesen Branch. Würde man gegen origin/master in dem Falle den Befehl anwenden, dann würden auch alle Patches bzw. Änderungen aus weiteren Commits ausgegeben werden, die sich zwischen tuxbox-hd/tuxbox-port und origin/master ergeben.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git format-patch -s tuxbox-hd/tuxbox-port

Ergebnis:

0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Das ist eigentlich schon alles. Diese Datei(en) können nun an einen Entwickler geschickt werden.

Patch von einem Einzel-Commit erstellen

zunächst das Log aufrufen, um den benötigten Commit zu finden. In diesem Beispiel liegt der betreffende Commit ein einem lokalem Branch und sollte unter den letzten paar commits zu finden sein. Pauschal suchen wir nun die letzten Commits ab:

git log -3

Dies gibt nun die letzten Commits aus:

commit ac7abd8db402724f9c195b2091c7a92997edce6e
Author: Thilo Graf <###@n###x.de>
Date:   Mon Apr 16 10:51:07 2012 +0200
 
    target ntp: add target for ntp
 
    neutrino sectionsd missed ntpdate with error log
    "getUTC: read: invalid argument
    ntpdate not found"
 
    ntpdate should also now can be intstalling with system-tools
 
 
    Signed-off-by: Thilo Graf <###@n###x.de>>
 
commit 3caecd682aea585f101286ec7cb550813c7ac1df
Author: Stefan Seyfried <seife@tuxbox-git.#######.de>
Date:   Sun Apr 15 19:52:05 2012 +0200
 
    start_neutrino: prepare for deep standby
 
commit 874ba0c75afe65ebd0a2482000634ac0c75303f2
Author: Stefan Seyfried <seife@tuxbox-git.#######.de>
Date:   Sun Apr 15 18:48:23 2012 +0200
 
    spark: use aotom FP to switch the box into deep standby
 
    For this to be really useful, we need support in neutrino.
lines 1-28/28 (END)

Wenn der gewünschte Commit dieser ist: ac7abd8db402724f9c195b2091c7a92997edce6e erzeugt folgendes Kommando einen entsprechenden Patch

 git format-patch -s -M -C ac7abd8db402724f9c195b2091c7a92997edce6e~1...ac7abd8db402724f9c195b2091c7a92997edce6e

Heraus kommt ein nummerierter Patch:

0001-target-ntp-add-target-for-ntp.patch


Stop hand.png HINWEIS:
  • Die Tilde (~) bei der ersten SHA1 Summe hat die Bedeutung das Git den Bezug auf die Anzahl nach der Tilde angegebenen Comit vor der SHA1 Summe nimmt (auf Commit 3caecd6), im Beispiel eben genau einen Commit davor. Man könnte so z.B. auch Bezug auf den drittletzten oder zehnten Comit vor der angebeben SHA1 Summe nehmen. Damit kann man auch mehrere Commits zu einem in Form eines Patches ohne Rebasing zusammen fassen.
  • Man muss sich nicht die langen SHA1 IDs merken. Git begnügt sich auch mit den ersten sieben Zahlen der SHA1 Summe, wenn es nicht andere Commits gibt die mit den selben Zahlen beginnen.
    • Der obere Befehl kann also auch verkürzt werden:
git format-patch -s -M -C ac7abd8~1...ac7abd8

Ergebnis:

0001-target-ntp-add-target-for-ntp.patch

Patch aus mehreren Commits erstellen

Angenommen man arbeitet lokal an einer Sache, die man üblicherweise in mehreren Commits und in einem separaten Branch abgearbeitet hat und möchte genau diese Commits nun als Patche weitergeben, kann man diese nun als Folge von Einzelpatches erzeugen. Befindet man sich also in einem lokalen Branch und dieser beinhaltet 2 Commits, und möchte genau diese letzten beiden Commits als Patche haben, würde man das etwa so machen:

$ git format-patch [BRANCH]~2

Ergebnis:

0001-dvbsi-try-to-fix-broken-neutrino-build-with-cst-dvbs.patch
0002-libdvbsi-add-patch-for-src-time_date_section.cpp.patch

Den oder die erzeugten Patche kann man nun per eMail an eine Mailingliste oder direkt an einen Entwickler schicken.

einen Patch von einer dritten Person erhalten

Es ist möglich, das Ihr von einer anderen Person einen Patch erhalten habt und diesen weitergeben wollt. Wenn diese Person nun wiederum den Patch nicht selbst weitergeben wollte, aber trotzdem einverstanden ist, das der Patch weitergegeben werden kann, dann könnt Ihr diesen Patch noch mit einem SignOff versehen. Dazu einfach die Option --signoff beim git-format-patch mit angeben. Damit fügt Ihr dem Patch ein Signed-by: <Euer Name> hinzu.

 
user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git format-patch tuxbox-hd/tuxbox-port --signoff

Ergebnis:

0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Danach wie oben schon beschrieben den Patch an einen Developer weiter geben.

einen Patch einspielen

Es gibt einige Möglichkeiten einen Patch direkt anzuwenden. Git stellt hierfür einige Kommandos bereit

git apply

git apply ist quasi das Git-Gegenstück zum allgemein bekannten Unix-Werkzeug patch. Dazu wird dieser Befehl benutzt:

git apply [/Pfad/zur/Patchdatei]

Einzige Bedingung ist, das Ihr im entsprechenden Git Repository seid.

user@pc~/gitprojects/buildsystem-cs/source/neutrino-hd [tuxbox-port]$ git apply 0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Die Anwendung eines solchen Patches ist also recht einfach, ist aber nur für lokales Arbeiten sinnvoll, um Schnelltests durchzuführen, ansonsten sollte man vorzugsweise auf git am zurückgreifen, insbesondere dann, wenn der Patch vom Autor als "commitreif" zugestellt wurde und für einen Commit in das Remote-Repo vorgesehen ist.

Wenn man auf diese Weise einen unformatierten Patch erhält, hat man als Entwickler leider nun den Aufwand nachträglich einige Daten für einen Commit zu ermitteln, um letztlich einen Commit in das Remoterepo durchzuführen zu können. Nach dem der Patch mit git apply angewendet wurde, muss man die Änderungen also nun selbst samt fehlender Angaben erst lokal committen:

$ git commit -a --author="MrX <MrX@mrxathome.de>" --message="This is my opinion what this patch is doing, but MrX should known it better"

git am

Im Unterschied zu git apply werden mit git am angewendete Patche wie Commits behandelt. Hat man also einen mit git format-patch formatierten Patch erhalten und angewendet, hat man diesen Patch bereits committet und relevante Daten wie z.B. Autor-Informationen, Commit Messaage in seine lokale Historie übernommen. Git am ist daher gegenüber der git apply Methode vorzuziehen, da hier der Aufwand für den Entwickler minimiert ist und auch die Leistungen von Contributoren eines Projektes gewürdigt werden. Die Chancen für eine Übernahme in das Projektrepo könnten je nach Umfang der Änderungen und gerade wegen des geringeren Aufwands auch steigen.

Ursprünglich ist git am dazu gedacht, Patche direkt aus EMails zu übernehmen, jedoch werden auch Dateien direkt übernommen. Befinden sich der oder die Patche im Stammverzeichnis des Gitrepos, reicht dieser Befehl:

 
git am 0001-neutrino.cpp-changing-debug-output-to-use-macro-dpri.patch

Bei mehreren Patchdateien kann man auch Platzhalter verwenden:

 
git am *.patch

Mailinglisten


Stop hand.png Bitte beachten, die internen Listen sind privat geführt und auch als solche zu verstehen. Es ist zwar möglich sich dort anzumelden, aber man wird nicht in jedem Fall registriert! Welche Listen auch Commit-EMails verteilen, ist jeweils vermerkt.

Öffentlich

Intern

Boards


Weblinks

Persönliche Werkzeuge
Namensräume

Varianten
Aktionen
Navigation
Downloads
Bedienung
Development
Kommunikation
Sonstiges
Drucken/exportieren
Werkzeuge