
# Primeros pasos

## Instalación

Instale Pitmaster mediante Composer:

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

## Requisitos

- **PHP 8.2+** con clases de solo lectura, enumeraciones y promoción de constructores
- **ext-zlib** para comprimir y descomprimir objetos (incluida en la mayoría de las instalaciones)
- **ext-json** para archivos de estado de operaciones y cargas útiles Git LFS API
- **ext-mbstring**, declarada en `composer.json`, por lo que Composer la requiere durante la instalación
- **ext-ctype** para validar hashes (habilitada en la mayoría de las compilaciones de PHP, pero no declarada en `composer.json`)

Las operaciones principales del repositorio no requieren el binario `git`, FFI ni herramientas externas. Las funciones opcionales tienen requisitos adicionales en tiempo de ejecución: la ejecución de hooks usa `proc_open()`, y el transporte SSH usa `ext-ssh2` cuando está cargado; de lo contrario, inicia el binario `ssh` del sistema mediante `proc_open()`.

## Abrir un repositorio existente

```php
use Pitmaster\Pitmaster;

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

Esto abre el repositorio en la ruta indicada. Pitmaster localiza el directorio `.git` (o resuelve un archivo `.git` en el caso de worktrees vinculados) e inicializa la base de datos de objetos, la base de datos de refs y la configuración.

`open()`, `init()` y `clone()` aceptan un arreglo de opciones 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());
```

Los hooks se ejecutan de forma predeterminada. `Pitmaster::processFreeOptions()` devuelve `['processes' => false, 'hooks' => false]`; las lecturas y escrituras locales siguen funcionando con ese identificador.

## Comprobar si una ruta es un repositorio

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

## Inicializar un repositorio nuevo

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

Esto crea la estructura de directorios `.git` con objetos, refs, HEAD (que apunta a `refs/heads/main`) y una configuración predeterminada.

Para crear un repositorio SHA-256, pase el formato de objeto como segundo argumento:

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

Los ID de objeto de ese repositorio tienen 64 caracteres hexadecimales, y la configuración registra `extensions.objectformat = sha256`. Los repositorios abiertos más adelante obtienen el formato de esa entrada de configuración.

## Leer el commit de HEAD

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

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

El método `head()` resuelve HEAD (siguiendo refs simbólicas) y devuelve un objeto `Commit`.

## Listar ramas y etiquetas

```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']
```

## Recorrer el historial 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";
}
```

También puede empezar desde un commit específico:

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

## Comprobar el estado del árbol de trabajo

```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 archivos y crear un 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";
```

El nombre y el correo electrónico del autor se resuelven en este orden: las variables de entorno `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, las variables de entorno `GIT_AUTHOR_NAME` / `GIT_AUTHOR_EMAIL`, las constantes `PITMASTER_AUTHOR_NAME` / `PITMASTER_AUTHOR_EMAIL`, la `.git/config` propia del repositorio (`user.name` y `user.email`) y, por último, `Pitmaster <pitmaster@localhost>`. Solo se lee el archivo de configuración del repositorio (y los archivos que incluye), no `~/.gitconfig`. El committer se resuelve del mismo modo a partir de los nombres `*_COMMITTER_*` y, si no se encuentran, usa las constantes del autor.

## Calcular diferencias

```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 un repositorio remoto

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

Esto descubre las referencias, obtiene el archivo del paquete, configura las ramas de seguimiento remoto y cambia a la rama predeterminada. HTTP(S) Las URL usan HTTP inteligente y recurren a HTTP simple; las URL SSH usan el transporte SSH. Pase la profundidad como tercer argumento para un clon superficial: `Pitmaster::clone($url, $path, 1)`.

## Leer cualquier objeto por su 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;
}
```

## Configuración

Pitmaster respeta `.git/config` del repositorio para la información del autor y las URL remotas. También puede establecer valores predeterminados globales con las constantes PHP, definidas antes de que se ejecute 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 | Valor predeterminado | Efecto |
|----------|---------|--------|
| `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL` | ninguno | Identidad del autor (consulte el orden anterior) |
| `PITMASTER_COMMITTER_NAME`, `PITMASTER_COMMITTER_EMAIL` | valores del autor | Identidad del confirmador |
| `PITMASTER_HTTP_TIMEOUT` | `30` | Tiempo de espera de HTTP inteligente en segundos (entero) |
| `PITMASTER_MAX_DELTA_CHAIN` | `50` | Profundidad máxima de la cadena delta al leer paquetes (entero) |
| `PITMASTER_OBJECT_CACHE_ENTRIES` | `1024` | Objetos conservados en la caché de objetos en memoria |
| `PITMASTER_OBJECT_CACHE_BYTES` | `16M` | Límite de bytes de la caché de objetos |
| `PITMASTER_PACK_RESOLVED_CACHE_ENTRIES` | `4096` | Objetos delta resueltos en caché por paquete |
| `PITMASTER_PACK_RESOLVED_CACHE_BYTES` | `32M` | Límite de bytes de esa caché de paquetes |
| `PITMASTER_MAX_PACK_MEMORY` | ninguno | Nombre anterior del límite de bytes de la caché de paquetes; solo se usa cuando `PITMASTER_PACK_RESOLVED_CACHE_BYTES` no está definido |

Los valores de bytes aceptan un entero o una cadena con el sufijo `k`, `m` o `g` (`'256M'`). Los valores no válidos usan el valor predeterminado.

Las variables de entorno prevalecen sobre las constantes de identidad: `PITMASTER_AUTHOR_NAME`, `PITMASTER_AUTHOR_EMAIL`, `PITMASTER_AUTHOR_DATE`, sus equivalentes `PITMASTER_COMMITTER_*` y las variables propias de git `GIT_AUTHOR_*` y `GIT_COMMITTER_*`. El transporte SSH lee las variables `PITMASTER_SSH_*`, descritas en [Protocolos](https://pitmaster.inline0.dev/es/docs/network/protocols).

No hay ninguna constante para el algoritmo de hash. El formato de objetos se elige al crear el repositorio (`Pitmaster::init($path, 'sha256')` o `init --object-format=sha256` en CLI) y luego se lee de la configuración del repositorio.
