Gentoo Logo

Disclaimer : Dit document is niet juist en is niet meer onderhouden.


Gentoo Linux CVS Uitleg

Inhoud:

1.  Inleiding

Uitleg overzicht

Deze uitleg heeft 2 delen. Het eerste legt je uit hoe je CVS gebruikt als niet-ontwikkelaar; i.e. om broncode van een CVS te halen en deze te updaten. Het tweede deel heeft als doel de ontwikkelaars bij te brengen hoe ze bestanden toevoegen en verwijderen uit CVS, en om andere ontwikkelzaken uit te voeren. Indien je nieuw bent tot CVS is het aan te raden dat je begint met de eerste sectie en zo verder gaat naar de andere secties; indien je al wat basis CVS ervaring hebt maar je als ontwikkelaar volledig de wereld van CVS moet kennen, zal je alles wat je wil weten in het tweede deel vinden, maar je kan altijd door het eerste deel gaan voor een snelle verfrissing :)

Wat is CVS en wat doet het?

CVS is een client/server systeem dat ontwikkelaars toelaat om hun projecten op een centrale locatie bij te houden, genaamd een "repository". Door gebruik te maken van de cvs client tools kunnen ontwikkelaars aanpassingen maken aan de inhoud van de repository. De repository zelf houdt alle aanpassingen bij waardoor alle stappen kunnen gevolgd worden. Ontwikkelaars kunnen oudere versies van broncodebestanden opvragen, een log van aanpassingen bekijken, of andere interessante taken uitvoeren wanneer dat nodig is.

De rol die CVS speelt

Veel open source projecten hebben eigen CVS servers welke door de ontwikkelaars gebruikt worden als centrale repository voor al hun werk. Ontwikkelaars maken vaak dagelijks aanpassingen aan de broncode in de CVS repository; vaak zitten deze ontwikkelaars overal ter wereld, waardoor CVS een manier is om hun collaboratief werk te centraliseren tot een cohesief geheel. CVS is de "organizerende lijm" die de ontwikkelaars toe staat aanpassingen te maken zonder de andere ontwikkelaars op hun tenen te trappen, zonder belangrijke gegevens kwijt te raken of updates van andere ontwikkelaars teniet te doen.

CVS -- bleeding-edge broncode

Wanneer de ontwikkelaars klaar zijn rollen zij een deel van hun werk van CVS uit in een .tar.gz bestand en brengen deze uit als nieuwe versie van hun software pakket. Maar soms is de laatste officiele release niet recent genoeg, dit kan wegens een groot aantal mogelijke oorzaken. In de eerste sectie van deze uitleg zal ik je tonen hoe CVS voor dit doel gebruikt wordt -- de laatste ontwikkelversie van een project downloaden voor je eigen gebruik.

Installeren van CVS

Om cvs te installeren, type gewoon emerge cvs in:

Codevoorbeeld 1.1: Installeren van CVS

#  emerge cvs 

Een lokale CVSROOT

Codevoorbeeld 1.2: De CVSROOT instellen

# CVSROOT=/home/cvsroot

Dit is een voorbeeld van een lokaal CVSROOT pad; je zal een soortgelijke CVSROOT gebruiken indien je wil verbinden met een lokale repository die in /home/cvsroot gevestigd is, of indien je een repository via NFS gemount hebt in /home/cvsroot.

Een remote password server CVSROOT

Codevoorbeeld 1.3: De CVSROOT instellen met vericatie

# CVSROOT=:pserver:cvs@foo.bar.com:/home/cvsroot

Dit is een voorbeeld van een CVSROOT voor een remote repository die op foo.bar.com gevestigd is en in de /home/cvsroot directorie van die machine leeft. De voorgaande ":pserver:" vertelt ons dat we moeten verbinden met de server via het CVS password server protocol, een protocol dat in CVS ingebouwd zit. Typisch gebruiken publieke CVS repositories het password server protocol om toegang aan anonieme gebruikers te geven.

Een remote rsh/ssh CVSROOT

Codevoorbeeld 1.4: RSH/SSH CVSROOT

# CVSROOT=drobbins@foo.bar.com:/data/cvs

