 Hallo erst mal zum Thema Macareal erweitern. Mein Name ist DSP von Entropia. Wir sind ein kleiner Haufen und ich dachte mir das fast schon. Von daher ist es naheliegend, dass hier einfach den Talk so macht, wie er euch gefällt, nämlich indem ihr möglichst viele Fragen stellt und wie auch ganz andere Themen zum Thema Git und Macareal besprechen können, als es prinzipiell vorgesehen ist. Von daher möglichst viele Fragen, möglichst viel über keine Ahnung, eure Probleme reden oder Missverständnisse reden oder was ihr machen wollt damit. Kurze Frage, wer hat Macareal eingesetzt bisher zu schauen? Okay, das ist gut, wer hat Git eingesetzt? Der Rest fast. Okay, das ist gut. Was ist Macareal? Macareal ist ein Distributed Version Control System. Das heißt, es ist ein verteiltes Versions-Control-System. Es ist für die ein zwei Leute, die noch nichts mit Git und Macareal zu tun hatten, vielleicht ein bisschen strange am Anfang, aber wir werden gleich sehen, wie das zutickt. Ein Riesenvorteil von Macareal ist es in Python geschrieben. Gegen das zu Git zum Beispiel, was in C und ein bisschen Shell und Perl geschrieben ist, ist Macareal komplett bis auf ein paar ganz kleine Komponenten in Python geschrieben. Die paar kleinen Komponenten sind zur Performanceoptimierung wurden da Python-Module in C implementiert. Genau darauf wollen wir heute hinaus, dass wir einfach ein bisschen wirklich in die Macareal API reingucken und eine Extension schreiben werden und einfach mal so gucken, wie kann ich einfach mein Versions-Control-System so ändern, wie ich Lust darauf habe, weil ich will einfach meine Tools so gestalten, wie ich sie brauche und wenn mir was fehlt, dann baue ich es mir halt im Notfall einfach dazu. Noch mal kurz, Macareal für die Leute, die es noch nicht eingesetzt haben, in fünf Minuten durchgesprochen. Man hat ein Kommando, das fängt an mit HG, das ist das chemische Symbol für Quicksilver und Macareal ist das der englische Begriff für Quicksilver und das ist irgendwie so halb, hat sich jemand gedacht, das ist so ein bisschen halb zusammenhängen. Von daher ist das Kürzel für die Kommandozeile HG Innet. Er legt ein neues Repository an und da sind wir schon bei der ersten Sachen für die Leute, die noch kein Distributed Version-Control-System in der Hand gehabt haben. Wenn ich ein HG Innet hier mache, dann habe ich plötzlich hier einen Ordner namens HG und das ist mein lokales Repository, denn alles ist erstmal lokal auf der Festplatte und das Einzige, was mir, also ich habe kein Server mehr, die die Revisionen speichert und ich speichere die Revisionen komplett auf der Platte. Das Einzige, was mir ein verteiltes Versions-Control-System abnimmt, ist, dass es mir ein Synchronisationsmechanismus an die Hand gibt. Wie gesagt, wir haben das Punkt HG verzeichnet, das sollte man besser nicht löschen, weil da sind alle Daten drin gespeichert und ansonsten hat man einfach sein Working Directory ganz normal, wie man es aus der Version, CVS und alle anderen cruden Systeme noch so kennt. Man kann Dateien hinzufügen mit HG-Add und HG-RM. Ich muss ein bisschen auf die Leute eingeben, weil ich so ein bisschen das Gefühl habe, dass die Leute mehr GIT können als Macquarie. Man muss eine Datei nur einmal mit HG-Add hinzufügen, weil es sowas wie ein Index nicht gibt. Also wenn wir eine Datei hinzugefügt haben, ich kann das mal kurz zeigen. HG-Add und da will ich natürlich wissen, hat sich was oder was hinzugefügt oder welche Dateien sind noch nicht hinzugefügt worden. Dann kann ich HG-Status machen und ich sehe das. Ganz klar eindeutig, was schon hinzugefügt worden ist und was beim nächsten commit mitcommitted werden würde. Kurz dazu noch ein bisschen, weil man will ja nicht immer HG-Status tippen. Macquarie hat ein Matching auf den Kommando-Zahlen, das auf den Kommando, das heißt wenn ich anfange HGST einzugeben und das ist eindeutig, als Anfang von dem Kommando, dann nimmt er das. Also HGST macht das gleiche, während HGST nicht funktionieren würde, weil es mehrdeutig ist, weil Surf, Show config, Status und Strip auch funktionieren. Bei Status ist noch ein bisschen Sonderrolle, weil ST ist eine Abkürzung, weil Strip würde ja auch anfangen mit ST. Aber HG-Sum zum Beispiel macht mir ein Summary und so weiter. Es muss einfach nur so lange matchen, dass es eindeutig ist, so viel matchen. Und damit kann ich mir raus suchen, was sich so geändert hat in meinem Repository, wenn ich was geändert habe irgendwie, wenn ich irgendwie Dateien editiert habe. Dann commit ich das ganze. HG-Commit kriegt wie immer eine Eingabe auf, dass ich bitte mein commit-Message reinschreiben soll. Ich weiß nicht, ich kann jetzt normalerweise pochig ewig darauf rum, dass die Leute ordentliche commit-Message schreiben, mache ich jetzt hier mal nicht, aber schreibt ordentliche commit-Messages, weil alles andere bringt eure mit Projekttypen irgendwie echt in den treibtes Hinten Wahnsinn. Genau, und dann will ich natürlich, also das wäre so alles, was man so prinzipiell grundlegend für sein kleines Mini-Projekt braucht. Ich kann Dateien hinzufügen, ich kann schauen, was ich geändert hat und habe also ein Repository. Ich kann in früher Revisionen zurück, das zeige ich gleich. Und dann will ich tendenziell meine Daten irgendwo hinschieben, weil ich will sie nicht lokal auf der Platte haben, weil das ist normalerweise nicht so gut, wenn man irgendwie einen Plattencrash hat oder irgendwie zu fremati über seinen Rechner gekippt hat oder so. Und man kann einfach mit dem Push-Kommando sein Repository irgendwo hinschieben. Mikril unterstützt vor allem, also hauptsächlich zwei Protokolle, das ist einmal SSH logischerweise, ich brauche einfach nur eine SSH-Axis auf irgendeinem Rechner und kann einfach da meine Daten hinschieben, mein Repository. Und das zweite ist HTTP, wobei man das kleine Randnotiz-HTTP-Support ist in Mikril deutlich besser als in Git, weil es ein intelligenteres Austauschformat war, also was man anfragt und was nicht und so weiter. Falls sich jemand schon mal gewundert hat, warum Google Code Mikril unterstützt und nicht Git, es ist genau HTTP-Support gewesen, also das ist der einzige Grund, weil Git einfach so schlechten HTTP-Support hatte über Jahre. Ein kleines Sonderfeature, was es immer in der Stelle noch gibt, wenn man mal lokal sein Repository hat und es irgendwo anders hinschieben will. Initial kann man sein lokales Repository auf einen anderen Rechner klonen, man kann natürlich aber auch genauso von irgendeinem anderen Rechner ein Repository lokal klonen. Das heißt, dass ich mir den kompletten Inhalt eines Repositories auf meine Platte schiebe bzw. von meiner Platte auf irgendwo anders hinschiebe oder auch auf meiner Platte hin und her schiebe. Es ist einfach nur ein kompletter initialer Kloneben, wie er schon gesagt wird. Gut, gibt es da zu fragen, weil das war jetzt echt super schnell, weil ich denke, alle kennen das. Okay, gut, kennen alle. Ich muss nichts mehr darüber sagen. HGlock ist logischerweise das ganz normale, ich kann mal reingucken, was so Leute gemacht haben und HG Update ist das, was ein Checkout in Git ist, dass ich einfach in zu einer früheren Revision springe mit minus R und dann der Revision-Nummer. Da kommen wir gleich zu einer Revision-Nummer, nämlich genau das hier. Und da wollen wir mit den Anfang so ein bisschen nochmal die Unterschiede zu Git herauszuschreiben und ein bisschen näher zu betrachten und das erste, was am Auffill sind Revision-Nummern, weil in Git haben wir nur Schar-1, das heißt 40 Zeichen, Hexadezimal, kodierte Zahlen, die relativ dumm zu merken sind. Ich muss hier nicht komplett merken, zum Glück, aber es reicht mit meistens schon, dass es die ersten sieben Zeichen relativ verwirrend sind für mich. Mikkel hat da ein bisschen andere Ansätze und zwar für das Lokal erst mal eine Revision-Nummer mit und zwar eine ganz normale, wie man sie aus der Version kennt, die ist nur lokal gültig. Also wenn ich irgendjemanden eine Revision, meine Repository gebe und der schiebt sich irgendeine andere Branch rein in der Pulti, eine andere Branch oder committed was, dann hat er eine andere Revision-Nummer 6, als ich eine Revision-Nummer 6 habe. Aber, weil ich lokal normalerweise nicht Lust habe, also relativ viel hin und her springe und relativ knapp meine Revision ansprechen will, habe ich einfach eine linear fortlaufende lokale Zahl für mein Repository. Also einfach 5, 12, sonst was, geht einfach auf von 0. Ich habe aber immer noch die Note ID, ist genau das gleiche wie in Git, dass ich einen kompletten Schar-1 habe, 40 Zeichen, ich kann ihn so kurz halten, wie er eindeutig ist im Repository und damit kann ich auch immer jeden Commit ansprechen. Das brauche ich natürlich, wenn ich mal jemanden mit jemanden Repository ausgetauscht habe und mit ihm über eine Revision sprechen will, dann kann ich ihm nicht sagen, Revision 5, weil er könnte eine andere Revision 5 in seinem Repository haben, weil er vielleicht einfach in einer anderen Reihenfolge gepult hat oder committed hat, als ich oder wir noch nicht ge-merged haben und da sprechen wir also immer von den Note IDs, weil die sind hoffentlich weltweit eindeutig, es gibt dann schon, wir können uns auch über Schar-1 streiten, aber keine Lust in der Stelle. Und dann gibt es sogenannte Pseudo IDs, die es noch gibt, und zwar ist es der Punkt einerseits, der die aktuellen Status in Verzeichnis markiert. Das heißt, der noch nicht committed Status ist selber wieder, kann man ansprechen, als Revision. Und Minuszahlen sind vom höchsten, von der höchsten Revision, die im Moment existiert, nach hinten. Also Minus 5 sind genau vier Revision von der obersten, von der neuesten Revision in meinem Repository. Das brauche ich halt relativ auf, wenn ich sage, okay, ich will zwei Revisionen zurückspringen, mache ich eigentlich HG Update, Minus R, Minus 3 und bin zwei Revisionen hinten. Genau, das sind die Pseudo IDs, es gibt noch die Pseudo ID-Tip für den, für die allerneueste Revisionen, die es im Repository gibt. Und dann gibt es sogenannte Refsets. Refsets ist eine relativ neue Sache, die viele Leute noch nicht so kennen, wenn sie McRae nicht wirklich intensiv machen. Das ist eine Query Language für Revisionen, die in McRae mittlerweile eingebaut ist. Ich kann Ranges Query, ich kann zum Beispiel sagen, ich will hier von der Revision 1 zu Revision 5 in alle Revisionen angezeigt kriegen, zum Beispiel bei Gitlock, HGlock. Oder ich will von 10 zu 5 ohne aber die 7, also die Revision 7 wird ausgelassen. Ich kann sagen, ich will die jüngst, die älteste Revision haben, bei der die Datei FU.C. hinzugefügt worden ist und so weiter. Das ist eine relativ komplizierte Query Language, sollte man mal gesehen haben, wenn man die verstanden hat, kann man ungefähr 90 Prozent aller Git-Kommandos, die irgendwie mit Lock zu tun hat, einfach in Refsets nachbauen. Ansonsten HG Help für die restlichen Kommandos, wenn man sich halt einfach mal das System so ein bisschen einfinden will. Aber dafür sind wir eigentlich nicht da. Ein Punkt noch mal, weil wir jetzt so ein bisschen in die Richtung gehen, okay, wir gehen davon aus, dass ihr so ein bisschen Ahnung habt, was so McRae tickt. Also schauen wir uns ein bisschen an, wie die Konzepte dahinter funktionieren, damit wir dann in den Extensions auch wissen, was wir machen und dass wir nicht kaputt machen. Und der erste Teil ist natürlich, dass wir gucken müssen, wie ordnet oder wie speichert McRae konzeptionell Geschichte, also History. Und das funktioniert genauso wie in Git. Ich habe einen Grafen und zwar in artzyklischen gerichteten Grafen. Das heißt in der Revision Null, was wir hier ganz links sehen, das ist die allererste Revision. Wenn ich danach committe, dann kennt die Nachfolger Revision. Also der zweite weiße Bobble zum Beispiel. Der weiß kennt genau sein Vorgänger und dessen Nachfolger kennt wieder sein Vorgänger und so weiter. Das heißt, ich kann so meine, meine Commit History aufbauen beziehungsweise, wenn ich eine Branch anlege, kriege ich halt so eine Abspaltung, wenn ich Merch kriege, kriege ich halt wieder was zusammengeschoben. Das ist eigentlich ein relativ normales Konzept in allen dezentralen Versionskontrollsystemen, dass man Geschichte, also History in Grafen repräsentiert. Ist das so altklar oder spreche ich über irgendwas, das ihr echt nicht wisst, weil sonst mache ich die Grafensache echt ganz langsam und ganz klar. Was welche, du meinst, welche Richtung gespeichert wird? Immer der Vorgänger wird nur gespeichert. Also und, und der, nee, es wird immer ein Delta gespeichert. Es wird ein Delta zwischen den beiden gespeichert. Also wenn ich eine, ich habe eine ursprüngliche Version, speichere mir dann mit, was sich geändert hat zwischen der ersten Version und der zweiten Version. Aber die zweite Version kennt nur, weiß nur, dass das Delta zwischen ihr und der ersten war. Nee, weil du, ja, theoretisch schon, aber mir kann es intelligent genug zu wissen, dass ich nach so und so viel Revision, nämlich genau dann, wenn die Delta Chain so groß wird, wie die File selber, dann speichert mit Curve das komplette File. Und dann muss ich nur soweit zurückgehen. Also ich muss nie die ganze Delta Chain zurückgehen. Aber klar, umso mehr Dateien du hast, umso mehr Delta, dass du mehr brauchst, um es aufzubauen, was aber einfach, weil es lokal liegt, extrem schnell geht. Also es ist ja genau das, was du beim, keine Ahnung, im Linux Kernel irgendwie einen Checkout machst auf eine frühe Revision, macht ja genau das gleiche, geht Delta Chains entlang ohne Ende. Aber die sind normalerweise nicht länger als, ich weiß nicht, wie es ein Macquarie genau ist, aber so liegt, im Regelfall ist es nicht länger als 20 Deltas oder 30 Deltas und also das geht locker mit modernen SSDs vor allem erst recht. Also ich habe noch nie irgendwie auf meinen Checkout gewartet. Genau, also noch mal für die Leute, die Git kennen, so eine Übersicht im Endeffekt die gleichen Kommandos. Aber es gibt eben ein paar ganz kleine Unterschiede und auf die müssen wir eingehen, wenn wir wirklich nachher tief reingehen wollen in die Core und uns die Dinge genauer anschauen wollen, damit wir genau wissen, warum das jetzt nicht so tickt, wie das vielleicht aus Git gewohnt, das wurde umgekehrt, warum Git manche Stellen anders tickt als Macquarie. Und das ist der allererste, wichtigste Ding, das missverstehen die allermeisten, wer sich Branching in Git angeschaut hat, der weiß, dass Branch ist nichts und das sind als Namen für Zweige in dem ganzen Grafen. Und diese Namen sind völlig egal, die können weggelöscht werden und können wieder hinzugefügt werden und sie werden nicht versioniert. Also Branchnamen werden in Git nicht versioniert. Und das ist fundamental anders in Macquarie. In Macquarie weiß jedes Change Set, wenn ich committe, dann wird in dem Change Set gespeichert, auf welcher Branche es war. Das heißt, ich kann eine Branche, wenn sie einmal angelegt und einmal committet worden ist, nicht mehr löschen. Das wird einfach im Change Set gespeichert, es hat ein paar Vor- und ein paar Nachteile. Der Nachteil ist ganz offensichtlich, ich kann nicht 20 Testbranches haben, was halt irgendwie in Git geht, weil jeder lokal seine kleine Testbranche hat und es interessiert keinen, ob das 20-mal Test heißt, weil es eben nicht mitgespeichert wird. In Macquarie kriegt man da Namenskonflikte, wenn man pech hat. Hat aber den riesigen Vorteil, dass die Bran, dass man, wenn man zurückgeht und halt der Branchnamen mehr erhalten bleibt. Also man kann einfach mal in Git aufersehenden Branchnamen verlieren und Branchnamen an sich haben, manchmal auch Informationen. Zum Beispiel Release 2 ist eine Information darüber, was die Branche eigentlich gemacht hat. Und das kann ich in Git verlieren und das ist halt dann auch blöd. Aber das ist wirklich ein fundamentaler Unterschied, wo so viele Leute wirklich auf die Schnauze fliegen und es ist deswegen in Macquarie mittlerweile drei andere Konzepte gibt, Branches zu implementieren. Und es gibt Gesamtdreie, also zwei andere noch, genau. Dann hat man die Neuzation der sogenannten Hats. Das sind die Endrevisionen in dem Grafen, die kein Nachfolge mehr haben. In dem Fall die war heller auf der Seite eingezeichnet. Das sind sogenannte Hats in Macquarie. Die müssen auch nicht unbedingt einen Namen haben. Die müssen sich eine eigene Branche haben. Sie können anonyme Hats sein, nur mit Revisionsnummern angebbar sind. Aber das ist einfach so dieser Begriff der Hats. In Git müssen die allen einen Branchnamen haben. Oder im Regelfall. Ja, es gibt ein bisschen Ausnahmen. Und es gibt kein Index. Also ich weiß nicht, wenn in Git gibt es den Index, in dem getrackt wird, was sich geändert hat zwischen Working Directory und dem Index und zwischen dem Index und dem Repository. Und der Index wird als einerseits als Speed Enhancement, einfach als Optimierung implementiert. Aber andererseits wird es vor allem auch dafür implementiert, dass man zum Beispiel nur Teile von der Datei markiert, dass sie beim nächsten Komet reingeworfen wird. Also das ist dieses typische Git-Add minus E oder Git-Add minus P Kommando. Diesen Index gibt es nicht in Macareal. Es gibt nichts in der Mitte, was irgendwie noch zusätzlich cached oder tracked. Was dazu führt, dass ich nicht dauernd Git-Commit-A machen muss oder HG-Commit-A, um den Index abzudaten. Ich muss nicht vorher meine Datei mit Git-Stage irgendwie staging, damit der Index das mitkriegt. Das funktioniert, muss man alles gar nicht machen. Es funktioniert genauso wie in allen anderen Versionskontrollsystem in Macareal. Das steht gibt es ein bisschen alleine da. Sondern in Macareal mache ich einfach Änderungen von der Datei, die schon getrackt ist, macht Kommit und das funktioniert. Wie gesagt, hat Vor-Hartnachteile, kann man sich lange überstreiten. Die Erfahrung zeigt, dass so viele Leute auf den Index, über den Index drüber steuern, dass ich es für die Bereicherung halte, dass es nicht drin ist. Und dann kommt eben dieser große Punkt mit den Extensions, dass Macareal nativ Extensions unterstützt. Das heißt, ich kann in Macareal über Python neue Kommandos hinzufügen. Ich kann Kommandos, die bereits existieren, rappen und editieren und Optionen hinzufügen und ihr Verhalten ändern. Und das ist ein fundamentales Konzept, weil während man in Git sagt, wir wollen alle Features in die Core reinpacken, weil es ist C. Wir werfen da alles rein und haben so ungefähr 1000 Optionen, die wir machen können, sagt man in Macareal. Wir wollen eine ganz, ganz, ganz einfache Basis haben, die völlig trivial ist, die nichts kann, die kann kein Rebase, keine Ahnung, die kann noch nicht mal den Grafen auf der Kommando-Zeile anzeigen. Das kann einfach im Endeffekt nur normal Versionskontrollsystem, Committon, Update, Push and Pull und wer nicht. Aber wir liefern erstens einen Haufen Extensions mit, die Leute, die wir maintainen und die Leute einfach anschalten können trivialerweise. Oder es gibt einfach große, so viele Extensions da draußen, die die Leute verwenden können, die sie einfach runterladen können und einfach irgendwo reinwerfen und dann funktioniert das Out of the Box. Und damit kriegt man, kann man seinen Macareal voll aufblasen zu einem genauso komplexen Ding wie Git. Genau. Und wir wollen eben jetzt mal gucken, wie können wir so ein Extensions schreiben? Und da schauen wir uns erst mal so ein bisschen das Repository Format von Macareal an, wie das so gesamt tickt, damit wir mal so ein bisschen Einblick haben, warum die Daten so gespeichert sind, wie sie gespeichert sind und warum die so relativ kompakt gespeichert sind. Und zwar besteht das eigentlich aus, besteht ein Macareal Repository aus 3 großen Indexen bzw. also 2 großen Indexen und noch so eine Indexstruktur, die File Index. Und alle 3 basieren auf demselben Format. Das besprechen wir gleich das Format. Und das erste ist das Reflock Format. Also alle 3, wir haben 3 Indexe und alle 3 Index haben drunterliegend die komplette gleiche Datenstruktur, den selben Aufbau. Der eine hat ein bisschen mehr, der andere ein bisschen weniger, aber die Grundstruktur ist klar. Sie haben einfach nur erstens einen Pointer in das Daten Format, damit, wenn ich den Index angeschaut habe, weiß wo ich hinspringen muss in Datenformat. Das hat Flags, es hat ein bisschen Längen Angaben, es hat eine Revision. Gegen, es hat einen Link auf die Revision, die Basis Revision, die dafür da ist, zu sagen, wann das, die Datei das letzte Mal komplett gespeichert wurde und nicht nur Deltas. Link Revision kommen wir noch dazu. Es gibt noch die beiden Vorgänger und die NoteID, die NoteID ist eben genau diese 200th Bit Hash. Und das ist eigentlich so, dass das ganze Format, das heißt, jeder einzelne Eintrag in diesem Format speichert im Endeffekt nicht viel mehr mit als seine beiden Vorgänger und ein bisschen minimal Daten dazu und vor allem das Offset in den Index. Das heißt, es ist sehr kompakt. Man kann sich das auch irgendwie mal mit so Indexen, Debuggen anschauen, wenn man Lust drauf hat. Und darauf aufbauen, auf diesem Reflex-Format ist das erste Format der FiLock. Der FiLock speichert alle Daten, die einen Datei editieren, also die alle Versionen einer Datei werden in dem FiLock gespeichert. Das heißt, in dem FiLock steht drin, okay. Das hier war Revision 1 von dem FiL und das hat übrigens die größte 20 Kilobyte, komprimiert hat das irgendwie 18 Kilobyte. Das hat übrigens den Vorgänger im FiL, also wenn ich das FiL rekonstruieren will, dann muss ich vielleicht, oder die vorherige Revision der Datei anschauen will, dann muss ich da zurückspringen, zu der ID und genau, das war's eigentlich schon, also mir würde auch gar nicht mehr drin gespeichert. Und der Punkt ist, das gibt's für jede Datei im Repository hinzufügen, gibt's einen File Format, so ein FiLock. Meines Erachtens zu einer der größten konzeptionellen Schwächen von McCurry, weil du keine Komprimierung in Überfalls hinwecken kannst, aber auf jeden Fall ist es relativ trivial. Und dann gibt's eben das Manifest und das Manifest sagt nichts anders als, wir haben jetzt die ganzen Feierrevisionen, wir haben Revision 1 bis 10, keine Ahnung, und eine Bar.C in Revision 1 bis 20 und jetzt wissen wir aber nicht, wenn ich in meinem Verzeichnis oder in meinem Repository die Version 5 wirklich auschecken will, die für mich sichtbare Change Version 5. Welche Revisionen im FiLock stehen dahinter, weil die Datei kann sich ja 30-mal geändert haben oder 20-mal und die Revisionsnummern werden einfach beim FiLock incremental hoch gezählt und sind nicht parallel zu der aktuellen ChangeLock-ID. Das heißt, wenn ich die ID 5 habe in meinem Commit, die Commit ID 5, ist das nicht die File ID 5 von der Datei unbedingt. Das kann auch die File ID 3 sein von der Datei. Und das Manifest sagt nichts anderes als okay, in der Revision Change Version 5 ist es übrigens die Datei in Revision 3 da. Das sieht dann einfach so aus. Da steht nichts anderes als Dateiname und dann steht da die Note ID, die ich suchen muss im FiLock, damit ich das wieder aufbauen kann. Eigentlich gar nicht so schwer. Und der ChangeLock macht nichts anderes als den Rest der Daten zu speichern, nämlich zu speichern, okay. Das ist die Repository Revision Nummer 5. Da gab es die Commit Message so und so, das ist der Autor so und so, an dem Datum so und so. Und wenn ich das komplette Repository an der Stelle wieder herstellen will, dann muss ich das Manifest an der Stelle anschauen und das Manifest benutzen, um dann aus den File Locks wieder die Daten zu suchen. Also genau das, der ChangeLock verweist auf das Manifest und das Manifest verweist auf die Feile, weil das Manifest im Endeffekt nur ist, wie das Verzeichnis aufgebaut ist. Und das ist so die grundlegende Struktur eigentlich total trivial, kann man super schnell in Pasa implementieren, gibt es auch so viele, aber es wird also immer noch in Python gelesen. Genau, und wenn ich, hat jemand gerade eine Urla, ich mag noch mal so wissen, wie viel Urla es ist. Okay, vielenfalls nicht gut. Und wenn ich mir so das grobe Repository Format weiß und weiß, wie ihre Revision Nummern so ticken, dann kann ich mich so ein bisschen dran wagen und endlich mal Extension schreiben. Und da wird mir auch ein bisschen was abgenommen, weil ich muss nicht sagen, das ist ja ein bisschen ungewöhnlich. Das ist ja ein bisschen ein bisschen ungewöhnlich. Erstmal zu Extensions, Extensions sind super trivial, im Endeffekt sind das eine Python-Datei oder ein Python-Modul, je nachdem wie ich es mal aussuche. Und die kann ich einfach nur aktivieren, indem ich in der HGRC, das ist die globale Macquariel-Konfiguration, reinschreibe die Namen der Extension, in dieser HG-Subversion geliefert worden und schreibt die automatisch rein. Ich brauche kein Fahrrad angeben, es gibt so ein paar Extensions, die mit Macquariel geliefert worden sind. Und wenn ich z.B. die HG-Subversion, was so das typische Git-SVN für Macquariel ist, wenn ich das benutzen will, dann gibt es das nicht, dann muss ich das erstmal runterladen. Dann schreibe ich einfach rein, Subversion ist gleich und gibt den Pfad zu der Datei an. Und dann wird es aufgerufen, um bestimmte Methoden werden darin aufgerufen, und das ist die Gesamt- im Extension-Mechanik schon. Ich kann wirklich super trivial Extensions da reinwerfen. Es hat natürlich den Nachteil, dass wenn ich Extensions habe, die was über Netzwerk machen, dann muss ich sie auf beiden Rechnern angeschaltet haben. Wenn der Extension nicht geladen wird auf der einen Seite, weil sie nicht angeschaltet ist und ich will mitgeliefert der Extensions, gibt es ein paar, eigentlich relativ wurscht, aber da sind einfach noch mal so typische Dinge, die du in Git Out-of-the-Box kriegst, die halt nicht direkt funktionieren, denn Macquariel muss das Color, wenn du kolorisierten Output haben willst, musst du halt die Color Extension anschreiben anmachen. Hat dafür Vorteile, dass ein bisschen kompliziertere Sachen wie Zero-Con das einfach auch funktionieren. Wir wollen eine Extension schreiben und das ist eigentlich echt super genial einfach, weil wenn ich nämlich diese Python-Datei meiner Global Macquariel-Config angegeben habe, dann kann ich einfach auf die Macquariel-Namespace zugreifen, da sorgt mir Macquariel dafür, dass das richtig gemacht wird. Und dann kann ich einfach anfangen, aus Macquariel in die API zu importieren, das ist primär meistens die Extension-API, die macht nichts anderes als ein paar Funktionen um einfach existieren Macquariel-Kommandos leichter zu rappen einfach nur schreiben, das ist ein paar Helferfunktionen. Utahl ist noch so ein bisschen, da sind so ein paar Helfer noch mal drin ich kann das local repo inkludieren oder importieren wo ich dann auf das Repository zugreifen kann und so weiter und vor allem will ich aber auch noch aus einem E18n will ich den underscore importieren um Translation zu haben, falls es nötig. Und dann gibt es diese drei großen Dinge, nämlich erstens X-Setup, Repository Setup steht da, SetUr, gibt es nicht, sondern das heißt Setup und CMD-Table. Und das ist eigentlich relativ straight forward, und zwar, wenn Macquariel gestartet wird und die Extension geladen wird, dann wird, wenn ich, wird aus dieser Datei, die ich angegeben habe in der Konfig, wird immer die Funktionen X-Setup aufgerufen. Und die Repository, das ist eine Klasse, in die einfach Output macht, einfach User-Interface. Da sind Funktionen wie Write, wie Status, wie Lieback drin. Und die raten mir das einfach nur, dass es schöner auf die Konsole ausgegeben wird und sowas wie irgendwie Verbows und so richtig gehandelt wird. Genau. Und Repositup wird aufgerufen, sobald ein Repository vorhanden ist, weil ich könnte ja theoretisch Macquariel auch außerhalb eines Repositories aufrufen, dann wird Repositup nie aufgerufen. Und wenn ich das innerhalb eines Repositories aufrufe und ein Repository vorhanden ist, ein Repository Objekt, dann kriege ich das direkt mit als Repo. Und damit habe ich eigentlich so mein Repository in der Hand und kann schön irgendwie grafen und lange laufen und so was. Und natürlich will ich meistens ein eigenes Modul, ein eigenes Kommando zur Verfügung stellen. Und dafür gibt es den CMD-Table. Und da gebe ich das einfach in der Hand. Das erste ist der Name einfach von dem Kommando. Dann kommt ein Tube, wo der erste Teil die Funktion ist, die aufgerufen werden soll. Und dann gibt es eine Parameterliste, die in der Held aufgezeigt wird und auch beim Pasen beachtet wird. Und dann gibt es noch ein Hilfetext. Und dann funktioniert eigentlich alles out of the box, sobald ich das gemacht habe, kann ich HG-HELP eingeben und mein Kommando taucht und das funktioniert einfach. Genau. Wie gesagt, X-Setup wird vor einem UI-Setup aufgerufen, was nicht wirklich verwendet wird mehr, weil das nämlich durch Repo-Setup ersetzt wurde. Das heißt ja um X-Setup und Repo-Setup und wenn wir das benutzen, können wir eigentlich alles machen. Jetzt schaue ich mal, ob ich meine kleine Demo habe, wenn ich noch die SSH-Verbindung zum Linusrechner habe, weil ich den Mac nur für Vorträge benutze, aber ich habe es hier noch nicht drauf. Also ich kann jetzt z.B. einen GPN-11 Pompier anlegen von Mac Core, Import, Extensions Mac Core, Def, GPN-11, keine Ahnung, jedes Kommando kriegt automatisch immer nur iObjekt und ein Repo mit und dann mache ich einfach World, CMD-Table, GPN-11 GPN-11 tragt das immer eine HGIC ein. Okay, jetzt schaue ich, ob es richtig geladen wurde, wurde es schon, aber sonst hätte ich mir jetzt hier einen Fehler geworfen. Ich schaue mal und hier sieht schon Enabled Extension, meine Extension ist drin und wenn ich jetzt HG GPN-11 aufrufe, dann brauche ich einen Repository, in dem ich besser drin bin, sonst schreit er. Von dem Moment an habe ich einen Repository in der Hand, ich habe eine Ausgabe in der Hand, genau, ich habe die ganzen Changes in der Hand, ich kann eigentlich machen, was ich will, ich kann kommenten, ich kann adden und so weiter und das ist eigentlich wirklich trivial aufzusetzen. Bei der UI gibt es halt so ein paar Methoden, so Standard Ride für ganze Mal Ausgabe, wenn ich das vorhin machen will, Notice, Status, Debug, selbst erklären und wenn ich komplett abbrechen will, weil den Kommando viel gestalten ist, werfe ich ein Yootle-Punkt-Abort-Exception und es war es. Dann habe ich die API zur Verfügung und die API ist ein bisschen größer als das, was da steht, aber das ist so das Wichtigste. Das eine Wichtigste ist das UI natürlich, dann kommt der Ref-Log und davon abgeleitet Chainslock, Manifest und File-Log, was einfach, wo ich wirklich auf den und so weiter, aber damit habe ich meistens an Objekten direkt gar nichts zu tun, weil alles über Repositories geht und dann habe ich eben die Repository-Klasse und die Repository-Klasse wird aufgeschlüsselt in das Local Repo, was einfach ein lokales Repository, auf dem ich mich gerade befinde, repräsentiert und das ist so das mächtigste, was ich haben kann, da kann ich einfach Commits machen, ich kann Branches anschauen, ich kann zu einer früheren Revision springen, sonst was machen. Es gibt auch ein SSH-Repo, also ich könnte auch einfach, wenn ich zum Beispiel eine Funktion überschreibe und der zu einem SSH-Repository pushe, dann kriege ich als Repo-Objekt plötzlich eine SSH-Repository in die Hand und wenn ich da einfach eine Funktion aufrufe, dann handelt der mir das automatisch, dass es über ein Protokoll zum SSH-Saber geht und dort von Mikro wie aufgefangen wird und in die richtige Funktion umgesetzt wird und zurückgeschleift wird und das gleiche mit HTTP-Repo, einfach ich fasse es halt einfach, ich rufe die Funktion auf und dahinter passiert Magic und es klappt und dann gibt es halt den Distate noch, das ist so der aktuelle Status meines Verzeichnisses, wenn ich zum Beispiel eine Änderung hinzugefügt habe oder noch nicht committed habe, dann hat sich der Distate geändert, aber das Repository noch nicht, weil es wurde ja noch nicht committed und der erste Commit schiebt es ins Repository rein, das heißt die Änderung würde ich nur in dem Distate sehen, aber jedes Repository weiß, kennt sein Distate und da kann ich einfach darauf zugreifen, also sobald ich das Repo-Objekt in der Hand hab, und kann lustige Dinge damit machen und nachschauen, was sich so geändert hat. Und wie gesagt, das Hauptding, mit dem man eigentlich die ganze Zeit zu tun hat, ist das LocalRepo und da kann ich erstmal so prinzipiell die einfachsten Dinge machen, wie ich will, gerne mal so ein Change Set in die Hand kriegen, Repo und dann ekelklammer auf ID, einfach irgendwie Revisionsnummer 5 und dann kriege ich die Revisionsnummer 5 und kann da plötzlich irgendwie gar einen Description aufrufen und kriege die Commit Message, die Methode und kriegt den Namen, genau, und das ist so alles, was ich so brauche im Regelfall. Genau, ich kann über Revisionsnummer 5 iterieren, das ich weiß jetzt echt nicht mehr, wo ich es hin hab, ich bin ein Volltraurig. Aber ich glaube, es war eigentlich irgendwie, was passiert mit irgendwie 3 Stunden Schlaf am Tag, ist das echt nicht so gut, wenn man Vorträge halten will. Also findet scheinbar nicht, ah doch, eine Current Honest, so hieß es, genau. Also ich kann ja zum Beispiel einfach, ich hab hier so noch wieder Helferklassen, die ich haben kann, so ein Deckwalker, der mir einfach sagt, okay, gib mir mal eine Revision Range, gib mir mal Revision in die Hand und ich helfe dir ja beide drüber zu iterieren und dem sage ich, okay, fangen wir beim Revision, einfach die Länge des Repositories wird automatisch auf die höchste Revisionsnummer gemappt, logischerweise, weil das Revision des Repositories ist so lang halt einfach. Und dann geh mir bis zur Revision 0 runter und mit dem Step-1 logischerweise und jetzt mach dir das als Generator, als Python Generator und gib mir eine Idee in die Hand, gib mir einen Change in Context und ich kann hier einfach ccx Description aufführen und das ist eigentlich so das komplette HG-Log in ganz primitiv nachgebaut. Also wenn ich das aufrufe, die zwei zahlen mit dem Kommando, dann gib dir mir einfach alle Commit-Messages aus, die er so in dem Repository findet. Also die APIs an der Stelle echt einfach. Das lokal Report hat echt 1000 Methoden, die muss man sich halt echt mal ein bisschen anschauen. Aber dann noch mal eine Sache, das Racken von Funktionen, der interessantere Teil kommt mit was können wir mit dem ganzen Kram alles anstellen. Kommen wir noch mal zu dem Ding, wenn ich jetzt mal was existieren, das überschreiben will. Zum Beispiel, ich weiß nicht, es gibt dieses Minus-S, Gid-Commit-Minus-S, wo immer so eine Sign-Offline hinten dran geschrieben wird. Das gibt's in Macquarie nicht. Aber es ist halt trivial zu Ihnen ändern eigentlich, weil eigentlich will ich nichts anders machen, als jedes Mal, wenn jemand committet mit diesem Flag, einfach hinten an den Commit-Message einen Text ran schreiben und dann und genau das kann ich einfach machen. Ich kann hier einfach irgendwie sagen, okay, Extensions ist diese API, habe ich importiert, hat eine Methode, dann gibt es diesen Commands-Punktable, das ist eigentlich immer das Gleiche, das gebe ich einfach an. Und dann sage ich die Methode, also das Kommando das überschrieben werden soll, Commit in dem Fall und sage, okay, überschreibt das mit der Methode, Mein-Commit. Mein-Commit ist eine von mir definierte Funktion, die die Originalfunktion als ersten Parameter mitkriegt, nämlich das Original-Commit, damit ich es halt wieder aufgerufen kann. Das UI, repo und die restlichen Parameter, die die Commit auch kriegen will, könnte. Und jetzt könnte ich einfach hier so, keine Ahnung, in den Pads einfach mal gucken, so ist da die Message drin, ja, wenn da die Message drin ist, dann überschreibe ich einfach, schreibe ich was Neues an die Message ran oder überschreibe die Message und dann mache ich den Commit eigentlich. Und wenn ich zum Beispiel einen neuen Flag brauche, weil ich sage, ich mache das nur, wenn der Flag-S gesetzt ist, dann kann ich hier unten noch mit Entry1 irgendwie sagen, Punkt Append, das ist übrigens immer Entry1 an der Stelle, weil mir Rep-Command als Entry dieses Dictionary-Eintracht zurückgibt, wo halt die Parameter-Liste im zweiten Ding, also von 0 angefangen 1 im Tupel drin ist. Und ich sage einfach, okay, ich will einen neuen Flag haben, minus T in dem Fall für Test oder so und der Default-Parameter ist irgendwie false. Also wenn er nicht angegeben wird, kriege ich an der Stelle dem Parameter als false zurück und fertig. Und damit kann ich eigentlich so komplett alles überschreiben, was ich irgendwie lustig bin und kann man einfach echt gut machen. Also ich habe mal paar Extensions geschrieben, Bookmarks zum Beispiel, es war so ein bisschen anonyme Branches für Macquarie, wo wir halt einfach so die Hälfte der Core-Kommandos irgendwie überschrieben haben mit dem Kram und das ist halt echt kein Act. Also es ist mittlerweile besser. Früher hat man, ich weiß nicht ob ich da früher gemacht, mittlerweile gibt es halt die API dafür. Und was ich damit machen kann, ich dachte mir, okay, irgendwie ich brauche ein cooles Projekt für den Kram, weil wir sind auf der GPN und irgendwie das ist alles nicht so beinruppend. Ich denke mir mal so, ich wollte mir so eine Dropbox bauen, so eine ganz triviale Dropbox und habe heute Morgen damit angefangen und deswegen ist sie nicht fertig, logischerweise. Aber sie tickt bis auf den Ding, dass sie noch nicht über Netzwerk synchronisiert, geht's eigentlich. Und zwar habe ich folgendes, wo ist es denn? Und zwar folgendes, ich habe angefangen und habe mir gesagt, okay, ich will das erste, was ich als Dropbox machen will, ich will mir einen Verzeichnis nachgucken, wenn sich da was ändert. Deswegen bin ich auch mit SSH auf meiner Linnungskiste drauf, weil da iNotify drauf ist, das ist eine Kernel extension, die mir Bescheid sagt, wenn sich was in dem Verzeichnis ändert. Und dafür gibt es ein Python Library, ich will es schrecklich zu benutzen, aber sie funktioniert so halbwegs. Und die benutze ich einfach, das ist ein bisschen kompliziert. Ich sage einfach, okay, ich will, wenn sich was hinzugefügt, wenn was hinzugefügt worden ist oder wenn jemand beim Schreiben fertig ist, weil Modified ist scheinbar nicht das Gleiche, wie Schreiben fertig. Es gibt auch Modified, aber Modified wird fünfmal mehr aufgerufen, deswegen habe ich ihn close write genommen. Und dann habe ich ihn aufgerufen, das ist einfach nur ein Event. Das ist die Klasse, die wird aufgerufen, wenn ich einen Event kriege von dem Fallsystem. Und registriere mir die Hübsche hier in dem Notifier und sage ihm dann, welches Verzeichnis gehandelt werden soll. Und da könnte ich jetzt eigentlich eine Konfig lesen und so weiter. Und ich habe einfach gesagt, nee, es ist ja ein Mikril Kommando. Wenn ich Mikril in einem Mikril Repository aufrufe, dann kriege ich natürlich auch das Verzeichnis. Und das nehme ich mir einfach, das Verzeichnis. Da, wo ich gerade drin bin, also das Repository Verzeichnis, das Repo.root, ich kriege ja, weil ich hier oben die Drop-Methode habe, da kriege ich immer ein Repository wieder mitgeliefert, das schon fertig initialisiert ist und dem macht der Route. Und sage dem einfach, okay, schau mal, was sich in diesem Verzeichnis ändert. Ich habe aus vorsichtshalberer Gründen noch meine Rekursionen ausgenommen, weil sich da drin ja auch das .hg-Verzeichnis befindet. Und wenn ich Rekursionen reinmache und was committe, dann ändert sich automatisch wieder was in dem .hg-Verzeichnis und damit lauf ich in Schleifen, die nicht so ganz lustig sind, weil ich auf meine eigenen Commits höre und die Commits committen will. Das ist nicht gut. Und dann sage ich halt keine Ahnung, Ausgabe und dann ist der Loop und der fängt einfach an und loopt. Hier habe ich wieder den CMD-Table und habe einfach das Kommando Drop genannt und genau. Und dann habe ich das noch ein bisschen erweitert, ich habe nur, ich habe nur schnell einfach neuere Versionen ausgecheckt, hoffentlich. Ah, nee, das habe ich noch nicht gemacht. Aber ich habe es hier gebackupt auf die gute Oldschoolweise, weil ich weiß, dass ich mit zu viel Mathe und zu wenig Schlaf nicht so gut bin. Okay. Und ich habe es halt ein bisschen aufgebohrt und habe dann angefangen, okay. So, wenn ich jetzt ein Event reinkriege, dann kriege ich, wenn sich was Neues hinzugefügt wurde, dann kriege ich diesen In-Create-Event. Das heißt einfach so, das ist so eine Namens-Convention von diesem Ein-Otify. Und dann habe ich ein Event und da steht ein Name drin von der Datei, die sich geändert hat oder hinzugefügt worden ist in dem Fall. Und jetzt erst, was ich mache, ich checke, ob dieser Datei nicht spezielle Namen hatten, weil Macquariel beim Kommitten selber Datei ganz kurz anlegt, temporäre Verzeichnisse und die wollen dann wieder selber hinzugefügt werden und deswegen muss man ein bisschen aufpassen. Egal. Und dann sage ich ihm, okay, schau mal, ob das überhaupt nicht in der HG-Ignor-Or drinsteht, so mit dem Match, wenn es halt da nicht drinsteht, also wenn es nicht ignoriert werden soll, die Datei. Dann mache ich einfach CND-Utile. Das ist einfach ein Command-Utile. Das sind Command-Utiles, die dafür designen worden, dass ich sie, dass ich innerhalb der API sozusagen das fertige Kommando zur Verfügung habe. Weil das Kommando, wie es original definiert ist, von außen braucht ein bisschen mehr ein bisschen mehr Betydelung und von daher habe ich das, habe ich diese Command-Utile und dem sage ich einfach, okay, ich habe die UI wieder, also die Ausgabe, Ausgabe-Objekt, das Repro-Objekt, das muss ich immer mit rumgeben. Ich habe einen Match auf dieses Command, auf dieses auf dieses Directory oder auf dieser Datei. Die Faults, Faults weiß gerade gar nicht, was es war. Ach doch, es war eigentlich, ob es nun dry run ist, also ob ich es nur emulieren will und gar nicht wirklich kompeten will und das andere war irgendwie der Branch-Name oder irgendwie sowas und rejected sagt mir, okay, wo das jetzt rejected ist, klar, also der Rückgabe ist halt ist halt true, wenn es halt rejected geworden ist, das heißt, ich habe es halt bloß nicht kompeten, ansonsten kompeten ich es. Und das war es, das war dann fertig kompeten, im Endeffekt sage ich halt Status noch. Und wenn sich halt, wenn irgendwie ein Schreibbefehl fertig geworden ist, dann habe ich wieder ein CMD-Utile für commit und kann einfach die Commit-Funktion aufrufen, kann eine Message angeben und die komme ich überhaupt auf den Kram. Also wie suche ich in dem Kram, dass ich auf die Idee komme, das zu verwenden, weil die, es gibt keine AP-Dokumentation in dem Fall. Wenn das jemand fragen wollte, es ist halt wie immer der Source. Ich schaue halt einfach meine Commands.py rein, wo alle Kommandos definiert worden sind in my career und sag einfach, hey, was macht denn eigentlich commit? Und dann sehe ich halt die commit-Methode und dann sehe ich halt schon, was die Commit-Methode macht, sie macht halt die Funktion, die ich alle nicht brauche, das ist mir völlig egal. Und dann kommt halt in der interessante Part, dass er halt auch wieder committ, mit der Commit-Funktion und eigentlich muss ich nur den Kram kopieren und kopiert das 1 zu 1 raus und habe damit einen fertigen commit, weil die ganzen Optionen, warum die gebe ich hier selber an, ich weiß ja, ob ich eine branch will oder nicht. Genau, und wenn... Hilfe. Genau, und damit habe ich einfach, wenn ich mit dem Freien fertig bin, mache ich einen commit, ansonsten mache ich einen Adventscreated und jetzt kann ich, das ist eigentlich so alles, das hat echt eine 3-4 Stunde gedauert, mit nachgucken, wie die commits funktionieren, weil ich das auch nicht auswendig weiß. Also ich gucke halt echt kurz in McRail nach in den Kommandos und sag okay, so funktioniert das, oder ich könnte auch das Kommando rappen oder so. Und dann kann ich hier reingehen und sagen, hoffentlich, wenn es funktioniert, ich mache hier ein init, okay. Jetzt mache ich ... Ah, ja, ich habe es vorauscommentiert. Tja, Tja, Tja. So, und jetzt, muss ich mir das Teil was reinlegen, dafür muss ich jetzt das H wieder auf den Fnord, HGI Dropbox 2. Okay, und jetzt beobachten wir uns mal kurz die Sache hier, weil das wird, da wird es detected, dass ich da was anlege, und hier lege ich was an. Also ich kann keine Verzeichnisse oder so reinwerfen, weil ich noch keine Rekursionen drin habe, ich kann einfach nur einzelne Dateien und ja, und tada, file added, but not yet committed, das ist genau dieser create event. Ich füge das, die Dateien zu, da hätte sie auch im Status automatisch hinzugefügt, mach, direkt beim, wenn er fertig ist mit dem Schreiben, schreibe ich, okay, es, kommenten wir es, und voila, fertig. Und der nächste Ding wäre einfach, dass ich danach nochmal das cmd-util für push aufrufe, und irgendwo auf einen Server zum Synchronisieren hinschicke und fertig. Und damit habe ich meine qualitative Dropbox, die halt nur die Hälfte kann, aber irgendwie selber gebaut ist und wahrscheinlich nicht funktioniert, aber auf jeden Fall keine Passwörter für vier Stunden oder so, die ich es nicht brauche, also ich mein, ist safe. Genau, und so kann ich halt da rumbauen. Es ist so ein bisschen so ein Einblick, was man so machen kann mit so einer Autify, so Geschichten, also wir hatten auch überlegt, uns einfach mal so Stammbäume in, in, in, in, mit Curl reinzuwerfen, also es ist einfach auch ein, hoffentlich meistens gerichteter Graf, also Zyklen wäre ein bisschen seltsam und und dann könnte man ja irgendwie so keine Ahnung, Stammbäume merken, wenn es Leute gibt, die sich dafür interessieren oder so, wenn man heiratet. Genau, ich weiß noch nicht, was Rebase in so einem Stammbaum ist, aber zum Thema Stabilität noch ein bisschen was, mit Curl hat ein Ansatz der ähnliches wie Git, dann behält sich vor, dass sich die interne API ändert. Die interne, interne API ist nicht stable und sie wird nie stable sein. Das heißt, ihr werdet immer nachbauen müssen und immer rumbauen müssen. Es gibt eine Abhilfe mit, es gibt zwei Abhilfen. Das erste ist, die einzige stabile API, die es im Moment gibt, ist die Ausgabe der Kommandos. Das heißt, einfach Systemaufruf auf das Kommando und die Ausgabe pasen, wie man das in Git auch macht. Das ist die einzige stabile API und weil das nicht ganz so cool ist ist, dass man seit zwei Wochen eine neue Option, dass man Curl in einem Demon-Modus starten kann oder einen CMD-Modus heißt das und dann über eine Unix-Pipe einfach Kommandos aufrufen kann und die Rückgabe des Kommandos kriegt und das ist auch eine stabile API. Genau, das kann man halt machen, aber wenn man halt Extension schreibt, dann rennt man immer den Curl-Developer hinterher, die auch echt gern was ändern, weil, keine Ahnung, man versucht den Code möglichst klar und einfach super viel Macriol machen. Also ich hab mir den Git Code angeschaut und versucht den Git-Ding einzubauen und ich hab das Ganze Macriol probiert und Macriol ist einfach so viel schöner, so viel einfacher, weil es hat auch irgendwie nur 30.000 Zeilen Code oder Python-Code, das ist das komplettes Ding, komplett Macriol mit allen Extensions, die so mitgeliefert werden hat, vielleicht 30.000, 40.000 Zeilen Code und da kommt man relativ schnell dahinter, was, wo, wie was macht und genau, das macht einfach mehr Spaß. Von daher wäre ich so mit meinem Teil fertig und jetzt hoffe ich, dass ihr ganz, ganz viele Fragen habt, die wir beantworten können, weil sonst ist es ja uninteressant. Fragen? Keine Fragen. Ja, dann hackt mal alle an Macriol rum und schaut mal, was ihr für coole Projekte habt. Also wenn jemand mal irgendwie so ein bisschen Macriol-Zack entfremden will, ich bin für ihr Ideen offen, mir ist noch nichts eingefallen, ich war ein bisschen unkreativ. Mekannte Macriol Extension? Ah nee, es gibt so was, die C-Pan gibt's nicht. Es gibt Wiki, es gibt das Wiki und es steht im Regelfall glaub ich relativ viel drin wenn ich, hab ich eine Connection ich sollte eine Connection haben. Egal, es gibt auf jeden Fall wirklich, um da gibt's eine eine Seite wo das eben drinsteht, die ganzen Extensions und die so gibt und es werden halt eben ein paar mitgeliefert wenn ich einfach so ein Macriol Verzeichnis berein schaue dann gibt's hier das HGX Verzeichnis und da liegen halt so ein paar Pi-Dateien drin und die sind, das sind alles Extensions also ACL, wenn man halt irgendwie Push- Control haben will, also User- Authentifizierung für Push, wenn man Backzille hat, wer so was noch verwendet Churn ist nur so ein bisschen Statistik wer wie viel Code gemacht hat, Color ist halt die Color Extension, ist klar, dass man halt einfach colorierten Output hat, damit es halt so aussieht, dann gibt's noch den Pager der Pager macht genau das Gleiche, dass ich nämlich HGlock so mache, weil sonst würde, wenn ich alle Konfigurationen ausschalte, geht das irgendwie das geht auch irgendwie wenn man alle Konfigurationen ausschaltet, sieht mit Kölnern mich plötzlich ganz anders aus und macht nicht mehr so ganz viel Spaß es gibt gar keine Optionen, die Ding auszuschalten auf jeden Fall, wenn ich die ausschalten würde dann würde das einfach durchrattern und ich müsste less aufrufen dahinter und es nach less pylpen und sonst was also da gibt es ein paar Extension und wie gesagt das Vicky hat so die meisten Sachen ja, die Frage jetzt ja ist hier eine gut Idee ja, es sieht halt nicht mehr so lustig aus also, es ist halt plötzlich unnütz irgendwie so und ich habe halt irgendwie help, halt nur noch die Hälfte der Kommandos, also es gibt halt gar nichts mehr, es gibt kein Rebase mehr, es gibt kein, keine Ahnung version mehr und kein pager, kein gar nichts, kein color output nichts, deswegen will man eigentlich relativ viele Extensions haben also ich habe auch echt eine ganze Reihe angebaut, also ich habe irgendwie die Convert Extension Progress damit man in der Progress Basis ein pager Patch Bomb ist für ein E-Mail Ding, damit man seine Patches per E-Mail wegschicken kann Racket ist so ein bisschen so eine Emulation von einem Index Color MQ ist so eine, so Patch Queues mal von Andrew Morton, das Quilt-Programm-Kennis und Patch Management-Programm, so was gibt es für Mikrole auch, das ist ziemlich mächtig um so kurz an Features zu basteln und das noch nicht zu committen und so ein bisschen immer dran rumschrauben zu dürfen und können Screens ist zum Beispiel so eine Extension dass ich halt nicht immer so HG Push SSH machen muss, sondern ich kann BEB für Bitbucket machen und dann macht er automatisch die, setzt er das um in die SSH-UL von Bitbucket für mich und also da gibt es halt echt so ein Stück geliefert und prompt ist nur ein, kann ich mir hübsche R-Prompt in meiner SSH basteln, wo meine Branche Name drin steht und so, Kram. Genau, also weitere Fragen wie wieder? Ja, klar, MQ Extension ist so gefragt und folgendes MQ funktioniert folgendes und zwar habe ich ein ganz normales Repository das ist normal mit der Revision 14706 und jetzt will ich anfangen darauf was rum zu basteln und ich bin mir noch nicht so sicher ob das was ich editiere nicht nochmal geändert werden soll normalerweise ist das Grundprinzip von MQ alles was einmal committed wurde ist einfach fest ist auch das ganze Repository Format ist auf Append only wirklich optimiert und sonst auch gar nicht, also re-Written von Repository Format tut echt weh und jetzt kann ich einfach sagen, okay ich will hier einen neuen Patch anlegen der bugfix 2323 und dann sehe ich halt, dann habe ich hier kein Quasarius, das sehe ich dass ich, dass dieser bugfix, gerade der Patches auf dem ich rumbaue und jetzt kann ich anfangen und sagen, okay ich editiere hier irgendwie was keine Ahnung kannst sehen so im Diff und jetzt sage ich, okay wenn ich jetzt committen würde das ganze mal committen, aber ich will es ja gar nicht und ich will das in diesen Patch schieben und ich will das mit diesem Patch Manage und dann mache ich einfach HGQ Refresh und damit wird der Patch, auf dem ich gerade arbeite, geupdatet mit den Änderungen die in dem Working Directory vorhanden sind und dann habe ich diesen Patch HGQDiff, kann ich anschauen was in dem Patch drin ist und kann das den immer wieder runternehmen und wieder mit Push drauf tun und wieder runternehmen vom Repository doch nicht die E-Mail-Adresse ist peinlich nehmt eine andere und Refreshing wieder und habe dem im Diff aber noch die Änderung von vorher, ich habe also 2011 und die E-Mail-Adresse geändert und sehe das immer auch im Lock, also im Lock taucht es auf, also wie wir hast ein ganz normaler Change nur mit dem Unterschied, dass ich diesen Change immer wieder runternehmen kann von dem Repository wieder draufschieben kann also es ist wirklich so ein Stack von Patches, die ich wieder hoch und runter schieben kann du willst also im Endeffekt willst du was, was du schon mal committed hast wieder ne ja du hast, also du hast, okay das folgen das, wenn ich das richtig verstanden habe korrigier mich an der Stelle also ich habe ein leeres Repository, das alles macht ich fange an und initiier was also ich habe die Änderung und jetzt entscheide ich mich, dass ich sagen will ich will es nicht committen oder was und da mache ich einfach HGQNew also leg den neuen Patch an Q, für alle diese QPatch Q, ganz die Q extension fängt alles, also mit MQ fängt alles mit Q an als Kommando sagt den Patchnamen Copy, Write, Change und dann legt er den automatisch an und packt automatisch die Änderung die im Repository drin waren schon initial da rein das heißt ich habe im QDiff habe ich es drin stehen im Patch ist es schon drin genau, aber es ist nicht im Repository, also ich habe es nicht committed sondern ich habe es nur in dem Patch drin okay und wie gesagt so handelt man halt einfach wenn man so ein Feature entwickelt baut man halt so 5 Patches und wenn man fertig ist macht man schiebt man die alle wieder hoch also applied sie und dann macht man QFinish und dann werden sie umgewandelt in echt Change Sets und dann ist es fertig und steht da ganz normal drin als Change Set auf irgendwo ein anderes Server dann kann ich es theoretisch wieder importieren also kann ich existieren in Changes wieder in meine Q reinnehmen gibt es heißt P-Branch Patch-Branch, ist eine Extension ja, ist eine Extension gibt es ich weiß nicht also wenn du als 2 Group Barsen gleichzeitig das Test kommt ein bisschen auf den Fall an wenn es geht Merchant, also wenn du Merchant kannst dann Merchant, also wenn du auf gerade auf 2.2 Arbeitest und auf 2.1 noch ein Backfix hast und dann würdest du auf 2.1 den Backfix machen und dann die 2.1er Branch in die 2.2er Branch Merchant und das würdest du immer wieder machen für jedes was du in 2.1 änderst würdest du's nach 2.2 Merchant das beinhaltet aber, weil Merch so ist dass alles was an vorherigen Revisionen auf der Einbranche gemacht wurden automatisch beinhaltet das implizit dass du sagst dass alle Änderungen die auf der 2.1er Branch gemacht worden auch in der 2.2er drin sein sollen und es gibt halt Fälle wo du auf der 2.1er Branch Dinge änderst die du in der 2.2er Branch nicht ändern willst also sei es keine Ahnung es gibt einen komplizierten richtigen Fix in der 2.2er Branch bereits aber es ist nicht möglich in der Zeit in dem Budget es auf der 2.1er Branch auch zu machen und der Release muss morgen raus und du kennst eine ganz dreckige Alternative dazu dann committest du sie halt und kannst es dann aber nicht mehr rein Merchant in die 2.2er und dann müsstest du halt ein bisschen gucken dann benutzt man also in dem Fall würde ich nach einer Zeit wieder remove das Chancet über Backout und dann Merchant aber wenn du das nicht machst dann musst du Transplant nehmen aber dann kriegst du die Branches halt nie mehr aufhand und das ist einfach nicht schön also du willst eigentlich im Regelfall immer auf der 1.1er Branch auf der 1.1er Branch fixen und das dann rein Merchant ist ungefähr klar geworden und wenn du dir zum Beispiel also wenn man sich zum Beispiel nicht sicher ist ahm ahm na ne fix muss ich noch verlängern aber einfach Merchant weitere Fragen wenn ihr eine Extension rumhaken wollt ihr könnt mich auch immer die ganze Zeit ansprechen wenn ihr wissen wollt warum Merchant viel besser ist als Git, könnt ihr mich auch fragen ich bin immer für zum Trollen zu haben ok und sonst kommt nachher her wenn ihr noch Fragen habt gut, fertig