• Non ci sono risultati.

Progettazione, realizzazione e collaudo di un modulo software come estensione dei principali web browser per l'acquisizione, il filtraggio e la trasmissione di dati tra due portali ad accesso autenticato.

N/A
N/A
Protected

Academic year: 2021

Condividi "Progettazione, realizzazione e collaudo di un modulo software come estensione dei principali web browser per l'acquisizione, il filtraggio e la trasmissione di dati tra due portali ad accesso autenticato."

Copied!
111
0
0

Testo completo

(1)

1

Candidato: Alessandro Manetti

Università di Pisa

Scuola di Ingegneria

Corso di laurea in Ingegneria Elettronica

Progettazione, realizzazione e collaudo di un modulo software come estensione dei principali web browser per l'acquisizione, il filtraggio e la trasmissione di dati tra due

portali ad accesso autenticato.

Relatori:

Prof.ssa Gigliola Vaglini Prof. Alessio Vecchio Prof. Mario G. C. A. Cimino

(2)
(3)

3

Introduzione

Con questo elaborato di tesi si è voluto realizzare un servizio informativo integrato via web, che si basa sull'accesso ad una serie di portali fornitori di dati, che richiedono accesso autenticato, secondo un certo workflow flow human-driven descritto in un manuale. Si assume che ciascun portale fornitore non possa disporre di un accesso machine-to-machine (ad esempio attraverso web service API), e che l'accesso ai dati richieda una supervisione/filtraggio dell'utente. In questo contesto, se non aiutato da software opportuni, l'utente è costretto a navigare tramite web browser sui vari portali, secondo il paradigma dello "human glue", raccogliendo i dati in modo esplicito con un grosso carico cognitivo ed una bassa usabilità.

Per rendere il work flow più rapido ed evitare all’utente il recupero “manuale” dei dati, si vuole adottare la tecnologia della estensione del browser, incapsulando la logica di integrazione ed eseguendo il work flow attraverso uno user-agent che mostra all'utente i passi essenziali da svolgere, automatizzando la raccolta dei dati e l'inserimento dei medesimi sul servizio integrato, in modo completamente trasparente ai fornitori di dati e al portale del servizio integrato medesimo.

Le estensioni del browser sono applicativi installati staticamente dentro i browser, e come tali permettono di superare la barriera della "regola della stessa origine", un importante concetto di sicurezza informatica per un ampio gruppo di linguaggi di script lato client, come per esempio JavaScript. La regola permette agli script in esecuzione in pagine che provengono dallo stesso sito di accedere ai reciproci metodi e proprietà senza specifiche restrizioni, impedendo invece l'accesso alla maggior parte dei metodi e delle proprietà tra pagine provenienti da siti diversi. Questo meccanismo è diventato di particolare importanza per le moderne applicazioni web che dipendono in modo esteso dai cookie HTTP per mantenere le sessioni utente autenticate, dal momento che i server agiscono in base alle informazioni dei cookie

(4)

4

per mostrare informazioni riservate o per effettuare azioni di cambio di stato. Una rigorosa separazione tra i contenuti che provengono da siti non correlati tra loro deve essere garantita dal lato client per prevenire la perdita dell'integrità e riservatezza dei dati.

(5)

5

Sommario

Introduzione ... 3

Goal ... 9

Scenario ... 13

Il software impostato come un wizard/help contestuale ... 14

Estensioni dei browser ... 15

Scelta del browser ... 15

Il progetto ... 17

HTML 5, CSS e Javascript: applicazioni sempre più complesse veramente cross platform ... 17

Gli strumenti ... 19

Visual studio o Visual studio code ... 19

Il browser ... 20

Estensioni: Chrome ... 21

Gestione software con versioning in repository Git ... 22

Repository: bitbucket.org ... 24

Git client: GitKraken ... 25

Le repository GIT e gli IDE complessi ... 28

Strumenti standard e tecnologie per la produzione di delle estensioni degli web browser ... 29

Le repository GIT ... 30

Premesse ... 30

Repository ... 30

Contenuto delle repository ... 30

Oggetti Commit ... 31

Intestazioni ... 32

Un semplice Repository ... 33

Riferimento ad un commit specifico ... 35

Fusioni ... 35

Fusioni (Merging) ... 36

(6)

6

Fusioni veloci in avanti (fast forward merge) ... 38

Utilizzi comuni delle fusioni ... 39

Cancellazione di un ramo ... 40

Collaborare ... 41

Sistema di controllo versione distribuito ... 42

Copia della repository ... 42

Ricezione di cambiamenti dal repository remoto ... 45

Invio di cambiamenti al repository remoto (push) ... 46

Invio (push) e fusioni veloci ... 47

Aggiunta e cancellazione di diramazioni remote ... 49

Git con un repository centrale ... 50

Rebasing (e perché evitarlo) ... 50

Rebasing in pratica ... 50

Pratiche di uso comune del rebasing ... 52

Diramazioni (brancing) ... 53

Creazione di una diramazione ... 53

Commutazioni tra diramazioni ... 54

La libreria: jQuery ... 56

Premesse ... 56

jQuery e le sue funzionalità base ... 57

Selettori CSS: elemento ... 57

Selettori CSS: #idelemento ... 58

Selettori CSS: .nomeClasse ... 58

Selettori CSS: elemento[attributo] ... 58

Selettori CSS: elemento[attributo=x] ... 58

Sele ori CSS: elemento[a ributoˆ=x] ... 59

Selettori CSS: elemento[attributo$=x] ... 59

Selettori CSS: elemento[attributo*=x] ... 59

Selettori CSS: padre > figli... 59

Selettori CSS: fratello+sorelle ... 60

Selettori CSS: fratello~sorelle ... 60

Selettori CSS: padri:has(discendenti) ... 61

Selettori di posizione: :first :last ... 61

(7)

7

Selettori di posizione: :even :odd ... 62

Selettori di posizione: :nth-child(n) :nth-child(even|odd) ... 62

Selettori di posizione: :eq(n) :lt(n) :gt(n) ... 62

Selettori custom ... 63

OPERAZIONI SU OGGETTI SELEZIONATI/CREATI ... 63

Navigazione del DOM ... 63

Manipolazione del DOM ... 64

Esempi Manipolazione del DOM ... 64

$(selettore).each() ... 64

Concatenazione operazioni ... 65

Concatenazione Avanzata .end() ... 65

GESTIONE EVENTI ... 66

Associare eventi agli elementi: bind ... 67

Passaggio dati alle funzioni di callback degli eventi ... 68

Lanciare eventi ... 69

Il software ... 70

Panoramica complessiva ... 70

Modellazione con i casi d’uso ... 70

Funzionamento: flusso di lavoro ... 75

Portale Alice ... 75

Portale Laureandosi – Moodle ... 76

Struttura del software ... 79

Prelevare i dati da Alice e inviarli a Laureandosi: form ... 79

Pagina di supporto ... 83

Funzionalità nella pagina di supporto ... 84

Aspetto grafico ... 85

Alfa ... 87

Alfa test... 87

Possibili miglioramenti ... 87

Look and feel ... 88

Modifica tramite css ... 88

(8)

8

Pubblicare estensione Google Chrome ... 89

Pubblicazione nello store ... 90

Trasformare l’estensione per Firefox ... 92

Appendice ... 95

Il codice sviluppato ... 95

File main.js dell’estensione ... 95

Pagina PHP ... 102

File a2m.js ... 103

File a2m.css ... 107

(9)

9

Goal

L'architettura progettata nel presente lavoro di tesi è nata dalla necessità di integrare due portali dell'Università di Pisa: Laureandosi ed Alice. Laureandosi è un servizio per aiutare studenti e Coordinamento Didattico a collaborare in modo efficiente negli ultimi giorni prima della cerimonia laurea. Il servizio importa i dati dal portale web degli studenti (Alice) per calcolare gli indici riguardanti il voto di laurea. Inoltre, Laureandosi permette la gestione dei file delle presentazioni di laurea. Genera anche dei report in formato pdf per le pre-lauree, e in formato ppt per la cerimonia di laurea. Fornisce al Coordinamento Didattico una interfaccia di monitoraggio e notifica. Laureandosi è stato progettato con un approccio per processi, e implementato su piattaforma Moodle, basata su tecnologie PhP/Apache.

