aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: d0bcd01fb7401bbb7307745ca4df083daba982c4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# 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