
# Πρωτόκολλα

Το Pitmaster υποστηρίζει πολλαπλά πρωτόκολλα μεταφοράς δικτύου για επικοινωνία με διακομιστές git. Το smart HTTP είναι το κύριο transport. Διατίθενται επιπλέον πρωτόκολλα για ευρύτερη συμβατότητα.

## Smart HTTP (κύριο)

Το προτεινόμενο transport. Λειτουργεί μέσω HTTPS και είναι το ευρύτερα χρησιμοποιούμενο πρωτόκολλο. Δεν υπάρχει API για προσαρμοσμένες κεφαλίδες ή διαπιστευτήρια· τα διαπιστευτήρια μπορούν να περαστούν μόνο στο URL (`https://user:token@host/repo.git`), το οποίο το PHP στέλνει ως βασικό έλεγχο ταυτότητας. Το `clone()` αποθηκεύει το URL, μαζί με τα διαπιστευτήρια, ως `remote.origin.url` στο `.git/config`. Τα αιτήματα χρησιμοποιούν τα stream wrappers του PHP, επομένως πρέπει να είναι ενεργοποιημένο το `allow_url_fopen`.

```php
use Pitmaster\Protocol\SmartHttpClient;

$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
```

Για όλες τις λεπτομέρειες, δείτε το [Smart HTTP](https://pitmaster.inline0.dev/el/docs/network/smart-http).

### Πρωτόκολλο v1

Το παραδοσιακό πρωτόκολλο smart HTTP. Όλα τα refs αποστέλλονται κατά τον εντοπισμό και η διαπραγμάτευση χρησιμοποιεί γραμμές want/have/done.

```php
use Pitmaster\Protocol\ProtocolV1;
```

### Πρωτόκολλο v2

Το νεότερο πρωτόκολλο με δομημένες εντολές (`ls-refs`, `fetch`). Είναι αποδοτικότερο για αποθετήρια με πολλά refs, επειδή ο πελάτης μπορεί να φιλτράρει τη λίστα refs.

Τα `clone()` και `fetch()` χρησιμοποιούν πάντα το πρωτόκολλο v1. Το πρωτόκολλο v2 είναι διαθέσιμο ρητά μέσω smart HTTP με τα `SmartHttpClient::discoverRefsV2()` και `UploadPackClient::fetchV2()`.

## Απλοϊκό HTTP

Εναλλακτική λύση για διακομιστές που δεν υποστηρίζουν το πρωτόκολλο smart HTTP. Το dumb πρωτόκολλο ανακτά αντικείμενα και pack μεμονωμένα μέσω απλών αιτημάτων GET HTTP.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Περιορισμοί του dumb HTTP:
- Δεν υπάρχει διαπραγμάτευση (ο πελάτης πρέπει να κατεβάσει τα πάντα)
- Δεν γίνεται συμπίεση delta κατά τη μεταφορά
- Είναι σημαντικά πιο αργό από το smart HTTP
- Ορισμένοι διακομιστές (GitHub, GitLab) δεν το υποστηρίζουν

Το dumb πρωτόκολλο ανακτά:
1. `GET /info/refs` (απλό κείμενο, χωρίς pkt-line)
2. `GET /HEAD` (προεπιλεγμένο branch)
3. `GET /objects/info/packs` (λίστα διαθέσιμων pack)
4. `GET /objects/pack/pack-<hash>.pack` και `.idx` (κάθε καταχωρισμένο pack και το index του)
5. `GET /objects/<xx>/<rest>` (μεμονωμένα loose αντικείμενα, με περιήγηση από τις κορυφές των refs)

Το βήμα 5 εκτελείται μόνο όταν ο διακομιστής δεν καταχωρίζει κανένα pack. Όταν καταχωρίζει pack, δεν λαμβάνονται αντικείμενα που υπάρχουν μόνο ως loose αρχεία στον διακομιστή ([#18](https://github.com/inline0/pitmaster/issues/18)). Ο dumb πελάτης δέχεται μόνο αναγνωριστικά αντικειμένων 40 χαρακτήρων (SHA-1). Τα `clone()` και `fetch()` επιστρέφουν στο dumb HTTP όταν αποτυγχάνει η ανταλλαγή smart HTTP.

## SSH

Το transport SSH χρησιμοποιεί την επέκταση `ssh2` PHP όταν είναι φορτωμένη. Διαφορετικά εκκινεί τον πελάτη συστήματος `ssh` μέσω `proc_open()`. Και στις δύο περιπτώσεις εκτελεί το `git-upload-pack` ή το `git-receive-pack` στο απομακρυσμένο σύστημα.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

Διευθύνσεις URL SSH:
```
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
```

Δεν απαιτείται επέκταση. Οι δύο διαδρομές λειτουργούν διαφορετικά:

**Πελάτης συστήματος `ssh`** (χρησιμοποιείται όταν δεν είναι φορτωμένο το `ssh2`). Το Pitmaster εκτελεί το `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, επομένως ο έλεγχος ταυτότητας και ο έλεγχος κλειδιού host ακολουθούν τη διαμόρφωση SSH και τον agent σας. Αυτές οι μεταβλητές περιβάλλοντος προσαρμόζουν την εντολή:

| Μεταβλητή | Επίδραση |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Εκτελέσιμο αρχείο που εκτελείται αντί του `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Περνά ως `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Περνά ως `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Περνά ως `-o StrictHostKeyChecking=<value>` |

Αυτή η διαδρομή εκκινεί διεργασία, επομένως δεν είναι διαθέσιμη σε handles που ανοίχτηκαν με `['processes' => false]`.

**Επέκταση `ssh2`** (προτιμάται πάντα όταν είναι φορτωμένη). Το Pitmaster πραγματοποιεί έλεγχο ταυτότητας με `~/.ssh/id_rsa` και έπειτα με `~/.ssh/id_ed25519` αν το κλειδί RSA υπάρχει αλλά απορρίφθηκε, και διαφορετικά με τον agent SSH. Οι μεταβλητές `PITMASTER_SSH_*` αγνοούνται και το κλειδί host του διακομιστή δεν επαληθεύεται σε αυτή τη διαδρομή ([#22](https://github.com/inline0/pitmaster/issues/22)).

Το transport SSH εκτελεί το `git-upload-pack` ή το `git-receive-pack` ως απομακρυσμένη εντολή και επικοινωνεί μέσω του καναλιού SSH, χρησιμοποιώντας το ίδιο πρωτόκολλο pkt-line με το smart HTTP.

## Πρωτόκολλο Git (TCP)

Το εγγενές πρωτόκολλο git επικοινωνεί μέσω της θύρας TCP 9418 χρησιμοποιώντας sockets PHP. Το `GitProtocolClient` υλοποιεί τον εντοπισμό refs και το `upload-pack` (ανάκτηση)· δεν μπορεί να κάνει push. Τα `clone()` και `fetch()` δεν δρομολογούν διευθύνσεις URL `git://` προς αυτό, επομένως χρησιμοποιήστε απευθείας τον πελάτη.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

Διευθύνσεις URL Git:
```
git://github.com/user/repo.git
```

Χαρακτηριστικά:
- Δεν υπάρχει έλεγχος ταυτότητας (στην πράξη μόνο για ανάγνωση)
- Δεν υπάρχει κρυπτογράφηση
- Έχει καταργηθεί από τους περισσότερους παρόχους φιλοξενίας
- Χρησιμοποιεί την ίδια πλαισίωση pkt-line με το smart HTTP

Το πρωτόκολλο git στέλνει το όνομα της υπηρεσίας και τη διαδρομή του αποθετηρίου ως αρχικό αίτημα και έπειτα συνεχίζει με τον τυπικό εντοπισμό refs pkt-line και τη διαπραγμάτευση pack.

## Πακέτα

Τα bundles Git είναι offline αρχεία pack με πληροφορίες refs. Επιτρέπουν τη μεταφορά δεδομένων αποθετηρίου χωρίς σύνδεση δικτύου.

```php
use Pitmaster\Protocol\Bundle;

// Read a bundle file
$bundle = Bundle::open('/path/to/repo.bundle');
$refs = $bundle->refs();
$packData = $bundle->packData();
$prerequisites = $bundle->prerequisites();

// Create one
$bundle = Bundle::create(['refs/heads/main' => $commitId], $packData);
$bundle->writeTo('/path/to/out.bundle');
```

Το Pitmaster διαβάζει κεφαλίδες bundle v2 και v3. Δεν υπάρχει μέθοδος `Repository` για εισαγωγή bundle: γράψτε το `packData()` στο `.git/objects/pack/`, δημιουργήστε το index του με το `PackIndexer::writeIndex()` και ενημερώστε μόνοι σας τα refs.

Μορφή bundle:
```
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)
```

Τα bundles είναι χρήσιμα για:
- Μεταφορές μέσω φυσικών μέσων (μονάδες USB)
- Σταδιακά αντίγραφα ασφαλείας
- Προετοιμασία clone σε περιβάλλοντα χωρίς σύνδεση δικτύου

## Ρηχοί κλώνοι

Το Pitmaster υποστηρίζει shallow clones, όπου ανακτάται μόνο περιορισμένο βάθος ιστορικού commit.

```php
use Pitmaster\Protocol\ShallowClone;
```

Περάστε ένα βάθος στο `Pitmaster::clone($url, $path, $depth)` ή στο `$repo->fetch($remote, $depth)`. Το αίτημα προσθέτει τη δυνατότητα `shallow` και μια γραμμή `deepen`:
```
want <hash>
deepen <depth>
```

Ο διακομιστής αποκρίνεται με γραμμές `shallow <hash>` που υποδεικνύουν πού περικόπηκε το ιστορικό. Το Pitmaster υπολογίζει το ρηχό όριο από το ίδιο το βάθος και χρησιμοποιεί τις γραμμές `shallow` του διακομιστή όταν ο υπολογισμός δεν βρίσκει τίποτα· το αποτέλεσμα αποθηκεύεται στο `.git/shallow`. Τα `ShallowClone::readShallow()`, `writeShallow()` και `isShallow()` λειτουργούν απευθείας με αυτό το αρχείο.

## Σύγκριση πρωτοκόλλων

| Πρωτόκολλο | Έλεγχος ταυτότητας | Κρυπτογράφηση | Αποστολή δεδομένων | Συνήθης χρήση |
|----------|------|-----------|-------------|-------------|
| Έξυπνο HTTP | Διαπιστευτήρια στο URL | HTTPS | Ναι | Κύριο μέσο μεταφοράς |
| Απλό HTTP | Διαπιστευτήρια στο URL | HTTPS | Όχι | Εναλλακτική για παλαιότερα συστήματα |
| SSH | Κλειδιά SSH ή agent | SSH | Ναι | Ιδιωτικά αποθετήρια, CI |
| Git (TCP) | Κανένα | Κανένα | Όχι | Αντίγραφα μόνο για ανάγνωση |
| Bundle | Δεν εφαρμόζεται | Δεν εφαρμόζεται | Δεν εφαρμόζεται | Μεταφορά εκτός σύνδεσης |

## Επιλογή μέσου μεταφοράς

Τα `Pitmaster::clone()`, `$repo->fetch()` και `$repo->push()` επιλέγουν το μέσο μεταφοράς από το URL:

| Μοτίβο URL | Μέσο μεταφοράς |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Οτιδήποτε άλλο (`https://...`, `http://...`) | Έξυπνο HTTP· τα clone και fetch επιστρέφουν στο απλό HTTP |

Οι διευθύνσεις URL `git://` και οι τοπικές διαδρομές δεν υποστηρίζονται από αυτές τις μεθόδους: αποστέλλονται στον πελάτη έξυπνου HTTP και αποτυγχάνουν. Χρησιμοποιήστε απευθείας το `GitProtocolClient` για `git://`. Ένα HTTPS URL που περιέχει και χρήστη και θύρα (`https://user@host:8443/repo.git`) εκλαμβάνεται προς το παρόν εσφαλμένα ως SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
