pkgmanager

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package pkgmanager implements luascript's git/URL-based package manager: the `luascript pkg add/install/remove` subcommands. It is deliberately server-less — a package is just a git repository (or any URL git can clone). Dependencies are recorded in a JSON manifest and pinned to exact commits in a JSON lockfile so installs are reproducible.

The runtime side needs no cooperation: packages are cloned into `./lua_modules/<name>`, which `vm/loader.go` already searches via package.path. Installing a package and `require`-ing it are fully decoupled.

JSON (not a `.lsc` table) is used for both files because the tool must round-trip them — read, mutate one dependency, write back — and hand- emitting Lua table literals from Go would not preserve formatting or comments anyway. Humans edit the manifest; the tool owns the lockfile.

Index

Constants

View Source
const LockName = "luascript-lock.json"

LockName pins each resolved dependency to an exact commit.

View Source
const ManifestName = "luascript.json"

ManifestName is the per-project dependency manifest, human-editable.

View Source
const ModulesDir = "lua_modules"

ModulesDir is the install root. It matches the `./lua_modules/...` entries added to baseSearchPath in vm/loader.go.

Variables

This section is empty.

Functions

This section is empty.

Types

type Env

type Env struct {
	Root    string
	Fetcher Fetcher
	Logf    func(format string, args ...any)
}

Env carries everything the commands operate on: the project root (where the manifest, lockfile, and lua_modules/ live), the Fetcher to clone with, and an optional progress logger. A zero Logf means silent.

func (*Env) Add

func (e *Env) Add(specStr, name string) error

Add fetches a single package, installs it under lua_modules/<name>, and records it in both the manifest and the lockfile. name may be "" to derive it from the spec's last path segment.

func (*Env) Install

func (e *Env) Install() error

Install fetches every dependency listed in the manifest that is not already present under lua_modules/. When the lockfile pins a commit for a package, that exact commit is checked out (reproducible install); otherwise the manifest's ref is resolved and written back to the lock.

func (*Env) Remove

func (e *Env) Remove(name string) error

Remove deletes the installed package and drops it from the manifest and lockfile. Removing something that is not installed still prunes the manifest/lock entries (and is not an error).

type Fetcher

type Fetcher interface {
	Fetch(spec Spec, destDir string) (commit string, err error)
}

Fetcher clones a package's source into destDir and reports the exact commit it landed on. destDir must not already exist; the fetcher creates it. The interface exists so command orchestration can be tested without a network or a git binary (see fakeFetcher in the tests).

type GitFetcher

type GitFetcher struct{}

GitFetcher fetches by shelling out to the system `git`. It clones over https, checks out the requested ref, records HEAD, then deletes the `.git` directory so installed packages are plain source trees (smaller, and no nested-repo surprises for the consuming project's own VCS).

func (GitFetcher) Fetch

func (GitFetcher) Fetch(spec Spec, destDir string) (string, error)

Fetch implements Fetcher using `git`.

type Lock

type Lock struct {
	Packages map[string]LockEntry `json:"packages"`
}

Lock is the parsed `luascript-lock.json`. It records, per installed package name, exactly what was fetched so a later `install` reproduces the same bytes regardless of where the upstream ref now points.

func LoadLock

func LoadLock(path string) (*Lock, error)

LoadLock reads the lockfile at path. A missing file yields an empty lock.

func (*Lock) Save

func (l *Lock) Save(path string) error

Save writes the lockfile as indented JSON.

type LockEntry

type LockEntry struct {
	Source string `json:"source"`
	Ref    string `json:"ref,omitempty"`
	URL    string `json:"url"`
	Commit string `json:"commit"`
}

LockEntry is one resolved dependency. Source is the `host/path` (no ref), Ref is the tag/branch/commit the user asked for ("" = default branch), URL is the clone URL git was given, and Commit is the exact resolved hash.

type Manifest

type Manifest struct {
	Name         string            `json:"name"`
	Version      string            `json:"version"`
	Dependencies map[string]string `json:"dependencies"`
}

Manifest is the parsed `luascript.json`. Dependencies maps a local package name (the name used in `require`) to a source spec of the form `host/path[@ref]` — e.g. "github.com/alice/router@v1.2.0".

func LoadManifest

func LoadManifest(path string) (*Manifest, bool, error)

LoadManifest reads and parses the manifest at path. A missing file is not an error: it returns an empty manifest so `pkg add` can bootstrap a project that has none yet. The caller distinguishes "absent" via the second return.

func (*Manifest) Save

func (m *Manifest) Save(path string) error

Save writes the manifest as indented JSON with a trailing newline. Map keys serialize in sorted order (encoding/json guarantees this), so the file is stable across runs and diff-friendly.

type Spec

type Spec struct {
	Source string // host/path, no scheme, no ref
	Ref    string // tag/branch/commit, or "" for the default branch
}

Spec is a parsed dependency source: a `host/path` with an optional ref (tag, branch, or commit) after `@`. Example inputs:

github.com/alice/router            -> Source=github.com/alice/router, Ref=""
github.com/alice/router@v1.2.0     -> Ref="v1.2.0"
gitlab.com/team/lib@main           -> Ref="main"

A bare `@` or empty source is rejected. Schemes (`https://`, `git@...`) are intentionally not accepted here: the source is a stable identity, and the clone URL is derived from it via CloneURL so the same package always resolves to the same lockfile key.

func ParseSpec

func ParseSpec(s string) (Spec, error)

ParseSpec splits a `host/path[@ref]` string into a Spec.

func (Spec) CloneURL

func (s Spec) CloneURL() string

CloneURL is the https git URL derived from the source. We always clone over https so no SSH keys are required for public packages.

func (Spec) DefaultName

func (s Spec) DefaultName() string

DefaultName derives the package's local name (the `require` name) from the last path segment, with a trailing `.git` stripped if present.

func (Spec) String

func (s Spec) String() string

String renders the spec back to `host/path[@ref]` form — the exact value stored as a manifest dependency.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL