W krainie CVS - czyli wielki kocioł

Umiemy już w miare klecić nowe spece, naprawiać stare - chcemy dołączyć do drużyny PLD... Musimy mieć więc możliwość pogrania na boisku, a nie tylko zasiadać na trybunach jako widz. Naszym boiskiem będzie CVS a możliwość czytania i pisania do niego (Read-Write) naszym sposobem na grę :)
Jak to życiu, aby coś dostać musimy najpierw się postarać i wykonać pare czynności.

Żeby otrzymać własne konto CVS należy uzyskać poparcie już aktywnych deweloperów. Zwykle osoby wykazujące się aktywnością na listach dyskusyjnych (podsyłające patche, itp.) prędzej czy później są wręcz proszone o zgłoszenie się po konto. W typowym przypadku wystarczy, że trzech deweloperów wyrazi poparcie kandydata na dewelopera (trzeci z nich powinien wskazać mu dokąd powinien się zgłosić po konto). Osoba popierająca kandydata jednocześnie staje się jego opiekunem i nadzoruje jego działania w początkowej fazie. W przypadku gdyby, mimo poparcia przez niektórych, osoba kandydata wywoływała kontrowersje, decyzja o jego przyjęciu (lub nie) będzie podjęta zgodnie z obowiązującą procedurą rozwiązywania konfliktów.

Kiedy już zostaniemy przyjęci, po pierwsze musimy sobie wymyśleć ksywke i hasło. Potem z linii poleceń wykonujemy jednolinijkowe polecenie - wstawiając za login i haslo odpowiednie dane:

perl -e 'print "login:" . crypt("haslo", join "", (".", "/", 0..9, "A".."Z", "a".."z")[rand 64, rand 64]) . "\n"'

w wyniku którego otrzymamy ciąg znaków podobny do:

login:/APGG.cfeqPpk

Ciąg ten kopiujemy do listu e-mail z prośbą o możliwość RW na CVS PLD i wysyłamy na adres cvsadmin@pld-linux.org
To narazie wszystko co możemy zrobić - trzeba czekać na odpowiedź od władzy CVS. Po kilku, kilkunastu lub kilkudziesięciu dniach przyjdzie mail z odpowiedzią. U mnie była to wiadomość podobna do:

Quoting Marek Ciesielski <marekc@adres.email>:

> Prosze o dostep RW do CVS PLD.
> dane do <login>:/APGG.cfeqPpk // oczywiście tej linii w mailu nie ma - dodałem ją dla przykładu :)

Witam,

twoje konto zostało założone, proszę dopisz się do CVSROOT/users

--
Admin CVS <imię i nazwisko> :)

Czyli pierwsze formalności mamy za sobą. Możemy już działać na CVS. Jednak proponuje znowu trochę teorii - tym razem zdecydowana większość dokumentacji jest w języku angielskim. Mamy więc bardzo dobry, oficjalny podręcznik CVS (uwaga ponad 800KB), książke kucharską CVS (uwaga ponad 600KB) - jest także opis po polsku - stworzony przez developerów PLD, a także książka z cyklu leksykon kieszonkowy "CVS" Gregor N. Purdy (koszt ok. 10PLN) - tak więc jest w czym wybierać.

Jeszcze raz zwróćmy uwagę na maila którego otrzymaliśmy. Jest tam coś o dopisaniu "users". Musimy wykonać zalecenie. Aby to zrobić musimy znowu przygotować sobie środowisko CVS - albo modyfikując istniejące, dotychczasowe konto "anonymous" albo tworząc od początku środowsko w nowym katalogu. Ja wybrałem pierwszy sposób (troche wbrew zaleceniom z dokumentacji - ale za to szybszy), polega on na modyfikacji każdego pliku "Root" w podkatalogach "CVS" - należy tam wpisać fraze:

:pserver:<nasz_login>@cvs.pld-linux.org:/cvsroot

Czyli w naszym przypadku wchodzimy do katalogu ./rpm i wchodzimy do każdego podkatalogu "CVS" i zmieniamy ręcznie plik "Root" - nie ma w tej chwili tych katalogów wiele, więc nie powinno to sprawić kłopotu.
Proponuje także poustawiać sobie zmienne CVS np. CVSEDITOR itp. (szczegóły - oczywiście dokumentacja).

Następnie możemy już spróbować zalogować się do CVS PLD:

[marekc@ciesiel1 rpm]$ cvs login
Logging in to :pserver:<nasz_login>@cvs.pld-linux.org:2401/cvsroot
CVS password:
[marekc@ciesiel1 rpm]$

