Home
Repository 32bit  Forum
Repository 64bit  Wiki

Modifiche

Breve introduzione a CVS

9 272 byte aggiunti, 17:47, 9 set 2006
nessun oggetto della modifica
# Terminato il lavoro il programmatore (A) aggiorna il progetto contenuto nel server CVS. In questo caso si parla di commit oppure, alternativamente, check in.
# Nel frattempo altri programmatori (B) potrebbero richiedere a CVS le modifiche al progetto non presenti nella loro working copy oppure l’ultima versione disponibile (C). CVS scaricherà o aggiornerà automaticamente (update) i file in questione.<br>
 {| align=center| [[Immagine:cvs.png]]|} 
Nel caso in cui due programmatori modifichino un file nello stesso punto, cioè vengano modificate le stesse linee di codice, CVS se ne accorge e, al tempo del commit o dell’update, notifica il conflitto (conflict). La soluzione
dei conflitti viene comunque lasciata ai programmatori coinvolti. Dando uno sguardo più approfondito si può notare come, vista la necessità di CVS di tenere traccia di tutte le modifiche al progetto fin dal suo inizio, queste vengano salvate internamente come una sequenza di diffs. Grazie a questo accorgimento CVS è in grado di ricostruire ogni versione precedente del progetto applicando a rovescio le modifiche. Sebbene un sistema di gestione delle versioni dia i maggiori vantaggi se usato per lo sviluppo di un progetto da parte di un team composto da numerose persone, ci sono buoni motivi perchè venga utilizzato anche per progetti sviluppati da un singolo programmatore. Oltre alla facilità di applicare o togliere modifiche ad un progetto si può anche citare l’evidente risparmio di spazio su disco. Così facendo infatti non si rende più necessario copiare più volte l’intero progetto per mantenerne diverse versioni. Un sistema di gestione delle revisioni rende inoltre più semplice la creazione di documenti riguardanti lo stato delle modifiche effettuate sul progetto (ad esempio i ChangeLog). Il numero di progetti sviluppati utilizzando CVS è sicuramente molto elevato e, tra di essi, possiamo ricordare a titolo di esempio il server Web Apache, i sistemi operativi FreeBSD, OpenBSD e NetBSD, il desktop manager Gnome e il database PostreSQL.
l’elenco di utenti abilitati (è probabile che ci siano piccole differenze oltre
ovviamente ai nomi degli utenti):
cvs:*:504:slack,anonymous
L’ultimo passo consiste nell’assegnare al repository i permessi corretti in
modo che riflettano questi cambiamenti:
root#cd /usr/local/ root#chgrp -R cvs cvsrepos/ root#chmod -R ug+rwx cvsrepos/
a questo punto tutti gli utenti elencati nel gruppo cvs possono iniziare un nuovo progetto nel nostro repository.
Per permettere l’accesso al repository via rete ad utenti privi di un account locale è necessario configurare il password-authenticating server, il servizio si rende indispensabile nel caso si desideri permettere gli accessi
* cliccate sul menu “Repository” e in seguito sulla voce “Repository”;
* apparirà il box denominato “Configura l’accesso ai repository”;
* cliccate il pulsante “Aggiungi” ed inserite il valore desiderato, nel nostro caso '':pserver:slackcvs:secret@192.168.1.1:/usr/local/cvsrepos/'', come mostrato in Figura 2 {| align=center|[[Immagine:cvs2.png|Figura]]|} 
* quindi “OK” ed ancora “OK”.
Cervisia è in grado di gestire più repository contemporaneamente quindi, se ne abbiamo necessità, possiamo ripetere la procedura precedente il numero di volte desiderato.
 {| align=center|[[Immagine:cvs3.png]]|} 
Ora che il repository è stato identificato dobbiamo scaricare i file del progetto. Questo può sembrare strano visto che abbiamo gli originali ancora sul nostro disco ma, a ben guardare, quella directory non contiene informazioni riguardanti CVS. Andiamo a fare quindi il nostro primo checkout con il quale verrà creata la sandbox:
* selezioniamo la voce “Checkout” dal menu “Repository”;
* indichiamo il repository, il progetto (“Modulo”), la directory di destinazione e diamo l’“OK”.
 {| align=center|[[Immagine:cvs4.png]]|} 
