opencode-repos 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +17 -7
- package/package.json +27 -27
- package/src/manifest.ts +21 -19
package/index.ts
CHANGED
|
@@ -333,7 +333,8 @@ async function ensureRepoAvailable(
|
|
|
333
333
|
cacheDir: string,
|
|
334
334
|
useHttps: boolean,
|
|
335
335
|
autoSyncOnExplore: boolean,
|
|
336
|
-
autoSyncIntervalHours: number
|
|
336
|
+
autoSyncIntervalHours: number,
|
|
337
|
+
explicitBranch?: string
|
|
337
338
|
): Promise<{
|
|
338
339
|
repoPath: string
|
|
339
340
|
branch: string
|
|
@@ -350,7 +351,8 @@ async function ensureRepoAvailable(
|
|
|
350
351
|
let actualBranch = branch
|
|
351
352
|
try {
|
|
352
353
|
await withManifestLock(async () => {
|
|
353
|
-
const
|
|
354
|
+
const cloneOptions = explicitBranch ? { branch: explicitBranch } : {}
|
|
355
|
+
const cloneResult = await cloneRepo(url, repoPath, cloneOptions)
|
|
354
356
|
actualBranch = cloneResult.branch
|
|
355
357
|
|
|
356
358
|
const now = new Date().toISOString()
|
|
@@ -957,7 +959,8 @@ When user mentions another project or asks about external code:
|
|
|
957
959
|
},
|
|
958
960
|
async execute(args) {
|
|
959
961
|
const spec = parseRepoSpec(args.repo)
|
|
960
|
-
const
|
|
962
|
+
const explicitBranch = spec.branch
|
|
963
|
+
const branch = explicitBranch || defaultBranch
|
|
961
964
|
const repoKey = `${spec.owner}/${spec.repo}`
|
|
962
965
|
|
|
963
966
|
const result = await withManifestLock(async () => {
|
|
@@ -992,7 +995,8 @@ When user mentions another project or asks about external code:
|
|
|
992
995
|
|
|
993
996
|
let actualBranch = branch
|
|
994
997
|
try {
|
|
995
|
-
const
|
|
998
|
+
const cloneOptions = explicitBranch ? { branch: explicitBranch } : {}
|
|
999
|
+
const cloneResult = await cloneRepo(url, destPath, cloneOptions)
|
|
996
1000
|
actualBranch = cloneResult.branch
|
|
997
1001
|
} catch (error) {
|
|
998
1002
|
const message =
|
|
@@ -1842,6 +1846,7 @@ Provide either \`query\` or a non-empty \`repos\` list.`
|
|
|
1842
1846
|
const targets: Array<{
|
|
1843
1847
|
repoKey: string
|
|
1844
1848
|
branch: string
|
|
1849
|
+
explicitBranch?: string
|
|
1845
1850
|
source?: RepoSource
|
|
1846
1851
|
remote?: string
|
|
1847
1852
|
path?: string
|
|
@@ -1862,6 +1867,7 @@ Provide either \`query\` or a non-empty \`repos\` list.`
|
|
|
1862
1867
|
targets.push({
|
|
1863
1868
|
repoKey: `${spec.owner}/${spec.repo}`,
|
|
1864
1869
|
branch: spec.branch || defaultBranch,
|
|
1870
|
+
explicitBranch: spec.branch ?? undefined,
|
|
1865
1871
|
})
|
|
1866
1872
|
debugInfo.selectedTargets.push({
|
|
1867
1873
|
repoKey: `${spec.owner}/${spec.repo}`,
|
|
@@ -1930,7 +1936,8 @@ Failed to parse \`${repo}\`: ${message}`
|
|
|
1930
1936
|
cacheDir,
|
|
1931
1937
|
useHttps,
|
|
1932
1938
|
autoSyncOnExplore,
|
|
1933
|
-
autoSyncIntervalHours
|
|
1939
|
+
autoSyncIntervalHours,
|
|
1940
|
+
target.explicitBranch
|
|
1934
1941
|
)
|
|
1935
1942
|
|
|
1936
1943
|
await requestExternalDirectoryAccess(
|
|
@@ -2067,6 +2074,7 @@ Be more specific or pass an explicit list with \`repos\`.
|
|
|
2067
2074
|
targets.push({
|
|
2068
2075
|
repoKey: selected.key,
|
|
2069
2076
|
branch,
|
|
2077
|
+
explicitBranch: branchOverride ?? undefined,
|
|
2070
2078
|
source: selected.source,
|
|
2071
2079
|
remote: selected.remote,
|
|
2072
2080
|
path: selected.path,
|
|
@@ -2099,7 +2107,8 @@ Be more specific or pass an explicit list with \`repos\`.
|
|
|
2099
2107
|
cacheDir,
|
|
2100
2108
|
useHttps,
|
|
2101
2109
|
autoSyncOnExplore,
|
|
2102
|
-
autoSyncIntervalHours
|
|
2110
|
+
autoSyncIntervalHours,
|
|
2111
|
+
target.explicitBranch
|
|
2103
2112
|
)
|
|
2104
2113
|
|
|
2105
2114
|
await requestExternalDirectoryAccess(
|
|
@@ -2181,7 +2190,8 @@ Be more specific or pass an explicit list with \`repos\`.
|
|
|
2181
2190
|
cacheDir,
|
|
2182
2191
|
useHttps,
|
|
2183
2192
|
autoSyncOnExplore,
|
|
2184
|
-
autoSyncIntervalHours
|
|
2193
|
+
autoSyncIntervalHours,
|
|
2194
|
+
spec.branch ?? undefined
|
|
2185
2195
|
)
|
|
2186
2196
|
repoPath = resolved.repoPath
|
|
2187
2197
|
await requestExternalDirectoryAccess(ctx as PermissionContext, repoPath)
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
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
|
-
|
|
2
|
+
"name": "opencode-repos",
|
|
3
|
+
"version": "0.3.3",
|
|
4
|
+
"description": "Repository cache, registry, and cross-codebase intelligence for OpenCode agents",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"opencode",
|
|
9
|
+
"opencode-plugin",
|
|
10
|
+
"repos",
|
|
11
|
+
"repository",
|
|
12
|
+
"cache",
|
|
13
|
+
"codebase"
|
|
14
|
+
],
|
|
15
|
+
"author": "Liam Vinberg",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/liamjv1/opencode-repos"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@opencode-ai/plugin": "*"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@opencode-ai/plugin": "^1.1.25",
|
|
26
|
+
"@types/bun": "^1.2.0",
|
|
27
|
+
"typescript": "^5.0.0"
|
|
28
|
+
}
|
|
29
29
|
}
|
package/src/manifest.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { homedir } from "node:os"
|
|
2
2
|
import { join } from "node:path"
|
|
3
|
-
import { mkdir, rename, unlink, stat } from "node:fs/promises"
|
|
3
|
+
import { mkdir, rename, unlink, stat, open } from "node:fs/promises"
|
|
4
4
|
|
|
5
5
|
export interface RepoEntry {
|
|
6
6
|
type: "cached" | "local"
|
|
@@ -27,7 +27,7 @@ let cacheDir = join(homedir(), ".cache", "opencode-repos")
|
|
|
27
27
|
let manifestPath = join(cacheDir, "manifest.json")
|
|
28
28
|
let manifestTmpPath = join(cacheDir, "manifest.json.tmp")
|
|
29
29
|
let lockPath = join(cacheDir, "manifest.lock")
|
|
30
|
-
const LOCK_STALE_MS =
|
|
30
|
+
const LOCK_STALE_MS = 30_000
|
|
31
31
|
|
|
32
32
|
function createEmptyManifest(): Manifest {
|
|
33
33
|
return {
|
|
@@ -72,31 +72,33 @@ async function isLockStale(): Promise<boolean> {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
async function acquireLock(): Promise<void> {
|
|
75
|
-
const maxAttempts =
|
|
76
|
-
const retryDelayMs =
|
|
75
|
+
const maxAttempts = 150
|
|
76
|
+
const retryDelayMs = 200
|
|
77
|
+
|
|
78
|
+
await mkdir(cacheDir, { recursive: true })
|
|
77
79
|
|
|
78
80
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
try {
|
|
82
|
+
const fd = await open(lockPath, "wx")
|
|
83
|
+
await fd.write(String(process.pid))
|
|
84
|
+
await fd.close()
|
|
85
|
+
return
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const code = (error as NodeJS.ErrnoException).code
|
|
88
|
+
if (code !== "EEXIST") {
|
|
89
|
+
throw error
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
|
|
92
|
-
await
|
|
93
|
-
|
|
94
|
-
return
|
|
95
|
-
} catch {
|
|
96
|
-
await Bun.sleep(retryDelayMs)
|
|
93
|
+
if (await isLockStale()) {
|
|
94
|
+
await unlink(lockPath).catch(() => {})
|
|
95
|
+
continue
|
|
97
96
|
}
|
|
97
|
+
|
|
98
|
+
await Bun.sleep(retryDelayMs)
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
await unlink(lockPath).catch(() => {})
|
|
100
102
|
throw new Error("Failed to acquire manifest lock after maximum attempts")
|
|
101
103
|
}
|
|
102
104
|
|