Wpisujemy hasło które wymyśleliśmy i jesteśmy zalogowani. Każdy komunikat błędu oznacza że coś wcześniej źle wykonaliśmy, albo że np. nie działa sieć. Login wykonujemy praktycznie raz i dopóki nie wykonamy polecenia "cvs logout" jesteśmy ciągle gotowi do pracy.

Czas już zabrać się za plik "users"

[marekc@ciesiel1 rpm]$ cvs get CVSROOT/users
U CVSROOT/users

[marekc@ciesiel1 rpm]$

Do naszego lokalnego repozytorium, do katalogu CVSROOT ściągneliśmy plik users, który służy w PLD do wpisania aliasu pocztowego - przy okazji możemy zobaczyć w jakim towarzystwie przyjdzie nam pracować :)

nasz_login:użytkownik_mail@domena_naszego_email:Imie i Nazwisko

Edytujemy odpowiednio więc plik user - wystarczy tylko drobna znajomość alfabetu i robimy nasz pierwszy commit - czyli potwierdzamy zmiany.

[marekc@ciesiel1 rpm]$cvs ci CVSROOT/users // po tym poleceniu edytujemy log
Checking in CVSROOT/users;
/cvsroot/CVSROOT/users,v <-- users
new revision: 1.40; previous revision: 1.39
done
cvs server: Rebuilding administrative file database
Mailing the commit message

[marekc@ciesiel1 rpm]$

Po wydaniu polecenia cvs ci CVSROOT/users otworzy się nasz ulubiony edytor i pojawi się coś podobnego do:

- added nasz_login // tu wpisujemy komentarz z kreseczką i po angielsku!!!
CVS: ---------------------------------------------------------------------
CVS: Enter Log. Lines beginning with `CVS:` are removed automatically
CVS:
CVS: Committing in .
CVS:
CVS: Updated Files:
CVS: CVSROOT/users
CVS: ---------------------------------------------------------------------

Właśnie dokonaliśmy pierwszej zmiany w repozytorium PLD. Od tej chwili każdy mail adresowany na <nasz_login>@pld-linux.org trafi na naszą skrzynkę pocztową.

Dalsza część naszych rozważań będzie już w formie konkretnych przykładów, ponieważ to co chcemy zrobić w repozytorium CVS PLD zależy od konkretnych potrzeb. Od tej chwili nikt już nas za rączke nie będzie prowadził, a czekają nas pot, krew, łzy i pierwsze "recenzje" naszych poczynań - np. na grupie PLD-devel czy kanale #PLD - a jedynymi nagrodami będzie brak tych recenzji, zdobyta wiedza, satysfakcja i działające paczki, których przez chwilę nikt na świecie nie będzie miał :)

Dodawanie plików do CVS PLD

Każdy nowy plik, który chcemy umieścić w repozytorium należy dodać za pomocą polecenia "cvs add"

