SVN Repository umsortieren

Aus NOBAQ
Zur Navigation springenZur Suche springen

Seit dem letzten Eintrag hab ich etliche Sachen gemacht, die ich hier beschreiben könnte. Beispielsweise das Aufsetzen eines Asterisk Servers, Einbinden von ISDN Geräten bzw. einen chan-capi-tp-Patch, der das ISDN Leistungsmerkmal "Terminal Portability" dem Asterisk-Channel chan_capi hinzufügt. Leider funktioniert das bei mir zu Hause nicht dank der sch** Telekom die sich auch noch stur stellt und behauptet es wäre freigeschaltet. Pack. So konnte ichs nicht ausprobieren.

Wie auch immer, zu SVN: Per cvs2svn hab ich im Frühling mein CVS Repositority nach SVN übernommen. Leider war das alles nicht gepflegt und ich zu faul, das Manual zu lesen. Also landete alles als subdirs eines gemeinsames Repositority in /trunk/.

Nun will ich dienstliche, private und Sachen für andere trennen und die Verzeichnisstruktur von trunk/projectX nach projectX/{trunk|branches|tags} auftrennen. Wie ich das genau mach beschreib ich hier kurz.


Für eine detaillierte Beschreibung bin ich zu faul, deshalb dokumentier ich hier nur mehr oder weniger die verwendeten Befehle.

Der Schlüssel an dem ganzen liegt im Befehl "svnadmin {dump|load}". Mit svnadmin load kann ich mir das komplette Repository (das sonst als Berkeley DB abgespeichert ist/wäre) in ein dump-Format schreiben lassen:

$ svn dump /var/lib/svn/main >svn.dat

Diese Datei wäre eine reine ASCII Datei, wenn man nicht Binärfiles im Repositority ablegen würde. Auf alle Fälle sind die Daten in einer HTTP-Protokoll ähnlichen Struktur gespeichert.

Ein weiteres sehr nützliches Tool ist "svndumpfilter", denn dieses kann man an die Pipe hängen und es filtert nur die Verzeichnisse raus die man braucht.

In meinem Fall hat es sehr lange gedauert, bis alles funktioniert hat. Zuerst hab ich gelöschte, leere Verzeichnisse mitexportiert, die irgendwelche Referenzen auf andere Nodes gehabt haben.

Im Endeffekt blieben dann folgende Verzeichnisse des Repos. (die dienstlichen), die ich behalten wollte:

‘/trunk/S.Time’ ‘/trunk/MiniazurXP’ ‘/trunk/Miniazur’ ‘/trunk/libminiazur’ ‘/tags/v1-1stable_20060803′ ‘/tags/v1-0stable_20060418/S.Time’ ‘/branches/S.Time-propsheets’ ‘/branches/niki/Miniazur’

Der folgende Befehl hat genau die rausgefiltert:

svnadmin dump /var/lib/svn/private | svndumpfilter include –drop-empty-revs –renumber-revs ‘trunk/S.Time’ ‘trunk/MiniazurXP’ ‘trunk/Miniazur’ ‘trunk/libminiazur’ ‘branches/S.Time-propsheets’ ‘tags/v1-1stable_20060803′ ‘tags/v1-0stable_20060418/S.Time’ >scc.dat 2>log.txt

–drop-empty-revs sorgt dafür, das Revisionen, die aufgrund des Filters leer bleiben gelöscht werden und –renumber-revs numeriert die vorbleibenden Revisionen von 1 weg neu. Das will ich.

Mittels

svnadmin load repos < scc.dat

könnte man das ganze wieder importieren. Erstes Problem gelöst.

Bleibt das diffizielere, zweite, nämlich die Pfade umzuändern. Per TortoiseSVN z.B. oder auch per “svn” ist keine gute Idee, denn dann wird das Verschieben geloggt und die Lognachrichten passen nicht mehr zu den Verzeichnissen. Also muss die ca 20MB große scc.dat manuell geändert werden.

Da Binärdateien drinnen sind, wollte ich zuerst per od das ganze in eine HEX-Datei konvertieren:

od -An -v -tx2 scc.dat >scc.hex

Da die betreffenden Abschnitte jedoch sowieso ASCII Abschnitte sind und das Herumjonglieren mit ASCII HEX Zeichen doch etwas unhandlich ist, habe ich perl doch für das bessere Tool befunden.