Dit is een voorbeeld van een CVSROOT die RSH of SSH gebruikt; in dit voorbeeld zal de CVS sever de repository op foo.bar.com proberen te raadplegen via de drobbins account. Indien de CVS_RSH omgevingsvariabele ingesteld is op "ssh" zal onze cvs client ssh gebruiken om te verbinden; anders zal rsh gebruikt worden. De ssh toegangsmethode is populair bij deze die in zitten over veiligheid; geen van de RSH en SSH methodes levert echter een goede manier voor anonieme gebruikers om de broncode binnen te halen. Om deze methode te gebruiken moet je een login account hebben op foo.bar.com.

Nog enkele andere zaken...

Naast CVSROOT moet je tevens weten welke module (verzameling van broncodebestanden) je wil gebruiken, alsook het wachtwoord dat je nodig hebt om in te kunnen loggen tot de CVS server. In tegenstelling tot anonieme ftp is er geen "standaard" formaat voor het anonieme paswoord, dus moet je het specifieke paswoord van de website of via via te weten komen. Als je eenmaal al deze informatie hebt ben je klaar om te beginnen.

Met CVS werken, deel 1

De broncode downloaden bestaat uit 2 stages. Allereerst moeten we inloggen op de wachtwoord server. Daarna moeten we de broncode downloaden via het checkout commando. Hieronder vind je een voorbeeld van de commandos die nodig zijn om de laatste Samba, een populair UNIX/Windows integratie project, te downloaden:

Codevoorbeeld 1.5: De CVSROOT instellen

# export CVSROOT=:pserver:cvs@pserver.samba.org:/cvsroot

Het eerste commando stelt de CVSROOT omgevingsvariabele in. Indien je deze variabele niet instelt vereisen de volgende 2 commandos een extra -d :pserver:cvs@pserver.samba.org:/cvsroot als argument voor het cvs commando. Het exporteren van de CVSROOT zorgt dus voor een winst inzake typen :)

Werken met CVS, deel 2

Hier zijn de commandos die nodig zijn om een kopie te verkrijgen van de developer broncode. Je kan best eerst eens de uitleg hieronder lezen en dan terugspringen om de commandos effectief uit te voeren:

Codevoorbeeld 1.6: Controleer de bronnen

# cvs login
(Inloggen op cvs@pserver.samba.org)
CVS password: (paswoord ingeven)

# cvs -z5 co samba
U samba/COPYING
U samba/Manifest
U samba/README
U samba/Read-Manifest-Now
U samba/Roadmap
U samba/WHATSNEW.txt
(...snip...)

Werken met CVS -- uitleg

Het eerste cvs commando logt ons in op de pserver, en het tweede commando zorgt ervoor dat de CVS client de samba module uitcheckt ("co") en dit met een gzip compressieniveau van 5 ("-z5") opdat de transfersnelheid over een trage link wat hoger zou liggen. Voor elk nieuw bestand dat aangemaakt wordt print cvs een "U [path]" uit, welke aanduidt dat dit bestand geupdate wordt op de schijf.

Checkout klaar

Eenmaal het checkout commando afgelopen is zal je een "samba" directorie zien in de huidige directorie dat de laatste broncode bevat. Je zal tevens opmerken dat alle directories een "CVS" subdirectorie hebben -- CVS slaat de nodige informatie in deze directories op, ze kan dus veilig genegeerd worden. Vanaf dit punt moeten we ons niets meer aantrekken van de CVSROOT variabele aangezien deze in die extra "CVS" directories opgeslagen zit. Herinner je eraan -- je moet enkel CVSROOT instellen voor de initiele login en checkout.

De broncode updaten

Voila, nu heb je verse broncode. Nu je deze hebt kan je hem compileren en installeren, bekijken of wat je dan ook met de broncode wilt doen.

Nu en dan zal je je broncode up2date willen maken met de broncode op de CVS server. Om dit te doen hoef je niet meer opnieuw in te loggen; je informatie wordt bijgehouden in de "CVS" directories. Allereerst moet je de hoofddirectorie (in dit geval "samba") binnengaan, en dan type je:

Codevoorbeeld 1.7: updaten van bronnen en mappen

# cvs update -dP

"cvs update", deel 1

Indien er nieuwe bestanden zijn, zal cvs als uitvoer "U [path]" regels geven voor elk bestand dat hij vindt. Indien je de broncode gecompileerd hebt zal je tevens een hoeveelheid "? [path]" regels te zien krijgen; deze zijn objectbestanden die cvs opmerkt die niet in de remote repository zitten.

