
# Tööpuud

Git tööpuud võimaldavad mitmel töökataloogil jagada üht hoidlat. Igal tööpuul on oma väljavõte (HEAD, indeks ja tööfailid), kuid see jagab peamise hoidlaga objektihoidlat, konfiguratsiooni ja pakitud viiteid. Pitmaster saab lingitud tööpuid luua, loetleda, lukustada ja eemaldada ning neid hoidlatena avada. Kärpimine, teisaldamine ja parandamine pole rakendatud.

## Mõisted

Tavalisel git hoidlal on üks tööpuu:

```
project/
  .git/          (directory)
  src/
  README.md
```

Tööpuude abil saate teha täiendavaid väljavõtteid:

```
project/                          (main worktree)
  .git/                           (the actual git directory)
    worktrees/
      review/                     (metadata for linked worktree)
        HEAD
        commondir
        gitdir

/tmp/review/                      (linked worktree)
  .git                            (file, not directory)
  src/
  README.md
```

Lingitud tööpuu `.git` on fail (mitte kataloog), mis sisaldab tööpuu suhtes suhtelist teed:
```
gitdir: ../../path/to/project/.git/worktrees/review
```

## Tööpuu loomine

```php
$repo = Pitmaster::open('/path/to/project');

// Create a linked worktree on a new branch
$wt = $repo->addWorktree('/tmp/review', 'feature/review');

echo $wt->path;        // '/tmp/review'
echo $wt->branch;      // 'feature/review'
echo $wt->gitDir;      // '/path/to/project/.git/worktrees/review'
var_dump($wt->isMain);      // bool(false)
var_dump($wt->isDetached);  // bool(false)
```

`addWorktree()` teeb järgmist:
1. Loob haru, kui seda pole olemas (HEAD-ist või määratud `$from` sissekandest)
2. Loob metaandmete kataloogi asukohta `.git/worktrees/<name>/`
3. Kirjutab tööpuu kataloogi faili `.git`
4. Kirjutab metaandmefailid `HEAD`, `commondir` ja `gitdir`
5. Kontrollib haru puu tööpuu kataloogi välja
6. Kirjutab tööpuu indeksi

Kui haru on juba olemas, eiratakse valikut `$from`. Erinevalt git-ist ei keela `addWorktree()` haru, mis on teises tööpuus juba välja kontrollitud, ega käivita konksu `post-checkout`.

### Selgesõnalise metaandmenimega

Kasutage valikulist argumenti `name`, kui mitu lingitud tööpuud võivad jagada sama väljavõtte baasinime.

```php
$wt = $repo->addWorktree(
    '/tmp/sandboxes/app',
    'feature/review',
    name: 'sandbox-app',
);
```

Seda metaandmenime kasutatakse asukohas `.git/worktrees/<name>/`, mitte asukohas `basename($path)`.

### Konkreetsest sissekandest

```php
$wt = $repo->addWorktree('/tmp/hotfix', 'hotfix/urgent', $repo->resolve('v1.0.0'));
```

## Tööpuude loetlemine

```php
$worktrees = $repo->worktrees();

foreach ($worktrees as $wt) {
    $type = $wt->isMain ? 'main' : 'linked';
    $branch = $wt->branch ?? 'detached';
    $locked = $wt->isLocked ? ' [locked]' : '';

    echo "{$wt->path} ({$type}) [{$branch}]{$locked}\n";
}
```

