
# Primeiros passos

## Instalação

Instale Pitmaster via Composer:

```bash
composer require pitmaster/pitmaster
```

## Requisitos

- **PHP 8.2+** com classes somente leitura, enums e promoção de construtor
- **ext-zlib** para compactação/descompactação de objetos (incluído na maioria das instalações)
- **ext-json** para arquivos de estado da operação e payloads Git LFS API
- **ext-mbstring**, declarado em `composer.json`, portanto Composer exige-o no momento da instalação
- **ext-ctype** para validação de hash (habilitado na maioria das compilações de PHP, mas não declarado em `composer.json`)

As operações principais do repositório não exigem o binário `git`, FFI ou auxiliares externos. Recursos opcionais têm requisitos adicionais de execução: a execução de hooks usa `proc_open()`, e o transporte SSH usa `ext-ssh2` quando carregado; caso contrário, inicia o binário `ssh` do sistema por meio de `proc_open()`.

## Abrir um repositório existente

```php
use Pitmaster\Pitmaster;

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

Isso abre o repositório no caminho indicado. Pitmaster localiza o diretório `.git` (ou resolve um arquivo `.git` para worktrees vinculadas) e inicializa o banco de dados de objetos, o banco de dados de refs e a configuração.

`open()`, `init()` e `clone()` aceitam um array de opções como último argumento:

```php
// Do not run .git/hooks scripts for this handle
$repo = Pitmaster::open('/path/to/project', ['hooks' => false]);

// Do not start any process: no hooks, no fsmonitor hook, no clone/fetch/push, no SSH
$repo = Pitmaster::open('/path/to/project', Pitmaster::processFreeOptions());
```

Hooks são executados por padrão. `Pitmaster::processFreeOptions()` retorna `['processes' => false, 'hooks' => false]`; leituras e gravações locais continuam funcionando nesse identificador.

## Verificar se um caminho é um repositório

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

## Inicializar um novo repositório

```php
$repo = Pitmaster::init('/path/to/new-project');
```

Isso cria a estrutura de diretórios `.git` com objetos, refs, HEAD (apontando para `refs/heads/main`) e uma configuração padrão.

Para criar um repositório SHA-256, passe o formato de objeto como segundo argumento:

```php
$repo = Pitmaster::init('/path/to/new-project', 'sha256');
```

Os IDs de objeto nesse repositório têm 64 caracteres hexadecimais, e a configuração registra `extensions.objectformat = sha256`. Repositórios abertos posteriormente obtêm o formato dessa entrada de configuração.

## Ler o commit de HEAD

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

echo "Commit: {$head->id->hex}\n";
echo "Author: {$head->author}\n";
echo "Message: {$head->message}\n";
```

O método `head()` resolve HEAD (seguindo refs simbólicas) e retorna um objeto `Commit`.

## Listar branches e tags

```php
// All branch names
$branches = $repo->branches();
// ['main', 'feature/login', 'bugfix/typo']

// Current branch name (null if detached)
$current = $repo->branch();
// 'main'

// All tag names
$tags = $repo->tags();
// ['v1.0.0', 'v1.1.0']
```

## Percorrer o histórico de commits

```php
// Last 20 commits from HEAD
$commits = $repo->log(20);

foreach ($commits as $commit) {
    echo substr($commit->id->hex, 0, 7) . " {$commit->message}\n";
}
```

Você também pode começar de um commit específico:

```php
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
```

## Verificar o estado da árvore de trabalho

```php
use Pitmaster\Status\FileStatus;

$entries = $repo->status();

foreach ($entries as $entry) {
    if ($entry->index === FileStatus::Untracked) {
        echo "?? {$entry->path}\n";
    } elseif ($entry->index === FileStatus::Modified) {
        echo "M  {$entry->path}\n";
    } elseif ($entry->worktree === FileStatus::Modified) {
        echo " M {$entry->path}\n";
    }
}
```

## Preparar arquivos e criar um commit

