70fde2221e
Update `findLatestCompatCommit` to use semantic versioning when identifying the latest compatibility commit. This ensures the correct commit is selected even when upstream tags diverge or are not strictly linear. - Add semver parsing and comparison utilities - Implement `targetSemver` to resolve versions from tags or commit messages - Filter and sort compatibility candidates by version relative to the target version - Add test case for diverging upstream tags
111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
import { afterEach, beforeEach, expect, test } from "bun:test"
|
|
import { mkdtemp, rm } from "node:fs/promises"
|
|
import { join } from "node:path"
|
|
import { tmpdir } from "node:os"
|
|
import { $ } from "bun"
|
|
import {
|
|
createCommit,
|
|
findLatestCompatCommit,
|
|
getCommitHash,
|
|
getCommitParents,
|
|
isAncestor,
|
|
recordAncestor,
|
|
updateBranch,
|
|
writeTree,
|
|
} from "./git"
|
|
|
|
const cwd = process.cwd()
|
|
let dir = ""
|
|
|
|
async function commit(message: string) {
|
|
await $`git add -A`.quiet()
|
|
await $`git -c user.name=Test -c user.email=test@example.com commit -m ${message}`.quiet()
|
|
return getCommitHash("HEAD")
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
dir = await mkdtemp(join(tmpdir(), "kilo-upstream-git-"))
|
|
process.chdir(dir)
|
|
await $`git init -b upstream`.quiet()
|
|
await $`git config user.name Test`.quiet()
|
|
await $`git config user.email test@example.com`.quiet()
|
|
})
|
|
|
|
afterEach(async () => {
|
|
process.chdir(cwd)
|
|
await rm(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
test("finds previous compatibility commit for transformed base", async () => {
|
|
await Bun.write("brand.txt", "opencode A\n")
|
|
const old = await commit("release: v1.0.0")
|
|
|
|
await Bun.write("brand.txt", "opencode B\n")
|
|
const target = await commit("release: v1.0.1")
|
|
await $`git tag v1.0.1 ${target}`.quiet()
|
|
|
|
await $`git checkout -b main ${old}`.quiet()
|
|
await $`git tag v1.0.0 ${old}`.quiet()
|
|
await Bun.write("brand.txt", "kilo A\n")
|
|
const prior = await commit("refactor: kilo compat for v1.0.0")
|
|
|
|
const found = await findLatestCompatCommit("main", target)
|
|
expect(found?.commit).toBe(prior)
|
|
expect(found?.upstream).toBe(old)
|
|
|
|
await $`git checkout ${target}`.quiet()
|
|
await $`git checkout -b opencode-v1.0.1`.quiet()
|
|
await Bun.write("brand.txt", "kilo B\n")
|
|
await $`git add -A`.quiet()
|
|
const tree = await writeTree()
|
|
const next = await createCommit(tree, "refactor: kilo compat for v1.0.1", prior)
|
|
await updateBranch("opencode-v1.0.1", next)
|
|
const base = (await $`git merge-base main opencode-v1.0.1`.text()).trim()
|
|
expect(base).toBe(prior)
|
|
expect(await getCommitParents(next)).toEqual([prior])
|
|
|
|
await $`git checkout main`.quiet()
|
|
expect(await recordAncestor(target, "merge: record upstream v1.0.1")).toBe(true)
|
|
const link = await getCommitHash("HEAD")
|
|
expect(await getCommitParents(link)).toEqual([prior, target])
|
|
expect(await isAncestor(target, link)).toBe(true)
|
|
|
|
const linked = (await $`git merge-base main opencode-v1.0.1`.text()).trim()
|
|
expect(linked).toBe(prior)
|
|
|
|
await $`git merge opencode-v1.0.1`.quiet()
|
|
const head = await getCommitHash("HEAD")
|
|
expect(await getCommitParents(head)).toEqual([link, next])
|
|
expect(await isAncestor(target, head)).toBe(true)
|
|
})
|
|
|
|
test("finds previous compatibility commit when upstream tags diverge", async () => {
|
|
await Bun.write("brand.txt", "opencode 1.4.9\n")
|
|
const old = await commit("release: v1.4.9")
|
|
await $`git tag v1.4.9 ${old}`.quiet()
|
|
|
|
await $`git checkout -b release-30 ${old}`.quiet()
|
|
await Bun.write("brand.txt", "opencode 1.14.30\n")
|
|
const side = await commit("release: v1.14.30")
|
|
await $`git tag v1.14.30 ${side}`.quiet()
|
|
|
|
await $`git checkout -b release-31 ${old}`.quiet()
|
|
await Bun.write("brand.txt", "opencode 1.14.31\n")
|
|
const target = await commit("release: v1.14.31")
|
|
await $`git tag v1.14.31 ${target}`.quiet()
|
|
|
|
await $`git checkout -b main ${old}`.quiet()
|
|
await Bun.write("brand.txt", "kilo 1.4.9\n")
|
|
const ancient = await commit("refactor: kilo compat for v1.4.9")
|
|
await Bun.write("brand.txt", "kilo 1.14.30\n")
|
|
const prior = await commit("refactor: kilo compat for v1.14.30")
|
|
|
|
expect(await isAncestor(side, target)).toBe(false)
|
|
expect(await isAncestor(old, target)).toBe(true)
|
|
|
|
const found = await findLatestCompatCommit("main", target)
|
|
expect(found?.commit).toBe(prior)
|
|
expect(found?.upstream).toBe(side)
|
|
expect(found?.commit).not.toBe(ancient)
|
|
})
|