Compare commits

..

11 Commits

Author SHA1 Message Date
2fcea0909d Merge pull request 'Improvements to installation process' (#1) from dev-server into main
Reviewed-on: #1
2025-03-27 17:46:53 +01:00
Rph :3
4ff7e3216c Implement setting alternative repo bases with the snowier.repo_base setting 2025-03-27 17:42:56 +01:00
Rph :3
6edfa118b1 Implement dev server 2025-03-27 17:42:45 +01:00
Rph :3
3772d67726 Add flake with Bun 2025-03-27 17:25:19 +01:00
7e21413e7b update installer to cleanup /tmp/ entirely 2025-03-27 10:57:10 +01:00
80f91cbcd9 oops 2025-03-27 10:01:33 +01:00
4d157bfee4 Write basic bootloader 2025-03-27 09:57:14 +01:00
db862f12ef hack might have been because of emulation bug..? 2025-03-25 19:29:22 +01:00
fc349f46e4 Always emulate bitwise operations for CC 2025-03-25 19:26:22 +01:00
6cf175e5f0 polish up installer 2025-03-25 19:20:04 +01:00
c7d7f9be98 Squashed commit of the following:
commit 51f79d4749
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 19:14:15 2025 +0100

    reduce useless downloads

commit 86d335f53e
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 19:13:26 2025 +0100

    fix everywhere

commit 3d23d1b618
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 19:10:54 2025 +0100

    update hashes

commit bbf2d23eb4
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 19:10:30 2025 +0100

    try this instead

commit 5c0cf083d9
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 19:05:42 2025 +0100

    istg if that was the problem

commit ac23c993d0
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 18:44:26 2025 +0100

    Fix other dumb mistake

commit 610893222b
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 18:43:41 2025 +0100

    Fix dumb mistake

commit bb0ee3e64e
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 18:42:33 2025 +0100

    Try fixing sha256 not loading

commit b0f8c1267a
Merge: e079d75 17e3a3b
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 17:46:06 2025 +0100

    Merge branch 'main' of git.colon-three.com:kodi/snowier

commit e079d75fab
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 17:45:55 2025 +0100

    Add debug print

commit 17e3a3b5a8
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 15:51:28 2025 +0100

    Second attempt to fix sha256

commit d575f3c98c
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 15:39:40 2025 +0100

    Fix typo

commit f8ef3b0210
Author: Kodi Craft <kodi@kdcf.me>
Date:   Tue Mar 25 15:38:42 2025 +0100

    Try using different implementation of sha256
2025-03-25 19:16:40 +01:00
14 changed files with 305 additions and 43 deletions

1
dev-server/.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

2
dev-server/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.direnv
node_modules

47
dev-server/bun.lock Normal file
View File

@@ -0,0 +1,47 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "dev-server",
"dependencies": {
"@elysiajs/static": "^1.2.0",
"elysia": "^1.2.25",
},
"devDependencies": {
"@types/bun": "latest",
},
"peerDependencies": {
"typescript": "^5",
},
},
},
"packages": {
"@elysiajs/static": ["@elysiajs/static@1.2.0", "", { "dependencies": { "node-cache": "^5.1.2" }, "peerDependencies": { "elysia": ">= 1.2.0" } }, "sha512-oLpAi8c+maPpA0XhhK3BELaIjIG+nXg/K9p8cFfW4q5ayRD59a3MOMOOGgpiXZkHJzLPWcouhhyyLAYtaANW4g=="],
"@sinclair/typebox": ["@sinclair/typebox@0.34.31", "", {}, "sha512-qQ71T9DsITbX3dVCrcBERbs11YuSMg3wZPnT472JhqhWGPdiLgyvihJXU8m+ADJtJvRdjATIiACJD22dEknBrQ=="],
"@types/bun": ["@types/bun@1.2.8", "", { "dependencies": { "bun-types": "1.2.7" } }, "sha512-t8L1RvJVUghW5V+M/fL3Thbxcs0HwNsXsnTEBEfEVqGteiJToOlZ/fyOEaR1kZsNqnu+3XA4RI/qmnX4w6+S+w=="],
"@types/node": ["@types/node@22.13.14", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-Zs/Ollc1SJ8nKUAgc7ivOEdIBM8JAKgrqqUYi2J997JuKO7/tpQC+WCetQ1sypiKCQWHdvdg9wBNpUPEWZae7w=="],
"@types/ws": ["@types/ws@8.18.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw=="],
"bun-types": ["bun-types@1.2.7", "", { "dependencies": { "@types/node": "*", "@types/ws": "*" } }, "sha512-P4hHhk7kjF99acXqKvltyuMQ2kf/rzIw3ylEDpCxDS9Xa0X0Yp/gJu/vDCucmWpiur5qJ0lwB2bWzOXa2GlHqA=="],
"clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="],
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
"elysia": ["elysia@1.2.25", "", { "dependencies": { "@sinclair/typebox": "^0.34.27", "cookie": "^1.0.2", "memoirist": "^0.3.0", "openapi-types": "^12.1.3" }, "peerDependencies": { "typescript": ">= 5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-WsdQpORJvb4uszzeqYT0lg97knw1iBW1NTzJ1Jm57tiHg+DfAotlWXYbjmvQ039ssV0fYELDHinLLoUazZkEHg=="],
"memoirist": ["memoirist@0.3.0", "", {}, "sha512-wR+4chMgVPq+T6OOsk40u9Wlpw1Pjx66NMNiYxCQQ4EUJ7jDs3D9kTCeKdBOkvAiqXlHLVJlvYL01PvIJ1MPNg=="],
"node-cache": ["node-cache@5.1.2", "", { "dependencies": { "clone": "2.x" } }, "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg=="],
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
}
}

61
dev-server/flake.lock generated Normal file
View File

@@ -0,0 +1,61 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1742923925,
"narHash": "sha256-biPjLws6FiBVUUDHEMFq5pUQL84Wf7PntPYdo3oKkFw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "25d1b84f5c90632a623c48d83a2faf156451e6b1",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"utils": "utils"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

17
dev-server/flake.nix Normal file
View File

@@ -0,0 +1,17 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, utils }:
utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
in {
devShell = with pkgs; mkShell {
buildInputs = with pkgs; [ bun ];
};
}
);
}

