# 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     │     TCP      │ sourcewatch (linux)     │
│   watches C:\src    │◄────────────►│   - receives manifest   │
│   ReadDirectory     │  connect     │   - syncs changed files │
│     ChangesW        │  :5151       │   - listens for events  │
└─────────────────────┘              └─────────────────────────┘
```

1. **Container** starts and listens on TCP port 5151
2. **Windows binary** connects to container, scans source directory (fast native NTFS), sends file metadata
3. **Container** compares with local state, copies only changed files
4. **Windows binary** watches for changes, sends events over TCP
5. **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 container

```bash
docker run -d -p 5151:5151 \
  -v C:\myproject:/host:ro \
  -v project-data:/data \
  sourcewatch
```

Or with Podman:

```bash
podman run -d -p 5151:5151 \
  -v C:\myproject:/host:ro \
  -v project-data:/data \
  sourcewatch
```

### Step 3: Start the Windows watcher

```powershell
# PowerShell
.\sourcewatch.exe -dir C:\myproject -connect localhost:5151

# Git Bash
./sourcewatch.exe -dir /c/myproject -connect localhost:5151
```

### Standalone mode (no Windows watcher)

If you don't need real-time watching, run with `-listen ""`:

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

## Flags

### Windows binary (sourcewatch.exe)

```
-dir string       Source directory to watch (required)
-connect string   TCP address of the container (default "localhost:5151")
-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")
-listen string     TCP address to listen on (default ":5151")
-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 TCP:

```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.21+ to build

## License

MIT
