Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ const { pkgs: tree } = await hydrate(pkg)
const { installed, pending } = await resolve(tree)

for (const pkg of pending) {
const install = await install(pkg)
const installation = await install(pkg)
// ^^ install packages that aren’t yet installed
// ^^ takes a logger parameter so you can show progress to the user
// ^^ you could do these in parallel to speed things up
// ^^ by default, versioned installs go to ~/.tea, separated from the user’s system. The install location can be customized, see next section.
installed.push(install)
await link(installation)
// ^^ creates v*, vx, vx.y symlinks ∵ some packages depend on this
installed.push(installation)
}

const { map, flatten } = useShellEnv()
Expand Down
3 changes: 2 additions & 1 deletion src/prefab/install.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Deno.test("install()", async runner => {
assertEquals(installation.pkg.version, pkg.version)
assertEquals(installation.path, conf.prefix.join(pkg.project, `v${pkg.version}`))

installation.path.rm({ recursive: true })
/// so next test works
installation.path.rm({ recursive: true })

stubber.restore()
})
Expand Down
37 changes: 37 additions & 0 deletions src/prefab/link.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useTestConfig } from "../hooks/useConfig.test.ts"
import { assert } from "deno/testing/asserts.ts"
import SemVer from "../utils/semver.ts"
import { Package } from "../types.ts"
import install from "./install.ts"
import link from "./link.ts";

Deno.test("link()", async runner => {
const pkg: Package = {
project: "tea.xyz/brewkit",
version: new SemVer("0.30.0")
}

await runner.step("link()", async () => {
useTestConfig()

const installation = await install(pkg)
await link(installation)
await link(installation) // calling twice works

/// test symlinks work
assert(installation.path.parent().join("v*").isDirectory())
assert(installation.path.parent().join(`v${pkg.version.major}`).isDirectory())
})

await runner.step("link() ×2 at once", async () => {
const installation = await install(pkg)
const p1 = link(installation)
const p2 = link(installation)

await Promise.all([p1, p2])

/// test symlinks work
assert(installation.path.parent().join("v*").isDirectory())
assert(installation.path.parent().join(`v${pkg.version.major}`).isDirectory())
})
})
18 changes: 14 additions & 4 deletions src/prefab/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,19 @@ export default async function link(pkg: Package | Installation) {
}

async function makeSymlink(symname: string) {
await Deno.symlink(
installation.path.basename(),
shelf.join(symname).rm().string,
{type: 'dir'})
try {
await Deno.symlink(
installation.path.basename(), // makes it relative
shelf.join(symname).rm().string,
{type: 'dir'})
} catch (err) {
if (err instanceof Deno.errors.AlreadyExists) {
//FIXME race condition for installing the same pkg simultaneously
// real fix is to lock around the entire download/untar/link process
return
} else {
throw err
}
}
}
}