"cvs update", deel 2

Bemerk tevens de 2 commandoregel opties die we gebruikt hebben voor "cvs update". "-d" zorgt ervoor dat cvs nieuwe directories aanmaakt indien nodig (dit gebeurt niet per default), en "-P" vertelt cvs om lege directories te verwijderen van je lokale kopie van de broncode. "-P" is een goed idee aangezien cvs de neiging heeft om veel lege directories (ooit gebruikt, maar dan genegeerd) te bevatten.

Wanneer je enkel de recentste versies wilt downloaden, dan is dat alles wat je hoeft te weten. Laten we nu eens kijken hoe je met CVS speelt als ontwikkelaar.

2.  CVS voor ontwikkelaars

Bestanden aanpassen

Als ontwikkelaar zal je hoogstwaarschijnlijk bestanden in de CVS moeten aanpassen. Om dit te doen moet je simpelweg de aanpassingen lokaal maken. Deze aanpassingen worden niet direct remote geplaatst, maar enkel wanneer je je aanpassingen "commit". Wanneer je al je aanpassingen getest hebt om er zeker van te zijn dat ze goed werken en als je werkelijk klaar bent om al je aanpassingen door te voeren, volg dan de volgende 2-stappen procedure. Allereerst moet je je broncodebestanden updaten door het volgende commando in te geven in je broncodedirectorie:

Codevoorbeeld 2.1: updaten van bronnen en mappen

# cvs update -dP

Anderen hun aanpassingen doorvoeren

Zoals we al eerder zagen zal "cvs update" je broncode up-to-date brengen met deze van de repository -- maar wat gebeurd er nu met de aanpassingen die jij gemaakt hebt? Raak niet in paniek, die werden niet weggesmeten. Indien een andere ontwikkelaar aanpassingen heeft gemaakt aan een bestand dat je niet aangeraakt hebt, dan zal dat bestand lokaal aangepast zijn.

Indien jij regels 1-10 van een bestand aangepast hebt, en een andere ontwikkelaar heeft regels 40-50 verwijderd en 12 nieuwe regels toegevoegd en tevens regels 30-40 aangepast en zijn aanpassingen in de CVS heeft gestoken, dan zal cvs intelligent als het is de aanpassingen in de lokale broncode steken zonder dat je aanpassingen verloren zijn gegaan. Dit laat toe dat meerdere ontwikkelaars aan verschillende delen van een bestand werken op hetzelfde moment.

Mergen is niet perfect

Indien echter meerdere ontwikkelaars aanpassingen gemaakt hebben aan dezelfde regels in het bestand, dan wordt het iets ingewikkelder. Indien dat gebeurd, dan zal cvs je zeggen dat er een conflict is opgetreden. Geen werk zal verloren zijn gegaan, maar je zal handmatig de aanpassing moeten samenvoegen, aangezien cvs nu niet weet wat hij moet doen om de conflicterende aanpassingen door te voeren.

De commit

We zullen direct eens zien hoe we dergelijke conflicten kunnen oplossen, maar laten we nu eerst veronderstellen dat er geen conflicten optreden nadat je "cvs update -dP" hebt ingegeven -- meestal zijn er namelijk geen conflicten. Zonder conflicten zijn je lokale broncodebestanden up-to-date en ben je klaar om je aanpassingen in de repository te steken door de volgende commandos uit te voeren:

Codevoorbeeld 2.2: De veranderingen permanent maken

# cvs commit

Wat doet commit?

cvs commit zal niet enkel je aanpassingen in de repository steken. Alvorens hij dat doet zal hij je default editor opstarten zodat je een uitleg kan geven over de aanpassingen die je gemaakt hebt. Als je eenmaal je commentaar hebt toegevoegd en het bestand opgeslagen en de editor verlaten, dan pas zal cvs de aanpassingen (en de uitleg) op de remote repository opslaan zodat deze beschikbaar is voor andere ontwikkelaars van je team.

De logs bekijken

Het is zeer eenvoudig om de volledige geschiedenis van een specifiek bestand te bekijken, samen met de commentaar die de ontwikkelaars (inclusief jezelf) toegevoegd hebben tijdens het committen. Om deze informatie te zien type je:

Codevoorbeeld 2.3: Bekijk log-informatie