Nella versione originale, l'utente doveva accedere al portale Alice, e copiare manualmente i dati sulla propria carriera all'interno del portale Laureandosi, attraverso la compilazione di un form. Lo strumento tipico per inviare informazioni dal client (browser) al server è da sempre il FORM1 html. Nelle versioni successive, si iniziò a pensare a soluzioni per automatizzare tale passaggio di informazioni. In base alle politiche di sicurezza dei browser, le pagine web di Laureandosi, non possono accedere alle pagine web del portale Alice. Si pensò quindi di adoperare la tecnologia delle estensioni del browser, che consiste nell'installare un applicativo (add-on) all'interno del browser, sviluppato attraverso scripting lato client, per estenderne le funzionalità del browser e rendere possibile la comunicazione automatizzata tra i due portali. Uno dei problemi delle estensioni è che diventano rapidamente obsolete in quanto i browser hanno frequenti aggiornamenti. Le versioni iniziali di laureandosi erano quindi poco robuste, poco manutenibili, poco standardizzate, e dopo pochi

1 Il form html (TAG <html>) permette di inviare il contenuto degli oggetti presenti al suo interno (per esempio input

testuli) ad una pagina specifica che è indicata nel suo attributo action. La pagina destinataria di tale form può leggere il contenuto degli oggetti inviati e quindi effettuare elaborazioni lato server.

(10)

10

mesi dal rilascio non potevano essere più installate per incompatibilità. Nella tesi presente l'architettura della estensione Alice2Laureandosi è stata completamente riprogetta, ripensando la logica del flusso dei dati, il formato di interscambio e la memoria di transito sulla base degli ultimi standard del web.

L’idea alla base di questa versione dell’estensione Alice2Moodle è quella di raccogliere le informazioni dal portale Alice e, tramite un form, inviarle ad una pagina “ponte” sul portale Laureandosi. La pagina ponte, aggiunta al portale senza modificare nulla dell’esistente, potrà implementare tutte le funzionalità di pre-elaborazione, riducendo al minimo il codice dell’estensione. Poiché la pagina è sul solito dominio, i dati così modificati si potranno salvare in SESSIONSTORAGE2 e quindi saranno disponibili nella pagina di compilazione della domanda di laurea attraverso gli script dell’estensione stessa.

Attraverso l’utilizzo di linguaggi veramente cross platform quali HTML5, Javascript e CSS, si potrà sviluppare un software utilizzabile in contesti differenti. Si prevede inoltre l’utilizzo di librerie ormai chiaramente facenti parte dello standard web, come jQuery, che permettono di scrivere codice molto più snello ed efficace.

2 Attraverso il localstorage dei browser è possibile salvare del testo. Diventa testo anche un oggetto json dopo che è

(11)

11

Le interazioni fra i vari sistemi, così come brevemente descritto nelle parti precedenti della presente, si possono così rappresentare:

Il servizio integrato, presente a seguito dell’installazione dell’estensione, fornisce il supporto all’utente per seguire un workflow adeguato e automatizzare le operazioni che non hanno bisogno dell’intervento umano per essere portate a termine.

La soluzione architetturale pensate per Laureandosi, può essere generalizzata ed adoperata in tutti i casi in cui bisogna integrare un certo numero di portali attraverso una serie di passi di navigazione (protocollo).

(12)

12

Più in dettaglio si possono evidenziare i passi di navigazione, che componendo il protocollo, permettono di portare a termine l’interazione fra di sistemi:

1) L'utente richiede il servizio integrato

2) Il web browser rimanda allo store di estensioni 3) L'utente scarica l'estensione

4) Installa l’estensione sul proprio browser

5) L’estensione, in base al contesto definito dall’url (5.1: richiesta implicita), fornisce le informazioni di base (5.2). L’utente, attraverso il browser richiede i dati previa autenticazione (5.3) e li importa nella pagina ponte (5.4). In questa pagina i dati vengono memorizzati in sessione (5.5) per renderli disponibili nei passi successivi. 6) I dati sono resi disponibili perché nel passo successivo siano utilizzati.

7) I dati memorizzati nel punto 5.4 vengono ora immessi nel sistema ricevente.

I due passi potrebbero essere considerati come unica interazione, poiché scaricare l’estensione dallo store implica la sua installazione.

(13)

13

Scenario

Lo scenario di questo elaborato di tesi, descritto nelle llinee guida nell’introduzione, descrive lo scambio di informazioni fra sistemi web distinti e contraddistinti da un accesso ad aree riservate con processo di autenticazione. Lo scambio di informazioni ha come scopo quello di recuperare i dati degli esami presenti sul portale Alice (https://www.studenti.unipi.it) dell’Università di Pisa per importarli sul portale Laureandosi (https://laureandosi.ing.unipi.it) della facoltà di Ingegneria.

Le piattaforme che gestiscono dati, generalmente mettono a disposizione API (Application Programming Interface) che permettono a terze parti l’utilizzo controllato delle informazioni. Questa funzionalità non è prevista sul portale Alice, quindi, per reperire le informazioni di interesse, si deve interagire direttamente con le pagine dove le stesse sono presenti.

Il contesto di sviluppo presenta molte limitazioni per quanto riguarda eventuali modifiche dirette, e precisamente:

-) Il portale alice non è modificabile

-) Il portale laureandosi è modificabile solo tramite aggiunte in sezioni/pagine nuove. In un progetto di questo tipo ci si deve adeguare ai limiti più stringenti, per questo l’unica soluzione è un’applicazione “terza”, che recuperi le informazioni da Alice e le riversi in Laureandosi.

Per operazioni di questo tipo, non nuove, si devono utilizzare tecniche di Web Scraping, ovvero script che analizzano il contenuto HTML della pagina e quindi reperiscono le informazioni, strutturandole secondo le specifiche necessità. Per fare questo, la strada scelta è quella di implementare le funzionalità richieste, tramite le

(14)

14

estensioni dei browser che permettono di utilizzare script come fossero presenti nella pagina web, senza modificare nulla lato server.

Le estensioni dei browser possono utilizzare javascript come linguaggio di programmazione e quindi hanno un core facilmente riutilizzabile in tutte le estensioni ormai presenti nei moderni browser. Inoltre tramite CSS e HTML 5 si possono aggiungere aspetti grafici che guidano l’utente verso l’utilizzo.

Il software impostato come un wizard/help

contestuale

Con l’avvento degli Smartphone il mondo del software ha subito un’evoluzione impensabile fino a poco tempo prima. L’utente si è abituato a “navigare” attraverso l’applicazione, senza essere obbligato a leggere nessun manuale tecnico. Le stesse GUI 3 si sono profondamente modificate. Siamo passati da un’interazione attraverso una navigazione con barre dei menu, a quella che avviene attraverso uno scorrimento di “pagine”. Questo comporta una nuova percezione dell’utente che ora si aspetta di interagire con il software appunto navigando e non più ricercando le funzionalità nei menu che aprono finestre dedicate.

Partendo da queste considerazioni abbiamo deciso di modificare completamente il precedente plugin Alice2Moodle. L’idea alla base è che l’unica operazione che esula dal “normale lavoro di utilizzo” sia l’installazione. L’utente (studente) è obbligato, per effettuare le operazioni richieste per conseguire la laurea, ad interagire con due portali. Partendo da questo, il lavoro si è concentrato sul fornire un’interfaccia che, adeguandosi alla pagina corrente del portale e allo stato dei dati presenti, fornisca

3 La GUI ( Graphic User Interface ) è l'interfaccia grafica per l'utente di un software. L'acronimo GUI identifica una

(15)

15

indicazioni tali da permettere di portare a termine le operazioni senza dover consultare nessuna guida. In questo senso, l’applicazione è sia uno wizard4, indica passo passo quello che serve, sia un help contestuale, ad ogni passo ha informazioni specifiche.

Lo strumento scelto per conseguire questo risultato è semplicemente un DIV (elemento HTML) che, iniettato nel DOM della pagina Web, riconosce la pagina corrente e presenta messaggi e funzionalità adeguate alla stessa pagina e allo stato dei dati.

Estensioni dei browser

