gitWeb – branching cz.1

W dzisiejszym wpisie opiszę jak zrealizowałem branchowanie w mojej aplikacji.

Na powyższym  gifie widzimy wszystkie funkcjonalności, które udało mi się do tej pory zrealizować. A są to:

  • Lista branchy
  • Stworzenie nowego brancha
  • Przełączenie się na inny branch
  • Pobranie drzewa comitów dla aktualnego brancha
  • Opisanie na drzewie commitów branchy

W tym wpisie opiszę kompletną ścieżkę implementacji od frontendu do wywołania biblioteki libgit2sharp. Podzielę to na 3 sekcje:

  • komenda jaką należy wykonać w konsoli gita
  • moduł VueJs
  • API wraz z implementacją libgit2sharp.

Jako, że każdy z elementów jest obszerny dzisiaj skupie się jedynie na opisie listy branchy i sposobie w jaki udało mi się zaimplementować dodanie nowego brancha.

Lista branchy

Za pomocą tej komendy w konsoli pokażą się wszystkie branche w repozytorium. Zarówno te lokalne jak i „śledzące” zdalne. Dodatkowo dostajemy informację na którym branchu obecnie się znajdujemy.

Komponent VueJs

Lista zaimplementowana została w komponencie o nazwie branch.vue. Nie chcę wklejać tu całego komponentu bo nie będzie to miało sensu. Wkleję jedynie najważniejsze kawałki odpowiedzialne za pobranie listy branych i ich wyświetlenie.

Pobranie danych odbywa się w następujący sposób:

Funkcja beforeMount wywoływana jest przed umieszczeniem komponentu na widoku. Jest to mój punkt wejściowy do aplikacji. Zostanie on nim dopóki nie wymyślę lepszego punktu wejściowego. Funkja jest bardzo prosta wywołuje ona akcję Vuex o nazwie GET_ALL_BRANCHES.

Jak widać akcja jest również prosta. Wywołany zostaje serwis, który odpytuje  WebApi. W przypadku poprawnego pobrania danych przekazywane są one do mutacji SET_ALL_BRANCHES. Ustawia ona stan aplikacji zgodnie z tym, jak powinno się to robić korzystając z Vuex. Tylko mutacje powinny zmieniać stan aplikacji.

Sam serwis do komunikacji wygląda następująco:

 

Jak widać wszystko jest dość przejrzyste i proste. Chciałbym aby cała aplikacja tak wyglądała 😉

API

Po stronie backendu funkcjonalności dotyczące branchy wystawione są za pomocą API w kontrolerze BranchController.cs.

Jeżeli chodzi o samo API wybrałem REST ze względu na to, że jest teraz super fancy i modny. A tak na serio to dzięki tej aplikacji chciałbym poznać to podejście. Jego wady, zalety, ograniczenia.

No więc lista branchy dostępna jest pod:

a sam kontroler jest zaimplementowany maksymalnie prosto:

Jak widać nic szczególnego, wstrzyknięty jedynie odpowiedni provider odpowiedzialny za obsługę branchów. Sam provider wygląda tak:

Ot i pierwsze spotkanie z libgit2Sharp. Jeszcze nie opisywałem tej biblioteki. Do providera wstrzykiwany jest obiekt typu IRepository. Jest to interfejs pochodzący właśnie z tej biblioteki. Stanowi on swoiste serce całego frameworka. Reprezentuje on repozytorium gita. Dzięki temu obiektowi mamy dostęp do prawie wszystkich (opiszę w kolejnych wpisach) operacji i zasobów, które możemy wywołać na repozytorium.

W tym konkretnym  przypadku pobranie listy branchy sprowadza się do zwykłej projekcji w Linq na kolekcji Branches. Klasa Branch jest moją klasą. Chciałem ograniczyć ilość zależności w aplikacji do minimum. Dlatego postanowiłem, że nie będę korzystał z dostępnych w bibliotece typów tylko stworze własne obiekty DTO. Dzięki temu podejściu zależność do libgit2Sharp mam wyłącznie w projekcie gitWeb.Core. Kontrolery nic nie wiedzą jaki provider do gita czy innego typu repozytorium jest wykorzystywany. Otwiera to furtkę do implementacji innych systemów kontroli wersji jak np Mercurial czy SVN bez konieczności większych zmian w aplikacji.

Nowy branch

Podstawowa komendą do stworzenia nowego brancha jest:

Oczywiście jest całe mnóstwo opcji, które można wykorzystać do jego stworzenia, ale w obecnej fazie wykorzystuję tą podstawową.

Dodatkowo, tworzone branche nie odwołują się do żadnego zdalnego brancha. Tą funkcjonalność dorobię w ramach Push i Pull.

Komponent VueJs

Do komponentu branch.vue musiałem dodać mini formularz który umożliwi mi wpisanie nazwy nowego brancha.

 

Po stronie komponentu do obsługi tworzenia nowego brancha mamy 2 funkcję:

clearCreationForm – prosta funkcja do czyszczenia stanu.

createBranch – tak jak w przypadku listy branchy, komponenty delegują całą logikę dotyczącą komunikacją z API do Vuex. A więc w tym przypadku wywołujemy akację CREATE_NEW_BRANCH. Przyjmuje ona jako parametr nazwę nowego brancha. Jeżeli operacja tworzenia przebiegnie pomyślnie, czyszczona jest forma z danymi.

Sama akcja w Vuex jest już bardziej skomplikowana:

Więc co tu się dzieje? Tak jak wspomniałem wcześniej, na początku wywoływana jest akcja CREATE_NEW_BRANCH. Akcja ta wywołuje serwis który z kolei wywołuje metodę API do stworzenia brancha. Jeżeli wszystko pójdzie zgodnie z planem to wywoływana jest akcja CHECKOUT_BRANCH.

W tej fazie projektu nowy branch jest automatycznie checkoutowany. I tak samo, jeżeli wszystko będzie w porządku to wywoływana jest (opisana wcześniej) akcja GET_ALL_BRANCHES.

W tym wpisie nie będę opisywał procesu checkoutowania., poświecę na niego osobny wpis.

Serwis odpowiedzialny za odwołanie się do API został zaimplementowany następująco:

API

Stworzyć nowy branch możemy odwołując się do poniższego zasobu:

Szybkie spojrzenie na kontroler oraz branchProvider:

W podstawowej formie żeby stworzyć branch należy jedynie wywołać metodę CreateBranch na obiekcie repozytorium oraz przekazać nazwę jako parametr.

Podsumowanie

Dzisiejszym wpisem rozpocząłem serię dotyczącą implementacji poszczególnych elementów projektu. Już powoli zaczyna coś działać! Strasznie mnie to nakręca do dalszego działania.

Widać wyraźnie, że biblioteka libgit2sharp jest naprawdę prosta w użyciu. Samo opisujące się metody i prosty interfejs sprawia, że bardzo dobrze się z niego korzysta. Dodatkowo community (github, stackOverflow) jest dość potężne, więc nie ma też problemu z rozwiązywaniem ewentualnych problemów czy błędów w samej bibliotece.

W kolejnym wpisie opisze kolejne części branchingu – a więc checkout brancha, zmianę nazwy oraz usunięcie.