Skip to content

Commit

Permalink
implement env
Browse files Browse the repository at this point in the history
Fixes: #167
  • Loading branch information
mengzhuo committed Sep 18, 2024
1 parent b08ff9c commit b12d34d
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ count below and mark it as done in this README.md. Thanks!
GNU coreutils. They are not 100% compatiable. If you encounter different behaviors,
compare against the true GNU coreutils version on the Linux-based tests first.

## Completed (66/109)
## Completed (67/109)

| Done | Cmd | Descripton |
| :-----: | --------- | ------------------------------------------------ |
Expand Down Expand Up @@ -77,7 +77,7 @@ compare against the true GNU coreutils version on the Linux-based tests first.
| ✓ | dirname | Strip last file name component |
| | du | Estimate file space usage |
| ✓ | echo | Print a line of text |
| | env | Run a command in a modified environment |
| ✓ | env | Run a command in a modified environment |
| ✓ | expand | Convert tabs to spaces |
| ✓ | expr | Evaluate expressions |
| ✓ | factor | Print prime factors |
Expand Down
38 changes: 38 additions & 0 deletions src/env/args.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import common

const app_name = 'env'
const app_description = 'run a program in a modified environment'

struct EnvArg {
// -0
nul_terminated bool

// -u
unsets []string

// -i
ignore bool

// command and arguments
cmd_args []string
}

pub fn new_args(args []string) !EnvArg {
mut fp := common.flag_parser(args)
fp.application(app_name)
fp.description(app_description)
fp.version(common.coreutils_version())

nul := fp.bool('null', `0`, false, 'end each output line with NUL, not newline')
unsets := fp.string_multi('unset', `u`, 'remove variable from the environment')
ignore := fp.bool('ignore-environment', `i`, false, 'start with an empty environment')

cmd_args := fp.finalize() or { return err }

return EnvArg{
nul_terminated: nul
unsets: unsets
ignore: ignore
cmd_args: cmd_args
}
}
15 changes: 15 additions & 0 deletions src/env/args_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module main

fn test_ignore() {
args := new_args(['t', '-i'])!
assert args.ignore == true
}

fn test_unset() {
args := new_args(['t', '-i', '-u', 'ABC'])!
assert 'ABC' in args.unsets

multi_args := new_args(['t', '-i', '-u', 'ABC', '-u', 'EFG'])!
assert 'ABC' in multi_args.unsets
assert 'EFG' in multi_args.unsets
}
Empty file removed src/env/delete.me
Empty file.
40 changes: 40 additions & 0 deletions src/env/env.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// env - run a program in a modified environment
import os
import maps

fn main() {
args := new_args(os.args) or {
eprintln(err)
return
}
run(args)
}

pub fn run(args EnvArg) {
mut envs := if args.ignore {
map[string]string{}
} else {
os.environ()
}

for key in args.unsets {
envs.delete(key)
}

if args.cmd_args.len == 0 {
eol := if args.nul_terminated { '\0' } else { '\n' }
for key, val in envs {
print('${key}=${val}' + eol)
}
return
}

cmd_path := os.find_abs_path_of_executable(args.cmd_args[0]) or {
eprintln(err)
return
}

os.execve(cmd_path, args.cmd_args[1..], maps.to_array(envs, fn (k string, v string) string {
return '${k}=${v}\0'
})) or { eprintln(err) }
}
25 changes: 25 additions & 0 deletions src/env/env_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os

fn test_help() {
result := os.execute_or_panic('${os.quoted_path(@VEXE)} run . -h')
assert result.exit_code == 0
assert result.output.contains('a modified environment')
}

fn test_same_env() {
result := os.execute_or_panic('${os.quoted_path(@VEXE)} run . -0')
assert result.exit_code == 0

env := os.execute_or_panic('env -0')
assert env.exit_code == 0
assert env.output == result.output
}

fn test_same_unset() {
result := os.execute_or_panic('${os.quoted_path(@VEXE)} run . -u PATH')
assert result.exit_code == 0

env := os.execute_or_panic('env -u PATH')
assert env.exit_code == 0
assert env.output == result.output
}

0 comments on commit b12d34d

Please sign in to comment.