12. Packages
A package is a git repository containing Korrin source that another
program can import. This section is the normative description of the
manifest, the lockfile, how a bare import specifier resolves once packages
exist, and the korrin pkg command that manages them
(ADR 0031,
ADR 0032).
Packages are pure Korrin source. There is no way, as of this milestone, to write a package in Rust and ship it — that is future work.
12.1 The manifest: korrin.toml
A directory with a korrin.toml and a src/lib.kor is a package.
[package]
name = "requests"
version = "0.3.0"
[dependencies]
json = { git = "https://github.com/alice/korrin-json", tag = "v1.2.0" }
[package].nameand[package].versionare the package's own declared identity. They play no role in how a dependent resolvesimport— see §12.3.[dependencies]is a table of local name → source. Each entry needs agitURL and exactly one oftag,branch, orrev. A package's own[dependencies]table must be empty — see §12.4.- The entry file is always
src/lib.kor, regardless of[package].name.
12.2 The lockfile: korrin.lock
# @generated by `korrin pkg` — do not edit by hand.
version = 1
[[package]]
name = "json"
git = "https://github.com/alice/korrin-json"
rev = "a1b2c3d4e5f6..."
path = ".korrin/packages/json"
korrin.lock pins the exact commit resolved for every dependency, even one
specified in korrin.toml by tag or branch. korrin pkg install writes
it; korrin pkg update is the only command that moves an existing pin. An
application commits korrin.lock; a package intended to be depended on does
not.
Fetched packages are checked out locally at .korrin/packages/<name>/, next
to the korrin.toml that declares them.
12.3 Resolution: one merged namespace
import_statement = "import" , STRING , [ "as" , NAME ] ;
Extends §11.1's resolution
rule with a third outcome for a bare (non-./) specifier:
./…or../…— a file, as §11.1 describes. Unchanged.- anything else — checked against the built-in module table
(§11.4, §11.5)
first, then against the current package's installed dependencies. No new
syntax distinguishes the two —
import "math"andimport "requests"are written identically. A name cannot appear in both tables:korrin pkg add/installrefuses to add a dependency whose local name collides with a built-in module's name (ADR 0032). A name in neither table isE0314.
import "not_a_real_package"
# error: E0314
A package's own bare imports resolve against that package's installed
dependencies (from its own korrin.toml/korrin.lock), not the top-level
program's — but since packages are leaf-only (§12.4), a package's own
[dependencies] table is always empty, so in practice a package's bare
imports can only ever reach built-in modules. A package's relative
(./) imports resolve against its own directory, exactly like any other
file's.
12.4 Leaf-only packages
A package's own korrin.toml must declare an empty (or absent)
[dependencies] table. korrin pkg add/install rejects a package that
declares one:
korrin pkg: "json" (https://github.com/alice/korrin-json) declares
dependencies of its own — packages with dependencies are not supported
in Milestone 5
A package may depend on nothing. Depending on another package is not yet possible for a package itself, only for a top-level program.
12.5 The korrin pkg command
| Command | Effect |
|---|---|
korrin pkg add <git-url> [--tag T | --branch B | --rev R] [--name NAME] | Adds a dependency to korrin.toml and resolves it into korrin.lock. NAME defaults to the repository's basename. |
korrin pkg remove <name> | Removes a dependency and re-resolves korrin.lock. |
korrin pkg install | Fetches everything korrin.toml declares that isn't already checked out at its pinned commit; writes or refreshes korrin.lock. |
korrin pkg update [name] | Re-resolves a tag- or branch-pinned dependency to its current tip commit. Updates every dependency if name is omitted. |
korrin pkg list | Prints each resolved dependency: name, git URL, pinned commit, local path. |
korrin pkg operations that fail (an unreachable git URL, a malformed
manifest, a rejected leaf-only or name-collision dependency) print a message
to standard error and exit non-zero. They are not Korrin diagnostics — there
is no source span to point at, since nothing runs a Korrin program during
korrin pkg add/install/update.
12.6 Errors
An installed-package import that cannot be resolved — no such name in the
lockfile, the checkout is missing on disk, or the package's src/lib.kor
fails to compile — is E0314, the same code a bad ./ or
built-in specifier already raises: all three are the same category of
problem ("this import could not be resolved, read, or compiled"), not
three different ones. A cycle that crosses from a program into a package and
back is E0315, exactly as for files (§11.6).