Un'estensione del browser è un plug-in, che ne estende le funzionalità. Per farlo, richiede l’installazione di un pacchetto software che rispetti alcune specifiche che possono differire a seconda del browser, ma che sono accomunate dalla possibilità di utilizzare tecnologie web come HTML, JavaScript e CSS.

Le estensioni possono cambiare l'interfaccia utente o aggiungere funzionalità anche cambiando il contenuto delle pagine web.

Scelta del browser

Come anticipato, tutti i browser che accettano estensioni permettono di utilizzare HTML, JavaScript e CSS, ma per farlo richiedono di organizzare il software in maniera proprietaria. Per questo motivo la prima cosa da fare è scegliere quali browser supportare, almeno in una prima fase di debug. L’unico metro possibile per una scelta di questo tipo è analizzare le “quote di mercato”.

4 wizard indica una procedura informatica, generalmente inglobata in una applicazione più complessa, che permette

all'utente di eseguire determinate operazioni (solitamente complesse) tramite una serie di passi successivi. Il termine deriva dalla lingua inglese e significa mago, volendo identificare, appunto come per magia, la semplicità dell'esecuzione della procedura altrimenti molto complessa.

(16)

16

Nel proseguo dell’elaborato si vedrà che grazie alla scelta della piattaforma di sviluppo su tecnologie web oriented, le modifiche richieste per sviluppare l’estensione per altri browser sono veramente ridotte.

Analizzando le statistiche di diffusione dei vari browser attraverso il grafico (fonte NetMarketShare) si osserva come Chrome sia in assoluto il browser più utilizzato e in continua crescita.

Altre fonti indicano percentuali ancora più sbilanciate verso Chrome. A prescindere da queste inevitabili oscillazioni (è impensabile che ci possano essere classifiche di utilizzo “certe”) è evidente come per questo motivo Chrome, unito al fatto che sia sicuramente il browser con vocazione “cross platform” per eccellenza, sia stato scelto per sviluppare la prima versione dell’estensione.

(17)

17

Il progetto

Le parti sviluppate per implementare le funzionalità richieste sono due: l’estensione di Chrome e la pagina di supporto per le elaborazioni degli esami prelevati da Alice. Per entrambe è stato usato l’IDE5 Visual Studio 2015. Nelle ultime versioni Microsoft ha rilasciato versioni gratuite che sono più che sufficienti per il codice sviluppato per questo progetto.

HTML 5, CSS e Javascript: applicazioni sempre più complesse

veramente cross platform