```php
// Stage specific files
$repo->add('src/Feature.php', 'tests/FeatureTest.php');

// Create a commit
$commitId = $repo->commit('Add new feature with tests');

echo "Created commit: {$commitId->hex}\n";
```

O nome e o e-mail do autor são determinados nesta ordem: as variáveis de ambiente `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, as variáveis de ambiente `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, as constantes `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, o próprio `.git/config` do repositório (`user.name` e `user.email`) e, por fim, `Pitmaster <pitmaster@localhost>`. Apenas o arquivo de configuração do repositório (e os arquivos incluídos nele) é lido, não `~/.gitconfig`. O committer é determinado da mesma forma a partir dos nomes `*_COMMITTER_*` e recorre às constantes do autor.

## Calcular diffs

```php
// Unstaged changes (worktree vs index)
$diffs = $repo->diff();

foreach ($diffs as $diff) {
    echo $diff->format(); // Unified diff output
}

// Staged changes (index vs HEAD)
$staged = $repo->diffStaged();
```

## Clonar um repositório remoto

```php
$repo = Pitmaster::clone('https://github.com/user/repo.git', '/path/to/destination');
```

Isso descobre refs, busca o arquivo pack, configura branches de rastreamento remoto e faz checkout da branch padrão. URLs HTTP(S) usam HTTP inteligente e recorrem a HTTP simples; URLs SSH usam o transporte SSH. Passe uma profundidade como terceiro argumento para um clone raso: `Pitmaster::clone($url, $path, 1)`.

## Ler qualquer objeto pelo hash

```php
$object = $repo->readObject($fullHash); // full 40-character (or 64 for SHA-256) hex hash

if ($object instanceof \Pitmaster\Object\Blob) {
    echo $object->content;
} elseif ($object instanceof \Pitmaster\Object\Commit) {
    echo $object->message;
}
```

## Configuração

Pitmaster respeita a `.git/config` do repositório para informações do autor e URLs remotas. Você também pode definir padrões globais com as constantes PHP, definidas antes da execução de Pitmaster:

```php
define('PITMASTER_AUTHOR_NAME', 'Your Name');
define('PITMASTER_AUTHOR_EMAIL', 'you@example.com');
define('PITMASTER_HTTP_TIMEOUT', 60);        // Seconds
define('PITMASTER_MAX_DELTA_CHAIN', 50);     // Max delta chain depth
define('PITMASTER_OBJECT_CACHE_BYTES', '64M');
```

| Constante | Padrão | Efeito |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | nenhum | Identidade do autor (veja a ordem acima) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | valores do autor | Identidade do committer |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Tempo limite do HTTP inteligente em segundos (inteiro) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Profundidade máxima da cadeia delta ao ler packs (inteiro) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Objetos mantidos no cache de objetos em memória |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Limite de bytes do cache de objetos |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Objetos delta resolvidos em cache por pack |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Limite de bytes desse cache de pack |
| `PITMASTER_MAX_PACK_MEMORY` | nenhum | Nome anterior para o limite de bytes do cache de pack, usado somente quando `PITMASTER_PACK_RESOLVED_CACHE_BYTES` não está definido |

Valores de bytes aceitam um inteiro ou uma string com sufixo `k`, `m` ou `g` (`'256M'`). Valores inválidos recorrem ao padrão.

Variáveis de ambiente substituem as constantes de identidade: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, os equivalentes `PITMASTER_COMMITTER_*` e as próprias variáveis `GIT_AUTHOR_*` e `GIT_COMMITTER_*` de git. O transporte SSH lê variáveis `PITMASTER_SSH_*`, descritas em [Protocolos](https://pitmaster.inline0.dev/pt/docs/network/protocols).

Não há uma constante para o algoritmo de hash. O formato do objeto é escolhido quando o repositório é criado (`Pitmaster::init($path, 'sha256')` ou `init --object-format=sha256` em CLI) e, depois, lido da configuração do repositório.
