Supporto di sincronizzazione

Nuove in Eclipse 3.0 sono le API per la gestione e la visualizzazione dello stato di sincronizzazione tra le risorse dello spazio di lavoro e le risorse presenti in un'altra ubicazione. Si fa riferimento a una risorsa esterna allo spazio di lavoro come a una variante. La sincronizzazione è l'azione di visualizzazione delle modifiche tra le risorse presenti in ubicazioni diverse e, facoltativamente, consente all'utente di influire sullo stato di sincronizzazione eseguendo un'azione. Le API di sincronizzazione sono ortogonali rispetto alle API RepositoryProvider e possono essere utilizzate senza un fornitore di repository. Lo scopo delle API di sincronizzazione è semplificare l'attività di implementazione dei diversi tipi di presentazione dello stato di sincronizzazione delle risorse. Quindi, l'API richiede un mezzo per effettuare query relative allo stato di sincronizzazione delle risorse, ma non richiede mezzi per influire sullo stato. I mezzi per influire sullo stato sono lasciati all'implementatore (nonostante l'UI fornisca gli hook per aggiungere ai menu voci specifiche del fornitore).

Terminologia

Prima di descrivere l'API di sincronizzazione, è utile presentare la terminologia e gli argomenti che vengono applicati quando si illustra la sincronizzazione dello spazio di lavoro.

Variante di una risorsa: una risorsa locale associata a una risorsa presente in un'altra ubicazione può essere definita variante di quella risorsa. Le risorse sono in genere molto simili ma possono differire leggermente (per modifiche alla risorsa locale o per modifiche apportate alla copia remota da altri utenti). Dal punto di vista centrale dello spazio di lavoro, si fa riferimento alla copia locale come alla risorsa e alle copie remote come alle varianti della risorsa.

Sincronizzazione:: la sincronizzazione è l'azione che consente all'utente di visualizzare le differenze tra le varianti della risorsa. La sincronizzazione non influisce sullo stato delle varianti ma fornisce una vista per consentire all'utente di comprendere le differenze tra i vari insiemi di varianti. È procedura comune, tuttavia, consentire agli utenti di influire sugli stati delle varianti (ad esempio, consentendo l'integrazione o l'inversione) durante la sincronizzazione.

Sincronizzazione a due vie e a tre vie: esistono due tipi base di determinazione dello stato di sincronizzazione: a due vie e a tre vie. Un confronto a due viene considera solo la risorsa locale e una singola variante della risorsa, a cui si fa riferimento come alla variante della risorsa remota. Questo tipo di confronto può visualizzare solo le differenze tra le due risorse ma non può offrire suggerimenti sulla correlazione tra le modifiche. Molti sistemi di repository dei codici supportano un confronto a tre vie per la determinazione dello stato di sincronizzazione. Questo tipo di confronto coinvolge la risorsa locale, una variante della risorsa remota e una variante della risorsa di base. La variante della risorsa di base rappresenta un antenato comune per le risorse locale e remota. Ciò consente di indicare la direzione della modifica per gli stati di sincronizzazione più sofisticati.

Tabella 1: gli stati di sincronizzazione

A due vie A tre vie
Modificato
Eliminato
Aggiunto
Modifica in uscita
Modifica in entrata
Eliminazione in uscita
Eliminazione in entrata
Aggiunta in uscita
Aggiunta in entrata
Modifica in conflitto
Eliminazione in conflitto
Aggiunta in conflitto

Nozioni fondamentali - SyncInfo

Le classi di org.eclipse.team.core.synchronize vengono utilizzate per descrivere lo stato di sincronizzazione. La classe più importante è SyncInfo, in quanto rappresenta la classe che effettivamente definisce lo stato di sincronizzazione. Tale classe può essere utilizzata come segue:

SyncInfo info = getSyncInfo(resource); // this is a simulated method of obtaining the sync info for a resource
int changekind = info.getKind();
if(info.getResourceComparator().isThreeWay()) {
if((changeKind & SyncInfo.DIRECTION_MASK) == SyncInfo.INCOMING) {
// do something
}
} else if(changeKind == SyncInfo.CHANGE) {
// do something else
}

La classe SyncInfo fornisce gli algoritmi di confronto a due vie e a tre vie, un client deve fornire le risorse e una classe che possa paragonare le risorse (IResourceVariantComparator). Di seguito viene riportato un comparatore varianti di esempio:

public class TimestampVariantComparator implements IResourceVariantComparator {	
protected boolean compare(IResourceVariant e1, IResourceVariant e2) {
if(e1.isContainer()) {
if(e2.isContainer()) {
return true;
}
return false;
}
if(e1 instanceof MyResourceVariant && e2 instanceof MyResourceVariant) {
MyResourceVariant myE1 = (MyResourceVariant)e1;
MyResourceVariant myE2 = (MyResourceVariant)e2;
return myE1.getTimestamp().equals(myE2.getTimestamp());
}
return false;
}
protected boolean compare(IResource e1, IResourceVariant e2) {

}
public boolean isThreeWay() {
return true;
}
}

SyncInfo info = new SyncInfo(resource, variant1, variant2, new TimestampComparator());
info.init(); // calculate the sync info

Questo pacchetto presenta anche insiemi progettati in modo specifico per contenere la risorsa SyncInfo e i filtri che possono essere applicati alle istanze di SyncInfo.

Gestione dello stato di sincronizzazione

Come illustrato negli esempi precedenti, le classi SyncInfo e IResourceVariantComparator consentono l'accesso allo stato di sincronizzazione delle risorse. Ma non è stato ancora descritto il modo in cui lo stato viene gestito. Un sottoscrittore fornisce l'accesso allo stato di sincronizzazione tra le risorse dello spazio di lavoro locale e un insieme di varianti delle risorse per le risorse che utilizzano un confronto a due vie o a tre vie, a seconda della natura del sottoscrittore. Un sottoscrittore fornisce le seguenti funzionalità:

Le API non definiscono il modo in cui viene creato un sottoscrittore, questa parte viene lasciata alle specifiche implementazioni. Ad esempio, il plugin CVS crea un sottoscrittore quando viene eseguita un'operazione di unione, un altro sottoscrittore per un'operazione di confronto ed un altro sottoscrittore quando si sincronizza lo spazio di lavoro locale con la sezione corrente.

Riesaminando il primo esempio di utilizzo di SyncInfo, è possibile verificare il modo in cui un sottoscrittore può essere utilizzato per accedere a SyncInfo.

// Create a file system subscriber and specify that the
// subscriber will synchronize with the provided file system location
Subscriber subscriber = new FileSystemSubscriber("c:\temp\repo");

// Allow the subscriber to refresh its state
subscriber.refresh(subscriber.roots(), IResource.DEPTH_INFINITE, monitor);

// Collect all the synchronization states and print
IResource[] children = subscriber.roots();
for (int i = 0; i < children.length; i++) {
printSyncState(children[i]);
}

...

void printSyncState(Subscriber subscriber, IResource resource) {
System.out.println(subscriber.getSyncInfo(resource).toString());
IResource[] children = subscriber.members(resource);
for (int i = 0; i < children.length; i++) {
IResource child = children[i];
if(! child.exists()) {
System.out.println(resource.getFullPath() + " doesn't exist in the workspace");
}
printSyncState(subscriber, children[i]);
}
}

Il punto importante da ricordare è che il sottoscrittore individua le risorse che non esistono nello spazio di lavoro e risorse non esistenti possono essere restituite da Subscriber#members() e da SyncInfo#getLocal().

Visualizzazione dello stato di sincronizzazione nell'UI

Viene ora illustrato il modo in cui lo stato viene effettivamente visualizzato dall'utente. ISynchronizeParticipant è il componente dell'interfaccia utente che visualizza lo stato di sincronizzazione e consente all'utente di influire su questo stato. La vista Sincronizzazione mostra i partecipanti alla sincronizzazione, ma è possibile anche visualizzare tali partecipanti nelle finestre di dialogo e nelle procedure guidate. Per fornire il supporto agli utenti in modo che visualizzino qualsiasi tipo di stato di sincronizzazione, anche gli stati non basati su SyncInfo e Subscribers, un partecipante è un componente molto generico.

Per aggiungere una procedura guidata di creazione di una sincronizzazione, è possibile utilizzare anche un punto di estensione denominato org.eclipse.team.ui.synchronizeWizards. Questo punto di estensione inserirà la procedura guidata nell'azione di sincronizzazione globale e nella vista Sincronizzazione, in modo che gli utenti possano creare facilmente una sincronizzazione di questo tipo.

Tuttavia, se si implementa un sottoscrittore, è possibile trarre vantaggio da un partecipante concreto denominato SubscriberParticipant che fornisce la seguente funzionalità:

Il modo migliore per illustrare questi concetti è visualizzarli nella pratica nel contesto di un semplice esempio. Per vedere come questi elementi vengono utilizzati insieme, andare alla sezione sincronizzazione cronologia locale. In alternativa, se si desiderano ulteriori informazioni su come utilizzare le API più avanzate, andare alla sezione Oltre le nozioni fondamentali.