Skip to content

Commit 99d7ff4

Browse files
authored
enable parcel file watcher, expand parcel ignore patterns, replace fs watcher for git branches with parcel (anomalyco#4805)
1 parent 3ff0eb3 commit 99d7ff4

File tree

5 files changed

+77
-62
lines changed

5 files changed

+77
-62
lines changed

packages/opencode/src/file/ignore.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export namespace FileIgnore {
66
"bower_components",
77
".pnpm-store",
88
"vendor",
9+
".npm",
910
"dist",
1011
"build",
1112
"out",
@@ -22,12 +23,21 @@ export namespace FileIgnore {
2223
".output",
2324
"desktop",
2425
".sst",
26+
".cache",
27+
".webkit-cache",
28+
"__pycache__",
29+
".pytest_cache",
30+
"mypy_cache",
31+
".history",
32+
".gradle",
2533
])
2634

2735
const FILES = [
2836
"**/*.swp",
2937
"**/*.swo",
3038

39+
"**/*.pyc",
40+
3141
// OS
3242
"**/.DS_Store",
3343
"**/Thumbs.db",

packages/opencode/src/file/watcher.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import z from "zod"
22
import { Bus } from "../bus"
3-
import { Flag } from "../flag/flag"
43
import { Instance } from "../project/instance"
54
import { Log } from "../util/log"
65
import { FileIgnore } from "./ignore"
76
import { Config } from "../config/config"
87
// @ts-ignore
98
import { createWrapper } from "@parcel/watcher/wrapper"
109
import { lazy } from "@/util/lazy"
10+
import type ParcelWatcher from "@parcel/watcher"
1111

1212
export namespace FileWatcher {
1313
const log = Log.create({ service: "file.watcher" })
@@ -44,32 +44,46 @@ export namespace FileWatcher {
4444
return {}
4545
}
4646
log.info("watcher backend", { platform: process.platform, backend })
47-
const sub = await watcher().subscribe(
48-
Instance.directory,
49-
(err, evts) => {
50-
if (err) return
51-
for (const evt of evts) {
52-
log.info("event", evt)
53-
if (evt.type === "create") Bus.publish(Event.Updated, { file: evt.path, event: "add" })
54-
if (evt.type === "update") Bus.publish(Event.Updated, { file: evt.path, event: "change" })
55-
if (evt.type === "delete") Bus.publish(Event.Updated, { file: evt.path, event: "unlink" })
56-
}
57-
},
58-
{
59-
ignore: [...FileIgnore.PATTERNS, ...(cfg.watcher?.ignore ?? [])],
47+
const subscribe: ParcelWatcher.SubscribeCallback = (err, evts) => {
48+
if (err) return
49+
for (const evt of evts) {
50+
log.info("event", evt)
51+
if (evt.type === "create") Bus.publish(Event.Updated, { file: evt.path, event: "add" })
52+
if (evt.type === "update") Bus.publish(Event.Updated, { file: evt.path, event: "change" })
53+
if (evt.type === "delete") Bus.publish(Event.Updated, { file: evt.path, event: "unlink" })
54+
}
55+
}
56+
57+
const subs = []
58+
const cfgIgnores = cfg.watcher?.ignore ?? []
59+
60+
subs.push(
61+
await watcher().subscribe(Instance.directory, subscribe, {
62+
ignore: [...FileIgnore.PATTERNS, ...cfgIgnores],
6063
backend,
61-
},
64+
}),
6265
)
63-
return { sub }
66+
67+
const vcsDir = Instance.project.vcsDir
68+
if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) {
69+
subs.push(
70+
await watcher().subscribe(vcsDir, subscribe, {
71+
ignore: ["hooks", "info", "logs", "objects", "refs", "worktrees", "modules", "lfs"],
72+
backend,
73+
}),
74+
)
75+
}
76+
77+
return { subs }
6478
},
6579
async (state) => {
66-
if (!state.sub) return
67-
await state.sub?.unsubscribe()
80+
if (!state.subs) return
81+
await Promise.all(state.subs.map((sub) => sub?.unsubscribe()))
6882
},
6983
)
7084

7185
export function init() {
72-
if (!Flag.OPENCODE_EXPERIMENTAL_WATCHER) return
86+
// if (!Flag.OPENCODE_EXPERIMENTAL_WATCHER) return
7387
state()
7488
}
7589
}