35
dev-server/index.ts Normal file
View File

@@ -0,0 +1,35 @@
import { Elysia } from 'elysia'
import { staticPlugin } from "@elysiajs/static"
import { stat, readdir, readFile } from "node:fs/promises"
import { createHash } from "node:crypto";
type IndexEntry = { src: string, dest: string, hash: string };
async function scanDir(scanIn: string, base: string, outputBase: string): Promise<IndexEntry[]> {
let files = await readdir(scanIn + "/" + base);
let results: IndexEntry[] = [];
for (let file of files) {
if (await stat(scanIn + "/" + base + "/" + file).then(r => r.isDirectory())) {
results = [...results, ...(await scanDir(scanIn, base + "/" + file, outputBase + file + "/"))]
} else {
results.push({
src: base + "/" + file,
dest: outputBase + file,
hash: createHash('sha256').update(await readFile(scanIn + "/" + base + "/" + file)).digest('hex')
});
}
}
return results;
}
new Elysia()
.get("/index.json", async () => scanDir("..", "src", "/"))
.get("/sha256.lua", async () => Bun.file("../sha256.lua"))
.use(staticPlugin({
assets: "../src",
prefix: "/src"
}))
.get("/install.lua", async () => Bun.file("../install.lua"))
.listen(parseInt(process.env.PORT || "3000"))

16
dev-server/package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "dev-server",
"module": "index.ts",
"type": "module",
"private": true,
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5"
},
"dependencies": {
"@elysiajs/static": "^1.2.0",
"elysia": "^1.2.25"
}
}

28
dev-server/tsconfig.json Normal file
View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["esnext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}

View File

@@ -2,6 +2,11 @@
{
"src": "src/startup.lua",
"dest": "/startup.lua",
"hash": "07219cd9561b41ce1f39209958076c471b17855679c968b42767b0122423c782"
"hash": "38b4f27b677716688ce5c27f416a3e4605e03d1a07f76df7b5ef1cedf4f355ea"
},
{
"src": "src/kernel/entry.lua",
"dest": "/kernel/entry.lua",
"hash": "5d17a09860a3d14346105e363c0b3333bf720c75c4670add778fd20a736dafb7"
}
]

View File

