a6d093536a
El SDK CI - dev / build-and-test (pull_request) Failing after 7s
- add -lm (el_runtime.c uses pow/sqrt/log/sin/cos/exp) - add -Wl,--allow-multiple-definition to gen2 (is_digit/is_whitespace defined in both elc-bootstrap.c and el_runtime.c; bootstrap predates the text-processing primitives commit) - remove colon from Self-host step name (Gitea YAML parser rejects it) - replace em dashes in step names with hyphens
281 lines
10 KiB
EmacsLisp
281 lines
10 KiB
EmacsLisp
// epm/src/epm.el — El Package Manager entry point
|
|
//
|
|
// epm manages vessels: versioned El source packages backed by Gitea releases.
|
|
// Each vessel corresponds to a Gitea repository under a shared org. Versions
|
|
// are Gitea release tags; source archives are attached as release assets named
|
|
// "<name>-<version>.tar.gz".
|
|
//
|
|
// Vessels are installed to ~/.el/packages/<name>/<version>/.
|
|
// The installed registry lives at ~/.el/packages/installed.json.
|
|
//
|
|
// Usage:
|
|
// epm publish # publish current project to registry
|
|
// epm install # install all dependencies from manifest.el
|
|
// epm install <vessel> # install a specific vessel (latest)
|
|
// epm install <vessel>@<ver> # install a specific vessel at a version
|
|
// epm list # list installed vessels
|
|
// epm info <vessel> # show metadata for a vessel
|
|
// epm info <vessel> <version> # show metadata for a specific version
|
|
// epm update # update all installed vessels
|
|
// epm update <vessel> # update a specific vessel
|
|
// epm check # check for available updates (no install)
|
|
//
|
|
// Configuration (environment):
|
|
// EPM_GITEA_API — Gitea API base URL (default: https://git.neuralplatform.ai/api/v1)
|
|
// EPM_REGISTRY_ORG — org hosting vessel repos (default: neuron-technologies)
|
|
// EPM_TOKEN — Gitea personal access token (required for publish)
|
|
//
|
|
// Import order: manifest.el, registry.el, install.el, update.el must be
|
|
// compiled first. This file imports all four and is the build entry point.
|
|
|
|
import "manifest.el"
|
|
import "registry.el"
|
|
import "install.el"
|
|
import "update.el"
|
|
|
|
// ── Subcommand handlers ───────────────────────────────────────────────────────
|
|
|
|
// cmd_publish reads manifest.el from the current directory and publishes
|
|
// the vessel to the Gitea registry as a release.
|
|
fn cmd_publish() -> Void {
|
|
let src: String = fs_read("manifest.el")
|
|
if str_eq(src, "") {
|
|
println("epm: no manifest.el found in current directory")
|
|
exit(1)
|
|
}
|
|
|
|
let name: String = manifest_name(src)
|
|
if str_eq(name, "") {
|
|
println("epm: manifest.el has no 'vessel' or 'package' declaration")
|
|
exit(1)
|
|
}
|
|
|
|
let version: String = manifest_version(src)
|
|
if str_eq(version, "") {
|
|
println("epm: manifest.el has no 'version' declaration")
|
|
exit(1)
|
|
}
|
|
|
|
let description: String = manifest_description(src)
|
|
let entry: String = manifest_entry(src)
|
|
let deps_json: String = manifest_deps(src)
|
|
|
|
println("epm: publishing " + name + " " + version + " ...")
|
|
|
|
let release_id: String = registry_publish(name, version, description, entry, deps_json)
|
|
if str_eq(release_id, "") {
|
|
println("epm: publish failed")
|
|
exit(1)
|
|
}
|
|
|
|
println("epm: published " + name + " " + version + " (release: " + release_id + ")")
|
|
}
|
|
|
|
// cmd_install_named installs a specific vessel by name (with optional version).
|
|
// Expects: install <name> or install <name>@<version>
|
|
fn cmd_install_named(spec: String) -> Void {
|
|
// spec may be "el-auth" or "el-auth@0.1.0"
|
|
let at: Int = str_index_of(spec, "@")
|
|
let vname: String = spec
|
|
let vver: String = ""
|
|
if at > 0 {
|
|
let vname = str_slice(spec, 0, at)
|
|
let vver = str_slice(spec, at + 1, str_len(spec))
|
|
}
|
|
|
|
println("epm: installing " + vname + " ...")
|
|
|
|
let ok: Bool = install_vessel(vname, vver)
|
|
if !ok {
|
|
println("epm: install failed")
|
|
exit(1)
|
|
}
|
|
|
|
// Notify about other available updates after a successful install
|
|
let outdated: Int = check_updates()
|
|
if outdated > 0 {
|
|
println("")
|
|
println(" note: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
|
|
}
|
|
}
|
|
|
|
// cmd_list prints all locally installed vessels.
|
|
fn cmd_list() -> Void {
|
|
let installed: String = read_installed()
|
|
if str_eq(installed, "") {
|
|
println("epm: no vessels installed")
|
|
return
|
|
}
|
|
if str_eq(installed, "{}") {
|
|
println("epm: no vessels installed")
|
|
return
|
|
}
|
|
|
|
let inner_len: Int = str_len(installed)
|
|
if inner_len < 2 {
|
|
println("epm: no vessels installed")
|
|
return
|
|
}
|
|
let body: String = str_slice(installed, 1, inner_len - 1)
|
|
let body_trimmed: String = str_trim(body)
|
|
if str_eq(body_trimmed, "") {
|
|
println("epm: no vessels installed")
|
|
return
|
|
}
|
|
|
|
println("epm: installed vessels:")
|
|
println("")
|
|
|
|
let pairs: [String] = str_split(body_trimmed, ",")
|
|
let pair_count: Int = native_list_len(pairs)
|
|
let i: Int = 0
|
|
while i < pair_count {
|
|
let pair: String = str_trim(native_list_get(pairs, i))
|
|
let colon: Int = str_index_of(pair, ":")
|
|
if colon > 0 {
|
|
let raw_key: String = str_trim(str_slice(pair, 0, colon))
|
|
let raw_val: String = str_trim(str_slice(pair, colon + 1, str_len(pair)))
|
|
let key_len: Int = str_len(raw_key)
|
|
let val_len: Int = str_len(raw_val)
|
|
let vname2: String = raw_key
|
|
let vver2: String = raw_val
|
|
if str_starts_with(raw_key, "\"") {
|
|
let vname2 = str_slice(raw_key, 1, key_len - 1)
|
|
}
|
|
if str_starts_with(raw_val, "\"") {
|
|
let vver2 = str_slice(raw_val, 1, val_len - 1)
|
|
}
|
|
println(" " + vname2 + " " + vver2)
|
|
}
|
|
let i = i + 1
|
|
}
|
|
}
|
|
|
|
// cmd_info prints detailed metadata for a specific vessel from the registry.
|
|
// argv is the full args list; idx is the position of the vessel name.
|
|
fn cmd_info(argv: [String], idx: Int) -> Void {
|
|
let argc: Int = native_list_len(argv)
|
|
if idx >= argc {
|
|
println("epm: usage: epm info <vessel> [version]")
|
|
exit(1)
|
|
}
|
|
|
|
let vname: String = native_list_get(argv, idx)
|
|
let vver: String = ""
|
|
if idx + 1 < argc {
|
|
let vver = native_list_get(argv, idx + 1)
|
|
}
|
|
|
|
let content: String = registry_find(vname, vver)
|
|
if str_eq(content, "") {
|
|
println("epm: vessel '" + vname + "' not found in registry")
|
|
exit(1)
|
|
}
|
|
|
|
let name: String = json_get_string(content, "name")
|
|
let ver: String = json_get_string(content, "version")
|
|
let desc: String = json_get_string(content, "description")
|
|
let dl_url: String = json_get_string(content, "download_url")
|
|
|
|
println("name: " + name)
|
|
println("version: " + ver)
|
|
println("description: " + desc)
|
|
println("download: " + dl_url)
|
|
|
|
let local_ver: String = installed_version(name)
|
|
if !str_eq(local_ver, "") {
|
|
println("installed: " + local_ver)
|
|
} else {
|
|
println("installed: (not installed)")
|
|
}
|
|
}
|
|
|
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
|
|
fn main() -> Void {
|
|
let argv: [String] = args()
|
|
let argc: Int = native_list_len(argv)
|
|
|
|
// argv[0] is the program name; subcommand is argv[1]
|
|
if argc < 2 {
|
|
println("epm — El Package Manager")
|
|
println("")
|
|
println("usage:")
|
|
println(" epm publish publish current project to registry")
|
|
println(" epm install install all dependencies (from manifest.el)")
|
|
println(" epm install <vessel> install a specific vessel (latest version)")
|
|
println(" epm install <vessel>@<ver> install a specific vessel at a version")
|
|
println(" epm list list installed vessels")
|
|
println(" epm info <vessel> show vessel metadata from registry")
|
|
println(" epm info <vessel> <version> show metadata for a specific version")
|
|
println(" epm update update all installed vessels")
|
|
println(" epm update <vessel> update a specific vessel")
|
|
println(" epm check check for available updates (no install)")
|
|
println("")
|
|
println("configuration:")
|
|
println(" EPM_GITEA_API Gitea API base URL (default: https://git.neuralplatform.ai/api/v1)")
|
|
println(" EPM_REGISTRY_ORG org hosting vessel repos (default: neuron-technologies)")
|
|
println(" EPM_TOKEN Gitea personal access token (required for publish)")
|
|
exit(0)
|
|
}
|
|
|
|
let sub: String = native_list_get(argv, 1)
|
|
|
|
if str_eq(sub, "publish") {
|
|
cmd_publish()
|
|
return
|
|
}
|
|
|
|
if str_eq(sub, "install") {
|
|
if argc >= 3 {
|
|
let spec: String = native_list_get(argv, 2)
|
|
cmd_install_named(spec)
|
|
} else {
|
|
cmd_install()
|
|
// Notify about other available updates after a successful install
|
|
let outdated: Int = check_updates()
|
|
if outdated > 0 {
|
|
println("")
|
|
println(" note: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if str_eq(sub, "list") {
|
|
cmd_list()
|
|
return
|
|
}
|
|
|
|
if str_eq(sub, "info") {
|
|
cmd_info(argv, 2)
|
|
return
|
|
}
|
|
|
|
if str_eq(sub, "update") {
|
|
if argc >= 3 {
|
|
let vessel_arg: String = native_list_get(argv, 2)
|
|
cmd_update(vessel_arg)
|
|
} else {
|
|
cmd_update("")
|
|
}
|
|
return
|
|
}
|
|
|
|
if str_eq(sub, "check") {
|
|
println("epm: checking for updates ...")
|
|
let outdated: Int = check_updates()
|
|
if outdated == 0 {
|
|
println("epm: all installed vessels are up to date")
|
|
} else {
|
|
println("")
|
|
println("epm: " + native_int_to_str(outdated) + " vessel(s) have newer versions available — run 'epm update' to upgrade")
|
|
}
|
|
return
|
|
}
|
|
|
|
println("epm: unknown subcommand '" + sub + "'")
|
|
println("run 'epm' with no arguments for usage")
|
|
exit(1)
|
|
}
|