perl -pi -e ‘befehl(e)’ datei

Wendet die in befehle eingebetteten regexp auf die ganze Datei an.

Zum Format: Alle Dateinamen/Operationen/Einträge (”nodes”) haben das Format:

Node-path: path/to/file

Also mal schauen, welche Pfade ich umsetzen will.

Im Prinzip will ich die Struktur:

projekt1{trunk|branches|tags} projekt2{trunk|branches|tags} projekt3{trunk|branches|tags}

Also hab ich mir mal eine Liste erstellt, welche Namen umgesetzt werden müssen:

Node-path: trunk/S.Time S.Time/trunk
Node-path: trunk/MiniazurXP MiniazurXP/trunk
Node-path: trunk/Miniazur Miniazur/trunk
Node-path: trunk/libminiazur libminiazur/trunk
Node-path: branches/S.Time-propsheets S.Time/branches/S.Time-propsheets
Node-path: tags/v1-0stable_20060418/libminiazur libminiazur/tags/v1-0stable_20060418
Node-path: tags/v1-0stable_20060418/Miniazur Miniazur/tags/v1-0stable_20060418
Node-path: tags/v1-0stable_20060418/MiniazurXP MiniazurXP/tags/v1-0stable_20060418
Node-path: tags/v1-1stable_20060803 S.Time/tags/v1-1stable_20060803

Das ergibt u.a. folgende regex:

s/^Node-path: trunk/([A-Za-z.]+)/$1/trunk/g;
s/^Node-path: branches/S.Time-propsheets/S.Time/branches/S.Time-propsheets/g;
s/^Node-path: tags/v1-0stable_20060418/([A-Za-z]+)/$1/tags/v1-0stable_20060418/g;
s/^Node-path: tags/v1-1stable_20060803/S.Time/tags/v1-1stable_20060803/g;

Achtung! Für Branches gibt es Referenzen auf andere Nodes, die mit “Node-copyfrom-path:” erstellt werden! Die müssen also auch umgesetzt werden!

Unterm Strich hat dieser Perl-Einzeiler die Arbeit übernommen:

perl -pi -e ’s/^Node-path: trunk/([A-Za-z.]+)/Node-path: $1/trunk/g;s/^Node-path: tags/v1-1stable_20060803/Node-path: S.Time/tags/v1-1stable_20060803/g;s/^Node-path: branches/S.Time-propsheets/Node-path: S.Time/branches/S.Time-propsheets/g;s/^Node-copyfrom-path: trunk/S.Time/Node-copyfrom-path: S.Time/trunk/g;s/^Node-copyfrom-path: (branches/S.Time-propsheets/[A-Za-z0-9./]+)/Node-copyfrom-path: S.Time/$1/g;’ scc.dat

Nun geht es ans Importieren. Ich habe lange dafür gebraucht, draufzukommen, dass die Verzeichnisse bereits existieren müssen, d.h. zuerst mit svn anlegen (sofern sie mehr als zwei Ebenen sind).

In meinem Fall hab ich die Befehle zum Löschen des alten Repositories und Anlegen des neuen bzw. der initiellen Verzeichnisse gleich in einen Befehl gepackt:

rm -r scc; svnadmin create scc; svn mkdir -m “Initial project roots” file:///root/svn/scc/S.Time file:///root/svn/scc/S.Time/branches file:///root/svn/scc/S.Time/tags file:///root/svn/scc/MiniazurXP file:///root/svn/scc/Miniazur file:///root/svn/scc/libminiazur

Nun kann das ganze mit

svnadmin load scc

importiert werden.

Treten Fehler auf? Kryptische Fehlermeldungen deuten auf folgende Sachen hin: - Beim “svnadmin dump” werden nicht alle Abhängigkeiten mitinkludiert (z.B. bei Branches) - Beim "svnadmin load" gilt das gleiche - Kontrollieren, ob im leeren Repos. die passenden Verzeichnisse angelegt wurden - Kontrollieren, ob alle Pfade auch wirklich richtig umgesetzt wurden.

Zum Schluss hab ich das ganze noch dav_svn tauglich gemacht:

chown -R svn.svn scc;
find scc -type d | xargs chmod 770;
find scc -type f | xargs chmod 660

und zurück nach /var/lib/svn geschoben. Das Überprüfen mit TortoiseSVN hat nach längerer Zeit endlich funktioniert.