updates
CI / test (push) Failing after 4m56s

This commit is contained in:
Raven Scott
2026-04-02 22:35:09 -04:00
parent efeee0088a
commit 2e26b14250
56 changed files with 1838 additions and 75 deletions
@@ -0,0 +1,17 @@
async function run(ctx, argv) {
const parts = argv.slice(1).filter((a) => a !== '--')
if (!parts.length) {
ctx.console.error('basename: missing operand')
return
}
const path = parts[0]
const suffix = parts[1] || ''
let base = path.replace(/\/+$/, '')
const slash = base.lastIndexOf('/')
base = slash === -1 ? base : base.slice(slash + 1)
if (!base) base = path
if (suffix && base.endsWith(suffix) && base.length > suffix.length) {
base = base.slice(0, -suffix.length)
}
ctx.console.log(base)
}
+17
View File
@@ -0,0 +1,17 @@
async function run(ctx, argv) {
const vfs = ctx.vfs
const files = argv.slice(1)
if (!files.length) {
const s = bareStdin(ctx)
ctx.console.log(s)
return
}
for (const f of files) {
const buf = await vfs.readFile(f)
if (!buf) {
ctx.console.error('cat: ' + f + ': No such file or directory')
continue
}
ctx.console.log(ctx.b4a.toString(buf))
}
}
+14
View File
@@ -0,0 +1,14 @@
async function run(ctx, argv) {
const parts = argv.slice(1).filter((a) => a !== '--')
if (!parts.length) {
ctx.console.error('dirname: missing operand')
return
}
for (const path of parts) {
const cleaned = path.replace(/\/+$/, '') || '/'
const i = cleaned.lastIndexOf('/')
const out =
i <= 0 ? (cleaned[0] === '/' ? '/' : '.') : cleaned.slice(0, i) || '/'
ctx.console.log(out)
}
}
+15
View File
@@ -0,0 +1,15 @@
async function run(ctx, argv) {
const parts = argv.slice(1)
let n = false
if (parts[0] === '-n') {
n = true
parts.shift()
}
const s = parts.join(' ')
const w = globalThis.process?.stdout?.write
if (typeof w === 'function') {
w.call(globalThis.process.stdout, s + (n ? '' : '\n'))
} else {
ctx.console.log(n ? s : s)
}
}
+33
View File
@@ -0,0 +1,33 @@
async function run(ctx, argv) {
const vfs = ctx.vfs
let n = 10
let start = 1
if (argv[1] === '-n' && argv[2]) {
n = parseInt(argv[2], 10) || 10
start = 3
} else if (argv[1] && /^-\d+$/.test(argv[1])) {
n = parseInt(argv[1].slice(1), 10) || 10
start = 2
}
const files = argv.slice(start).filter((a) => a !== '--')
const take = (s) => {
const lines = s.split('\n')
const out = lines.slice(0, n).join('\n')
ctx.console.log(
out + (out && !out.endsWith('\n') && lines.length > n ? '\n' : '')
)
}
if (!files.length) {
take(bareStdin(ctx))
return
}
for (const f of files) {
const buf = await vfs.readFile(f)
if (!buf) {
ctx.console.error('head: ' + f + ': No such file')
continue
}
if (files.length > 1) ctx.console.log('==> ' + f + ' <==')
take(ctx.b4a.toString(buf))
}
}
+5
View File
@@ -0,0 +1,5 @@
async function run(ctx, argv) {
ctx.console.log(
'Bare OS userland — builtins: cd, export, exit | /bin: ls pwd cat echo test basename dirname wc head tail uname pathchk help'
)
}
+47
View File
@@ -0,0 +1,47 @@
async function run(ctx, argv) {
const vfs = ctx.vfs
let showAll = false
let longFmt = false
const paths = []
for (let i = 1; i < argv.length; i++) {
const a = argv[i]
if (a === '--') {
paths.push(...argv.slice(i + 1))
break
}
if (a.startsWith('-') && a.length > 1) {
for (let j = 1; j < a.length; j++) {
const c = a[j]
if (c === 'a') showAll = true
else if (c === 'l') longFmt = true
else if (c === '1') longFmt = false
}
continue
}
paths.push(a)
}
const targets = paths.length ? paths : ['.']
for (const t of targets) {
if (targets.length > 1) ctx.console.log(t + ':')
let names
try {
names = await vfs.readdir(t)
} catch (e) {
ctx.console.error('ls: cannot access ' + t + ': ' + (e.message || e))
continue
}
if (!showAll) names = names.filter((n) => n !== '.' && n !== '..')
if (!longFmt) {
ctx.console.log(names.join(' '))
} else {
for (const n of names) {
const sub = t === '.' || t === './' ? n : t.replace(/\/$/, '') + '/' + n
const st = await vfs.stat(sub)
const tag = st ? (st.type === 'directory' ? 'd' : '-') : '?'
const sz = st && st.size != null ? String(st.size) : '0'
ctx.console.log(tag + 'rwxr-xr-x 1 user user ' + sz + ' ' + n)
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
async function run(ctx, argv) {
const paths = argv.slice(1).filter((a) => !a.startsWith('-'))
if (!paths.length) {
ctx.console.error('pathchk: missing operand')
return
}
for (const p of paths) {
if (!p.length) {
ctx.console.error('pathchk: empty path name')
continue
}
if (p.length > 4096) {
ctx.console.error('pathchk: path too long')
continue
}
if (p.includes('\0')) {
ctx.console.error('pathchk: NUL in path')
continue
}
}
}
+3
View File
@@ -0,0 +1,3 @@
async function run(ctx, argv) {
ctx.console.log(ctx.vfs.getcwd())
}
+29
View File
@@ -0,0 +1,29 @@
async function run(ctx, argv) {
const vfs = ctx.vfs
let n = 10
let start = 1
if (argv[1] === '-n' && argv[2]) {
n = parseInt(argv[2], 10) || 10
start = 3
}
const files = argv.slice(start).filter((a) => a !== '--')
const take = (s) => {
let lines = s.split('\n')
if (s.endsWith('\n') && lines[lines.length - 1] === '') lines.pop()
const slice = lines.length <= n ? lines : lines.slice(-n)
ctx.console.log(slice.join('\n'))
}
if (!files.length) {
take(bareStdin(ctx))
return
}
for (const f of files) {
const buf = await vfs.readFile(f)
if (!buf) {
ctx.console.error('tail: ' + f + ': No such file')
continue
}
if (files.length > 1) ctx.console.log('==> ' + f + ' <==')
take(ctx.b4a.toString(buf))
}
}
+30
View File
@@ -0,0 +1,30 @@
async function evalTest(ctx, args) {
if (!args.length) return false
if (args[0] === '!') {
const inner = await evalTest(ctx, args.slice(1))
return !inner
}
if (args.length === 3) {
const [a, op, b] = args
if (op === '=') return a === b
if (op === '!=') return a !== b
return false
}
if (args.length === 2) {
const op = args[0]
const p = args[1]
const st = await ctx.vfs.stat(p)
if (op === '-e' || op === '-a') return st != null
if (op === '-f') return st != null && st.type === 'file'
if (op === '-d') return st != null && st.type === 'directory'
if (op === '-z') return p.length === 0
if (op === '-n') return p.length > 0
return false
}
if (args.length === 1) return args[0] !== ''
return false
}
async function run(ctx, argv) {
ctx.exitCode = (await evalTest(ctx, argv.slice(1))) ? 0 : 1
}
+32
View File
@@ -0,0 +1,32 @@
async function run(ctx, argv) {
const flagArgs = argv.slice(1).filter((a) => a.startsWith('-') && a !== '--')
const all = argv.includes('-a')
const noFlag = flagArgs.length === 0
const wantS = all || argv.includes('-s') || noFlag
const wantN = all || argv.includes('-n')
const wantR = all || argv.includes('-r')
const wantM = all || argv.includes('-m')
const wantV = all || argv.includes('-v')
let name = 'BareOS'
let version = '0.1'
const buf = await ctx.vfs.readFile('/etc/os-release')
if (buf) {
const t = ctx.b4a.toString(buf)
for (const line of t.split('\n')) {
const id = line.match(/^NAME=(.*)$/)
if (id) name = id[1].replace(/^"|"$/g, '')
const ver = line.match(/^VERSION=(.*)$/)
if (ver) version = ver[1].replace(/^"|"$/g, '')
}
}
const parts = []
if (wantS) parts.push(name)
if (wantN) parts.push('bare-os')
if (wantR) parts.push(version)
if (wantV) parts.push('bare-userland')
if (wantM) parts.push('unknown')
ctx.console.log(parts.join(' '))
}
+36
View File
@@ -0,0 +1,36 @@
function count(s) {
const lines = (s.match(/\n/g) || []).length
const words = s.trim() ? s.trim().split(/\s+/).length : 0
const bytes = new TextEncoder().encode(s).length
return { lines, words, bytes }
}
async function run(ctx, argv) {
const vfs = ctx.vfs
const files = argv.slice(1).filter((a) => !a.startsWith('-'))
if (!files.length) {
const s = bareStdin(ctx)
const c = count(s)
ctx.console.log(' ' + c.lines + ' ' + c.words + ' ' + c.bytes)
return
}
let tLines = 0
let tWords = 0
let tBytes = 0
for (const f of files) {
const buf = await vfs.readFile(f)
if (!buf) {
ctx.console.error('wc: ' + f + ': No such file')
continue
}
const s = ctx.b4a.toString(buf)
const c = count(s)
tLines += c.lines
tWords += c.words
tBytes += c.bytes
ctx.console.log(' ' + c.lines + ' ' + c.words + ' ' + c.bytes + ' ' + f)
}
if (files.length > 1) {
ctx.console.log(' ' + tLines + ' ' + tWords + ' ' + tBytes + ' total')
}
}