# cvs log myfile.c

Het "cvs log" commando is recursief, dus indien je de volledige log wil bekijken van de volledige directoriestructuur, moet je enkel in de directorie het volgende typen:

Codevoorbeeld 2.4: Bekijk de log-informatie

# cvs log | less

Commit opties

Indien je een andere editor wil gebruiken dan deze die cvs opstart moet je de EDITOR omgevingsvariabele aanpassen naar de editor die je wil gebruiken. Dergelijke instelling plaats je het best in ~/.bashrc.

Codevoorbeeld 2.5: Je editor instellen

export EDITOR=/usr/bin/jpico

Alternatief kan je tevens een logboodschap meegeven op de commandoregel zodat cvs geen editor moet opstarten:

Codevoorbeeld 2.6: Veranderingen aanbrengen met een klein logbestand

# cvs commit -m 'I fixed a few silly bugs in portage.py'

Het .cvsrc bestand

Alvorens we verder gaan met het bekijken van meer cvs commandos raad ik je aan om een ~/.cvsrc bestand aan te maken. Door dit bestand te creeren in je homedirectorie kan je cvs instellen om default al je eigen keuze van opties te gebruiken zodat je die niet telkens moet meegeven als commandoargumenten. Hieronder zie je een aanbevolen .cvsrc bestand:

Codevoorbeeld 2.7: aangeraden basisinstellingen

cvs -q
diff -u -b -B
checkout -P
update -d -P

Het .cvsrc bestand, vervolg

Naast het instellen van een hoeveelheid interessante CVS commandos plaatst de eerste regel CVS in zogenaamde stille modus waardoor de uitvoer van het commando meer consistent en leesbaar wordt. Als je dit bestand gebruikt kan je tevens "cvs update" uitvoeren ipv "cvs update -dP".

Een bestand toevoegen aan de repository

Het is zeer eenvoudig om een broncodebestand toe te voegen aan CVS. Allereerst maak je het bestand aan. Daarna type je het volgende in:

Codevoorbeeld 2.8: Een bastand toevoegen

# cvs add myfile.c
cvs server: use 'cvs commit' to add this file permanently

Dit zorgt ervoor dat cvs dit bestand toevoegt aan de repository gedurende de volgende "cvs commit". Tot dan zullen andere ontwikkelaars het bestand niet zien.

Een directorie toevoegen aan de repository

Het toevoegen van een directorie aan CVS gaat op ongeveer dezelfde manier:

Codevoorbeeld 2.9: Een map toevoegen

# mkdir foo
# cvs add foo
Directory /home/cvsroot/mycode/foo added to the repository

In tegenstelling tot het toevoegen van een bestand zal een toegevoegde directorie direct beschikbaar zijn op de repository; een cvs commit is niet nodig. Eenmaal je de lokale directorie aan CVS hebt toegevoegd zal je zien dat er een "CVS" directorie in die directorie aangemaakt werd om daarin de nodige informatie op te slaan. Je kan dus gemakkelijk zien of een directorie al dan niet in CVS zit door te kijken of er een CVS subdirectorie is.

"cvs add" notities

Oh en zoals je wel kan vermoeden, alvorens je een bestand of directorie toevoegt aan de repository moet je er wel voor zorgen dat de parent directorie al in de CVS zit. Anders zal je een foutmelding krijgen die er als volgt uitziet:

Codevoorbeeld 2.10: Een bestand aanmaken en een foutmelding krijgen..

# cvs add myfile.c
cvs add: cannot open CVS/Entries for reading: No such file or directory
cvs [add aborted]: no repository

Werken met "cvs update", deel 1

Alvorens we een kijkje nemen naar hoe je conflicten oplost, zullen we eerst moeten wennen aan de uitvoer van het "cvs update" commando. Indien je een ~/.cvsrc bestand aangemaakt hebt met daarin "cvs -q" dan zal je merken dat de "cvs update" uitvoer heel wat eenvoudiger te lezen is. "cvs update" informeert je over wat het doet en ziet door een enkelvoudig karakter weer te geven, een spatie, en daarachter de desbetreffende bestandsnaam. Bijvoorbeeld:

Codevoorbeeld 2.11: De CVS updaten

# cvs update -dP
? distfiles
? packages
? profiles

Werken met "cvs update", deel 2