[marekc@ciesiel1 SPECS]$ cvs add nasz_nowy_pakiet.spec
cvs server: scheduling file `nasz_nowy_pakiet.spec' for addition
cvs server: use 'cvs commit' to add this file permanently

[marekc@ciesiel1 SPECS]$

Jak widać z komentarza, aby zakończyć dodanie pliku należy zatwierdzić zmianę za pomocą polecenia "cvs ci" (polecenia podaje w formie skróconej) - Samo zatwierdzanie (commit) robiliśmy już wcześniej przy okazji pliku "users".

Aktualizacja plików

Pliki możemy zaktualizować względem CVS - jeżeli nasz plik jest nowszy nie zostanie dokonana żadna zmiana na naszym lokalnym repozytorium. Aktualizacją nie dokonujemy zmian na zdalnym repozytorium.
Jeżeli w danym katalogu mamy już zdefiniowaną kartotekę (czyli mamy już odpowiedni podkatalog CVS) to aktualizacją możemy ściągnąć nowy plik.

[marekc@ciesiel1 SPECS]$ cvs up python.spec
P python.spec

[marekc@ciesiel1 SPECS]$

W powyższym przykładzie dokonaliśmy aktualizacji pliku "python.spec". Literka "P" określa stan aktualizacji. Poniżej przedstawie możlwe kody:

- "A" - Plik dodany. Oznacza że na pliku dokonano operacji "ADD" (czyli dodanie do repozytorium) ale nie wykonano commitu (zatwierdzenia)
- "C" - Plik aktualizowany jest w konflikcie ze zdalnym repozytorium. Czyli np. dokonaliśmy zmian na lokalnym repozytorium i nasz plik jest "nowszy" względem zdalnego repozytorium.
- "M" - Plik został zmodyfikowany w zdalnym repozytorium ale nie było żadnych konfliktów.
- "P" - Plik był "łatany" przez serwer (kod podobny do "U")
- "R" - Plik usunięty ale nie zatwierdzony. Czyli dokonano operacji "cvs remove" ale nie zatwierdzono zmian (poleceniem "cvs ci")
- "U" - Plik został zaktualizowany
- "?" - Plik jest w naszym repozytorium lokalnym ale nie ma go w zdalnym repozytorium CVS

Zatwierdzanie zmian i Distfiles

Sam przykład zatwierdzania zmian mogliśmy poznać wcześniej. Jest to najczęściej wykonywana operacja na CVS.
Jednak chciałbym zwrócić uwagę na inny sposób składowania źródeł natywnych. W pewnym momencie okazuje się, że składowanie wszystkich plików w repozytorium CVS jest mało efektywne i powoduje zbyt duże obciążenia serwerów. Dlatego też w PLD zastosowano mechanizm Distfiles którego krótki opis możemy odszukać tu. W wielkim skrócie oznacza to że preparując odpowiednio spec (pamiętacie tajemnicze md5?) i korzystając z odpowiednich opcji programu ./builder możemy sterować ściąganiem plików do distfiles. Tak naprawdę najczęściej wykorzystane są dwie opcje ./builder - "5" i "U". Jest to także powód używania programu ./builder (a nie frazy "rpmbuild -ba"), którego kopie najlepiej ściągnąć z CVS. Pamiętajmy także o tym, że w systemie istnieje inny builder, który jest dostarczany z narzędziami rpm ale oczywiście nie ma on możliwości pracy z distfiles. I jeszcze jedna uwaga: Distfiles jest przeznaczony tylko dla źródeł natywnych - wszelkie patche i nasze pliki dodajemy normalnie do CVS (najczęściej do katalogu SOURCES).

Oto przykłady użycia ./builder z odpowiednimi opcjami:

[marekc@ciesiel1 SPECS]$ ./builder -5 mantis.spec
# $Revision: 1.8 $, $Date: 2004/05/18 15:55:34 $
--20:32:59-- http://dl.sourceforge.net/mantisbt/mantis-0.18.0a4.tar.gz
=> `mantis-0.18.0a4.tar.gz'
Translacja dl.sourceforge.net... zrobiono.
Łączenie się z dl.sourceforge.net[193.1.219.87]:80... połączono się.
Żądanie HTTP wysłano, oczekiwanie na odpowiedź... 200 OK
Długość: 485,797 [application/x-tar]

100%[====================================>] 485,797 17.99K/s ETA 00:00

20:33:25 (17.99 KB/s) - zapisano `mantis-0.18.0a4.tar.gz' [485797/485797]

Updating source-0 md5.
[marekc@ciesiel1 SPECS]$

Opcje "5" i "U" są podobne, z tym że "5" próbuje poprawić md5 korzystając z istniejącego sources w lokalnym repozytorium. Natomiast "U" próbuje zawsze ściągnąć źródła z podanego przez spec URL. Taka jest teoria. Ja praktycznie używam opcji "U" kasując wcześniej źródła z lokalnego repozytorium, ponieważ w innym przypadku wyskakują dziwne błędy o konflikcie z parametrem -nd

[marekc@ciesiel1 SPECS]$ ./builder -U mantis.spec
# $Revision: 1.8 $, $Date: 2004/05/18 15:55:34 $
--20:44:39-- http://dl.sourceforge.net/mantisbt/mantis-0.18.0a4.tar.gz
=> `mantis-0.18.0a4.tar.gz'
Translacja dl.sourceforge.net... zrobiono.
Łączenie się z dl.sourceforge.net[193.190.198.97]:80... połączono się.
Żądanie HTTP wysłano, oczekiwanie na odpowiedź... 200 OK
Długość: 485,797 [application/x-gzip]

100%[====================================>] 485,797 18.80K/s ETA 00:00

