Skip to content

Commit

Permalink
We can do minor semver-intersections
Browse files Browse the repository at this point in the history
Full algo is for someone else to write
  • Loading branch information
mxcl committed Sep 26, 2022
1 parent 9cbdf3b commit b97f856
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
19 changes: 15 additions & 4 deletions src/prefab/hydrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,25 @@ export default async function hydrate(
if (children.has(dep.project)) {
if (!bootstrap.has(dep.project)) {
console.warn(`${dep.project} must be bootstrapped to build ${node.project}`)

//TODO the boostrap should keep the version constraint since it may be different
bootstrap.add(dep.project)
}
} else {
/// we already traced this graph
const found = graph[dep.project]
if (found && found.count() < node.count()) {
found.parent = node
} else if (!found) {
if (found) {
/// we already traced this graph

if (found.count() < node.count()) {
found.parent = node
}

//FIXME strictly we only have to constrain graphs that contain linkage
// ie. you cannot have a binary that links two separate versions of eg. openssl
// or (maybe) services, eg. you might suffer if there are two versions of postgres running (though tea mitigates this)
found.pkg.constraint = semver.intersect(found.pkg.constraint, dep.constraint)

} else {
const new_node = new Node(dep, node)
graph[dep.project] = new_node
await ascend(new_node, new Set([...children, dep.project]))
Expand Down
53 changes: 47 additions & 6 deletions src/utils/semver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,24 @@ export default class SemVer {
return `${this.major}.${this.minor}.${this.patch}`
}

eq(other: SemVer): boolean {
return this.compare(other) == 0
eq(that: SemVer): boolean {
return this.compare(that) == 0
}

neq(other: SemVer): boolean {
return !this.eq(other)
neq(that: SemVer): boolean {
return !this.eq(that)
}

compare(other: SemVer): number {
return _compare(this, other)
gt(that: SemVer): boolean {
return this.compare(that) >= 0
}

lt(that: SemVer): boolean {
return this.compare(that) <= 0
}

compare(that: SemVer): number {
return _compare(this, that)
}

components(): [number, number, number] {
Expand Down Expand Up @@ -153,6 +161,20 @@ export class Range {
}
}

eq(that: Range): boolean {
if (this.set.length !== that.set.length) return false
for (let i = 0; i < this.set.length; i++) {
const [a,b] = [this.set[i], that.set[i]]
if (typeof a !== 'string' && typeof b !== 'string') {
if (a[0].neq(b[0])) return false
if (a[1].neq(b[1])) return false
} else if (a != b) {
return false
}
}
return true
}

satisfies(version: SemVer): boolean {
if (this.set === '*') {
return true
Expand All @@ -179,13 +201,32 @@ export class Range {
}
}


function _compare(a: SemVer, b: SemVer): number {
if (a.major != b.major) return a.major - b.major
if (a.minor != b.minor) return a.minor - b.minor
return a.patch - b.patch
}
export { _compare as compare }


export function intersect(a: Range, b: Range): Range {
if (b.set === '*') return a
if (a.set === '*') return b
if (a.eq(b)) return a

if (a.set.length == 1 && b.set.length == 1) {
const [c,d] = [a.set[0], b.set[0]]
const e = c[0].gt(d[0]) ? c[0] : d[0]
const f = c[1].gt(d[1]) ? c[1] : d[1]
a.set = [[e,f]]
return a
}

throw new Error(`couldn’t intersect ${a} and ${b}`)
}


//FIXME yes yes this is not sufficient
export const regex = /\d+\.\d+\.\d+/

Expand Down

0 comments on commit b97f856

Please sign in to comment.