aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: 0fd0e23a171e00b880eaf26ed5a87eb9c4048b73 (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
# 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