20:45:04 (18.80 KB/s) - zapisano `mantis-0.18.0a4.tar.gz' [485797/485797]

Updating source-0 md5.
[marekc@ciesiel1 SPECS]$


Odnogi (Branche) i Etykiety (Tag)

W każdym większym CVSie, projekty główne rozgałęziają się tworząć tzw. branche - W przypadku PLD np. istnieje stabilny, lecz już troche leciwy branch "RA-branch", który wywodzi się z brancha głównego HEAD. W pewnym momencie RA-branch został "zamrożony" i dokonywane są na nim tylko zmiany zawierające poprawki poważnych błędów lub aktualizacje związane z bezpieczeństwem. Branch HEAD "żyje" dalej i są w nim dokonywane zmiany i powstają nowe pakiety. Odgałęzień może być (i jest) wiele, co na początku troche gmatwa spojżenie na CVS ale później doceniamy zalety tego rozwiązania. Dane odnogi mają przydzielone odpowiednie etykiety "lepkie" (ang. sticky tag) - czyli etykieta jest przekazywana każdej następnej wersji w danej odnodze. Zwykłe etykiety (ang. tag) możemy użyć np. do okreslenia indywidualnego stanu danego pliku - określając np. tag STABLE, UNSTABLE lub DEVELOP.
Jeżeli chodzi o etykietowanie to trzeba zachować rozwagę. Musimy być pewni że wiemy co chcemy osiągnąć, bo możemy popsuć prace komuś innemu (dotyczy to także zmian w cudzych specach).

Praktycznie najczęściej wykorzystywane są następujące opcje związane z odnogami i etykietami:

[marekc@ciesiel1 SPECS]$ cvs status -v mldonkey.spec // Statystyka odnóg i etykiet
===================================================================
File: mldonkey.spec Status: Up-to-date

Working revision: 1.14.2.8 // Rewizja (wersja) robocza na lokalnym CVS
Repository revision: 1.14.2.8 /cvsroot/SPECS/mldonkey.spec,v // Rewizja na zdalnym CVS
Sticky Tag: RA-branch (branch: 1.14.2) // Dane dotyczące lepkiej etykiety - związanej z branchem (odnogą)
Sticky Date: (none)
Sticky Options: (none)

Existing Tags: // Istniejące etykiety zwykłe
mldonkey-2_5_3-2 (revision: 1.14.2.7)
STABLE (revision: 1.14.2.7)
mldonkey-2_5-1 (revision: 1.14.2.2)
RA-branch (branch: 1.14.2)

[marekc@ciesiel1 SPECS]$

Sam sposób robienia odnóg pozostawiam innym - lepiej poczytać np. opis CVS PLD bo sam tego jeszcze nie robiłem :). Etykietowanie możemy wykonać np.: mając plik w naszym lokalnym repozytorium wydajemy polecenie:

cvs tag UNSTABLE plik.spec

czyli plik.spec otrzymał etykietę UNSTABLE.

Ostatnim przykładem będzie przenoszenie zmian między odnogami (branchami). Robiąc jakiś spec w głównej odnodze HEAD doszliśmy do wniosku, że zmiany można ogłosić w odnodze RA-branch. Można spróbować wykonać polecenie:

cvs update -r RA-branch -j HEAD mldonkey.init

ale najczęściej różnice między wersjami w odnogach są tak duże, że otrzymamy komunikat o braku automatycznej możliwości przeniesienia zmian. Wtedy można rozwiązać ten problem innym sposobem. Tworzymy np. w podkatalogu "SPECS" katalog "RA-branch" (nazwa katalogu jest nieistotna, ale pomocna). W podkatalogu "RA-branch" wykonujemy:

[marekc@ciesiel1 RA-branch]$ cvs get -A SPECS/plik.spec // parametr "A" usuwa tag
[marekc@ciesiel1 RA-branch]$ cd SPECS
[marekc@ciesiel1 SPECS]$ cvs tag -b RA-branch plik.spec // nowy tag dla odnogi RA-branch
[marekc@ciesiel1 SPECS]$ cp z_HEAD_plik.spec // podmieniamy plik na właściwy z HEAD
[marekc@ciesiel1 SPECS]$ cvs commit -r RA-branch plik.spec // zatwierdzamy zmiany jako RA-branch
[marekc@ciesiel1 SPECS]$

Myślę że komentarze są czytelne. Gdy zrobimy co najmniej jedną taką operację, to istniejący katalog RA-branch może nam służyć do późniejszych operacji kopiowania zmian między odnogami (np. korzystając z opcji "cvs up".
Zdarza się często, że chcemy dać sygnał iż dany pakiet powinien zostać przebudowany przez buildery PLD (czyli takie zdalne komputery-muły robocze, które przygotowują pakiety) - wtedy podczas wpisywania komentarza po wydaniu polecenia "cvs ci" należy napisać np.

- updated to version 2.5.3. Release 1 STBR for RA update general

STBR jest skrótem od "Send To Builder Request"


Zbliżamy się do końca naszego praktycznego poradnika. Nie zostało poruszonych wiele kwestii, które wyjdą w codziennej pracy. Dlatego mamy do pomocy dokumentacje, listy dyskusyjne, IRC, zasoby CVS i przeglądarkę GOOGLE ;). Praca ta miała na celu wprowadzić w świat pracy developerskiej i pokazać praktyczne rozwiązania niektórych problemów - reszta zależy od naszej wiedzy i pracowitości - i pamiętajmy, że najważniejsze to rozwijać swoje zdolności, bo od tego zależy nasza przyszłość i przyszłość projektu dla którego pracujemy :)