[Add] Implement build system for user scripts.

This commit is contained in:
Ritchie Cunningham 2025-10-27 21:44:39 +00:00
parent 20f2e5a104
commit 9b6106f8aa
5 changed files with 110 additions and 23 deletions

View File

@ -0,0 +1,27 @@
-- /bin/build - "Compiles" a .lua file into an executable.
local source_filename = arg[1]
if not source_filename then
return "build: missing file operand"
end
-- Check for .lua extension.
if not source_filename:match("%.lua$") then
return "build: input file must be a .lua file"
end
local current_dir = bettola.get_current_dir(context)
local source_node = current_dir.children[source_filename]
if not source_node then
return "build: cannot open '" .. source_filename .."': No such file"
end
if source_node.type ~= 0 then
return "build: '" .. source_filename .. "' is not a regular file"
end
local executable_filename = source_filename:gsub("%.lua$", "")
local source_content = source_node.content
return bettola.create_executable(context, executable_filename, source_content)

View File

@ -78,6 +78,50 @@ std::string write_file(Session& context, const std::string& path,
return ""; return "";
} }
std::string create_executable(Session& context, const std::string& path,
const std::string& content) {
vfs_node* parent_dir = nullptr;
std::string filename;
if(path[0] == '/') {
Machine* session_machine = context.get_session_machine();
vfs_node* root = session_machine->vfs_root;
size_t last_slash = path.find_last_of('/');
if(last_slash == 0) {
parent_dir = root;
filename = path.substr(1);
} else {
std::string parent_path = path.substr(0, last_slash);
parent_dir = find_node_by_path(root, parent_path);
filename = path.substr(last_slash+1);
}
} else {
parent_dir = context.get_current_dir();
filename = path;
}
if(!parent_dir) {
return "create_executable: cannot create file '" + path + "': No such file or directory";
}
if(parent_dir->type != DIR_NODE) {
return "create_executable: cannot create file in '" + get_full_path(parent_dir)
+ "': Not a directory";
}
/* Overwrite if exists. */
auto it = parent_dir->children.find(filename);
if(it != parent_dir->children.end()) {
delete it->second;
parent_dir->children.erase(it);
}
vfs_node* new_exec = new_node(filename, EXEC_NODE, parent_dir);
new_exec->content = content;
parent_dir->children[filename] = new_exec;
return "";
}
std::string cd(Session& context, const std::string& path) { std::string cd(Session& context, const std::string& path) {
vfs_node* current_dir = context.get_current_dir(); vfs_node* current_dir = context.get_current_dir();

View File

@ -13,6 +13,8 @@ vfs_node* get_current_dir(Session& context);
std::string rm(Session& context, const std::string& filename); std::string rm(Session& context, const std::string& filename);
std::string write_file(Session& context, const std::string& path, std::string write_file(Session& context, const std::string& path,
const std::string& content); const std::string& content);
std::string create_executable(Session& context, const std::string& path,
const std::string& content);
std::string ls(Session& context); std::string ls(Session& context);
std::string cd(Session& context, const std::string& path); std::string cd(Session& context, const std::string& path);
std::string scp(Session& context, const std::string& source, std::string scp(Session& context, const std::string& source,

View File

@ -26,6 +26,7 @@ LuaProcessor::LuaProcessor(Session& context) {
bettola_api.set_function("rm", &api::rm); bettola_api.set_function("rm", &api::rm);
bettola_api.set_function("ls", &api::ls); bettola_api.set_function("ls", &api::ls);
bettola_api.set_function("write_file", &api::write_file); bettola_api.set_function("write_file", &api::write_file);
bettola_api.set_function("create_executable", &api::create_executable);
bettola_api.set_function("get_current_dir", &api::get_current_dir); bettola_api.set_function("get_current_dir", &api::get_current_dir);
bettola_api.set_function("cd", &api::cd); bettola_api.set_function("cd", &api::cd);
bettola_api.set_function("scp", &api::scp); bettola_api.set_function("scp", &api::scp);

View File

@ -93,23 +93,36 @@ std::string Session::process_command(const std::string& command) {
args.push_back(arg); args.push_back(arg);
} }
/* Find the /bin directory in the current machine's VFS. */ vfs_node* command_node = nullptr;
if(command_name.find('/') != std::string::npos) {
/* Path provided, find node directly. */
command_node = find_node_by_path(_session_machine->vfs_root, command_name);
} else {
/* No path, search current dir then /bin. */
vfs_node* current_dir = get_current_dir();
if(current_dir->children.count(command_name)) {
command_node = current_dir->children.at(command_name);
} else {
vfs_node* bin_dir = find_node_by_path(_session_machine->vfs_root, "/bin"); vfs_node* bin_dir = find_node_by_path(_session_machine->vfs_root, "/bin");
if(bin_dir && bin_dir->type == DIR_NODE) { if(bin_dir && bin_dir->children.count(command_name)) {
auto it = bin_dir->children.find(command_name); command_node = bin_dir->children.at(command_name);
if(it != bin_dir->children.end()) {
vfs_node* command_node = it->second;
if(command_node->type == EXEC_NODE) {
/* Execute the script. */
bool is_remote = (_session_machine != _home_machine);
sol::object result = lua.execute(command_node->content, *this, args, is_remote);
return result.is<std::string>() ? result.as<std::string>()
: "[Script returned an unexpected type]";
} }
} }
} }
return "Unknown command: " + command_name + "\n"; if(command_node) {
if(command_node->type == EXEC_NODE) {
bool is_remote = (_session_machine != _home_machine);
sol::object result = lua.execute(command_node->content, *this, args, is_remote);
return result.is<std::string>() ? result.as<std::string>()
: "[Script returned non-string value]";
} else if(command_node->type == DIR_NODE) {
return "Cannot execute '" + command_name + "' It is a directory.";
} else {
return "Cannot execute '" + command_name + "': Not an executable file.";
}
}
return "Unknown command: " + command_name;
} }
std::string Session::write_file(const std::string& path, const std::string& content) { std::string Session::write_file(const std::string& path, const std::string& content) {