Skip to content

Commit

Permalink
feat(std): more commands (#185)
Browse files Browse the repository at this point in the history
* feat(std): more command

* removed functions

* download

* Update main.ab

added is_root and is_command

* feat(download): improved fallback

* amber fix

* feat(test): is_command

* feat(test): create_symbolic_link

* feat(test): added 3 tests

* feat(test): added 2 tests

* fix(test): download

* feat: spin up a small web server for download() test

* fix: regenerate Cergo.lock

* feat(env): 3 new functions

* fix(amber): now should compile

* fix(amber): now should compile

* fix(amber): clean

* fix(test): removed write

* fix(test): maybe

* fix(test): wip

* fix(test): wip

* ci(cache): now will use CI cache, so it will be more fast between jobs

---------

Co-authored-by: b1ek <me@blek.codes>
Mte90 and b1ek authored Jul 1, 2024
1 parent dee0b4e commit 2baeaa1
Showing 5 changed files with 293 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -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
@@ -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"

87 changes: 87 additions & 0 deletions src/std/main.ab
Original file line number Diff line number Diff line change
@@ -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
@@ -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};
@@ -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;
}
}

#[test]
fn input() {
let prompt_message = "Please enter your name:";
@@ -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")
}

0 comments on commit 2baeaa1

Please sign in to comment.