Loend sisaldab alati esmalt põhitööpuud ja seejärel lingitud tööpuid. Kutsuge põhivaramu käepidemel `worktrees()`: lingitud tööpuu käepidemel näitab põhikirje praegu lingitud tööpuu enda teed ([#14](https://github.com/inline0/pitmaster/issues/14)).

## Tööpuu eemaldamine

```php
$repo->removeWorktree('review');          // by metadata name
$repo->removeWorktree('/tmp/review');     // or by worktree path

// Force remove (even if locked)
$repo->removeWorktree('review', force: true);
```

Tööpuu eemaldamisel:
1. Kontrollitakse, kas tööpuu on lukus (ebaõnnestub, kui `$force` ei ole tõene)
2. Eemaldatakse tööpuu kataloogist fail `.git`
3. Eemaldatakse metaandmete kataloog asukohast `.git/worktrees/`

Tööpuu faile automaatselt ei kustutata. Haru jääb alles.

## Lingitud tööpuu avamine

Lingitud tööpuu saab avada nagu iga muud varamut:

```php
$repo = Pitmaster::open('/tmp/review');

// Pitmaster detects the .git file and follows the gitdir reference
echo $repo->isLinkedWorktree();  // true
echo $repo->gitDir();            // '/path/to/project/.git/worktrees/review'
echo $repo->commonGitDir();      // '/path/to/project/.git'
echo $repo->workDir();           // '/tmp/review'
```

Varamutoimingud lahendavad teed järgmiselt:
- **Objektid**: loetakse ühisest git-kataloogist ja kirjutatakse sinna (`project/.git/objects/`)
- **Seadistus**: loetakse ühisest git-kataloogist (`project/.git/config`)
- **Packed-refs**: loetakse ühisest git-kataloogist
- **HEAD**: tööpuupõhine (iga tööpuu jälgib oma haru), koos `ORIG_HEAD`, `MERGE_HEAD` ja teiste toiminguviidetega
- **Indeks**: tööpuupõhine (igal tööpuul on oma ettevalmistusala)
- **Lahtised viited**: harud ja sildid on ühiskataloogis (`project/.git/refs/`)
- **Konksud**: loetakse tööpuu git-kataloogist, seega jagatud konksud ei käivitu ([#12](https://github.com/inline0/pitmaster/issues/12))

Stash ei toeta veel lingitud tööpuid: see loeb identiteedi tööpuupõhisest kataloogist, kus seadistus puudub, ja kirjutab sinna ka reflogi ([#14](https://github.com/inline0/pitmaster/issues/14)).

## Tööpuu väärtusobjekt

```php
use Pitmaster\Worktree\Worktree;

$wt->name;          // Metadata name (null for the main worktree)
$wt->path;          // Working directory path
$wt->gitDir;        // Per-worktree git dir
$wt->branch;        // Branch name (null if detached)
$wt->head;          // ObjectId of HEAD commit
$wt->isMain;        // true for the main worktree
$wt->isDetached;    // true if HEAD is detached
$wt->isLocked;      // true if worktree is locked
$wt->lockReason;    // Lock reason, or null when there is none (an empty reason is also null)
```

## WorktreeManager

Madalatasemeliseks tööpuude haldamiseks. `WorktreeManager::add()` kirjutab ainult metaandmed ja faili `.git`: see ei loo haru, ei kontrolli faile välja ega kirjuta indeksit. Kasutage toimiva väljavõtte saamiseks valikut `$repo->addWorktree()`. Haru peab juba olemas olema (või olema täielik viitenimi, näiteks `refs/tags/v1.0.0`, mis lahutab HEAD-i harust).

```php
use Pitmaster\Worktree\WorktreeManager;

$manager = new WorktreeManager($repo->commonGitDir(), $mainWorkDir);

// List
$worktrees = $manager->list();

// Add
$wt = $manager->add('/tmp/review', 'feature/review');
$wt = $manager->add('/tmp/review', 'feature/review', 'review-app');

// Remove
$manager->remove('review');
$manager->remove('review', force: true);

// Lock/unlock (metadata name only)
$manager->lock('review', 'Do not delete, code review in progress');
$manager->unlock('review');
```

## Tööpuude lukustamine

```php
// Lock (prevents removal)
$manager->lock('review', 'Code review in progress');

// Attempt to remove locked worktree
try {
    $manager->remove('review');
} catch (\RuntimeException $e) {
    // "Worktree is locked: review (Code review in progress)"
}

// Force remove ignores the lock
$manager->remove('review', force: true);

// Unlock
$manager->unlock('review');
```

Lukk salvestatakse failina asukohta `.git/worktrees/<name>/locked`. Faili sisu on lukustamise põhjus (võib olla tühi).

## Tööpuude tuvastamine

```php
// Check if a path is a linked worktree
if (Pitmaster::isWorktree('/tmp/review')) {
    echo "This is a linked worktree\n";
}

// Resolve the common git dir from any path
$common = Pitmaster::commonGitDir('/tmp/review');
// '/path/to/project/.git'

// Resolve a .git file to the actual git directory
$gitDir = WorktreeManager::resolveGitFile('/tmp/review');
// '/path/to/project/.git/worktrees/review'
```

## Failipaigutus

### Lingitud tööpuude põhitööpuu metaandmed

```
.git/worktrees/<name>/
  HEAD         Per-worktree HEAD (symbolic ref or detached hash)
  commondir    Relative path to the shared git dir ("../..")
  gitdir       Path back to the worktree's .git file, as passed to addWorktree()
  locked       Present if locked (content = reason)
  index        Per-worktree index/staging area
```

### Lingitud tööpuu .git-fail

```
gitdir: <relative path to>/project/.git/worktrees/<name>
```

### Ressursside jagamine

| Ressurss | Asukoht | Jagatud? |
|----------|----------|---------|
| Objektid | `$commonDir/objects/` | Jah |
| Seadistus | `$commonDir/config` | Jah |
| Packed-refs | `$commonDir/packed-refs` | Jah |
| Konksud | `$gitDir/hooks/` | Ei: Pitmaster ei käivita lingitud tööpuudes jagatud konkse |
| HEAD | `$gitDir/HEAD` | Ei (tööpuupõhine) |
| Indeks | `$gitDir/index` | Ei (tööpuupõhine) |
| Lahtised viited | `$commonDir/refs/` | Jah (HEAD ja toiminguviited, näiteks `MERGE_HEAD`, on tööpuupõhised) |
