MEVA (ang. Modular & Extensible Versioning Assistant) to rozproszony system kontroli wersji wyposażony w interfejsy CLI oraz GUI, zaimplementowany w języku Rust. Projekt został zrealizowany w ramach pracy inżynierskiej na Wydziale Matematyki i Nauk Informacyjnych Politechniki Warszawskiej przez zespół w składzie:
Promotorem pracy był mgr inż. Tomasz Herman.
- Obsługiwane polecenia
- Graficzny interfejs użytkownika
- Architektura
- Skrypty użytkownika
- Instalacja
- Instrukcja użytkownika
- Generowanie dokumentacji projektu
| Polecenie | Opis |
|---|---|
init |
Inicjalizuje nowe, puste repozytorium. |
add |
Dodaje zawartość plików do indeksu. |
commit |
Tworzy nowe zatwierdzenie w repozytorium. |
status |
Wyświetla stan plików w drzewie roboczym (zmodyfikowane, nieśledzone). |
log |
Pokazuje historię commitów. |
ls-files |
Wyświetla informacje o plikach w indeksie i drzewie roboczym. |
ls-tree |
Wyświetla zawartość obiektu drzewa. |
show |
Wyświetla szczegóły zatwierdzenia. |
diff |
Pokazuje zmiany między zatwierdzeniami, zatwierdzeniem a drzewem roboczym itp. |
restore |
Przywraca pliki w drzewie roboczym. |
config |
Pobiera i ustawia opcje konfiguracyjne (create, get, set, unset, list, edit). |
ignore |
Zarządza ignorowaniem plików (add, remove, check, edit). |
branch |
Listuje, tworzy lub usuwa gałęzie. |
checkout |
Przełącza gałęzie lub przywraca pliki drzewa roboczego. |
merge |
Scala historię z innej gałęzi do bieżącej. |
remote |
Zarządza zdalnymi repozytoriami (add, remove, show, rename, get-url, set-url). |
clone |
Klonuje repozytorium do nowego katalogu. |
fetch |
Pobiera obiekty i referencje ze zdalnego repozytorium. |
pull |
Pobiera (fetch) i scala (merge) zmiany ze zdalnego repozytorium lub z lokalnej gałęzi. |
push |
Aktualizuje zdalne referencje wraz z powiązanymi obiektami. |
plugins |
Zarządza systemem skryptów użytkownika (register, unregister, list, info, edit). |
Projekt meva zorganizowany jest jako Rust Workspace i został podzielony jest na 6 modułów (ang. crates).
meva/
├── gui/
│ └── ...
├── cli/
│ └── ...
├── server/
│ └── ...
├── engine/
│ └── ...
├── plugins/
│ └── ...
├── shared/
│ └── ...
├── Cargo.toml
├── LICENSE
└── README.md
| Moduł | Opis |
|---|---|
cli |
Interfejs wiersza poleceń, który pozwala na skryptowe zarządzanie repozytorium. |
gui |
Interfejs graficzny dla użytkownika końcowego w formie aplikacji desktopowej, wspierający podzbiór funkcjonalności interfejsu wiersza poleceń. |
server |
Moduł sieciowy. Obsługuje protokoły synchronizacji z repozytorium zdalnym, a także uwierzytelnianie i autoryzację użytkowników. |
engine |
Główny moduł implementujący logikę poszczególnych operacji na repozytorium. |
plugins |
System rozszerzeń w postaci skryptów użytkownika, uruchamianych jako procesy potomne. |
shared |
Biblioteka pomocnicza, przechowująca logikę wspólną dla wszystkich modułów. |
Projekt generuje trzy niezależne pliki wykonywalne: meva, meva-gui oraz meva-server odpowiednio dla modułów cli, gui oraz server.
System kontroli wersji MEVA należy do klasy systemów rozproszonych (DVCS ang. Distributed Version Control System). W przeciwieństwie do systemów scentralizowanych (ang. centralized), takich jak SVN, gdzie pełna historia zmian znajduje się wyłącznie na głównym serwerze, w modelu przyjętym przez system MEVA każdy użytkownik posiada własną, kompletną kopię zdalnego repozytorium.
Diagram ilustruje współpracę dwóch niezależnych użytkowników za pośrednictwem węzła centralnego:
Węzeł oznaczony jako Repozytorium zdalne pełni funkcję źródła danych (ang. single source of truth). Przechowuje ono wspólną historię projektu, do której dostęp mają wyłącznie uprawnieni użytkownicy. Użytkownik 2, za pośrednictwem aplikacji desktopowej (Klient GUI), rozpoczyna pracę poprzez wykonania operacji clone. Jej wynikiem jest lokalna kopii zdalnego repozytorium, oznaczona na schemacie jako Repozytorium lokalne 2.
Zarówno Użytkownik 1, korzystający z interfejsu konsolowego (Klient CLI), jak i Użytkownik 2 przesyłają swoje zatwierdzone zmiany za pomocą polecenia push. Operacja ta aktualizuje stan zdalnego repozytorium.
W celu zsynchronizowania stanu swojego lokalnego repozytorium z postępami innych członków zespołu, użytkownicy wykorzystują polecenia fetch (pobranie brakujących obiektów bez integracji zmian) oraz pull (pobranie zmian połączone ze ich scalaniem).
System MEVA nie implementuje własnego, niskopoziomowego protokołu transportowego opartego bezpośrednio na gniazdach TCP. Zamiast tego, przyjęto architekturę opartą na tunelowaniu ruchu przez protokół SSH (ang. Secure Shell). Całość wymiany danych, w tym negocjacja historii oraz transfer obiektów, odbywa się wewnątrz bezpiecznego kanału.
Protokół pobierania danych (meva-upload-pack) stanowi fundament operacji fetch oraz clone. Jego zadaniem jest synchronizacja stanu repozytorium lokalnego z repozytorium zdalnym poprzez pobranie jedynie brakujących obiektów historii. Protokół ten jest uruchamiany bezpośrednio po zakończeniu wstępnej fazy rozgłaszania referencji i składa się z dwóch etapów: negocjacji historii oraz transferu danych (generowania i wysyłania paczki).
Diagram sekwencji dla protokołu meva-upload-pack:
Protokół wysyłania danych (meva-receive-pack) stanowi fundament operacji push. Jego zadaniem jest synchronizacja stanu repozytorium zdalnego z repozytorium lokalnym klienta, a także zarządzanie stanem zdalnych referencji. Protokół ten jest uruchamiany bezpośrednio po zakończeniu wstępnej fazy rozgłaszania referencji i składa się z 3 etapów: przesyłania poleceń aktualizacji referencji, transferu danych (generowania i wysyłania paczki) oraz raportowania aktualizacji referencji.
Diagram sekwencji dla protokołu meva-receive-pack:
System kontroli wersji MEVA został zaprojektowany jako rozwiązanie otwarte na rozszerzenia. Oprócz wbudowanego zestawu poleceń, udostępnia on mechanizm skryptów użytkownika (nazywanych również pluginami), który pozwala na automatyzację zadań, walidację danych oraz integrację zewnętrznych narzędzi bez konieczności ingerencji w kod źródłowy samej aplikacji.
Projektując moduł skryptów użytkownika, przyjęto szereg założeń definiujących jego zachowanie, zakres oraz sposób interakcji z otoczeniem:
-
Model zdarzeń: System obsługuje dwa rodzaje zdarzeń:
pre-execute: Występujące przed wykonaniem właściwej operacji (np.commit,push). Służy do walidacji oraz modyfikacji danych wejściowych. Błąd zwrócony przez plugin w tej fazie skutkuje natychmiastowym przerwaniem całej operacji.post-execute: Występujące po pomyślnym wykonaniu operacji. Służy do raportowania i analizowania wyników polecenia. Błąd w tej fazie nie wpływa na wynik operacji wykonanej już na repozytorium.
-
Zakresy: Pluginy mogą być rejestrowane na dwóch poziomach widoczności:
- Lokalny: Ogranicza działanie skryptu do pojedynczego repozytorium. Konfiguracja i skrypty przechowywane są wewnątrz katalogu
.meva/plugins/. - Globalny: Rozszerza widoczność na wszystkie repozytoria danego użytkownika w systemie. Konfiguracja i skrypty przechowywane są w katalogu domowym użytkownika (
~/.meva/plugins/).
- Lokalny: Ogranicza działanie skryptu do pojedynczego repozytorium. Konfiguracja i skrypty przechowywane są wewnątrz katalogu
-
Niezależna komunikacja: Interfejs wymiany danych między systemem a pluginem jest zrealizowany poprzez system plików. W momencie wywołania, skrypt otrzymuje ścieżkę do tymczasowego pliku JSON (tzw. pliku kontekstu), co uniezależnia mechanizm od języka programowania, w którym napisano rozszerzenie.
-
Synchroniczne wykonanie: Pluginy są uruchamiane synchronicznie, jeden po drugim. Kolejność ich wykonywania wynika z priorytetu (
order) nadanego podczas rejestracji. -
Kontrola czasu wykonania: Istnieje możliwość zdefiniowania maksymalnego czasu wykonania osobno dla każdego zarejestrowanego skryptu. Jeżeli wykonanie logiki zapisanej w pluginie potrwa dłużej niż określony limit, system automatycznie przerywa wykonanie, informując o przekroczeniu czasu.
-
Przechwytywanie wejścia/wyjścia: System w pełni zarządza standardowymi strumieniami (
stdin,stdout,stderr) każdego skryptu. Strumienie wyjściowe są przechwytywane w czasie rzeczywistym, dzięki czemu komunikaty wypisywane na standardowe wyjście (stdout) i standardowe wyjście błędów (stderr) są jednocześnie prezentowane użytkownikowi w konsoli oraz zapisywane w logach wywołania. Skrypty mogą pobierać dane od użytkownika poprzez standardowe wejście (stdin). -
Konfiguracja: Działanie całego systemu rozszerzeń jest kontrolowane przez wpisy w głównych plikach konfiguracyjnych (sekcja
[plugins]), co pozwala na ich szybkie włączenie lub wyłączenie bez konieczności odinstalowywania skryptów czy rekompilacji kodu.
Istotną cechą systemu rozszerzeń jest brak wymogu tworzenia pluginów w konkretnym języku programowania. Zamiast dostarczać wewnętrzne API lub biblioteki dynamiczne (.dll, ang. dynamic link libraries), system MEVA wykorzystuje mechanizm procesów potomnych oraz komunikację opartą na plikach. Procesy potomne komunikują się poprzez ustandaryzowany plik kontekstu operacji w formacie JSON.
Plugin został zdefiniowany jako dowolny plik wykonywalny lub skrypt interpretowany (na przykład w języku Python, JavaScript, PowerShell czy Bash).
Proces wymiany danych wygląda następująco:
- System MEVA generuje plik tymczasowy w formacie JSON, zawierający metadane polecenia (kontekst wykonywanej operacji).
- System uruchamia skrypt użytkownika jako osobny proces, przekazując ścieżkę do pliku kontekstu jako pierwszy argument wywołania.
- Skrypt odczytuje dane, wykonuje swoją logikę i (opcjonalnie) modyfikuje plik kontekstu. Może również zapisać w nim informację o błędzie oraz zwrócić niezerowy kod wyjścia, przerywając wykonanie kolejnych skryptów lub samego polecenia.
Dzięki takiemu podejściu użytkownik ma pełną swobodę w doborze technologii do tworzenia rozszerzeń, o ile w danym środowisku systemowym dostępny jest odpowiedni interpreter.
System pluginów posiada własną, ustrukturyzowaną hierarchię plików, która umożliwia logiczną organizację skryptów i ich metadanych. Zdefiniowano dwa poziomy zasięgu pluginów: globalny (dla użytkownika systemu operacyjnego) oraz lokalny (dla konkretnego repozytorium).
.meva/plugins/
├── .invocations/
│ ├── commit/
│ │ ├── 20260112-202222/
│ │ │ ├── invocation.log
│ │ │ ├── pre-execute-context.json
│ │ │ ├── post-execute-context.json
│ │ │ ├── stdout.log
│ │ │ └── stderr.log
│ │ └── ...
│ └── ...
├── commit/
│ ├── plugins.json
│ ├── validate_message.py
│ └── ...
├── config/
│ ├── set/
│ │ ├── plugins.json
│ │ └── ...
│ └── unset/
│ ├── plugins.json
│ └── ...
└── ...
Komunikacja między systemem MEVA a skryptami użytkownika odbywa się poprzez wymianę sformalizowanych obiektów danych w formacie JSON.
Każdy plik kontekstu operacji, do którego ścieżka jest przekazywana jako pierwszy argument pozycyjny podczas uruchamiania skryptu, zawiera cztery główne sekcje: metadane (context), dane wejściowe (pre-payload), dane wyjściowe (post-payload) oraz kanał błędów (error).
{
"context": {
"command": "commit",
"event": "pre-execute",
"timestamp": "2026-01-12T12:34:56Z",
"working_dir": "/home/john/company_project"
},
"pre-payload": {
"message": "Implement user authentication.",
"author": {
"name": "John Doe",
"email": "john.doe@example.com"
},
"amend": false
},
"post-payload": {
"commit_hash": "a1b2c3d4e5f6...",
"changes": [
{
"added": {
"new_path": "src/auth.rs",
"insertions": 45
}
}
]
},
"error": null
}Rola poszczególnych sekcji obiektu JSON jest następująca:
context: Sekcja zawierająca podstawowe informacje o kontekście wywołania skryptu użytkownika. Znajdują się tu informacje o typie polecenia (command), rodzaju zdarzenia (event), czasie wywołania (timestamp) oraz katalogu roboczym (working_dir).pre-payload: Sekcja zawierająca dane wejściowe specyficzne dla danego polecenia. Są one dostępne zarówno w faziepre-execute, jak ipost-execute.post-payload: Sekcja przeznaczona na wynik działania operacji. W faziepre-executewartość ta zawsze wynosinull. W faziepost-execute(jak na rysunku przedstawiającym kontekst poleceniacommit) zawiera ona informacje dotyczące rezultatu polecenia.error: Opcjonalna sekcja, która w przypadku poprawnego wykonania skryptu użytkownika przyjmuje wartośćnull. Plugin może ją zmodyfikować w celu zgłoszenia błędu wykonania.
W przypadku polecenia commit informacje zawarte w pre-payload obejmują między innymi treść wiadomości, dane autora oraz flagi sterujące (np. amend). Sekcja post-payload zawiera natomiast między innymi skrót zatwierdzenia, a także listę plików objętych zatwierdzeniem wraz z metadanymi (np. liczbę zmodyfikowanych linii).
Skrypt użytkownika ma możliwość przerwania łańcucha wywołań następujących po nim pluginów, a w fazie pre-execute — dodatkowo zablokowania wykonania głównego polecenia (np. uniemożliwienia utworzenia zatwierdzenia, którego format wiadomości nie spełnia określonych wymogów).
Sygnałem do przerwania operacji jest zakończenie procesu pluginu z kodem wyjścia (ang. exit code) różnym od zera. W takiej sytuacji system MEVA analizuje pole error w pliku kontekstu, aby wyświetlić użytkownikowi przyczynę blokady.
{
"code": "VALIDATION_ERROR",
"message": "Commit message must reference an Azure DevOps work item (e.g. AB#1234)",
"details": "Regex pattern '^AB#\\d+' not matched"
}Obiekt ten składa się z trzech pól:
code: Stały identyfikator typu błędu (np.VALIDATION_ERROR).message: Komunikat przeznaczony bezpośrednio dla użytkownika końcowego, wyjaśniający, dlaczego operacja została przerwana.details: Opcjonalne pole zawierające szczegóły techniczne, pomocne w diagnostyce.
W celu zaprezentowania praktycznego zastosowania omówionych mechanizmów, przedstawiona zostanie przykładowa implementacja pluginu walidacyjnego. Scenariusz ten zakłada integrację systemu MEVA z platformą Azure DevOps. Jedną z cech tej platformy jest identyfikowanie elementów roboczych (ang. work items) poprzez unikalny identyfikator (liczbę).
Wymaganiem biznesowym może być oznaczanie każdego zatwierdzenia identyfikatorem odpowiadającego mu elementu roboczego poprzez umieszczenie tego identyfikatora na początku wiadomości zatwierdzenia.
Poniżej przedstawiono kompletny kod skryptu napisanego w języku Python. Realizuje on logikę walidacji w fazie pre-execute, wykorzystując mechanizm pliku kontekstu do komunikacji z systemem MEVA.
#!/usr/bin/env python3
import sys, json, re
filename = sys.argv[1]
with open(filename, "r", encoding="utf-8") as f:
data = json.load(f)
msg = data.get("pre-payload", {}).get("message", "")
pattern = r"^AB#[0-9]+"
if not re.match(pattern, msg):
data["error"] = {
"code": "VALIDATION_ERROR",
"message": "Commit message must reference an Azure DevOps work item (e.g. AB#1234)",
"details": f"Regex pattern '{pattern}' not matched"
}
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
sys.exit(1)
data["error"] = None
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
sys.exit(0)Wszystkie pliki związane z rozszerzeniami przechowywane są w katalogu plugins/. Dla zasięgu lokalnego katalog ten znajduje się wewnątrz folderu .meva/, natomiast dla zasięgu globalnego jego lokalizacja to katalog domowy użytkownika (ścieżka ``~/.meva/plugins/`).
Pluginy są grupowane w katalogach odpowiadających nazwom poleceń, na które mają one reagować (np. commit/, config/set/). Taka struktura umożliwa szybkie zlokalizowanie wszystkich skryptów zarejestrowanych na wywołanie konkretnego polecenia.
Zarówno narzędzie wiersza poleceń (CLI), jak i interfejs graficzny (GUI) są dystrybuowane jako samodzielne pliki wykonywalne, co eliminuje konieczność instalowania skomplikowanych zależności w systemie użytkownika końcowego.
System MEVA został napisany w języku Rust, dlatego do skompilowania kodu źródłowego wymagana jest obecność dedykowanych dla tego języka narzędzi (ang. Rust toolchain). Zalecana wersja kompilatora to 1.88.0 lub nowsza.
Aby zweryfikować poprawność instalacji środowiska, należy wywołać w wierszu poleceń polecenia sprawdzające wersje kompilatora rustc oraz menedżera pakietów cargo:
rustc --version
# rustc 1.88.0 (6b00bc388 2025-06-23)
cargo --version
# cargo 1.88.0 (873a06493 2025-05-10)Klient wiersza poleceń jest podstawowym narzędziem do interakcji z systemem MEVA. Jego instalacja polega na skompilowaniu kodu źródłowego oraz skonfigurowaniu ścieżek systemowych.
Kompilację należy wykonać z poziomu katalogu głównego projektu, wykorzystując menedżer pa kietów cargo:
cargo build --release --bin mevaWygenerowany plik wykonywalny zostanie domyślnie umieszczony w katalogu target/release/.
Uruchomienie systemu MEVA za pomocą wiersza poleceń z dowolnego miejsca systemu operacyjnego wymaga dodania ścieżki z plikiem wykonywalnym do zmiennej środowiskowej PATH.
Po zainstalowaniu oprogramowania, należy zdefiniować tożsamość użytkownika. Konfiguracja tożsamości polega na określeniu wartości dla kluczy user.name oraz user.email w globalnym pliku konfiguracyjnym w katalogu domowym użytkownika.
W celu stworzenia pliku konfiguracyjnego oraz ustawienia wartości user.name oraz user.email należy wykonać następujące polecenia:
meva config create
meva config set --global user.name "John Doe"
meva config set --global user.email "john.doe@example.com"
Aplikacja kliencka z graficznym interfejsem użytkownika MEVA GUI stanowi alternatywę dla narzędzi wiersza poleceń, oferując wizualną reprezentację historii zmian i statusu repozytorium. W celu skompilowanie interfejsu graficznego, należy użyć polecenia:
cargo build --release --bin meva-guiPodobnie jak w przypadku klienta konsolowego, wynikowy plik wykonywalny (meva-gui lub meva-gui.exe) zostanie domyślnie umieszczony w katalogu target/release/.
Uruchomienie aplikacji desktopowej MEVA GUI za pomocą wiersza poleceń z dowolnego miejsca systemu operacyjnego wymaga dodania ścieżki z plikiem wykonywalnym do zmiennej środowi
skowej PATH.
Proces budowania wersji produkcyjnej serwera przebiega analogicznie do procedur opisanych dla narzędzi klienckich. W przypadku serwera SSH cel binarny nazywa się meva-server. Właściwe polecenie kompilacji przyjmuje postać:
cargo build --release --bin meva-serverFundamentem bezpieczeństwa serwera MEVA jest asymetryczna kryptografia oparta na protokole SSH. Aby serwer mógł bezpiecznie zestawiać połączenia i potwierdzać swoją tożsamość przed klientami, konieczne jest wygenerowanie pary kluczy hosta.
Polecenie generujące parę kluczy wygląda następująco:
ssh-keygen -t ed25519 -f ./server_host_key -C "meva-server-host"opt/meva-server/
├── bin/
│ └── meva-server
├── config/
│ ├── mevaserverconfig.toml
│ ├── access.toml
│ └── authorized_keys
├── secrets/
│ ├── server_host_key
│ └── server_host_key.pub
├── logs/
│ └── ...
└── repositories/
└── ...
| Katalog | Przeznaczenie |
|---|---|
bin/ |
Katalog, w którym przechowywany jest plik wykonywalny zdalnego serwera SSH. |
config/ |
Katalog, w którym przechowywane są wszystkie pliki sterujące zachowaniem serwera. |
secrets/ |
Katalog dla danych krytycznych z punktu widzenia bezpieczeństwa, w szczególności dla klucza prywatnego serwera. |
logs/ |
Katalog na pliki z logami serwera, umożliwiające monitorowanie jego pracy oraz diagnostykę błędów. |
repositories/ |
Katalog, w którym serwer przechowuje pliki i historię wszystkich obsługiwanych repozytoriów. Każde repozytorium otrzymuje własny podkatalog, wewnątrz którego znajduje się właściwa baza danych systemu MEVA. |
W systemie MS Windows odpowiednikiem katalogu opt/ jest folder Program Files.
[server]
port = 2223
address = "0.0.0.0"
host_key = "./secrets/server_host_key"
repositories_root = "./repositories"
[access]
authorized_keys = "./config/authorized_keys"
policy_file = "./config/access.toml"
[logging]
level = "info"
detailed = true
log_file = "./logs/server.log"
rotate_size = 10485760 # Rotacja przy 10MiB
keep_logs = 7 # Przechowywanie 7 ostatnich plikówSekcja [server]:
Sekcja ta definiuje podstawowe parametry pracy usługi sieciowej oraz lo kalizację danych.
port: Numer portu TCP, na którym serwer nasłuchuje połączeń przychodzących (domyślnie 2223, aby uniknąć konfliktu z systemowym SSH na porcie 22).address: Adres IP interfejsu sieciowego. Wartość0.0.0.0oznacza nasłuchiwanie na wszystkich dostępnych interfejsach sieciowych.host_key: Względna lub bezwzględna ścieżka do pliku zawierającego klucz prywatny serwera.repositories_root: Ścieżka do katalogu głównego, w którym przechowywane będą wszystkie repozytoria systemu MEVA.
Sekcja [access]:
Wskazuje lokalizację plików odpowiedzialnych za uwierzytelnianie i autory zację.
authorized_keys: Ścieżka do pliku zawierającego listę kluczy publicznych użytkowników uprawnionych do nawiązania połączenia.policy_file: Ścieżka do pliku access.toml, definiującego szczegółowe uprawnienia dla poszczególnych użytkowników i repozytoriów.
Sekcja [logging]:
Konfiguruje sposób zbierania logów w trakcie działania serwera.
level: Określa minimalny poziom ważności komunikatów zapisywanych w logach. Możliwe wartości (od najmniej do najbardziej szczegółowych) to:error: Tylko błędy krytyczne uniemożliwiające dalsze działanie.warn: Ostrzeżenia o potencjalnych problemach.info: Standardowe informacje o przebiegu działania operacji.debug: Szczegółowe informacje diagnostyczne przydatne w trakcie diagnozowania błędów.
detailed: Wartość logiczna (true/false). Określa sposób formatowania wpisów. Jeśli ustawiona natrue, logi zawierają dodatkowe metadane, takie jak sygnatura czasowa, nazwa pliku źródłowego i numer linii kodu, w której wystąpiło zdarzenie.log_file: Ścieżka do pliku wyjściowego, w którym zapisywane są logi.rotate_size: Maksymalny rozmiar pliku logów w bajtach, po przekroczeniu którego następuje jego rotacja (zamknięcie i zmiana nazwy). Wartość 10485760 odpowiada 10 MiB (mebibajtów).keep_logs: Liczba plików archiwalnych przechowywanych po rotacji. Starsze pliki są automatycznie usuwane, co pozwala na kontrolowanie zużycia przestrzeni dyskowej.
Wsystemie MEVA zaimplementowano model uprwanień oparty na rolach, definiowanych w pliku access.toml. Model ten umożliwia przypisywanie uprawnień odczytu (read) oraz zapisu (write) zdefiniowanym użytkownikom do poszczególnych repozytoriów. Wpisy w pliku access.toml mają postać:
[company_project.john-doe]
read = true
write = truePlik ten przechowuje listę kluczy publicznych (w formacie SSH Ed25519) użytkowników uprawnionych do łączenia się z serwerem.
Przykładowy wpis w pliku authorized_keys wygląda następująco:
ssh-ed25519 <KLUCZ-PUBLICZNY> john-doegdzie john-doe to nazwa użytkownika, która posłuży do jego identyfikacji w systemie uprawnień.
Katalog zdefiniowany w pliku konfiguracyjnym mevaserverconfig.toml jako repositories_root jest miejscem, w którym serwer przechowuje pliki i historię wszystkich obsługiwanych repozytoriów. Każde repozytoium otrzymuje własny podkatalog, wewnątrz którego znajduje się właściwa baza danych systemu MEVA. Gdy użytkownik końcowy wykonuje operację push, przy pomocy interfejsu CLI lub GUI, serwer autoryzuje żądanie, a następnie zapisuje nowe obiekty w odpowiednim podkatalogu.
Aplikacja meva-server przyjmuje ścieżkę do głównego pliku konfiguracyjnego (plik mevaserverconfig.toml) jako argument pozycyjny. Dodatkowo, poziom szczegółowości komunikatów diagnostycznych wyświetlanych na standardowym wyjściu (stdout) sterowany jest poprzez zmienną środowiskową RUST_LOG.
Polecenie uruchomienia serwera w systemie operacyjnym MS Windows:
$env:RUST_LOG = "info"; .\bin\meva-server.exe ‘
"C:\meva\server\config\mevaserverconfig.toml"
Polecenie uruchomienia serwera w systemie operacyjnym Linux:
RUST_LOG=info ./bin/meva-server \
"/opt/meva-server/config/mevaserverconfig.toml"
Aby uruchomić zestaw testów jednostkowych zdefiniowanych w kodzie źródłowym, należy w głównym katalogu projektu wywołać polecenie:
cargo test
Polecenie to automatycznie skompiluje kod w trybie testowym (który może zawierać dodatkowe asercje niewidoczne w wersji produkcyjnej), a następnie uruchomi wszystkie funkcje oznaczone atrybutem #[test].
Pomyślny przebieg testów:
...
test repositories::meva_repository::tests::init_creates_expected_structure ... ok
test repositories::meva_repository::tests::init_fails_if_repo_already_exists ... ok
test result: ok. 47 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
finished in 0.04s
Jeśli środowisko nie spełnia wymagań, testy zakończą się niepowodzeniem, oznaczonym komunikatem FAILED:
...
test repositories::meva_repository::tests::init_creates_expected_structure ... ok
test repositories::meva_repository::tests::init_fails_if_repo_already_exists ... FAILED
test result: FAILED. 46 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out;
finished in 0.01s
Interfejs linii poleceń został wyposażony w mechanizm pomocy o ustandaryzowanym formacie komunikatów oraz walidację wprowadzanych argumentów. System pomocy dostępny jest na dwóch poziomach:
- Pomoc globalna: Wywołanie
meva –-help(lub w wersji skróconej-h) wyświetla listę wszystkich dostępnych poleceń podrzędnych wraz z ich krótkim opisem oraz dostępne flagi globalne. - Pomoc kontekstowa: Każde polecenie (np.
commit,clone) posiada własny ekran pomocy, dostępny poprzez wywołanie:meva <polecenie> –-help. Prezentuje on składnię danej operacji, wymagane i opcjonalne argumenty pozycyjne oraz flagi.
System MEVA opiera swoje działanie na plikach konfiguracyjnych w formacie TOML. Umożliwiają one dostosowanie zachowania narzędzia, od podstawowych danych użytkownika po ustawienia sieciowe i parametry skryptów użytkownika.
Zarządzanie konfiguracją odbywa się za pomocą polecenia zbiorczego meva config.
Domyślna zawartość globalnego pliku konfiguracyjnego:
# Meva Configuration File
# Edit this file to customize your global settings
[user]
name = "Your Name"
email = "your.email@example.com"
signing_key = "path/to/client/signing/key"
[editor]
default = "vim"
[plugins]
enabled = false
collect_logs = falseOprócz interfejsu wiersza poleceń, system MEVA oferuje dedykowaną aplikację desktopową, która ułatwia zarządzanie repozytoriami użytkownikom preferującym środowiska graficzne. GUI stanowi nakładkę na silnik CLI, zapewniając dostęp do ograniczonego zbioru funkcjonalności systemu.
Bieżące utrzymanie serwera MEVA sprowadza się do zarządzania plikami konfiguracyjnymi znajdującymi się w katalogu config/. Poniżej opisano kluczowe procedury administracyjne na przykładzie wdrożenia projektu o nazwie company_project dla użytkownika john-doe.
Fizyczne utworzenie struktury danych repozytorium odbywa się poprzez polecenie meva init wywołane w stworzonym dla projektu katalogu umieszczonym wewnątrz katalogu repositories/. Wprzypadku projektu o nazwie company_project polecenie powinno zostać wywołane z poziomu repositories/company_project/.
Proces rejestracji nowego użytkownika w systemie składa się z dwóch etapów: wygenerowania pary kluczy po stronie klienta oraz zarejestrowania klucza publicznego na serwerze.
Generowanie klucza po stronie klienta:
ssh-keygen -t ed25519 -f ./id_ed25519 -C "john-doe"Wwyniku tej operacji użytkownik uzyskuje plik klucza publicznego id_ed25519.pub, którego zawartość musi bezpiecznym kanałem przekazać administratorowi serwera.
Administrator, po otrzymaniu klucza publicznego, musi dodać go do pliku authorized_keys, znajdującego się w katalogu konfiguracyjnym serwera
(np. /opt/meva-server/config/authorized_keys). Każdy klucz powinien znajdować się w osobnej linii i kończyć się identyfikatorem użytkownika, który będzie później wykorzystywany w polityce dostępu.
Ostatnim etapem jest zdefiniowanie uprawnień w pliku access.toml. W celu umożliwienia użytkownikowi john-doe pracy z repozytorium company_project, należy dodać nową sekcję o schematycznej nazwie [nazwa_projektu.nazwa_użytkownika].
Konfiguracja uprawnień w pliku access.toml:
[company_project.john-doe]
read = true
write = trueAby wygenerować dokumentację publicznego API poszczególnych modułów projektu i otworzyć ją w domyślnej przeglądarce należy użyć polecenia:
cargo doc --openAby wygenerować kompletną dokumentację, uwzględniającą również elementy prywatne (przydatne dla deweloperów rozwijających projekt) i otworzyć ją w przeglądarce należy użyć polecenia:
cargo doc --document-private-items --open

