La possibilità di scrivere applicazioni che riescano a funzionare su tutti i sistemi operativi è da sempre uno degli obiettivi principali degli sviluppatori. Ci sono stati tentativi importanti, fra i quali sicuramente merita una menzione particolare Java, che permette l’implementazione della multipiattaforma attraverso l’idea della creazione di una “virtual machine” che possa essere installata su diversi OS e quindi interpretare il codice generato. Ci sono stati altri tentativi “classici” di sviluppo di supporto alla multipiattaforma quali per esempio Mono (http://www.mono-project.com/) che merita di essere menzionato perché sulla sua idea è stato creato uno strumento di sviluppo per dispositivi mobili che sta avendo un grande successo commerciale e tecnico (Xamarin: https://www.xamarin.com/).

Lo sviluppo esponenziale del web di questi anni ha imposto il raggiungimento di user experience attraverso l’utilizzo di pagine web sempre più simili e paragonabili ad applicazioni installate. I browser sono diventati il contenitore adatto per implementare logiche complesse, disaccoppiando il front-end dalle tecnologie di back-end (server diversi, linguaggi lato server differenti etc.).

5 Ambiente di sviluppo integrato (Integrated Development Environment ovvero IDE) è un software che permette lo

(18)

18

Dopo una fase in cui la logica si sviluppava in massima parte lato server, ora le moderne web-app sviluppano quasi tutta la logica direttamente lato client, utilizzando la sinergia fra javascript e CSS per creare interfacce ricche e prestazionali. Il lato negativo di questo tipo di sviluppo è che essendo javascript un linguaggio interpretato (così come i vari CSS), la quantità di file inclusi nelle pagine web e utilizzati dai browser per ricreare effetti paragonabili a software tradizionali impone un uso importante delle risorse della macchina. Un esempio per tutti, la suite di prodotti web di Google (https://gogle.drive.com) che fornisce strumenti di office automation (simile alla suite office di Microsoft) completamente basati su piattaforma web. L’utilizzo, se si monitorano le risorse RAM richieste, richiede un uso intenso della macchina.

In verità lo sviluppo di applicazioni basate su strumenti js e css non è ancora completamente maturo. A parte alcune librerie ormai standard, una per tutti jQuery6, ci sono molte librerie che sono nate per risolvere problemi specifici e che ad oggi non sono ancora organizzate in maniera tale da risultare uno standard consolidato (JQuery escluso).

Per contro le grandi case produttrici di software o comunque player importanti del web (Microsoft, Google o Facebook) stanno sempre più convergendo verso piattaforme condivise (Typescript 7 che è supportato da Angular 28) oppure stanno sviluppando framework con l’intento di mettere ordine nello sviluppo di webapp

6 jQuery è una libreria (non un framework!) JavaScript per applicazioni web. Nasce con l'obiettivo di semplificare la

selezione, la manipolazione, la gestione degli eventi e l'animazione di elementi DOM in pagine HTML, nonché implementare funzionalità AJAX.

7 TypeScript è un linguaggio di programmazione libero ed Open source sviluppato da Microsoft. Si tratta di un

Super-set di JavaScript che basa le sue caratteristiche su ECMAScript 6. TypeScript estende la sintassi di JavaScript, in questo modo qualunque programma scritto in JavaScript è anche in grado di funzionare con TypeScript senza nessuna modifica. TypeScript è stato progettato per lo sviluppo di grandi applicazioni ed una volta compilato produce JavaScript. Ricalca in maniera quasi pedissequa la sintassi di C#.

8 Angular2, discendente da Angularjs, è un framework basata su Typescript che permette di sviluppare applicazioni

(19)

19

(React9 di Facebook). Tali framework hanno lo svantaggio di complicare non poco lo sviluppo avendo una curva di apprendimento ben diversa da quella del javascript e dell’uso di librerie.

Un altro limite importante, rispetto allo sviluppo di applicazioni “standard” è la mancanza di strumenti di sviluppo davvero all’altezza.

Gli strumenti

Poiché il codice è semplice si poteva usare uno strumento di sviluppo anche molto più semplice, come un editor di testo evoluto tipo Note++

Visual studio o Visual studio code

Il famoso IDE nella sua versione gratuita (Visual Studio Express ) è l’ambiente di sviluppo usato. Valide alternative, più leggere, possono essere Visual studio code o Atom.

Le principali caratteristiche dell’IDE che sono state utilizzate sono:

Intellisense che permette di avere il completamento automatico del codice evitando fastidiosi errori di sintassi che in javascript, linguaggio che non viene compilato, si manifestano solo a runtime.

9 React è una libreria open source mantenuta da Facebook e sviluppata su javascript. Permette di sviluppare in

maniera organica applicazioni complesse basate sul pattern MVC e implementa la logica delle "single page application".

(20)

20

Tale funzionalità, anche se meno evoluta, è presente anche negli altri ambiente di sviluppo menzionati.

Visione complessiva del progetto grazie alla funzione di Esplora Soluzione

Il browser

Nello sviluppo di applicazioni web uno strumento importante è anche il browser utilizzato per il debug. Sempre Chrome negli ultimi tempi ha soppiantato Firefox per ricchezza di funzionalità nella console degli sviluppatori o per la disponibilità di estensioni per arricchire le funzionalità di debug (per esempio il json visualizer). Anche in questo caso le funzionalità utilizzate fra quelle messe a disposizione degli sviluppatori sono molto modeste, e in particolare la funzione di console.

Attraverso questa parte vengono rilevati eventuali errori e viene evidenziato il contenuto delle console.log(“Messaggio”) che normalmente, inserito in punti di interesse del codice, permette di verificarne specifiche caratteristiche. Questo permette di valutare l’andamento del codice e lo stato delle variabili senza interrompere l’esecuzione con fastidiosi alert. Chrome permette anche di fare un debug “passo passo” molto utile.

(21)

21

Estensioni: Chrome

Google Chrome consente la creazione di estensioni che possono essere applicazioni molto complesse. Per lo scopo di questo elaborato ci limiteremo ad estensioni che modificano il comportamento delle pagine Web, quelli che nel gergo delle applicazioni Chrome vengono detti Content Scripts.

Per realizzare estensioni Content Scripts per Chrome si può utilizzare JavaScript che ci consente di usare tutte le librerie ormai standard delle web application quale per esempio jQuery.

Le estensioni di questo tipo permetteno di utilizzare stili (file css), logica di funzionamento (file js) e pagine popup (html). Il cuore dell’applicazione è il file manifesto (manifest.json) che è un file in formato json che descrive le caratteristiche dell’applicazione, le quali vengono definite come coppie chiave-valore. Le specifiche sono in File manifest (https://developer.chrome.com/extensions/manifest).

Nel dettaglio, almeno della parte di nostro interesse possiamo osservare come Il file manifest descriva l’applicazione:

"name": "…", "version": "…", "description": "…",

Descriva le risorse utilizzate con la loro ubicazione e le pagine in cui l’estensione deve funzionare:

"content_scripts": [

{

"matches": [ "https://xyz/*", "https://zxy/"], "js": [ "path/nomefile.js", " path/nomefile.js "], "css": [ " path/nomefile.css" ]

} ]

Nel file manifest si possono definire molti altri aspetti, rendendo però il lavoro dedicato solo a Chrome, l’unico altro aspetto che si è deciso di gestire è:

(22)

22

"default_icon": "path/icona.png", "default_popup": "path/pagina.html", "default_title": "Titolo"

},

questo aggiunge una finestra richiamabile dall’icona dell’estensione

Gestione software con versioning in repository Git

Git è un DVCS (Distributed Version Control System), cioè sistema software per il controllo di versione distribuito (versioning), realizzato nel 2005 da Linus Torvalds10. Il versioning è un meccanismo attraverso il quale è possibile tenere traccia delle modifiche apportate ad un progetto; quest’ultimo può essere costituito da un singolo file (Word di Microsoft ha un sistema di versioning) o da un insieme di file (progetto software) le cui diverse versioni vengono registrate e possono essere richiamate in un momento successivo ogni volta che se ne presenti la necessità.

La particolarità degli archivi GIT è quella di avere un controllo di versione distribuito. In linea generale le repository sono definibili come degli archivi per la raccolta ordinata dei dati relativi ad un progetto (ad esempio un package software). Un DVCS prevede che il controllo degli ultimi snapshot generati (una sorta di “istantanee” dei file allo stato corrente) venga affidato ai client che eseguiranno delle copie complete dei repository. Il vantaggio di questo meccanismo risulta evidente: poiché il client ha

(23)

23

una copia dei repository si potranno utilizzare per il ripristino anche in assenza di servizi remoti.

La dinamica descritta dalla figura è possibile grazie ad un’apposita funzionalità per la creazione di backup completi, denominata checkout dei repository: essa in pratica consente di generare una copia di un repository locale o di un server remoto tramite un comando per la sua clonazione.

Ogni operazione possibile, quali per esempio clonare una repository, effettuare push o pull, il merge e così via, sono possibili tramite righe di comando da terminale. La scelta fatta per questo lavoro è di utilizzare uno strumento grafico che agevoli le operazioni, abbassando molto la curva di apprendimento.

(24)

24

Repository: bitbucket.org

Nel mercato sono presenti molte repository che permettono un utilizzo gratuito per scopo non commerciale. La più famosa è sicuramente github (https://github.com/) che però non permette di avere repository private. Fra quelle che invece, almeno per una quantità limitata di spazio, permettono la creazione di progetti non condivisi si è scelto di utilizzare bitbucket (https://bitbucket.org/), anche perché si integra perfettamente con lo strumento grafico utilizzato per la gestione.

Per l’utilizzo della piattaforma si è utilizzato il solito account google creato per le estensioni, quindi accedendo al sito e andando a creare un nuovo utente, la situazione che ci viene proposta è:

Una volta effettuati tutti i passaggi richiesti per attivare il nuovo profilo la prima operazione che si deve compiere è creare una repository, semplicemente dandole un nome.

La repository appena creata avrà fra i membri del team di lavoro lo user che l’ha creata, ma potrà anche averne altri già presenti a sistema. Per esempio ho aggiunto il mio profilo personale utilizzando questa funzionalità:

(25)

25

Una volta aggiunto un utente al team si può decidere il suo ruolo. Se non si sceglie di attribuire il ruolo di amministratore si possono decidere le autorizzazioni possibili fra lettura e scrittura.

Fatte queste semplici operazioni nella dashboard si vedono tutte le repository nelle quali l’utente attualmente loggato ha accesso.

Dopo questi semplici passi le interazioni con bitbucket si possono ritenere concluse perché la gestione dei sorgenti avverrà attraverso Gitkraken.

Git client: GitKraken

Gitkraken è un client Git visuale gratuito per l’utilizzo non commerciale. Fra le caratteristiche che lo contraddistinguono, oltre una ricchezza grafica invidiabile, quella che credo sia importante sottolineare è che è un software costruito sfruttando la piattaforma Electron (https://electron.atom.io/). Non è scopo di questa tesi entrare nei dettagli ma sottolineare come, attraverso strumenti e linguaggi normalmente confinati nel web (HTML5, CSS e Javascript) si possano sviluppare applicativi desktop, anche complessi, completamente cross platform, sfruttando il medesimo principio di funzionamento delle app ibride per i dispositivi mobile (Cordova e Phonegap).

Una volta installato GitKraken sulla propria macchina, la situazione che si presenta all’utilizzatore è:

(26)

26

Quindi sono messe in evidenza le principali operazioni per interagire con una repository: Navigarla, clonarla in locale o inizializzarla. Scegliamo di clonare la repository remota (per ora vuota).

Dal menu file andiamo ad aprire la repository locale appena creata:

La inizializziamo e infine troviamo la seguente situazione

(27)

27

Al fine di ottenere una configurazione pronta all’uso:

Dopo che abbiamo copiato nella directory origine di Git i file del progetto e quindi abbiamo effettuato un push da master

Ed effettuato il merge completo da Master a Develop. A questo punto il progetto è pronto per essere gestito completamente via Git. Lo sviluppo avverrà attraverso l’area develop creando nuovi breanch (feature) per sviluppi programmati e invece utilizzando Hotfix per intervenire direttamente sul ramo scelto (develop o master) nel caso in cui sia sorto un problema urgente e fuori dal flusso programmato.

(28)

28

Le repository GIT e gli IDE complessi

Gli ambienti di sviluppo complessi (Integrated Development Environment), quali per esempio Visual Studio, utilizzano per il loro funzionamento molti file di configurazione, una parte dei quali è corretto che non vengano inseriti fra i file da sincronizzare perché relativi all’installazione.

Per gestire la corretta sincronizzazione in questo scenario è possibile inserire nella directory del progetto un file di esclusioni, che appunto si chiama “.gitignore”. La corretta configurazione di tale file è complessa, ma ogni ambiente di sviluppo ha ormai i propri template per le repository di tipo GIT. L’utilizzo del template per Visual Studio, che comprende anche la configurazione corretta di molti scenari con diverse estensioni installate, soddisfa le necessità nella quasi totalità dei casi.

La struttura del template utilizzato è, nei punti essenziali:

# User-specific files *.suo *.user *.userosscache *.sln.docstates # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ [Xx]64/ [Xx]86/ [Bb]uild/ bld/ [Bb]in/ [Oo]bj/

# Visual Studio 2015 cache/options directory .vs/

(29)

29

Strumenti standard e tecnologie per la produzione di

delle estensioni degli web browser

In questa sezione si presentano con più dettagli alcuni degli strumenti/librerie/tecniche utilizzate. Lo scopo non è quello di spiegare in modo esaustivo ogni singolo aspetto, ognuno dei quali meriterebbe una trattazione a sé, ma far vedere come il loro utilizzo nello sviluppo di questa tesi sia frutto di standard ormai consolidati.

Per la trattazione delle funzionalità delle repository GIT si è fatto riferimento ad una breve guida (Understanding Git Conceptually di Charles Duan ref.

http://www.eecs.harvard.edu/~/cduan/techical/git) che ha un’impostazione

rigorosa, ma improntata all’utilizzo dello strumento.

Per la trattazione delle principali funzionalità di jQuery si è fatto riferimento ad alcune dispense del politecnico di Torino (Introduzione a jQuery di Emiliano Castellina) che, seppure non recentissime, introducono a tutte le funzionalità della libreria che sono poi state utilizzate nello sviluppo del codice dell’estensione e della pagina di supporto. Un supporto completo alle API si trova in http://api.jquery.com/

(30)

30

Le repository GIT

Premesse

La gestione del versioning attraverso le repository GIT sta diventanto rapidamente l’approccio più utilizzato. La gesione del versioning, specialemte in ambienti collaborativi articolati e per progetti complessi, è complicata e presuppone una conoscenza dello strumento specialistica. Questa trattazione, attraverso un approccio concettuale, indicherà cosa succede quando si effettuano le operazioni più comuni. L’obiettivo sarà, prima di tutto, spiegare il mondo di Git ed i suoi scopi e, solo in un secondo luogo, illustrare dell'uso dei comandi di Git per la gestione di tale mondo. Si comincerà col descrivere il modello dati di Git, cioè il repository. Da qui si descriveranno le varie operazioni che Git fornisce per l'elaborazione del repository, cominciando dalla più semplice (aggiunta di dati ad un repository) passando progressivamente verso le operazioni più complesse di diramazione (branching) e fusione (merging).

Poi si discuterà dell'uso di Git in un contesto collaborativo.

Infine si analizzerà la funzione di rebase di Git, che fornisce un'alternativa al merging, esponendone i pro e i contro.

Repository

Contenuto delle repository

Lo scopo di Git è la gestione di un progetto, o un insieme di file, che cambiano nel tempo. Git memorizza queste informazioni in una struttura dati chiamata repository. Un repository Git contiene, insieme ad altri, i seguenti elementi:

(31)

31

 un insieme di riferimenti a oggetti commit, chiamati intestazioni (o head). Il repository Git viene memorizzato nella stessa directory del progetto, in una sottodirectory di nome “.git”. Degne di nota sono le differenze con i sistemi di controllo versione a repository centralizzato come CVS o Subversion:

 c'è solo una directory “.git”, nella directory radice del progetto.

 il repository è memorizzato in file a fianco al progetto. Non c'è un repository del server centrale.

Oggetti Commit

Un oggetto commit contiene:

 un insieme di file, che riflette lo stato di un progetto in un dato punto nel tempo.

 uno o più riferimenti agli oggetti commit genitori.

 un nome SHA111, una stringa a 40-caratteri che identifica univocamente l'oggetto commit. Il nome viene creato componendo un hash di aspetti rilevanti del commit, per cui commit identici avranno sempre lo stesso nome.

Gli oggetti commit genitori sono quei commit che sono stati modificati per produrre lo stato successivo del progetto. In generale un oggetto commit avrà un commit genitore, poiché generalmente si prende il progetto in un dato stato, si fanno alcuni cambiamenti, e si salva il nuovo stato del progetto.

Un progetto possiede sempre un oggetto commit senza genitori. Questo è il primo commit eseguito sul repository del progetto.

Per quanto detto è possibile immaginare un repository come un grafo aciclico diretto di oggetti commit, con puntatori ai commit genitori che puntano sempre indietro nel

(32)

32

tempo, fino al primo commit. Partendo da qualsiasi commit, si può camminare lungo l'albero, scorrendo i commit genitori, per vedere la cronistoria dei cambiamenti che portano a quel particolare commit.

L'idea che sta dietro a Git è che il controllo versione consiste nella elaborazione di questo grafo di commit. Ogniqualvolta si voglia eseguire una qualche operazione per interrogare o modificare il repositoryitory, si può pensare l'operazione in questi termini: “in che modo voglio interrogare o modificare il grafo dei commit?”.

In riferimento al grafo, si evidenzia come lo strumento proposto (GitKraken) utilizzi visivamente questo concetto:

Intestazioni

Una intestazione (o head) è semplicemente un riferimento ad un oggetto commit. Ogni intestazione possiede un nome. Come impostazione predefinita, c'è una intestazione in ogni repository chiamata master. Un repository può contenere qualsiasi numero di intestazioni. In ogni istante, c'è una intestazione selezionata come “intestazione corrente”. Questa intestazione ha come alias HEAD, sempre scritto in maiuscolo.

(33)

33

Poiché spesso è fatto rifermento agli “head” e agli “HEAD”, è oppotuno sottolineare come una “head” (minuscolo) si riferisca ad una qualsiasi delle intestazioni con nome presente nel repository, mentre “HEAD” (maiuscolo) si riferisce esclusivamente alla intestazione correntemente attiva.

Un semplice Repository

Per creare un repository, si deve prima creare una directory per il progetto, se questa non esiste già, e quindi selezionarla fra quelle presenti nella propria macchina. Una volta fatto questo si potrà eseguire il comando git init. La directory non deve necessariamente essere vuota.

mkdir [progetto] cd [progetto] git init

Ciò creerà una directory “.git” nella directory [progetto].

Un commit, per essere completato, ha bisogno che vengano fatte due operazioni:

1. Dire a Git quali file includere nel commit, con il comando git add (aggiungi). Se

un file non è cambiato dal commit precedente (il commit “genitore”), Git lo includerà automaticamente nel commit che si sta effettuando. Sarà invece necessario aggiungere solo i file che sono stati aggiunti o modificati. Il comando aggiunge ricorsivamente le directory, per cui git “add” aggiungerà ogni file modificato.

(34)

34

2. Chiamare git commit per creare l'oggetto commit. Il nuovo oggetto commit

avrà HEAD come suo genitore.

Come scorciatoia, git commit con l’opzione –a (git commit –a) aggiungerà automaticamente tutti i file modificati (ma non quelli nuovi).

Se si modifica un file ma non lo si aggiunge, allora Git includerà le versioni precedenti (prima della modifica) al commit.

Nell’ipotesi che si siano creati tre commit in questo modo, il repository avrà questo aspetto: ----> tempo ----> (A) <-- (B) <-- (C) ^ | master ^ | HEAD

dove (A), (B), e (C) sono rispettivamente il primo, secondo e terzo commit. Altri comandi utili a questo punto sono:

• git log che mostra, fra l’altro, il registro di tutti i commit cominciando da HEAD

sino al commit iniziale.

• git status che mostra quali file sono cambiati tra lo stato corrente del progetto

e HEAD. I file vengono divisi in tre categorie: nuovi file che non sono stati aggiunti (con il comando git add), file modificati che non sono stati aggiunti, e file che sono stati aggiunti.

• git diff che mostra le differenze tra HEAD e lo stato corrente del progetto. Con

l'opzione --cached compara i file aggiunti con HEAD, altrimenti compara i file non ancora aggiunti.

(35)

35

• git mv e git rm che marcano rispettivamente i file da spostare (o rinominare) e

da rimuovere, in modo simile a git add.

Pertanto un flusso di lavoro potrebbe essere così indicato:

1. Sviluppo di una parte di progetto.

2. git status per controllare i file modificati.

3. git diff [file] per vedere esattamente che modifiche sono presenti. 4. git commit -a -m [messaggio] per fare il commit.

Riferimento ad un commit specifico

Git prevede diversi metodi per riferirsi a specifici commit. Eccone alcuni:

• Dal nome SHA1, che si può ottenere da git log. • Dai primi caratteri del nome SHA1.

• Per intestazione. Per esempio, HEAD si riferisce all'oggetto commit riferito da

HEAD. Si può usare anche il nome, come per esempio master.

• Relativamente a un commit: ponendo il carattere dell'accento circonflesso (^)

dopo il nome del commit fa in modo di recuperare il genitore di quel commit. Per esempio, HEAD^ è il genitore dell'intestazione del commit corrente.

Nello strumento utilizzato questo equivale e cliccare nel punto di interesse del diagramma

Fusioni

Collaborare nella realizzazione di un progetto significa lavorare su una parte di esso e poi mettere a disposizione le modifiche fatte, ovvero fondere il codice modificato nel progetto.

(36)

36

Fusioni (Merging)

Dopo aver finito di implementare una nuova caratteristica in una diramazione del progetto (branch), normalmente nasce l’esigenza di riporatare tale caratteristica nel ramo principale (main) del progetto stesso, in modo tale che tutti possano usarla o più semplicemente che diventi parte del progetto principale. Ciò può essere eseguito con i comandi git merge o git pull.

La sintassi per tali comandi è la seguente: git merge [intestazione]

git pull [intestazione]

In entrambi i casi il risultato è identico, ma la necessità della versione pull sarà evidente quando si analizzeranno progetti con più sviluppatori che operano sul medesimo progetto.

Chiamando l'intestazione corrente current, e quella da fondere merge. I comandi merge e pull eseguono le seguenti operazioni.

1. Identificare l'antenato comune di current e merge (che chiameremo

commit-antenato).

2. Se antenato è uguale a merge, allora non serve fare nulla. Se

commit-antenato è uguale a current, allora è necessario eseguire un fast forward merge.

3. Determinare i cambiamenti tra commit-antenato e merge. 4. Cercare di fondere tali cambiamenti nei file in current.

5. Se non ci sono conflitti, creare un nuovo commit, con due genitori, current e

merge. Impostare current (e HEAD) in modo da puntare a questo nuovo commit, e aggiornare i file di lavoro del progetto.

(37)

37

6. Se c'era un conflitto occorre inserire gli appropriati marcatori di conflitto e

informare l'utente. Non verrà creato nessun commit.

Può verificarsi che quando si esegue una fusione, se ci sono cambiamenti di cui non sono stati fatti i commit dei file, Git possa confondersi molto. Perciò è preferibile assicurarsi di fare il commit di ogni cambiamento effettuato prima di una fusione. Per portar fuori l'intestazione master nuovamente, finire di scrivere le nuove istruzioni e importare tali cambiamenti che si erano effettuati nelle intestazioni (fix-headers). Il repository avrà questo aspetto:

+--- (D) / | (A) -- (B) -- (C) --- (E) | | fix-headers master | HEAD

dove (E) è il commit che riflette la versione completa con i nuovi dati. Si eseguirà:

git merge fix-headers

Se non ci sono conflitti, il repository ottenuto sarà: +--- (D) ---+ / | \ (A) -- (B) -- (C) --- (E) -- (F) | | fix-headers master | HEAD

Il commit merge è (F), che ha come genitori (D) e (E). Dato che (B) è l'antenato comune tra (D) e (E), i file in (F) dovrebbero contenere i cambiamenti tra (B) e (D), cioè le correzioni delle intestazioni, incorporate nei file da (E).

(38)

38

Nota sulla terminologia: quando si dice “fondere (merge) intestazione A in intestazione B,” si intende che intestazione B è la intestazione corrente, e che sta traendo i cambiamenti dalla intestazione A in essa. Intestazione B viene aggiornata; nulla viene effettuato su intestazione A (se si sostituisce la parola “fusione” con la parola “estrazione” si rende più il senso dell'operazione).

Risoluzione dei conflitti

Un conflitto si verifica se il commit da fondere ha un cambiamento in una determinata posizione e il commit corrente possiede un cambiamento nella stessa posizione. Git non ha modo di sapere quale dei due cambiamenti possa avere la precedenza.

Per risolvere il commit, è necessario modificare i file per armonizzare i cambiamenti in conflitto. Poi eseguire git add per aggiungere i file alla soluzione, ed eseguire git commit per fare il commit a seguito della fusione corretta. Git è in grado di ricordare di essere stato interrotto in mezzo ad una fusione, perciò imposta correttamente i genitori del commit.

Fusioni veloci in avanti (fast forward merge)

Una fusione veloce in avanti è una semplice ottimizzazione per la fusione. Mettiamo che il repository appaia nel modo seguente:

+-- (D) -- (E) / | (A) -- (B) -- (C) | | | corrente da-fondere | HEAD

e si esegua git merge da-fondere. In questo caso, tutto ciò che Git necessita di fare è di impostare corrente in modo da farlo puntare ad (E). Dato che (C) è il parente comune, non ci sono cambiamenti da “fondere”.

(39)

39

Da cui si deriva che il repository fuso ottenuto appaia in questo modo: +-- (D) -- (E) / | (A) -- (B) -- (C) | | da-fondere, corrente | HEAD

Cioè, da-fondere e corrente puntano entrambi al commit (E), e HEAD punta ancora a corrente.

Si osservi che non viene creato nessun nuovo oggetto commit per la fusione. Git sposta solo i puntatori delle intestazioni.

Utilizzi comuni delle fusioni

Le più frequenti ragioni per fondere due “diramazioni” (branch) dello sviluppo sono essenzialmente due. La prima, come detto poc'anzi, è per estrarre i cambiamenti da una diramazione, creata per esempio per sviluppare e testare delle nuove caratteristiche, e trasportarli nel ramo principale. Il secondo uso è per trasportare il ramo principale nel ramo di test che si sta sviluppando. Ciò mantiene il ramo di test aggiornato con gli ultimi aggiornamenti di riparazione bug e di aggiunta di nuove caratteristiche, aggiunti al ramo principale. Facendo ciò con cadenza regolare, si riduce il rischio di creare un conflitto, che solitamente emerge quando si voglia poi fondere le nuove caratteristiche in test, dentro il ramo principale.

Uno svantaggio di queste procedure è che il ramo di test finirà con l'avere molti commit di fusione. Una soluzione alternativa di questo problema è il rebasing12, malgrado a sua volta non sia scevro da altri problemi.

(40)

40

Cancellazione di un ramo

Dopo aver fuso un ramo di sviluppo nel ramo principale, probabilmente il ramo di sviluppo non servirà più. Di conseguenza si potrà cancellare così da evitare di affollare inutilmente il listato generato dal comando git branch.

Per cancellare un ramo occorre usare il comando git branch -d [intestazione]. Ciò rimuoverà semplicemente l'intestazione specificata dall'elenco delle intestazioni del repository.

Per esempio, nel repository preso dall'esempio precedente:

+--- (D) ---+ / | \ (A) -- (B) -- (C) --- (E) -- (F) | | fix-headers master | HEAD

è probabile che non servano più le intestazioni fix-headers. Perciò possiamo usare: git branch -d fix-headers

ed il repository risultante sarà: +--- (D) ---+ / \

(A) -- (B) -- (C) --- (E) -- (F) | master |

(41)

41

Nota importante: git branch -d causerà una segnalazione di errore se il ramo da cancellare non è raggiungibile da un'altra intestazione.

Consideriamo il repository seguente: +--- (E)

/ |

(A) -- (B) -- (C) | | | head1 head2

Supponiamo che si decida di cancellare head2. Ora, è possibile usare il commit (E)? Non è possibile farne il check out, dato che non è un'intestazione. Lo step E non appare né nei log, né in qualsiasi altra parte, dato che non è un antenato di head1. Per cui il commit (E) è praticamente inutile. Nella terminologia Git, è un “dangling commit” (commit pendente) e le sue informazioni sono perse.

Git permette di usare l'opzione -D per forzare la cancellazione di un ramo che crei un commit pendente. Comunque, dovrebbero essere rare le situazioni in cui si debba effettuare quest'operazione.

Collaborare

Una caratteristica chiave di Git è che il repository è memorizzato a fianco alle copie di lavoro dei file sotto controllo di versione (la directory “.git” creata con il comando init). Il vantaggio di ciò consiste nel fatto che il repository memorizza l'intera cronologia del progetto, e che Git può funzionare senza bisogno di collegarsi ad un server esterno.

Questo implica anche che, se si vuole gestire il repository, è necessario avere l'accesso ai file di lavoro. Di conseguenza, due sviluppatori che usano Git non possono, come impostazione predefinita, condividere lo stesso repository.

Per condividere il lavoro tra più sviluppatori, Git usa un modello distribuito di controllo versione. Esso assume che non ci sia un repository centrale. È possibile,

(42)

42

naturalmente, usare un repository come “centrale”, ma è necessario comprendere il modello distribuito su cui è basato.

Sistema di controllo versione distribuito

Nel caso in cui si voglia lavorare assieme ad uno stesso progetto e qualcuno del team abbia già effettuato del lavoro su di esso, ci sono tre aspetti che devono essere considerati affinché ciò sia possibile:

1. Come ottenere dal membro del team una copia aggiornata del lavoro.

2. Come inserire i cambiamenti effettuati dal membro del team nel proprio

repository.

3. Come aggiornare il membro del team sui propri cambiamenti effettuati.

Git è fornito di un insieme di protocolli di trasporto per la condivisione delle informazioni sul repository, come SSH e HTTP. Il metodo più semplice (che si può usare come test) è comunque accedere simultaneamente ad entrambi i repository dallo stesso filesystem.

Ogni protocollo viene identificato da una “specifica-remota”. Per i repository presenti sullo stesso filesystem, la specifica-remota è semplicemente il percorso necessario per raggiungere l'altro repository.

Copia della repository

Per fare una copia del repository e renderla disponibile per sviluppare il proprio lavoro, occorre usare il comando git clone [specifica-remota].

(43)

43

La [specifica-remota] identifica la posizione del repository del membro del team, che può anche semplicemente essere un'altra cartella nel filesystem. Qualora il repository fosse accessibile tramite un protocollo di rete come ssh, Git si riferisce ad esso tramite un nome stile URL, come il seguente: ssh://server/repository.

Per esempio, se il repository è posizionato in ~/jdoe/project, il comando sarà: git clone ~/jdoe/project

Ciò effettuerà le operazioni seguenti:

• Creazione di una directory project e inizializzazione di un repository in essa. • Copia di tutti gli oggetti commit e riferimenti alle intestazioni prelevandoli dal

progetto al nuovo repository locale.

• Aggiunta di un riferimento a repository remoto di nome origin nel nuovo

repository, e associazione di origin con ~/jdoe/project come descritto sotto (analogamente a master, origin è il nome predefinito usato da Git).

• Aggiunta di intestazioni remote di nome origin/[nome-intestazione] che

corrispondono alle intestazioni nel repository remoto.

• Impostazione di una intestazione nel repository per tenere traccia della

corrispondente intestazione origin/[nome-intestazione-corrente], cioè quella che era attualmente attiva nel repository clonato.

Un riferimento repository remoto è il nome che Git usa per riferirsi al repository remoto (generalmente esso sarà origin). Tra l'altro, Git associa internamente la specifica-remota con il riferimento repository remoto, in modo tale da non aver mai bisogno di riferirsi nuovamente al repository originale.

Una diramazione che traccia una diramazione remota, mantiene un riferimento interno alla diramazione remota.

(44)

44

Da notare è che così si possiede una copia completa dell'intero repository del team. Quando si dirama, commit, fonde, o si opera in altro modo sul repository, si opera solo sul proprio repository. Git interagisce con il repository remoto solamente quando glielo si chiede esplicitamente (push).

Poniamo che il repository del team abbia la seguente struttura: +---(E) / | (A) -- (B) -- (C) -- (D) | | | master feature | HEAD

Dopo la clonazione, il nostro repository apparirà in questo modo: +--- (E)

/ |

(A) -- (B) -- (C) -- (D) | | |

origin/master, master origin/feature |

HEAD

Se si desidera lavorare con la diramazione origin/feature remota localmente, si deve impostare manualmente una diramazione tracciante. Ciò lo si effettua tramite il comando seguente:

git branch --track [nuova-diramazione-locale] [diramazione-remota]

L’esempio riportato, quel comando sarà git branch --track feature origin/feature. Si noti che l'opzione --track è abilitata in modo predefinito e perciò è ridondante.

(45)

45

Ricezione di cambiamenti dal repository remoto

Dopo aver clonato il repository, un membro del team aggiunge dei commit al proprio repository. Un altro membro del team come può ottenere le copie di questi cambiamenti?

Il comando git fetch [riferimento-repository-remoto] recupera i nuovi oggetti commit del repository e crea e/o aggiorna le intestazioni remote di conseguenza. Come impostazione predefinita, il [riferimento-repository-remoto] è origin.

Poniamo che ora il repository del team appaia in questo modo:

+--- (E) -- (F) -- (G) / | (A) -- (B) -- (C) -- (D) -- (H) | | | master feature | HEAD

Dopo il comando git fetch, il proprio repository dovrebbe apparire nel modo seguente:

+--- (E) --- (F) ---- (G) / | |

(A) -- (B) -- (C) -- (D) --- (H) | | | | | master feature origin/master origin/feature

| HEAD

Si noti che le proprie intestazioni non sono state modificate. L'unica differenza è che le intestazioni remote, quelle che cominciano con “origin/”, sono state aggiornate insieme all'aggiunta dei nuovi oggetti commit.

(46)

46

Ora, per aggiornare le proprie intestazioni master e feature per riflettere i cambiamenti apportati, si utilizza fa una fusione, di solito materialmente con un comando git pull. La sintassi generica è:

git pull [riferimento-repository-remoto] [nome-intestazione-remota]

Ciò fonderà l'intestazione di nome [riferimento-repository-remoto]/[nome-intestazione-remota] in HEAD.

Git possiede due caratteristiche che rendono l'operazione più semplice. La prima consiste nel fatto che, se una intestazione viene impostata tracciante, un semplice git pull senza argomenti fonderà la corretta intestazione remota. La seconda è che git pull eseguirà automaticamente un fetch.

Perciò, nell'esempio sopra, effettuato un git pull sul proprio repository, la propria intestazione master verrà spostata in avanti al commit (H):

+--- (E) --- (F) --- (G) / | |

(A) -- (B) -- (C) -- (D) --- (H) | | |

| feature origin/master, origin/feature master |

HEAD

Invio di cambiamenti al repository remoto (push)

Ponendo che si voglia modificare il proprio repository, si vorrà successivamente spedire questi cambiamenti nelle varie repository del team.

Il comando git push, che esegue ovviamente l'operazione opposta di pull, spedisce i dati al servente remoto. La sua sintassi completa è la seguente:

(47)

47

Quando il comando viene invocato, Git richiede che il repository remoto faccia le operazioni seguenti:

• Aggiunta di nuovi oggetti commit spediti dal repository inviato.

• Impostazione di [nome-intestazione-remota] in maniera da puntare allo stesso commit che punta sul repository inviante.

Sul repository inviante, Git aggiorna anche il riferimento alla corrispondente intestazione remota.

Se non vengono aggiunti argomenti al comando git push, esso invierà tutte le diramazioni nel repository impostate come traccianti.

Invio (push) e fusioni veloci

Git richiede che l'invio (push) provochi una fusione veloce in avanti nel repository remoto. Per questo motivo, prima della fusione, l'intestazione remota deve puntare ad un antenato del commit a cui dovrà puntare dopo la fusione.

La ragione di questo è che ogni diramazione dovrebbe contenere una versione incrementalmente migliorata del progetto. Una fusione veloce in avanti indica sempre un semplice miglioramento su una diramazione, dato che l'intestazione viene solo spostata in avanti e non ricollegata in un punto differente nell'albero. Se l'intestazione si sposta in un punto differente nell'albero, allora l'informazione su come la diramazione è arrivata al suo stato più recente è persa.

Per esempio, immaginiamo che il repository remoto assomigli al seguente: (A) -- (B) -- (C) |

master

(48)

48

+--- (D) / |

(A) -- (B) -- (C) | | | other master

Ora, se si invia master al repository remoto, esso prenderà la seguente forma: +--- (D)

/ |

(A) -- (B) -- (C) | | master

Ora (C) è un commit pendente. Inoltre, la diramazione master ha perso ogni ricordo del fatto che essa puntava a (C). Perciò, (C) non fa più parte della cronistoria di master. Può succedere che si provi a ricevere i cambiamenti con pull dal repository remoto senza ottenere come risultato una fusione veloce in avanti. Questo può accadere, ad esempio, quando si effettuano dei cambiamenti su una diramazione nel repository locale e vengano effettuati dei cambiamenti anche nella diramazione del repository remoto. Consideriamo la seguente situazione:

+-- (D) / |

(A) -- (B) -- (C) (A) -- (B) | | | master master

Repository locale Repository remoto

Questa situazione può emergere se, per esempio, si è prelevato per ultimo dal repository quando master era al commit (B), si è fatto del lavoro ed avanzato master al commit (C), e un altro sviluppatore, lavorando sul repository remoto, effettua del lavoro differente per avanzare master a (D).

Prelevando master dal repository remoto Git fonde i due cambiamenti in un nuovo commit, e sposta master ad un nuovo commit di fusione.

(49)

49

+--- (D) ---+ / \

(A) -- (B) -- (C) -- (E) | master

In alternativa, si può usare il rebasing, come spiegato successivamente, per riscrivere il nostro commit (C). Comunque, il miglior approccio è di evitare del tutto il problema lavorando su diramazioni separate finché non si è pronti a “mettere in pruduzione” le proprie modifiche, effettuare un pull sulla propria diramazione (branch) e quindi, risolti i conflitti, effettuare un commit e un push.

Aggiunta e cancellazione di diramazioni remote

Si può creare una nuova diramazione nel repository remoto partendo dalla propria copia locale, aggiungendo così una nuova diramazione remota che utilizza, nei puntamenti, la propria intestazione corrente. Consideriamo il riferimento al repository remoto origin, e il nome della diramazione attuale nuova-diramazione. I comandi da eseguire sono:

git push origin nuova-diramazione git checkout [qualche-altra-diramazione]

git branch -f nuova-diramazione origin/nuova-diramazione git checkout nuova-diramazione

Il primo comando creerà innanzitutto l'intestazione appropriata nel repository remoto e poi spedirà fuori (push) il nuovo commit della diramazione. I restanti tre vengono usati per ricreare la nuova diramazione utile a tenere traccia della diramazione remota.

Per cancellare una diramazione nel repository remoto, usare il seguente comando: git push [riferimento-repository-remoto]:[nome-intestazione]

(50)

50

si noti che mettere un segno di duepunti (“:”) prima del nome dell'intestazione, significa spedire (push) “nessun dato” in quell'intestazione nel repository remoto. Per elencare le diramazioni remote disponibili occorre usare git branch -r.

La possibilità di creare diramazioni sulla repository remota si riporta per completezza. Nel lavoro abituale, è buona prassi tenere la repository centrallizzata priva di branch, che per definizione sono lavori eseguiti su particolari esigenze e da un particolare membro del team.

Git con un repository centrale

Chiarito come Git trasmette le informazioni tra repository usando push e pull, allora l'impostazione di un repository centrale per un progetto è semplice. Gli sviluppatori fanno semplicemente il proprio lavoro eseguendo push e pull verso il repository centrale.

Alla creazione del repository centrale, si può usare un repository “bare”. Esso consiste in un repository che non contiene file di lavoro, ma solo informazioni del repository. Ciò è utile dato che un repository centrale non deve essere modificato direttamente ma solo attraverso comandi push e pull.

Rebasing (e perché evitarlo)

Il rebasing, come accennato in precedenza, è un’alternativa al merging

Rebasing in pratica

Git offre una caratteristica unica, chiamata rebasing, come alternativa alla fusione (merging). La sua sintassi è la seguente:

git rebase [nuovo-commit]

(51)

51

• Identifica ogni commit antenato del commit corrente ma non del

[nuovo-commit]. Ciò può essere pensato come un processo a due passi: nel primo, trova l'antenato comune del [nuovocommit] e del commit corrente; chiamiamolo commit antenato. Nel secondo, raccoglie tutti i commit tra il commit antenato e il commit corrente.

• Determina cos'è cambiato per ognuno di questi commit, e mette da parte

questi cambiamenti.

• Imposta l'intestazione corrente in modo da puntare al [nuovo-commit].

• Per ogni cambiamento messo da parte, riapplica tale cambiamento

nell'intestazione corrente e crea un nuovo commit.

Il risultato è che HEAD, il commit corrente, è un discendente di [nuovo-commit], ma contiene tutti i cambiamenti come se fossero stati fusi con [nuovo-commit].

Per esempio, immaginiamo che un repository assomigli a questo: +--- (D) / | (A) -- (B) -- (C) | | | master nuova-diramazione | HEAD

Eseguendo git rebase master produrrà la situazione seguente: +--- (E) / | (A) -- (B) -- (C) | | | master nuova-diramazione | HEAD

dove (E) è un nuovo commit che incorpora i cambiamenti tra (B) e (D), ma riorganizzati per porre tali cambiamenti su (C).

(52)

52

Rebase ha il vantaggio che non c'è la creazione di un commit di fusione. Per contro, dato che HEAD non è un discendente del commit HEAD pre-rebase, il rebasing può essere problematico, principalmente perché una intestazione su cui è stato fatto un rebase non può essere inviata (tramite push) ad un server remoto, dato che essa non è il risultato di una fusione veloce in avanti. Inoltre, esso provoca una perdita di informazioni: non si può più sapere che (D) era una volta sull'intestazione nuova-diramazione. Ciò conduce ad un “cambiamento di cronistoria” che può confondere chi era già a conoscenza del commit (D).

Pratiche di uso comune del rebasing

A causa della sovramenzionata pericolosità del rebasing, conviene riservarne l'uso per le seguenti due situazioni:

la prima di queste è quando si sta sviluppando una diramazione per proprio conto non condividendola con nessuno; la si può elaborare con rebase per

mantenere la diramazione aggiornata rispetto al ramo principale. Poi, quando alla fine si fonde il proprio ramo di sviluppo nel ramo principale, esso sarà libero da commit di fusione, dato che apparirà come se il ramo di sviluppo fosse un

discendente del ramo principale. Inoltre, il ramo principale può spostarsi in avanti con una fusione veloce in avanti, invece che tramite un commit di una fusione normale.

la seconda è quando si esegue un commit di un ramo che cambia

contemporaneamente anche in una macchina remota. Si può usare rebase per spostare i propri commit, permettendo di spedire (push) i propri commit nel repository remoto. Dall'esempio di cui sopra:

(53)

53

+-- (D) / |

(A) -- (B) -- (C) (A) -- (B) | | | master master Repository

locale Repository remoto

Se si esegue un prelievo tramite fetch, il proprio repository somiglierà al seguente: +--- (D)

/ |

(A) -- (B) -- (C) | | | master origin/master

Ora, assumendo che master sia la propria intestazione corrente, se si esegue: git rebase origin/master, Il proprio repository assomiglierà a:

+--- (D) ---+ / | \

(A) -- (B) | (E) | | origin/master master

Commit (E) contiene i cambiamenti effettuati tra commit (B) e (C), ma ora commit (E) è un discendente di (D). Ciò permette di spedire (push) la propria intestazione master, come fusione veloce in avanti, per aggiornare origin/master.

Diramazioni (brancing)

Una diramazione (brach) è uno sviluppo parallelo al progetto principale (per esempio su una singola feature del software) che, terminata, verrà fusa nel progetto principale.

Creazione di una diramazione

Per creare una diramazione, poniamo ad esempio che il nostro repository somigli al seguente:

(A) -- (B) -- (C) | master |

Riferimenti

Documenti correlati

Determinare la tensione del cavo se il corpo ruota intorno al punto P compiendo 1 giro al secondo.. Esprimere il risultato in newton (

L’energia meccanica totale del punto si conserva durante il moto poiché gli attriti sono trascurabili. Determinare la reazione vincolare del piano

Durante i test della funzionalità di inserimento dei dati dei clienti è risultato che il tempo impiegato per la geocodifica era elevato: in effetti è stato utilizzato un semplice

Come ultima cosa inserire il blocco Wait(ms) situato nella palette Functions alla voce Programming  Timing e collegarlo a una costante con valore 100 cliccando il tasto destro.

L’algoritmo è iterativo: una volta verificate le soglie per tutti i punti (eccetto i seed points) e individuati quelli appartenenti al terreno, viene costruito

Uno dei problemi ancora aperti nell’elaborazione dei dati LIDAR è quello del filtraggio della nuvola di punti risultato della misura, al fine di separare punti appartenenti al

VISTO il decreto legislativo n. a) in base al quale AgID svolge, tra le altre, le funzioni di: “Emanazione di linee guida contenenti regole, standard e guide tecniche, nonché di

In assenza di tali analisi, per la definizione dell’azione sismica si può fare riferimento ad un approccio dell’azione semplificato, che si basa sull’individuazione di categorie