Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(std): more commands #185

Merged
merged 23 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@ jobs:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Cache dependencies installed with cargo
uses: actions/cache@v3
with:
path: |
./target
~/.cargo
key: rust-${{ hashFiles('Cargo.lock') }}
restore-keys: rust-${{ hashFiles('Cargo.lock') }}
- name: Run all tests
run: cargo test --verbose
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ itertools = "0.11.0"
clap = { version = "4.4.18", features = ["derive"] }
tempfile = "3.10.1"

# test dependencies
[dev-dependencies]
tiny_http = "0.12.0"
assert_cmd = "2.0.14"
predicates = "3.1.0"

Expand Down
87 changes: 87 additions & 0 deletions src/std/main.ab
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,90 @@ pub fun includes(arr, value) {
}
return false
}

pub fun is_command(command: Text): Bool {
if (unsafe $command -v "{command}" > /dev/null$) {
return true
}
return false
}

pub fun create_symbolic_link(origin: Text, destination: Text): Bool {
if file_exist(origin) {
unsafe $ln -s "{origin}" "{destination}"$
return true
}

echo "The file {origin} doesn't exist!"
return false
}

pub fun create_dir(path: Text): Null {
if not dir_exist(path) {
unsafe $mkdir -p "{path}"$
}
}

pub fun make_executable(path: Text): Bool {
if file_exist(path) {
unsafe $chmod +x "{path}"$
return true
}

echo "The file {path} doesn't exist!"
return false
}

pub fun switch_user_permission(user: Text, path: Text): Bool {
if file_exist(path) or dir_exist(path) {
unsafe $chown -R "{user}" "{path}"$
return true
}

return false
}

pub fun download(url: Text, path: Text): Bool {
if {
is_command("curl") {
unsafe $curl -o "{path}" "{url}"$
}
is_command("wget") {
unsafe $wget "{url}" -P "{path}"$
}
is_command("aria2c") {
unsafe $aria2c "{url}" -d "{path}"$
}
else {
return false
}
}

return true
}

pub fun is_root(): Bool {
if (unsafe $id -u$ == "0") {
return true
}

return false
}

pub fun get_env_var(var: Text): Text {
let _var = unsafe $echo "\$\{!var}"$
if _var != "" {
return _var
}

if file_exist(".env") {
unsafe $source ".env"$
return unsafe $echo "\$\{!var}"$
}

return ""
}

pub fun load_env_file(): Null {
unsafe $export "\$(xargs < .env)" > /dev/null$
}
159 changes: 159 additions & 0 deletions src/tests/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::fs;
use std::io::Read;
use std::io::Write;
use std::path::PathBuf;
use std::time::Duration;
use tempfile::tempdir;
use tempfile::TempDir;
use std::process::{Command, Stdio};
Expand All @@ -22,6 +23,16 @@ fn mkfile() -> (PathBuf, TempDir) {
(file_path, temp_dir)
}

fn http_server() {
use tiny_http::{Server, Response};

let server = Server::http("127.0.0.1:8081").expect("Can't bind to 127.0.0.1:8081");
for req in server.incoming_requests() {
req.respond(Response::from_string("ok")).expect("Can't respond");
break;
}
Comment on lines +26 to +33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa! Didn't expect http_server in the compiler. Does the curl actually download a file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is used only for tests and that part was implemented by @b1ek.

Because initially I did to download a website but the issue was that what is if the user is not connected to internet or the page is not available?

}

#[test]
fn input() {
let prompt_message = "Please enter your name:";
Expand Down Expand Up @@ -430,3 +441,151 @@ fn lines() {
";
test_amber!(code, "line: hello\nline: world")
}

#[test]
fn is_command() {
let code = "
import { is_command } from \"std\"
main {
if is_command(\"cat\") {
echo \"exist\"
}
}
";
test_amber!(code, "exist")
}

#[test]
fn create_symbolic_link() {
let code = "
import { create_symbolic_link } from \"std\"
main {
unsafe $touch /tmp/amber-symbolic$
if create_symbolic_link(\"/tmp/amber-symbolic\", \"/tmp/amber-symbolic-link\") {
echo \"created\"
} else {
echo \"failed\"
}
unsafe $rm /tmp/amber-symbolic$
unsafe $rm /tmp/amber-symbolic-link$
}
";
test_amber!(code, "created")
}

#[test]
fn create_dir() {
let code = "
import { create_dir, dir_exist } from \"std\"
main {
create_dir(\"/tmp/amber-test\")
if dir_exist(\"/tmp/amber-test\") {
unsafe $rm /tmp/amber-test$
echo \"created\"
}
}
";
test_amber!(code, "created")
}

#[test]
fn make_executable() {
let code = "
import { make_executable } from \"std\"
main {
unsafe $touch /tmp/amber-symbolic$
if make_executable(\"/tmp/amber-symbolic\") {
echo \"created\"
}
unsafe $rm /tmp/amber-symbolic$
}
";
test_amber!(code, "created")
}

#[test]
fn switch_user_permission() {
// We use `whoami` to get the running user to assign again the same user as permission
let code = "
import { switch_user_permission } from \"std\"
main {
unsafe $touch /tmp/amber-symbolic$
if switch_user_permission(unsafe $whoami$,\"/tmp/amber-symbolic\") {
echo \"done\"
}
unsafe $rm /tmp/amber-symbolic$
}
";
test_amber!(code, "done")
}

#[test]
fn download() {
let server = std::thread::spawn(http_server);

let code = "
import { download, is_command, exit } from \"std\"
main {
let tempfile = unsafe $mktemp$
if download(\"http://127.0.0.1:8081/\", tempfile) {
$cat {tempfile}$ failed {
echo \"{tempfile} does not exist!!\"
}
unsafe $rm -f {tempfile}$
}
}
";

test_amber!(code, "ok");

std::thread::sleep(Duration::from_millis(150));
assert!(server.is_finished(), "Server has not stopped!");
}

#[test]
fn is_root() {
let code = "
import { is_root } from \"std\"
main {
if not is_root() {
echo \"no\"
}
}
";
test_amber!(code, "no")
}

#[test]
fn get_env_var() {
let code = "
import { get_env_var, file_write } from \"std\"
main {
let path = unsafe $mktemp -d /tmp/amber-XXXX$
unsafe $cd {path}$
unsafe file_write(\".env\", \"TEST=1\")
if get_env_var(\"TEST\") == \"1\" {
echo \"yes\"
}
unsafe $rm -fr {path}$
}
";
test_amber!(code, "yes")
}

#[test]
fn load_env_file() {
let code = "
import { load_env_file, get_env_var, file_write } from \"std\"
main {
let path = unsafe $mktemp -d /tmp/amber-XXXX$
unsafe $cd {path}$
unsafe file_write(\".env\", \"TEST=1\")
load_env_file()
if get_env_var(\"TEST\") == \"1\" {
echo \"yes\"
}
unsafe $rm -fr {path}$
}
";
test_amber!(code, "yes")
}
Loading