# sourcewatch

A file synchronization tool that watches a Windows source directory and syncs changes to a Docker container via Unix socket IPC. Respects `.gitignore` rules.

## Architecture

```
Windows Host                          Docker Container
┌─────────────────────┐              ┌─────────────────────────┐
│ sourcewatch.exe     │              │ sourcewatch (linux)     │
│   watches C:\src    │   AF_UNIX    │   - receives manifest   │
│   ReadDirectory     │◄────────────►│   - syncs changed files │
│     ChangesW        │   socket     │   - listens for events  │
└─────────────────────┘              └─────────────────────────┘
```

1. **Windows binary** scans source directory (fast native NTFS) and sends file metadata
2. **Container** compares with local state, copies only changed files
3. **Windows binary** watches for changes, sends events over socket
4. **Container** receives events and syncs in real-time

## Building

### Windows binary (sourcewatch.exe)

```bash
# From Windows (Git Bash, PowerShell, or cmd)
go build -o sourcewatch.exe .

# Cross-compile from Linux/Mac
GOOS=windows GOARCH=amd64 go build -o sourcewatch.exe .
```

Requires Go 1.24+ and `github.com/fsnotify/fsnotify` (automatically downloaded).

### Docker/Podman image (linux container)

```bash
# Build image
docker build -t sourcewatch .

# Or with Podman
podman build -t sourcewatch .
```

## Usage

### Step 1: Build the Windows binary

```bash
GOOS=windows GOARCH=amd64 go build -o sourcewatch.exe .
```

### Step 2: Start the Windows watcher

```bash
# PowerShell
.\sourcewatch.exe -dir C:\myproject -socket D:\sourcewatch.sock

# Git Bash
./sourcewatch.exe -dir /c/myproject -socket /d/sourcewatch.sock
```

### Step 3: Start the container

```bash
docker run -d \
  -v D:\sourcewatch.sock:/run/sourcewatch.sock \
  -v C:\myproject:/host:ro \
  -v project-data:/data \
  sourcewatch
```

Or with Podman:

```bash
podman run -d \
  -v D:\sourcewatch.sock:/run/sourcewatch.sock \
  -v C:\myproject:/host:ro \
  -v project-data:/data \
  sourcewatch
```

### Standalone mode (no Windows watcher)

If you don't need real-time watching, run without `-socket`:

```bash
docker run -v /path/to/source:/host:ro -v data:/data sourcewatch
```

## Flags

### Windows binary (sourcewatch.exe)

```
-dir string       Source directory to watch (required)
-socket string    Unix socket path to serve events on (required)
-log-level string Log level: debug, info, warn, error, none (default "info")
-verbose          Enable verbose logging (shorthand for -log-level debug)
```

### Container (sourcewatch)

```
-host string       Host source directory (default "/host")
-data string       Data destination directory (default "/data")
-socket string     Unix socket to receive events from (default "/run/sourcewatch.sock")
-verbose           Enable verbose logging (shorthand for -log-level debug)
-log-level string  Log level: debug, info, warn, error, none (default "info")
-dry-run           Preview what would be synced without copying
```

## Protocol

Communication uses newline-delimited JSON over Unix socket:

```json
{"type":"manifest","files":{"path":{"size":1234,"modtime":"2024-01-01T00:00:00Z","mode":"0644"}}}
{"type":"manifest_done"}
{"type":"event_create","path":"new/file.go"}
{"type":"event_write","path":"modified/file.go"}
{"type":"event_remove","path":"deleted/file.go"}
```

## .gitignore support

- Full gitignore spec: `*`, `**`, `[]`, `!` negation
- Nested `.gitignore` files (child patterns override parents)
- Patterns scoped to their directory
- `.git` directory always skipped

Example `.gitignore`:
```
*.log
build/
!important.log
```

## Limitations

- One-way sync only (`/host` → `/data`)
- `/host` must be read-only
- `?` single-character wildcard not supported (go-gitignore limitation)
- Windows binary requires Go 1.24+ to build

## License

MIT