packages/opencode/src/project/project.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export namespace Project {
1212
.object({
1313
id: z.string(),
1414
worktree: z.string(),
15+
vcsDir: z.string().optional(),
1516
vcs: z.literal("git").optional(),
1617
time: z.object({
1718
created: z.number(),
@@ -80,9 +81,16 @@ export namespace Project {
8081
.cwd(worktree)
8182
.text()
8283
.then((x) => x.trim())
84+
const vcsDir = await $`git rev-parse --path-format=absolute --git-dir`
85+
.quiet()
86+
.nothrow()
87+
.cwd(worktree)
88+
.text()
89+
.then((x) => x.trim())
8390
const project: Info = {
8491
id,
8592
worktree,
93+
vcsDir,
8694
vcs: "git",
8795
time: {
8896
created: Date.now(),

packages/opencode/src/project/vcs.ts

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { $ } from "bun"
2-
import { watch, type FSWatcher } from "fs"
32
import path from "path"
43
import z from "zod"
54
import { Log } from "@/util/log"
65
import { Bus } from "@/bus"
76
import { Instance } from "./instance"
7+
import { FileWatcher } from "@/file/watcher"
88

99
const log = Log.create({ service: "vcs" })
1010

@@ -39,49 +39,31 @@ export namespace Vcs {
3939

4040
const state = Instance.state(
4141
async () => {
42-
if (Instance.project.vcs !== "git") {
43-
return { branch: async () => undefined, watcher: undefined }
42+
const vcsDir = Instance.project.vcsDir
43+
if (Instance.project.vcs !== "git" || !vcsDir) {
44+
return { branch: async () => undefined, unsubscribe: undefined }
4445
}
4546
let current = await currentBranch()
4647
log.info("initialized", { branch: current })
4748

48-
const gitDir = await $`git rev-parse --git-dir`
49-
.quiet()
50-
.nothrow()
51-
.cwd(Instance.worktree)
52-
.text()
53-
.then((x) => x.trim())
54-
.catch(() => undefined)
55-
if (!gitDir) {
56-
log.warn("failed to resolve git directory")
57-
return { branch: async () => current, watcher: undefined }
58-
}
59-
60-
const gitHead = path.join(gitDir, "HEAD")
61-
let watcher: FSWatcher | undefined
62-
// we should probably centralize file watching (see watcher.ts)
63-
// but parcel still marked experimental rn
64-
try {
65-
watcher = watch(gitHead, async () => {
66-
const next = await currentBranch()
67-
if (next !== current) {
68-
log.info("branch changed", { from: current, to: next })
69-
current = next
70-
Bus.publish(Event.BranchUpdated, { branch: next })
71-
}
72-
})
73-
log.info("watching", { path: gitHead })
74-
} catch (e) {
75-
log.warn("failed to watch git HEAD", { error: e })
76-
}
49+
const head = path.join(vcsDir, "HEAD")
50+
const unsubscribe = Bus.subscribe(FileWatcher.Event.Updated, async (evt) => {
51+
if (evt.properties.file !== head) return
52+
const next = await currentBranch()
53+
if (next !== current) {
54+
log.info("branch changed", { from: current, to: next })
55+
current = next
56+
Bus.publish(Event.BranchUpdated, { branch: next })
57+
}
58+
})
7759

7860
return {
7961
branch: async () => current,
80-
watcher,
62+
unsubscribe,
8163
}
8264
},
8365
async (state) => {
84-
state.watcher?.close()
66+
state.unsubscribe?.()
8567
},
8668
)
8769

packages/sdk/js/src/gen/types.gen.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,14 @@ export type EventSessionError = {
589589
}
590590
}
591591

592+
export type EventFileWatcherUpdated = {
593+
type: "file.watcher.updated"
594+
properties: {
595+
file: string
596+
event: "add" | "change" | "unlink"
597+
}
598+
}
599+
592600
export type EventVcsBranchUpdated = {
593601
type: "vcs.branch.updated"
594602
properties: {
@@ -647,14 +655,6 @@ export type EventServerConnected = {
647655
}
648656
}
649657

650-
export type EventFileWatcherUpdated = {
651-
type: "file.watcher.updated"
652-
properties: {
653-
file: string
654-
event: "add" | "change" | "unlink"
655-
}
656-
}
657-
658658
export type Event =
659659
| EventInstallationUpdated
660660
| EventInstallationUpdateAvailable
@@ -677,12 +677,12 @@ export type Event =
677677
| EventSessionDeleted
678678
| EventSessionDiff
679679
| EventSessionError
680+
| EventFileWatcherUpdated
680681
| EventVcsBranchUpdated
681682
| EventTuiPromptAppend
682683
| EventTuiCommandExecute
683684
| EventTuiToastShow
684685
| EventServerConnected
685-
| EventFileWatcherUpdated
686686

687687
export type GlobalEvent = {
688688
directory: string
@@ -692,6 +692,7 @@ export type GlobalEvent = {
692692
export type Project = {
693693
id: string
694694
worktree: string
695+
vcsDir?: string
695696
vcs?: "git"
696697
time: {
697698
created: number

0 commit comments

Comments
 (0)