Nel luogo indicato per la creazione della sandbox, CVS creerà gli stessi file e directory che abbiamo importato sul server, con l’aggiunta di un’ulteriore directory CVS in tutta la struttura11. CVS utilizza l’omonima directory
per immagazzinare le informazioni di controllo delle versioni. Nel file CVS/Entries troviamo infatti le informazioni riguardanti ogni singolo file contenuto in quel livello:
D/DirB////
il formato di queste informazioni segue il modello /nome file/numero di revisione/data e ora// per i file (che possono tranquillamente avere numero di revisione differente l’uno dall’altro), le directory invece non hanno numeri di revisione o data e vengono indicate con la lettera “D”. La Figura 5 mostra il risultato delle nostre azioni. Nella parte alta della finestra troviamo le cartelle e i file che compongono il progetto hello_world, nella parte bassa abbiamo l’output del comando di checkout. Accanto adogni file, Cervisia mostra il suo stato (attualmente tutti i file sono in stato "Aggiornato" a causa del checkout), il numero di revisione (tutti i file partono dalla revisione 1.112) e il timestamp con l’indicazione della data.
 {| align=center|[[Immagine:cvs4cvs5.png]]|} 
Applichiamo qualche semplice modifica al file ''HelloWorld.java e DirB/Predi.java''. Notiamo come lo stato dei file rimanga "Aggiornato" anche se noi sappiamo che questo non corrisponde a verità. Come mai? La risposta è semplice: dal momento del checkout CVS non ha più comunicato con il server e quindi non può fare nessuna supposizione sul reale
stato del file (teniamo presente che in un contesto reale, con più programmatori impegnati nello sviluppo, il file sul server potrebbe essere cambiato dopo il nostro checkout). Per forzare CVS a darci lo stato reale dei file
directory principale del progetto. Noteremo lo stato dei due file modificati diventare "Modificato localmente". Se non desideriamo effettuare ulteriori modifiche e giudichiamo soddisfacente il nostro lavoro siamo pronti per
spedire al server la versione aggiornata del progetto. È tempo di fare un commit e, quindi, selezioniamo la directory principale e poi "File &rarr; Fai Commit". Ci verrà presentato un box in cui sono elencati i file che stiamo inviando ed un’apposito campo di testo in cui inserire il commento al commit. Effettuata l’operazione lo stato dei file tornerà ad "Aggiornato" e verrà incrementato di uno il valore della revisione. ''HelloWorld.java e DirB/Predi.java'' adesso saranno in revisione 1.2, tutti gli altri ancora fermi a 1.1. La Figura 6 mostra la situazione dopo un’ulteriore modifica a ''Hello-World.java'' seguita da un update. Un nuovo commit porterà ''Hello-World.java'' alla revisione 1.3 e così via.
 
{| align=center
|[[Immagine:cvs6.png]]
|}
 
=== Aggiungere e rimuovere file o directory ===
Checkout, update e commit sono i tre comandi base per lavorare con CVS. Spesso però capita di dover aggiungere o rimuovere file o directory dal progetto; per questi compiti abbiamo bisogno dei comandi add e remove. Aggiungere o rimuovere un file è un processo che si sviluppa in due passi:
# prima bisogna aggiungere il file alla working copy utilizzando il comando add o remove (in Cervisia bisogna selezionare il file interessato e "File &rarr; Aggiungi al Repository" oppure "File &rarr; Rimuovi dal
Repository");
# in seguito è necessario eseguire un commit per inviare le modifiche al server.
L’aggiunta di una directory invece si esegue in un solo passo (add), con le stesse modalità viste per i file, senza però la necessità del commit. Per la rimozione si consiglia di eliminare prima tutti i file contenuti nella
directory ed in seguito di utilizzare il comando di update con il flag -P attivo.
 