"cvs update" gebruikt het "?" karakter om je uit te leggen dat het niets weet over het desbetreffende bestand dat het lokaal vindt. Het is geen deel van de repository, en is tevens niet gekend als kandidaat om toegevoegd te worden. Hieronder vind je een lijst met alle mogelijke uitvoerkarakters die je kan tegenkomen:

Codevoorbeeld 2.12: informatie bericht U

U [path]

Wordt gebruikt wanneer een bestand gemaakt is op je lokale repository en niet is veranderd sindsdien.

Codevoorbeeld 2.13: informatie bericht A

A [path]

Dit bestand staat klaar om toegevoegd te worden en dat zal dan ook gebeuren tijdens de volgende "cvs commit".

Werken met "cvs update", deel 3

Codevoorbeeld 2.14: informatie bericht R

R [path]

In tegenstelling tot "A" laat "R" je weten dat het bestand ingesteld staat om verwijderd te worden uit de repository. Dit zal gebeuren tijdens de volgende "cvs commit".

Codevoorbeeld 2.15: informatie bericht M

M [path]

Dit wil zeggen dat dit bestand aangepast werd door jou. Bijkomend is het mogelijk dat er andere aanpassingen van de repository succesvol in het bestand gestoken zijn.

Codevoorbeeld 2.16: informatie bericht C

C [path]

Het "C" karakter duidt aan dat dit bestand een conflict heeft en manuele aanpassing vereist alvorens je je aanpassingen met "cvs commit" kan doorvoeren.

Inleiding tot het oplossen van conflicten

Laten we nu eens kijken hoe we een conflict oplossen. De auteur is zeer nauw betrokken bij het Gentoo Linux project, en die heeft een eigen cvs server op cvs.gentoo.org. De ontwikkelaars houden zich meestal bezig met het aanpassen van de broncodebestanden in de "gentoo-x86" module. Binnenin deze module hebben we een bestand genaamd "ChangeLog" dat alle opmerkingen bij aanpassingen bevat.

Een conflict voorbeeld

Aangezien dit bestand door bijna alle ontwikkelaars aangepast wordt telkens zij een aanpassingen maken in de CVS, is deze een primaire oorzaak van conflicten -- hieronder zie je een voorbeeld conflict. Laten we zeggen dat we de volgende regels willen toevoegen aan de ChangeLog:

Codevoorbeeld 2.17: 'changelog' inhoud 1

date 25 Feb 2001

This is the thing I added myself

Maar net voordat we dit willen committen heeft een andere ontwikkelaar de volgende regels bovenaan ChangeLog geplaatst:

Codevoorbeeld 2.18: 'changelog' inhoud 2

date 25 Feb 2001

This is the part added by another developer

Een voorbeeld conflict, vervolg

Wanneer ik nu "cvs update -dP" uitvoer (wat je altijd moet doen voor een commit) merk je dat CVS niet de mogelijkheid heeft om de aanpassingen te mergen aangezien we beiden regels op dezelfde plaats hebben toegevoegd -- hoe weet CVS nu welke regel er eerst moet komen? Dus krijg ik de volgende fout van CVS:

Codevoorbeeld 2.19: een cvs-fout

RCS file: /home/cvsroot/gentoo-x86/ChangeLog,v
retrieving revision 1.362
retrieving revision 1.363
Merging differences between 1.362 and 1.363 into ChangeLog
rcsmerge: warning: conflicts during merge
cvs server: conflicts found in ChangeLog
C ChangeLog

Conflicten oplossen, deel 1

Eeekes, een conflict! Gelukkig is het oplossen van conflicten eenvoudig. We starten onze favoriete editor op en zien de volgende tekst bovenaan het ChangeLog bestand:

Codevoorbeeld 2.20: de 'changelog' inhoud

<<<<<<< ChangeLog
date 25 Feb 2001

This is the thing I added myself

=======
date 25 Feb 2001

This is the part added by another developer

>>>>>>> 1.363

Conflicten oplossen, deel 2

In plaats van de ene versie boven de andere te kiezen heeft CVS beide versies aan de ChangeLog toegevoegd, en heeft deze omringd met speciale karakters om duidelijk te maken waar de verschillen zitten. Het is nu mijn beurt om dit te vervangen met de correcte tekst. In dit geval is het een combinatie van beide teksten:

Codevoorbeeld 2.21: de 'changelog' inhoud

date 25 Feb 2001

This is the thing I added myself

This is the part added by another developer

Nu dat we de conflicten opgelost hebben en de speciale karakters verwijderd hebben kunnen we de aanpassingen in de CVS repository steken.

Conflicten oplossen; tips

Wanneer je een bestand moet aanpassen voor conflicten moet je ervoor zorgen dat je het volledige bestand doorloopt op zoek naar de conflicten; indien je een specifiek conflict vergeet te adresseren zal cvs niet toestaan dat je het bestand commit. Het is natuurlijk tevens zeer belangrijk dat je de speciale karakters verwijdert uit het conflicterende bestand. Een andere tip -- indien je een fout gemaakt hebt tijdens het oplossen van een conflict kan je de originele kopie van het bestand terugvinden in ".#bestandsnaam.versie".

Een bestand verwijderen

Het is nu tijd om de laatste eigenschap aan te leren -- verwijderen van bestanden uit de repository. Dit is een 2-stage proces. Allereerst verwijder je het bestand uit je lokale repository, en daarna voer je de nodige "cvs remove" commandos uit:

Codevoorbeeld 2.22: Een bestand verwijderen

# rm myoldfile.c
# cvs remove myoldfile.c

Een bestand verwijderen, vervolg

Het bestand zal klaargemaakt worden om verwijderd te worden uit de repository, wat dan ook zal gebeuren gedurende de daaropvolgende commit. Eenmaal gecommit zal het bestand officieel verwijderd zijn uit de repository. CVS zal echter dit bestand niet wegsmijten en zal de volledige geschiedenis van dit bestand bijhouden, dit in geval dat je het bestand weer nodig zou blijken te hebben in de toekomst. Dit is een van de vele zaken die cvs doet om je belangrijke broncode veilig te stellen.

"cvs remove" is recursief, wat wil zeggen dat je een heleboel bestanden kan verwijderen om dan "cvs remove" uit te voeren (zonder bijkomende argumenten) om al deze bestanden door CVS aan te laten duiden als verwijderd, wat dan zal gebeuren gedurende de daaropvolgende commit.

Een map verwijderen

Indien je een volledige directorie wil verwijderen raden we het volgende proces aan. Allereerst verwijder je alle bestanden in de directorie:

Codevoorbeeld 2.23: Verwijder een map

# rm *.c
# cvs remove

Een map verwijderen, vervolg

Daarna voeren we een commit uit:

Codevoorbeeld 2.24: Plaats je veranderingen online!

# cvs commit

Hier volgt de truc: voer de volgende stappen uit om de directorie te verwijderen:

Codevoorbeeld 2.25: Verwijder een map

# cd ..
# cvs remove mydir
# rm -rf mydir

Merk op dat het verwijderen van de directorie geen nieuwe commit vereistte -- directories worden in real time aangemaakt en verwijderd.

Gedaan!

De uitleg over CVS is nu afgelopen -- ik hoop dat deze tutorial hulpzaam is/was. Er is nog heel wat meer over CVS te vertellen dan wat hier neergeschreven was, maar gelukkig zijn er een heleboel goede bronnen van waaruit je meer kan leren:

Over dit document

De originele versie van dit artikel is voor het eerst verschenen op IBM DeveloperWorks, en is eigendom van Westtech Information Services. Dit document is een aangepaste versie van dat artikel, en bevat enkele verbeteringen aangebracht door het Gentoo Linux Documentatie team.



Print

Upgedate op 23 mei 2005

De originele versie van dit document wordt niet meer onderhouden

Korte inhoud: Deze uitleg introduceert CVS - Concurrent Versions System - aan de lezers. CVS wordt gebruikt door ontwikkelaars waar ook ter wereld om software op een flexibele en collaborerende manier te ontwikkelen. Dit document heeft als doel de beginners uit te leggen hoe je snel aan CVS gewend raakt. Of je nu CVS wil gebruiken om broncode in te voegen, of om CVS als een volwaardige ontwikkelaar te gebruiken, deze uitleg is de manier om snel je weg te vinden.

Daniel Robbins
Auteur

Xavier Neys
Redacteur

Sven Vermeulen
Vertaler

Tiemo Kieft
Vertaler

Dimitry Bradt
Vertaler

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.