@@ -1,4 +1,5 @@
local repoRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"
local defaultRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"
local repoRoot = settings.get("snowier.repo_base") or defaultRoot
local URLs = {
fileIndex = repoRoot .. "index.json",
@@ -33,12 +34,12 @@ local function main()
shafile.close()
sharequest.close()
end
log.debug(package.path)
package.path = package.path .. ";/?;/?.lua" -- hack to solve 'wget run'
local hash = require("sha256")
log.info("Downloading index file")
local indexrequest = http.get(URLs.fileIndex)
local index = textutils.unserializeJson(request.readAll())
local index = textutils.unserializeJSON(indexrequest.readAll())
indexrequest.close()
if (index == nil) then
@@ -58,12 +59,13 @@ local function main()
local destfile = fs.open(v.dest, "r")
local filehash = hash.sha256(destfile.readAll())
destfile.close()
if filehash ~= v.sha256 then
if filehash ~= v.hash then
toDownload[#toDownload+1] = v
end
end
end
if #toDownload > 0 then
log.info(#toDownload .. " files to download")
for k, v in ipairs(toDownload) do
if not fs.exists("/tmp") then
@@ -82,14 +84,20 @@ local function main()
tempfile.close()
if filehash ~= v.hash then
log.error("File " .. v.dest .. " (from " .. v.src .. ") has a mismatched hash.")
log.error("Installation aborted.")
log.error("Installation aborted. Remember to clean /tmp manually.")
return
end
end
log.info("Installing")
for k, v in ipairs(toDownload) do
fs.move("/tmp/" .. v.hash .. ".lua", v.dest)
fs.delete(v.dest)
fs.copy("/tmp/" .. v.hash .. ".lua", v.dest)
end
fs.delete("/tmp/")
else
log.info("Nothing to do")
end
log.info("Installation complete!")

View File

@@ -193,6 +193,9 @@ if print_debug_messages then
print(" "..method)
end
-- For computercraft, use emulated mode for the sake of compatibility
branch = "EMUL"
--------------------------------------------------------------------------------
-- BASIC 32-BIT BITWISE FUNCTIONS
@@ -208,8 +211,6 @@ if branch == "FFI" or branch == "LJ" or branch == "LIB32" then
-- Your system has 32-bit bitwise library (either "bit" or "bit32")
-- ADJUSTED FOR COMPUTERCRAFT
AND = b.band -- 2 arguments
OR = b.bor -- 2 arguments
XOR = b.bxor -- 2..5 arguments
@@ -219,17 +220,17 @@ if branch == "FFI" or branch == "LJ" or branch == "LIB32" then
SHR = b.brshift
-- ROL = b.rol or b.lrotate -- second argument is integer 0..31
-- ROR = b.ror or b.rrotate -- second argument is integer 0..31
function ROL(x, n)
x = x % 2^32 * 2^n
local r = x % 2^32
return r + (x - r) / 2^32
end
--function ROL(x, n)
-- x = x % 2^32 * 2^n
-- local r = x % 2^32
-- return r + (x - r) / 2^32
--end
function ROR(x, n)
x = x % 2^32 / 2^n
local r = x % 1
return r * 2^32 + (x - r)
end
--function ROR(x, n)
-- x = x % 2^32 / 2^n
-- local r = x % 1
-- return r * 2^32 + (x - r)
--end
NOT = b.bnot -- only for LuaJIT
NORM = b.tobit -- only for LuaJIT

5
src/kernel/entry.lua Normal file
View File

@@ -0,0 +1,5 @@
-- kernel entrypoint
-- this is responsible for initializing core kernel services
-- required to advance to the next step of the OS
os.run({}, "/rom/programs/advanced/multishell.lua") -- placeholder

View File

@@ -1 +1,37 @@
print("Hello, World!")
-- Bootloader
-- This script is only responsible for killing rednet and jumping to the kernel
-- based on some code rph wrote and gave me
local function main()
if not _G["rednet"] then
return
end
local o = os.pullEventRaw
os.pullEventRaw = function()
local a = table.pack(o())
if a[1] == "modem_message" then
if string.match(debug.traceback(), "/rom/apis/rednet.lua") then
print("[D] Rednet called os.pullEventRaw, crashing")
error("nya")
end
end
return table.unpack(a)
end
local p = _G.printError
_G.printError = function()
print("[D] Got printError call, cleaning and jumping to kernel")
_G.printError = p
_G.os.pullEventRaw = o
_G["rednet"] = nil
os.run({}, "/kernel/entry.lua")
end
print("[D] Queueing bogus modem message")
os.queueEvent("modem_message")
end
main()

View File

@@ -4,7 +4,7 @@
open index.json
| each {|entry|
{src: $entry.src, dest: $entry.dest,
hash: (cat $entry.src | hash sha256)}
hash: (open $entry.src | hash sha256)}
}
| collect
| save -f index.json