=== Ma c’è di più ===
Nel nostro esempio siamo gli unici sviluppatori a poter effettuare delle modifiche al repository, in una situazione reale invece ci saranno un certo numero di programmatori che, come noi, andranno a modificare alcune parti del progetto. Per tenere traccia di tutte queste modifiche e sincronizzare la nostra working copy con il repository, si utilizza ancora una volta il comando update. In Cervisia si trova nel menu “File” e si chiama ovviamente "Aggiorna".
Nell’eventualità che altri programmatori abbiano modificato alcuni file esattamente negli stessi punti in cui lo abbiamo fatto noi, CVS ci segnala il conflitto e si rifiuta di portare a termine il commit o l’update per quei particolari file. Nel seguente esempio è stato creato volutamente un conflitto per evidenziare come CVS lo segnali all’interno del codice:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Ciao!!!");
<<<<<<< HelloWorld.java
System.out.println("Bonjour!);
=======
System.out.println("Mandi!");
>>>>>>> 1.8
}
}
in questo caso il codice contenuto tra "<<<<<<< HelloWorld.java" e "=======" è quello che abbiamo inserito noi e crea un conflitto con la linea "System.out.println(Mandi!);" presente nella revisione 1.8 del file contenuta nel server. La soluzione dei conflitti è lasciata ai programmatori coinvolti. Spesso è utile conoscere l’altro autore della porzione di codice che crea il conflitto, per fare ciò è sufficente andare a leggere i logs utilizzando il comando "Visualizza &rarr; Sfoglia log". Adesso siamo a conoscenza delle interazioni fondamentali con un server
CVS, nel caso sorgano esigenze più specifiche si rimanda ai manuali in bibliografia.
 
= Lo sviluppo di software =
Adesso che padroneggiamo le basi dello sviluppo di un progetto software con CVS è necessario approfondire alcuni aspetti che sono rilevanti ai fini del rilascio del nostro software al mondo.
 
== Snapshots (Data e Tags) ==
Immaginiamo di aver raggiunto una situazione in cui il nostro software abbia una stabilità tale da diventare una release ufficiale. Generalmente, se non si vuole concedere l’accesso al server CVS, si crea un pacchetto da distribuire e, fatto questo, lo sviluppo prosegue andando ad aggiungere nuove features. A questo punto il progetto contenuto nel repository potrebbe essere profondamente differente dall’ultimo rilascio ufficiale e non necessariamente funzionante. Nel malaugurato caso che venga scoperto un pericoloso bug nell’ultima versione ufficiale, si rende necessaria un’operazione di bugfix. Sorge però un problema e riguarda il fatto che in CVS la versione rilasciata al pubblico non corrisponde più alla versione nel repository. L’unico modo per poter lavorare sui sorgenti con cui è stato creato il pacchetto è di ricordarsi in che revisione erano tutti file al momento del
rilascio, il che non è proprio agevole. CVS ci viene in soccorso fornendoci due metodi per accedere a vecchie
revisioni del progetto. La prima si basa sull’utilizzo della data: molto semplicemente, si richiede a CVS il progetto esattamente come era un particolare giorno del passato:
cvs -q update -D "2005-02-13 23:59:59 GMT"
in questo modo la nostra sandbox conterrà uno snapshot del progetto nello stesso stato in cui si trovava il 13 febbraio 2005. Questa soluzione però ci costringe a ricordarci le date di, almeno, tutti i rilasci effettuati e per questo viene usata solo in casi particolari. Quello che generalmente si desidera fare è di rendere disponibile un
progetto nello stato in cui si trovava al tempo di uno specifico evento (un rilascio pubblico, una versione stabile, . . . ). Per rendere possibile questa astrazione dalla data si utilizza la tecnica del tagging. Un tag è un’etichetta
aggiunta a tutti i file sulla base della working copy di uno sviluppatore:
cvs -q tag Rilascio_2005-02-13
Bisogna notare come ciò non significhi aggiungere un tag a tutti i file con uguale numero di revisione, bensì marcare i file con il più alto numero di revisione disponibile nella working copy associandoli allo stesso tag (la Figura 7 mostra questa situazione). Il tag è applicato immediatamente sia nella working copy che nel repository, non c’è quindi la necessità di effettuare un commit poichè i file coinvolti non vengono modificati ma soltatno le informazioni contenute nei logs. Se nella working copy dello sviluppatore sono presenti delle modifiche ai file, rispetto al repository, queste non verranno prese in considerazione da cvs e il tag interesserà il numero di revisione più alto per quel file al momento presente nel repository. Per questo motivo si tende a sincronizzare la sandbox con il repository prima di applicare un tag.
 
