buninu-linux 0.8.56 → 0.9.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/initramfs/bin/tar +34 -46
- package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +103 -0
- package/initramfs/buninu/apps/bunmsh/PORTING.md +133 -15
- package/initramfs/buninu/apps/bunmsh/help/awk.md +38 -0
- package/initramfs/buninu/apps/bunmsh/help/break.md +21 -0
- package/initramfs/buninu/apps/bunmsh/help/chmod.md +8 -2
- package/initramfs/buninu/apps/bunmsh/help/cmp.md +29 -0
- package/initramfs/buninu/apps/bunmsh/help/continue.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/cp.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/diff.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/egrep.md +26 -0
- package/initramfs/buninu/apps/bunmsh/help/export.md +2 -2
- package/initramfs/buninu/apps/bunmsh/help/expr.md +30 -0
- package/initramfs/buninu/apps/bunmsh/help/fgrep.md +25 -0
- package/initramfs/buninu/apps/bunmsh/help/grep.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/ls.md +4 -2
- package/initramfs/buninu/apps/bunmsh/help/mkdir.md +1 -1
- package/initramfs/buninu/apps/bunmsh/help/print.md +3 -0
- package/initramfs/buninu/apps/bunmsh/help/return.md +23 -0
- package/initramfs/buninu/apps/bunmsh/help/sed.md +8 -3
- package/initramfs/buninu/apps/bunmsh/help/set.md +12 -3
- package/initramfs/buninu/apps/bunmsh/help/tr.md +4 -0
- package/initramfs/buninu/apps/bunmsh/help/trap.md +22 -0
- package/initramfs/buninu/apps/bunmsh/help/uniq.md +27 -0
- package/initramfs/buninu/apps/bunmsh/package.json +1 -1
- package/initramfs/buninu/apps/bunmsh/src/awk.js +203 -0
- package/initramfs/buninu/apps/bunmsh/src/diff.js +222 -0
- package/initramfs/buninu/apps/bunmsh/src/fancy-ls.js +15 -4
- package/initramfs/buninu/apps/bunmsh/src/main.js +21 -5
- package/initramfs/buninu/apps/bunmsh/src/sed.js +159 -0
- package/initramfs/buninu/apps/bunmsh/src/shell.js +1283 -540
- package/initramfs/buninu/apps/bunmsh/test/awk-reference.test.js +35 -0
- package/initramfs/buninu/apps/bunmsh/test/awk.test.js +62 -0
- package/initramfs/buninu/apps/bunmsh/test/posix-bootstrap.test.js +595 -0
- package/initramfs/buninu/apps/bunmsh/test/utility-reference-cases.mjs +98 -0
- package/initramfs/buninu/apps/bunmsh/test/utility-reference.test.js +23 -0
- package/initramfs/buninu/apps/jsgotty/client-kitty.mjs +61 -0
- package/initramfs/buninu/apps/jsgotty/client.mjs +16 -0
- package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
- package/initramfs/buninu/apps/jsgotty/package.json +1 -1
- package/initramfs/buninu/apps/jsgotty/tests/client-kitty.test.mjs +43 -0
- package/initramfs/etc/resolv.conf +2 -1
- package/initramfs/usr/share/doc/buninu-linux/tar.md +11 -0
- package/package.json +1 -1
- package/scripts/fetch.js +2 -0
- package/test/tar-strip.test.js +36 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {test,expect} from 'bun:test';
|
|
2
|
+
import {compileAwk,executeAwk} from '../src/awk.js';
|
|
3
|
+
const reference=process.env.BUNMSH_AWK_REFERENCE;
|
|
4
|
+
const cases=[
|
|
5
|
+
['fields','{print NF, $1, $2, NR, FNR}','a 2\nb 3\n'],
|
|
6
|
+
['sum','{sum+=$2} END {print sum}','a 2\nb 3\n'],
|
|
7
|
+
['precedence','BEGIN {print 1+2*3, -2^2, (2^3)^2, (2+3)*4}',''],
|
|
8
|
+
['division','BEGIN {x=10; print x/2, x%3; x/=2; print x}',''],
|
|
9
|
+
['postfix fields','{i=1; print $i++; print i, $0}','4 5\n'],
|
|
10
|
+
['scalar type','BEGIN {print (x==0), (x==""), ("0" ? 1 : 2), ("10" < 2)}',''],
|
|
11
|
+
['input type','{print ($1 ? 1 : 2), ($1 < 2)}','0\n10\n'],
|
|
12
|
+
['array','BEGIN {a["x"]=3; a["y"]=4; for(k in a)s+=a[k]; delete a["x"]; print s, ("x" in a), ("y" in a)}',''],
|
|
13
|
+
['subscript','BEGIN {a[1,2]=7; print a[1,2]}',''],
|
|
14
|
+
['loop','BEGIN {for(i=0;i<4;i++){if(i==2)continue;s+=i;} print s; while(s>2)s--; do s++; while(s<5); print s}',''],
|
|
15
|
+
['function','function f(x) {if(x<=1)return 1;return x*f(x-1)} BEGIN {print f(5)}',''],
|
|
16
|
+
['regex','/yes/ {print} !/yes/ {print "no:" $0}','yes\nother\n'],
|
|
17
|
+
['range','/start/,/end/ {print}','omit\nstart\ninside\nend\nomit\n'],
|
|
18
|
+
['sub and gsub','{n=gsub(/a/,"[&]");sub(/b/,"B");print n, $0}','aaba\n'],
|
|
19
|
+
['split','BEGIN {n=split("a:b:c",a,":");print n,a[2];n=split(" ab cd ",a," ");print n,a[1],a[2]}',''],
|
|
20
|
+
['match','BEGIN {print match("abc123",/[0-9]+/),RSTART,RLENGTH; print match("abc",/z/),RSTART,RLENGTH}',''],
|
|
21
|
+
['strings','BEGIN {print substr("abcdef",2,3), index("abc","b"), length("abc"), toupper("Ab"), tolower("Ab")}',''],
|
|
22
|
+
['format','BEGIN {printf "%s:%03d:%.2f:%x\\n", "x", 4, 2.5, 255}',''],
|
|
23
|
+
['change fields','{OFS=":";$2="X";print $0;NF=4;print $0;NF=1;print $0}','a b c\n'],
|
|
24
|
+
['change record','{$0="new fields";print NF,$1,$2}','old\n'],
|
|
25
|
+
['flow','{if(NR==2)next;print; if(NR==3)exit 4} END {print "end"}','a\nb\nc\nd\n'],
|
|
26
|
+
['escaped regex','/a\\/b/ {print}','a/b\na b\n'],
|
|
27
|
+
['BEGIN END','BEGIN {print "begin"} END {print "end"}',''],
|
|
28
|
+
];
|
|
29
|
+
if(!reference)test.skip('awk reference (set BUNMSH_AWK_REFERENCE)',()=>{});
|
|
30
|
+
for(const [name,source,input] of reference?cases:[])test(`awk reference: ${name}`,async()=>{
|
|
31
|
+
const p=Bun.spawn([reference,source],{stdin:Buffer.from(input),stdout:'pipe',stderr:'pipe',env:{...process.env,LC_ALL:'C'}});
|
|
32
|
+
const [status,stdout,stderr]=await Promise.all([p.exited,new Response(p.stdout).text(),new Response(p.stderr).text()]);
|
|
33
|
+
const actual=executeAwk(compileAwk(source),[{name:'-',text:input}]);
|
|
34
|
+
expect({...actual,stderr:''}).toEqual({status,stdout,stderr});
|
|
35
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {test,expect} from 'bun:test';
|
|
2
|
+
import {compileAwk,executeAwk} from '../src/awk.js';
|
|
3
|
+
import {createState,execute,decode} from '../src/shell.js';
|
|
4
|
+
const run=(s,text='',options={})=>executeAwk(compileAwk(s),[{name:'-',text}],options);
|
|
5
|
+
test('awk parenthesized print lists and continued argument lists',()=>{
|
|
6
|
+
expect(run('BEGIN {printf("%s:%d\\n",\n "x", 7); print (2,\n 3); print (2+3)*4, (4>3)}').stdout).toBe('x:7\n2 3\n20 1\n');
|
|
7
|
+
});
|
|
8
|
+
test('awk scalar parameters shadow global arrays and callers do not supply scope',()=>{
|
|
9
|
+
expect(run('function inner(x) {return x} function outer(flags) {return inner(flags)} function global() {return x} function caller(x) {return global()} BEGIN {flags[0]="global"; x=9; print outer("local"), caller(2)}').stdout).toBe('local 9\n');
|
|
10
|
+
});
|
|
11
|
+
test('awk substitution preserves backslashes before ordinary replacement characters',()=>{
|
|
12
|
+
expect(run(String.raw`BEGIN {x="C++"; gsub("\\+", "\\+", x); print x; print ("C++" ~ x)}`).stdout).toBe('C\\+\\+\n1\n');
|
|
13
|
+
});
|
|
14
|
+
test('awk output pipes share input until close, return status and can reopen',async()=>{
|
|
15
|
+
const r=await execute(`builtin awk 'BEGIN {print "a" | "builtin cat 1>&2"; print "b" | "builtin cat 1>&2"; print close("builtin cat 1>&2"); print "c" | "builtin cat 1>&2"; print close("exit 7")}'`,createState(),{capture:true});
|
|
16
|
+
expect(r.status).toBe(0);expect(decode(r.stdout)).toBe('0\n0\n');expect(decode(r.stderr)).toBe('a\nb\nc\n');
|
|
17
|
+
const p=await execute(`builtin awk 'BEGIN {print "x" | "builtin cat >/dev/null; exit 7"; print close("builtin cat >/dev/null; exit 7")}'`,createState(),{capture:true});
|
|
18
|
+
expect(p.status).toBe(0);expect(decode(p.stdout)).toBe('7\n');
|
|
19
|
+
});
|
|
20
|
+
test('awk fields, counters, arithmetic and END',()=>{
|
|
21
|
+
expect(run('{sum += $2; print NR, $1} END {print sum}', 'apple 2\npear 3\n').stdout).toBe('1 apple\n2 pear\n5\n');
|
|
22
|
+
});
|
|
23
|
+
test('awk arrays, numeric loops, for-in, membership and deletion',()=>{
|
|
24
|
+
expect(run('BEGIN {a["x"]=4; a["y"]=5; for(k in a) sum+=a[k]; delete a["x"]; for(i=0;i<3;i++) sum++; print sum, ("x" in a), ("y" in a)}').stdout).toBe('12 0 1\n');
|
|
25
|
+
});
|
|
26
|
+
test('awk regex, substitutions, split, fields and printf',()=>{
|
|
27
|
+
expect(run('/yes/ {gsub(/yes/,"Y"); n=split($0,a,":"); printf "%s:%d\\n", a[1], n}', 'no\nyes:yes\n').stdout).toBe('Y:2\n');
|
|
28
|
+
expect(run('BEGIN {print substr("abcdef",2,3), index("abc","b"), length("abc")}').stdout).toBe('bcd 2 3\n');
|
|
29
|
+
});
|
|
30
|
+
test('awk functions, conditionals and flow',()=>{
|
|
31
|
+
expect(run('function twice(x) {return x*2} {if ($1=="skip") next; print twice($1)} END {print "end"}', '3\nskip\n4\n').stdout).toBe('6\n8\nend\n');
|
|
32
|
+
});
|
|
33
|
+
test('awk Autoconf substitutions preserve inserted values',()=>{
|
|
34
|
+
const source=`BEGIN {S["CC"]="tcc"; S["FLAGS"]="-O2"; for(key in S) S_is_set[key]=1; FS="\\007"}
|
|
35
|
+
{line=$0; nfields=split(line,field,"@"); len=length(field[1]); for(i=2;i<nfields;i++){key=field[i]; keylen=length(key); if(S_is_set[key]){value=S[key]; line=substr(line,1,len) "" value "" substr(line,len+keylen+3); len+=length(value)+length(field[++i]);}else len+=1+keylen;} print line}`;
|
|
36
|
+
expect(run(source,'cc=@CC@ flags=@FLAGS@ keep=@UNKNOWN@\n').stdout).toBe('cc=tcc flags=-O2 keep=@UNKNOWN@\n');
|
|
37
|
+
});
|
|
38
|
+
test('awk getline from a file and file output',()=>{
|
|
39
|
+
const writes=[];
|
|
40
|
+
const r=run('BEGIN {while((getline x < "file")>0) print x > "out"; close("file"); print "done"}', '',{readFile:()=> 'a\nb\n',writeFile:(...a)=>writes.push(a)});
|
|
41
|
+
expect(r.stdout).toBe('done\n');expect(writes).toEqual([['out','a\n',false],['out','b\n',true]]);
|
|
42
|
+
});
|
|
43
|
+
test('awk builtin handles piped input without a native awk',async()=>{
|
|
44
|
+
const r=await execute("printf 'a 2\\nb 3\\n' | builtin awk '{sum += $2} END {print sum}'",createState(),{capture:true});
|
|
45
|
+
expect(r.status).toBe(0);expect(decode(r.stdout)).toBe('5\n');expect(decode(r.stderr)).toBe('');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('awk exponentiation is right associative (mawk reference)',()=>{
|
|
49
|
+
// Host mawk 1.3.4 returns 512. BusyBox 1.36.1 returns 64 for this case.
|
|
50
|
+
expect(run('BEGIN {print 2^3^2}').stdout).toBe('512\n');
|
|
51
|
+
});
|
|
52
|
+
test('awk builtin parses field separators and numeric -v assignments',async()=>{
|
|
53
|
+
const r=await execute("printf 'a:3\n' | builtin awk -F: -v limit=10 '{print $2, (limit < 2)}'",createState(),{capture:true});
|
|
54
|
+
expect(r.status).toBe(0);expect(decode(r.stdout)).toBe('3 0\n');expect(decode(r.stderr)).toBe('');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('awk quoted operator strings remain concatenation operands',()=>{
|
|
58
|
+
expect(run('BEGIN {print "x" "/" "y", "a" "+" "b", 3/2, "in", "}", ";", "(", "++"}').stdout)
|
|
59
|
+
.toBe('x/y a+b 1.5 in } ; ( ++\n');
|
|
60
|
+
const install='BEGIN {files["."]=""; dirs["."]=1} {d=$3; if(dirs[d]!=1){print "d",d; dirs[d]=1} if($2==$4) files[d]=files[d] " " $1; else {print "f",$3 "/" $4,$1}} END {for(d in files) print "f",d,files[d]}';
|
|
61
|
+
expect(run(install,'ld-new ld-new . ld.bfd\n').stdout).toBe('f ./ld.bfd ld-new\nf . \n');
|
|
62
|
+
});
|