mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-30 17:14:40 +08:00
feat(upstream): record last merged tag in .opencode-version
Avoids the ls-remote + merge-base --is-ancestor walk in last() for the common case by reading the recorded tag from .opencode-version. merge.ts writes the file as part of the pre-merge compat commit so future runs of fix-kilocode-markers, reset-to-upstream, and find-reset-candidates can resolve the base tag instantly. Seeded with v1.14.33 (PR #9978).
This commit is contained in:
@@ -0,0 +1 @@
|
||||
v1.14.33
|
||||
@@ -243,7 +243,9 @@ Options:
|
||||
--dry-run Show what would change without writing the file
|
||||
```
|
||||
|
||||
The command finds the newest upstream tag already merged into `HEAD`, reads that upstream version of the file, applies the same branding transforms used by upstream merge automation, strips existing `kilocode_change` markers from the current file, and adds fresh markers around the remaining lines that differ from upstream.
|
||||
The command finds the newest upstream tag already merged into `HEAD` (read from `.opencode-version` at the repo root, falling back to an `ls-remote` + `merge-base --is-ancestor` walk), reads that upstream version of the file, applies the same branding transforms used by upstream merge automation, strips existing `kilocode_change` markers from the current file, and adds fresh markers around the remaining lines that differ from upstream.
|
||||
|
||||
The `.opencode-version` file is a single-line tag (e.g. `v1.14.33`) recorded by `merge.ts` after every successful upstream merge. Editing it by hand pins the "last merged" tag for the per-file commands above; delete it to fall back to the slower automatic discovery.
|
||||
|
||||
### reset-to-upstream.ts
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import { transformConflictedScripts, transformAllScripts } from "./transforms/tr
|
||||
import { transformConflictedExtensions, transformAllExtensions } from "./transforms/transform-extensions"
|
||||
import { transformConflictedWeb, transformAllWeb } from "./transforms/transform-web"
|
||||
import { resolveLockFileConflicts, regenerateLockFiles } from "./transforms/lock-files"
|
||||
import { writeVersion } from "./utils/upstream"
|
||||
|
||||
interface MergeOptions {
|
||||
version?: string
|
||||
@@ -508,6 +509,11 @@ async function main() {
|
||||
const keepOursResults = await resetToOurs(config.keepOurs, { dryRun: false, verbose: options.verbose })
|
||||
logger.success(`Reset ${keepOursResults.length} files to Kilo's version`)
|
||||
|
||||
// 6k. Record the last merged upstream tag so future automation can find it
|
||||
// without walking ls-remote + isAncestor for every tag.
|
||||
const versionFile = await writeVersion(targetVersion.tag)
|
||||
logger.success(`Recorded ${targetVersion.tag} in ${versionFile.split("/").pop()}`)
|
||||
|
||||
// Clean untracked build artifacts from Kilo-specific directories.
|
||||
// These packages don't exist in upstream, so their .gitignore files are absent
|
||||
// on the opencode branch. Artifacts like bin/, out/, .next/ etc. would otherwise
|
||||
|
||||
@@ -15,6 +15,12 @@ import { isAncestor } from "./git"
|
||||
const url = "https://github.com/anomalyco/opencode.git"
|
||||
const workflows = [".github/workflows/publish.yml", ".github/workflows/beta.yml"]
|
||||
|
||||
/**
|
||||
* Repo-relative path of the file that records the last merged upstream tag.
|
||||
* Single line containing the upstream tag (e.g. `v1.14.33`).
|
||||
*/
|
||||
export const versionFile = ".opencode-version"
|
||||
|
||||
export async function root() {
|
||||
return (await $`git rev-parse --show-toplevel`.text()).trim()
|
||||
}
|
||||
@@ -39,6 +45,9 @@ export async function remote() {
|
||||
}
|
||||
|
||||
export async function last(): Promise<VersionInfo> {
|
||||
const recorded = await readVersionFile()
|
||||
if (recorded) return recorded
|
||||
|
||||
const source = await remote()
|
||||
|
||||
info(`Fetching upstream tags from ${source}...`)
|
||||
@@ -53,6 +62,59 @@ export async function last(): Promise<VersionInfo> {
|
||||
throw new Error("Could not find a merged upstream tag in HEAD")
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the recorded last-merged upstream tag from `.opencode-version`. Returns
|
||||
* null if the file is missing/empty, or if the recorded tag cannot be resolved
|
||||
* to a commit (e.g. tags have not been fetched yet). Falls back to the
|
||||
* isAncestor-based discovery in `last()`.
|
||||
*/
|
||||
async function readVersionFile(): Promise<VersionInfo | null> {
|
||||
const repo = await root()
|
||||
const file = Bun.file(`${repo}/${versionFile}`)
|
||||
if (!(await file.exists())) return null
|
||||
|
||||
const tag = (await file.text()).trim()
|
||||
if (!tag) return null
|
||||
|
||||
const version = parseVersion(tag)
|
||||
if (!version) {
|
||||
warn(`${versionFile} contains '${tag}' which is not a valid version tag; ignoring`)
|
||||
return null
|
||||
}
|
||||
|
||||
const commit = await resolveTag(tag)
|
||||
if (!commit) return null
|
||||
|
||||
return { version, tag, commit }
|
||||
}
|
||||
|
||||
async function resolveTag(tag: string): Promise<string | null> {
|
||||
const local = await $`git rev-parse --verify --quiet ${tag}^{commit}`.quiet().nothrow()
|
||||
if (local.exitCode === 0) return local.stdout.toString().trim()
|
||||
|
||||
const source = await remote()
|
||||
info(`Tag ${tag} not present locally; fetching from ${source}...`)
|
||||
const fetch = await $`git fetch ${source} tag ${tag} --no-tags`.quiet().nothrow()
|
||||
if (fetch.exitCode !== 0) {
|
||||
warn(`Failed to fetch tag ${tag}: ${fetch.stderr.toString()}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const after = await $`git rev-parse --verify --quiet ${tag}^{commit}`.quiet().nothrow()
|
||||
return after.exitCode === 0 ? after.stdout.toString().trim() : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the merged upstream tag in `.opencode-version` so subsequent runs of
|
||||
* `last()` resolve instantly without an `ls-remote` walk.
|
||||
*/
|
||||
export async function writeVersion(tag: string): Promise<string> {
|
||||
const repo = await root()
|
||||
const path = `${repo}/${versionFile}`
|
||||
await Bun.write(path, `${tag}\n`)
|
||||
return path
|
||||
}
|
||||
|
||||
export async function versions(source: string): Promise<VersionInfo[]> {
|
||||
const result = await $`git ls-remote --tags ${source}`.quiet().nothrow()
|
||||
if (result.exitCode !== 0) throw new Error(`Failed to list upstream tags: ${result.stderr.toString()}`)
|
||||
|
||||
Reference in New Issue
Block a user