{| align=center
|[[Immagine:cvs7.png]]
|}
 
Per ottenere uno snapshot basato sui tag è sufficiente passare il suo nome a CVS come fosse un numero di revisione:
cvs checkout -r Rilascio_2005-02-13
con questo comando otterremo il checkout dei file associati al tag "Rilascio_2005-02-13", da notare che questo risultato lo si avrà anche anche a distanza di molte modifiche al repository. Sia che si utilizzi il metodo basato sulla data che quello basato sui tag, CVS non ci permette di effettuare commit di versioni modificate del
progetto a partire da uno snapshot. Questo avviene perchè i file sono stati già modificati una volta nel passato e quelle modifiche non possono essere sovrascritte a meno di andare incontro ad un’inconsistenza della history del repository. Nella prossima sezione verrà presentato il modo utilizzato da CVS per aggirare questo limite e permetterci di sistemare il bug nella nostra applicazione.
 
== Branches e sviluppo ad albero ==
Un progetto/modulo in CVS e’ paragonabile ad un albero. La versione iniziale del modulo e’ definita HEAD e forma il tronco (trunk) dell’albero. Proprio come gli alberi anche un modulo CVS puo’ avere dei rami (branches). Il modulo puo’ essere spezzato in piu’ rami, il cui sviluppo puo’ continuare senza intaccare l’HEAD del modulo. Un modulo può avere più di un ramo che poggia sull’HEAD ed è possibile far nascere rami nuovi da quelli gia’ esistenti. Il processo appena descritto prende il nome di Braching e consiste nel duplicare la linea di sviluppo in due rami separati. Una modifica effettuata ad un ramo non influenzerà l’altro. Riprendiamo il nostro esempio. L’ultimo rilascio è stato associato al tag "Rilascio_2005-02-13" e quindi effettuiamo un checkout basato su quel tag per ottenere i sorgenti del progetto su cui lavorare. Affinchè CVS ci permetta di apportare le modifiche necessarie creiamo un branch con il
comando tag -b:
cvs -q tag -b Rilascio_2005-02-13-bugfix-branch
a questo punto è possibile apportare tutte le modifiche necassarie a risolvere il bug ed effettuare il commit che ci permette di tenere traccia del nostro lavoro. Il commit creerà una versione parallela del progetto basata sui sorgenti associati al tag utilizzato (Figura 8). Da questa versione parallela possiamo ricavare una patch da distribuire priva del bug. Nel caso ci rendessimo conto che anche la versione attualmente in sviluppo è soggetta allo stesso bug, CVS ci permette di utilizzare il lavoro fatto sul branch per risolvere la questione. È possibile infatti eseguire un merge dal branch al trunk:
 
{| align=center
|[[Immagine:cvs8.png]]
|}
 
cvs -q update -j Rilascio_2005-02-13-bugfix-branch
attraverso il quale le modifiche effettuate sul branch vengono incorporate nel codice sorgente della revisione attualmente in sviluppo, ovviamente nel caso in cui non si verifichino conflitti.
 
= Riferimenti bibliografici =
[BF] M. Bar, K. Fogel: Open Source Development with CVS, Paraglyph Press, 2003 (http://cvsbook.red-bean.com/)
 
[C] P. Cederqvist et al: Version Management with CVS (for CVS 1.11.18), Free Software Foundation, 2004
(https://www.cvshome.org/docs/manual/)
 
[V] V. Venugopalan: CVS Best Practice, 2002 (http://www.magiccauldron.com /cm/cvs-bestpractices/)
 
[W] C. L. Woelz: Learning CVS Using KDE’s Cervisia, 2004 (http://osnews.com/story.php?news_id=6096&page=1)
[[Utente:Arjuda|Arjuna Del Toso]]
789
contributi