From 7019724ab5c818e18fb5ee61b6b14487c47da3ec Mon Sep 17 00:00:00 2001 From: dacctal Date: Fri, 17 Jul 2026 00:18:01 +0000 Subject: more features but memory leak --- src/build.c | 20 +++--- src/fetch.c | 4 +- src/help.c | 5 +- src/lua_globs.c | 9 ++- src/lua_install.c | 196 ---------------------------------------------------- src/lua_vars.c | 2 - src/parse_args.c | 27 ++++---- src/pkg_create.c | 39 ++++++----- src/pkg_exists.c | 54 +++++++++++++++ src/pkg_free.c | 2 + src/pkg_install.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/pkg_remove.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 505 insertions(+), 252 deletions(-) delete mode 100644 src/lua_install.c create mode 100644 src/pkg_exists.c create mode 100644 src/pkg_install.c create mode 100644 src/pkg_remove.c (limited to 'src') diff --git a/src/build.c b/src/build.c index 0b97af7..740d739 100644 --- a/src/build.c +++ b/src/build.c @@ -12,7 +12,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with this program. If not, see . @@ -35,8 +34,7 @@ bool target_build(lua_State *L, char* lua_file, str *target) { install_dependencies(L); } lua_pop(L, 1); - if (!lua_try_function(L, lua_file, "build")) - lua_pop(L, 2); + if (!lua_try_function(L, lua_file, "build")) return false; return true; } @@ -56,7 +54,7 @@ bool repo_build(package_t *pkg) { return false; } bool target_success = target_build(L, "init.lua", &pkg->target); - lua_pop(L, 3); + lua_pop(L, 4); return target_success; } @@ -119,24 +117,24 @@ bool config_build(package_t *pkg) { } bool build_loop(package_t *pkg) { - log_info("attempting init.lua: 'repositories.%.*s.build'", str_fmt(&pkg->name)); + if (flags.verbose) log_info("attempting init.lua: 'repositories.%.*s.build'", str_fmt(&pkg->name)); if (repo_build(pkg)) { return true; } - log_warn("failed init.lua: 'repositories.%.*s.build'", str_fmt(&pkg->name)); + if (flags.verbose) log_warn("failed init.lua: 'repositories.%.*s.build'", str_fmt(&pkg->name)); - log_info("attempting bldit.lua"); + if (flags.verbose) log_info("attempting bldit.lua"); if (bldit(pkg)) { return true; } - log_warn("failed bldit.lua"); + if (flags.verbose) log_warn("failed bldit.lua"); - log_info("attempting init.lua: 'build_systems'"); + if (flags.verbose) log_info("attempting init.lua: 'build_systems'"); if (config_build(pkg)) { return true; } - log_warn("failed init.lua: 'build_systems'"); + if (flags.verbose) log_warn("failed init.lua: 'build_systems'"); return false; } bool build(package_t *pkg) { char cwd[MAX_PATH_LEN]; getcwd(cwd, MAX_PATH_LEN); - if (str_equal_cstr(&pkg->src, cwd) && !pkg->is_local) chdir(pkg->src.data); + if (!str_equal_cstr(&pkg->src, cwd) && !pkg->is_local) chdir(pkg->src.data); if (build_loop(pkg)) return true; log_error("no usable build system was found for %.*s", str_fmt(&pkg->name)); diff --git a/src/fetch.c b/src/fetch.c index 87c632d..3792a5e 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -51,7 +51,7 @@ bool fetch(package_t *pkg) { if (pkg->url.data == NULL || pkg->src.data == NULL) { - log_warn("invalid pkg: url or src is NULL"); + if (flags.verbose) log_warn("invalid pkg: url or src is NULL"); return false; } @@ -97,7 +97,7 @@ bool fetch(package_t *pkg) { waitpid(pid, &status, 0); bool result = (WEXITSTATUS(status) == 0); - if (!result) { log_warn("git clone failed"); } + if (!result) { log_error("git clone failed"); } return result; } diff --git a/src/help.c b/src/help.c index bacdcd9..a568e7c 100644 --- a/src/help.c +++ b/src/help.c @@ -21,7 +21,6 @@ #include #include "help.h" - #include "globs.h" void help(void) { @@ -70,7 +69,7 @@ void help(void) { printf(RED "subcommand flags" COLOR_RESET ":\n"); for (size_t i = 0; i < LENGTH(cmd_flags); i++) { - printf(COLOR_RESET "\t" GREEN "%-2s" COLOR_RESET ", " YELLOW + printf(COLOR_RESET " " GREEN "%-2s" COLOR_RESET ", " YELLOW "%-12s" BLUE "%-16s" GRAY "# %s\n" COLOR_RESET, cmd_flags[i].short_flag, cmd_flags[i].long_flag, cmd_flags[i].arg, cmd_flags[i].desc); @@ -78,7 +77,7 @@ void help(void) { printf("\n" RED "modifier flags" COLOR_RESET ":\n"); for (size_t i = 0; i < LENGTH(mod_flags); i++) { - printf(COLOR_RESET "\t" GREEN "%-2s" COLOR_RESET ", " YELLOW + printf(COLOR_RESET " " GREEN "%-2s" COLOR_RESET ", " YELLOW "%-12s" BLUE "%-16s" GRAY "# %s\n" COLOR_RESET, mod_flags[i].short_flag, mod_flags[i].long_flag, mod_flags[i].arg, mod_flags[i].desc); diff --git a/src/lua_globs.c b/src/lua_globs.c index b14eb3a..5f333a4 100644 --- a/src/lua_globs.c +++ b/src/lua_globs.c @@ -61,7 +61,7 @@ void init_lua_state(void) { } if (file_exists(cfg.repos.data)) { if (luaL_loadfile(L, cfg.repos.data) || lua_pcall(L, 0, 0, 0)) { - log_warn("cannot load repository file: %s", lua_tostring(L, -1)); + if (flags.verbose) log_warn("cannot load repository file: %s", lua_tostring(L, -1)); lua_pop(L, 1); } } @@ -76,7 +76,7 @@ void init_bldit_state(void) { luaL_openlibs(B); if (luaL_loadfile(B, "bldit.lua") || lua_pcall(B, 0, 0, 0)) { if (flags.verbose) - log_warn("cannot run bldit: %s", lua_tostring(B, -1)); + if (flags.verbose) log_warn("cannot run bldit: %s", lua_tostring(B, -1)); return; } lua_pushfstring(B, "%s", inst_dirs.prefix.data); @@ -140,7 +140,7 @@ bool lua_try_function(lua_State *L, char *lua_file, char *fname) { lua_isnt_type(fname, "function"); lua_pop(L, 1); } else if (lua_pcall(L, 0, 1, 0) != LUA_OK) { - log_warn( + if (flags.verbose) log_warn( "%s: '%s' function borked: %s", lua_file, fname, lua_tostring(L, -1) ); @@ -148,7 +148,7 @@ bool lua_try_function(lua_State *L, char *lua_file, char *fname) { return false; } if (!lua_isnumber(L, -1) || lua_tonumber(L, -1) != 0) { - log_warn( + if (flags.verbose) log_warn( "%s: '%s' failed: %s", lua_file, fname, lua_tostring(L, -1) ); @@ -166,7 +166,6 @@ bool lua_try_table(lua_State *L, char *lua_file, char *tname) { bldit_isnt_type(tname, "table"); else lua_isnt_type(tname, "table"); - lua_pop(L, 1); return false; } return true; diff --git a/src/lua_install.c b/src/lua_install.c deleted file mode 100644 index 5bf5270..0000000 --- a/src/lua_install.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - - pkgit - package it! - - Copyright (C) 2026 dacctal - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - - -#include - -#include "pkgit_lua.h" - -#include "add_repo.h" -#include "build.h" -#include "fetch.h" -#include "files.h" -#include "globs.h" -#include "log.h" -#include "pkg.h" - -void install_dependencies(lua_State *L) { - while (lua_next(L, -2) != 0) { - const char *depname = lua_tostring(L, -2); - if (depname && lua_istable(L, -1)) { - lua_getfield(L, -1, "url"); - str_slc dep_url = mstrslc(lua_tostring(L, -1)); - lua_pop(L, 1); - lua_getfield(L, -1, "version"); - str_slc dep_version = mstrslc(lua_tostring(L, -1)); - lua_pop(L, 1); - package_t pkg = pkg_create(dep_url); - pkg.version = str_from_str_slc(dep_version); - const int top = lua_gettop(L); - char cwd[MAX_PATH_LEN]; - if (getcwd(cwd, sizeof(cwd)) != NULL) { - //install_pkg(pkg); - chdir(cwd); - } - lua_settop(L, top); - pkg_free(&pkg); - } - lua_pop(L, 1); - } -} - -bool target_install(lua_State *L, char* lua_file, str *target) { - if (!lua_try_table(L, lua_file, target->data)) { - lua_pop(L, 1); - return false; - } - lua_pop(L, 1); - lua_try_function(L, lua_file, "pre_install"); - lua_pop(L, 1); - if (!lua_try_function(L, lua_file, "install")) { - lua_pop(L, 1); - return false; - } - lua_pop(L, 1); - lua_try_function(L, lua_file, "post_install"); - lua_pop(L, 1); - return true; -} - -bool repo_install(package_t *pkg) { - lua_getglobal(L, "repositories"); - if (!config_loaded || !lua_istable(L, -1)) { - lua_isnt_type("repositories", "table"); - lua_pop(L, 1); - return false; - } - if (!lua_try_table(L, "init.lua", pkg->name.data)) { - lua_isnt_type(pkg->name.data, "table"); - lua_pop(L, 2); - return false; - } - if (!lua_try_table(L, "init.lua", "targets")) return false; - bool target_success = target_install(L, "init.lua", &pkg->target); - lua_pop(L, 3); - return target_success; -} - -bool bldit_install(package_t *pkg) { - init_bldit_state(); - //if (!is_bldit_usable()) { - // log_error("bldit version is newer than the installed pkgit version"); - // log_error("consider updating pkgit"); - // if (!flags.force) return false; - //} - lua_pushfstring(B, "%s", inst_dirs.prefix.data); - lua_setglobal(B, "prefix"); - lua_pop(B, 1); - if (!lua_try_table(B, "bldit.lua", "targets")) return false; - bool target_success = target_install(B, "bldit.lua", &pkg->target); - lua_pop(B, 2); - lua_close(B); - return target_success; -} - -bool config_install(package_t *pkg) { - lua_getglobal(L, "build_systems"); - lua_pushnil(L); - bool target_success = false; - while (lua_next(L, -2) != 0) { - const char *key = lua_tostring(L, -2); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - continue; - } - str file_path = str_format("%.*s/%s", str_fmt(&pkg->src), key); - if (access(file_path.data, F_OK) != 0) { - lua_pop(L, 1); - continue; - } - str_free(&file_path); - if (!lua_try_table(L, "init.lua", "targets")) { - lua_pop(L, 2); - continue; - } - target_success = target_install(L, "init.lua", &pkg->target); - lua_pop(L, 2); - } - lua_pop(L, 1); - return target_success; -} - -void pkg_install(package_t *pkg) { - if (is_directory(pkg->src.data)) { - if (!flags.force) { - log_info("%.*s is already installed.", str_fmt(&pkg->name)); - return; - } else { - log_warn("%.*s is already installed.", str_fmt(&pkg->name)); - } - } - char cwd[MAX_PATH_LEN]; - getcwd(cwd, MAX_PATH_LEN); - if (str_equal_cstr(&pkg->src, cwd)) chdir(pkg->src.data); - - //if (pkg->is_local) { - // cpdir(cwd, pkg->src); - //} else { - log_pkgit("fetching " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); - if (!fetch(pkg)) return; - log_pkgit("fetched " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); - //} - - log_pkgit("building " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); - if (!build(pkg)) return; - log_pkgit("built " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); - - bool install_success = false; - log_info("attempting init.lua: 'repositories.%.*s.install'", str_fmt(&pkg->name)); - if (!install_success && repo_install(pkg)) - install_success = true; - log_info("attempting bldit.lua: 'repositories.%.*s.install'", str_fmt(&pkg->name)); - if (!install_success && bldit_install(pkg)) - install_success = true; - log_info("attempting init.lua: 'build_systems'", str_fmt(&pkg->name)); - if (!install_success && config_install(pkg)) - install_success = true; - if (!install_success) { - log_error("no install function availible for package: %.*s", str_fmt(&pkg->name)); - return; - } - log_success("installed " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); - - bool repo_exists = false; - //for (size_t i = 0; i < cached_repos_count; i++) { - //char *repo_name = name_from_url(cached_repos[i].source_key); - //if (strcmp(repo_name, pkg.name) == 0) { repo_exists = true; } - //free(repo_name); - //} - - if (!repo_exists) { - log_pkgit("adding " GREEN "%.*s" COLOR_RESET , &pkg->name); - if (pkg->url.len > 0) { - add_repo(pkg); - log_pkgit("added " GREEN "%.*s" COLOR_RESET , &pkg->name); - } - } else { - log_info("repo already exists, done"); - } -} diff --git a/src/lua_vars.c b/src/lua_vars.c index ddb4c5a..7420ae0 100644 --- a/src/lua_vars.c +++ b/src/lua_vars.c @@ -58,11 +58,9 @@ void init_install_directories(void) { void init_prefix_directory(void) { lua_getglobal(L, "prefix"); if (!lua_isstring(L, -1)) { -// printf(PRINT_ERROR "init.lua: 'prefix' is not a string.\n"); lua_isnt_type("prefix", "string."); return; } inst_dirs.prefix = mstr(lua_tostring(L, -1)); -// snprintf(prefix_dir, MAX_PATH_LEN, "%s", lua_tostring(L, -1)); lua_pop(L, 1); } diff --git a/src/parse_args.c b/src/parse_args.c index d4719c7..61e1fcb 100644 --- a/src/parse_args.c +++ b/src/parse_args.c @@ -23,14 +23,13 @@ #include "parse_args.h" +#include "build.h" #include "globs.h" #include "log.h" #include "str.h" // #include "declare.h" // #include "easter_egg.h" #include "help.h" -// #include "name_from_url.h" -// #include "pkg_build.h" #include "pkg.h" // #include "pkg_search.h" // #include "pkg_install.h" @@ -38,7 +37,7 @@ // #include "pkg_list.h" // #include "pkg_remove.h" // #include "pkgit_globals.h" -// #include "repo_add.h" +#include "add_repo.h" // #include "update.h" #define COMMAND(large, small) \ @@ -50,7 +49,10 @@ void cmd_add(char **argv, int i) { if (argv[i + 1]) { printf("add repo %s\n", argv[i + 1]); - // repo_add(argv[i + 1], name_from_url(argv[i + 1])); + str_slc arg = mstrslc(argv[i + 1]); + package_t pkg = pkg_create(arg); + add_repo(&pkg); + pkg_free(&pkg); } else { NOT_ENOUGH_ARGS(argv[i], "url"); } @@ -61,16 +63,16 @@ void cmd_build(int argc, char **argv, int i) { for (int j = i + 1; j < argc; j++) { if (argv[j][0] == '-') continue; - printf("build pkg %s\n", argv[j]); - // str_slc arg = mstrslc(argv[j]); - // package_t pkg = pkg_create(arg); - // pkg_build(pkg); + str_slc arg = mstrslc(argv[j]); + package_t pkg = pkg_create(arg); + build(&pkg); + pkg_free(&pkg); } } else { - printf("build pkg .\n"); - // str_slc arg = mstrslc("."); - // package_t pkg = pkg_create(arg); - // pkg_build(pkg); + str_slc arg = mstrslc("."); + package_t pkg = pkg_create(arg); + build(&pkg); + pkg_free(&pkg); } } @@ -79,7 +81,6 @@ void cmd_install(int argc, char **argv, int i) { for (int j = i + 1; j < argc; j++) { if (argv[j][0] == '-') continue; - printf("install pkg %s\n", argv[j]); str_slc arg = mstrslc(argv[j]); package_t pkg = pkg_create(arg); pkg_install(&pkg); diff --git a/src/pkg_create.c b/src/pkg_create.c index de20038..728a955 100644 --- a/src/pkg_create.c +++ b/src/pkg_create.c @@ -7,7 +7,6 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -15,7 +14,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . - */ #include @@ -26,8 +24,11 @@ #include "files.h" #include "globs.h" #include "log.h" +#include "pkgit_lua.h" #include "str.h" +str new_arg_str; + static str get_destdir(str_slc cwd, str_slc arg) { str_slc name = str_slc_from_after_delim(arg, '/'); if (str_slc_first(arg) == '.') @@ -75,29 +76,25 @@ static void assign_pkg_target(package_t *pkg, str *new_arg_str) { if (str_find_char(&pkg->target, '@')) pkg->target.len--; str_free(&tmp_arg); pkg->name.len -= pkg->target.len + 1; + } else if (!flags.verbose) { + pkg->target = mstr("quiet"); } else pkg->target = mstr("default"); } package_t pkg_create(str_slc arg) { package_t pkg = { .is_local = false, }; - char cwd[MAX_PATH_LEN]; getcwd(cwd, MAX_PATH_LEN); str_slc cwd_slc = mstrslc(cwd); str cwd_str = mstr(cwd); str dest_dir = get_destdir(cwd_slc, arg); - str new_arg_str = str_from_str_slc(arg); + str tmp_str = str_from_str_slc(arg); + str_copy_into(&new_arg_str, &tmp_str); + str_free(&tmp_str); bool is_installed_locally = is_directory(dest_dir.data); - - bool is_in_repos = false; - // for (size_t i = 0; i < cached_repos_count; i++) { - // if (strcmp(new_arg, cached_repos[i].source_key) == 0) { - // is_in_repos = true; - // break; - // } - // } + bool is_in_repos = pkg_exists(&new_arg_str); assign_pkg_version(&pkg, &new_arg_str); assign_pkg_target(&pkg, &new_arg_str); @@ -105,12 +102,12 @@ package_t pkg_create(str_slc arg) { str tmp = str_from_after_delim(&new_arg_str, '@'); new_arg_str.len -= tmp.len + 1; str_free(&tmp); - } - if (str_find_char(&new_arg_str, ',')) { + } if (str_find_char(&new_arg_str, ',')) { str tmp = str_from_after_delim(&new_arg_str, ','); new_arg_str.len -= tmp.len + 1; str_free(&tmp); } + if (strncmp(arg.data, "http", 4) == 0 || strncmp(arg.data, "ssh", 3) == 0) { pkg.url = new_arg_str; pkg.name = str_from_after_delim(&new_arg_str, '/'); @@ -119,12 +116,9 @@ package_t pkg_create(str_slc arg) { pkg.name = str_from_after_delim(&cwd_str, '/'); pkg.is_local = true; } else if (is_in_repos) { - // for (size_t i = 0; i < cached_repos_count; i++) { - // if (strcmp(new_arg, cached_repos[i].source_key) == 0) { - // pkg.url = strdup(cached_repos[i].source_value); - // break; - // } - // } + str tmp_url = pkg_get_url(&new_arg_str); + str_copy_into(&pkg.url, &tmp_url); + str_free(&tmp_url); pkg.name = new_arg_str; } else if (is_installed_locally) { pkg.url = mstr(""); @@ -132,12 +126,17 @@ package_t pkg_create(str_slc arg) { pkg.is_local = true; } else { log_error("'%.*s' is not a valid package", str_fmt(&arg)); + str_free(&cwd_str); + str_free(&dest_dir); + str_free(&new_arg_str); exit(EXIT_FAILURE); } + if (str_find_char(&new_arg_str, ',') && str_find_char(&new_arg_str, '@') ) pkg.name.len--; pkg.src = get_pkgsrc(pkg); + str_free(&cwd_str); str_free(&dest_dir); return pkg; diff --git a/src/pkg_exists.c b/src/pkg_exists.c new file mode 100644 index 0000000..05aa238 --- /dev/null +++ b/src/pkg_exists.c @@ -0,0 +1,54 @@ +/* + + pkgit - package it! + + Copyright (C) 2026 dacctal + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "pkgit_lua.h" +#include "str.h" + +bool pkg_exists(str *name) { + lua_getglobal(L, "repositories"); + if (!config_loaded || !lua_istable(L, -1)) { + lua_pop(L, 1); + return false; + } + if (!lua_try_table(L, "init.lua", name->data)) { + lua_pop(L, 2); + return false; + } + lua_pop(L, 2); + return true; +} + +str pkg_get_url(str *name) { + lua_getglobal(L, "repositories"); + if (!config_loaded || !lua_istable(L, -1)) { + lua_pop(L, 1); + return mstr(""); + } + if (!lua_try_table(L, "init.lua", name->data)) { + lua_pop(L, 2); + return mstr(""); + } + lua_getfield(L, -1, "url"); + if (lua_isstring(L, -1)) { + return mstr(lua_tostring(L, -1)); + } + lua_pop(L, 3); + return mstr(""); +} diff --git a/src/pkg_free.c b/src/pkg_free.c index 2b1d670..12659fe 100644 --- a/src/pkg_free.c +++ b/src/pkg_free.c @@ -1,4 +1,5 @@ #include "pkg.h" +#include "globs.h" void pkg_free(package_t *pkg) { str_free(&pkg->name); @@ -6,4 +7,5 @@ void pkg_free(package_t *pkg) { str_free(&pkg->version); str_free(&pkg->target); str_free(&pkg->src); + str_free(&new_arg_str); } diff --git a/src/pkg_install.c b/src/pkg_install.c new file mode 100644 index 0000000..b727d01 --- /dev/null +++ b/src/pkg_install.c @@ -0,0 +1,200 @@ +/* + + pkgit - package it! + + Copyright (C) 2026 dacctal + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + + +#include + +#include "pkgit_lua.h" + +#include "add_repo.h" +#include "build.h" +#include "fetch.h" +#include "files.h" +#include "globs.h" +#include "log.h" +#include "pkg.h" + +void install_dependencies(lua_State *L) { + while (lua_next(L, -2) != 0) { + const char *depname = lua_tostring(L, -2); + if (depname && lua_istable(L, -1)) { + lua_getfield(L, -1, "url"); + str_slc dep_url = mstrslc(lua_tostring(L, -1)); + lua_pop(L, 1); + lua_getfield(L, -1, "version"); + str_slc dep_version = mstrslc(lua_tostring(L, -1)); + lua_pop(L, 1); + package_t pkg = pkg_create(dep_url); + pkg.version = str_from_str_slc(dep_version); + const int top = lua_gettop(L); + char cwd[MAX_PATH_LEN]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + //install_pkg(pkg); + chdir(cwd); + } + lua_settop(L, top); + pkg_free(&pkg); + } + lua_pop(L, 1); + } +} + +bool target_install(lua_State *L, char* lua_file, str *target) { + if (!lua_try_table(L, lua_file, target->data)) { + lua_pop(L, 1); + return false; + } + //lua_try_function(L, lua_file, "pre_install"); + if (!lua_try_function(L, lua_file, "install")) { + lua_pop(L, 1); + return false; + } + //lua_try_function(L, lua_file, "post_install"); + lua_pop(L, 1); + return true; +} + +bool repo_install(package_t *pkg) { + lua_getglobal(L, "repositories"); + if (!config_loaded || !lua_istable(L, -1)) { + lua_isnt_type("repositories", "table"); + lua_pop(L, 1); + return false; + } + if (!lua_try_table(L, "init.lua", pkg->name.data)) { + lua_isnt_type(pkg->name.data, "table"); + lua_pop(L, 2); + return false; + } + if (!lua_try_table(L, "init.lua", "targets")) return false; + bool target_success = target_install(L, "init.lua", &pkg->target); + lua_pop(L, 3); + return target_success; +} + +bool bldit_install(package_t *pkg) { + init_bldit_state(); + if (!bldit_loaded) { + lua_close(B); + return false; + } + //if (!is_bldit_usable()) { + // log_error("bldit version is newer than the installed pkgit version"); + // log_error("consider updating pkgit"); + // if (!flags.force) return false; + //} + lua_pushfstring(B, "%s", inst_dirs.prefix.data); + lua_setglobal(B, "prefix"); + lua_pop(B, 1); + if (!lua_try_table(B, "bldit.lua", "targets")) return false; + bool target_success = target_install(B, "bldit.lua", &pkg->target); + lua_pop(B, 2); + lua_close(B); + return target_success; +} + +bool config_install(package_t *pkg) { + lua_getglobal(L, "build_systems"); + lua_pushnil(L); + bool target_success = false; + while (lua_next(L, -2) != 0) { + const char *key = lua_tostring(L, -2); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + continue; + } + str file_path = str_format("%.*s/%s", str_fmt(&pkg->src), key); + if (access(file_path.data, F_OK) != 0) { + lua_pop(L, 1); + str_free(&file_path); + continue; + } + str_free(&file_path); + if (!lua_try_table(L, "init.lua", "targets")) { + lua_pop(L, 2); + continue; + } + target_success = target_install(L, "init.lua", &pkg->target); + lua_pop(L, 2); + if (target_success) break; + } + lua_pop(L, 1); + return target_success; +} + +void pkg_install(package_t *pkg) { + if (is_directory(pkg->src.data)) { + if (!flags.force) { + log_info("%.*s is already installed.", str_fmt(&pkg->name)); + return; + } else { + if (flags.verbose) log_warn("%.*s is already installed.", str_fmt(&pkg->name)); + } + } + char cwd[MAX_PATH_LEN]; + getcwd(cwd, MAX_PATH_LEN); + if (str_equal_cstr(&pkg->src, cwd)) chdir(pkg->src.data); + + //if (pkg->is_local) { + // cpdir(cwd, pkg->src); + //} else { + log_pkgit("fetching " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); + if (!fetch(pkg)) return; + log_pkgit("fetched " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); + //} + + log_pkgit("building " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); + if (!build(pkg)) return; + log_pkgit("built " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); + + bool install_success = false; + log_info("attempting init.lua: 'repositories.%.*s.install'", str_fmt(&pkg->name)); + if (!install_success && repo_install(pkg)) + install_success = true; + log_info("attempting bldit.lua: 'repositories.%.*s.install'", str_fmt(&pkg->name)); + if (!install_success && bldit_install(pkg)) + install_success = true; + log_info("attempting init.lua: 'build_systems'", str_fmt(&pkg->name)); + if (!install_success && config_install(pkg)) + install_success = true; + if (!install_success) { + log_error("no install function availible for package: %.*s", str_fmt(&pkg->name)); + return; + } + log_success("installed " GREEN "%.*s" COLOR_RESET , str_fmt(&pkg->name)); + + //bool repo_exists = false; + + //for (size_t i = 0; i < cached_repos_count; i++) { + //char *repo_name = name_from_url(cached_repos[i].source_key); + //if (strcmp(repo_name, pkg.name) == 0) { repo_exists = true; } + //free(repo_name); + //} + + //if (!repo_exists) { + // log_pkgit("adding " GREEN "%.*s" COLOR_RESET , &pkg->name); + // if (pkg->url.len > 0) { + // add_repo(pkg); + // log_pkgit("added " GREEN "%.*s" COLOR_RESET , &pkg->name); + // } + //} else { + // log_info("repo already exists, done"); + //} +} diff --git a/src/pkg_remove.c b/src/pkg_remove.c new file mode 100644 index 0000000..1d4be14 --- /dev/null +++ b/src/pkg_remove.c @@ -0,0 +1,199 @@ +/* + + pkgit - package it! + + Copyright (C) 2026 dacctal + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include +#include +#include +#include +#include +#include + +#include "pkgit_lua.h" +#include "files.h" +#include "globs.h" +#include "log.h" + +bool target_uninstall(lua_State *L, char* lua_file, str *target) { + if (!lua_try_table(L, lua_file, target->data)) { + lua_pop(L, 1); + return false; + } + if (!lua_try_function(L, lua_file, "uninstall")) { + lua_pop(L, 1); + return false; + } + lua_pop(L, 1); + return true; +} + +bool repo_uninstall(package_t *pkg) { + if (!config_loaded || !lua_istable(L, -1)) { + lua_isnt_type("repositories", "table"); + lua_pop(L, 1); + return false; + } + if (!lua_try_table(L, "init.lua", pkg->name.data)) { + lua_isnt_type(pkg->name.data, "table"); + lua_pop(L, 2); + return false; + } + if (!lua_try_table(L, "init.lua", "targets")) return false; + bool target_success = target_uninstall(L, "init.lua", &pkg->target); + lua_pop(L, 3); + return target_success; +} + +bool bldit_uninstall(package_t *pkg) { + init_bldit_state(); + if (!bldit_loaded) { + lua_close(B); + return false; + } + //if (!is_bldit_usable()) { + // log_error("bldit version is newer than the installed pkgit version"); + // log_error("consider updating pkgit"); + // if (!flags.force) return false; + //} + lua_pushfstring(B, "%s", inst_dirs.prefix.data); + lua_setglobal(B, "prefix"); + lua_pop(B, 1); + if (!lua_try_table(B, "bldit.lua", "targets")) return false; + bool target_success = target_uninstall(B, "bldit.lua", &pkg->target); + lua_pop(B, 2); + lua_close(B); + return target_success; +} + +bool config_uninstall(package_t *pkg) { + lua_getglobal(L, "build_systems"); + lua_pushnil(L); + bool target_success = false; + while (lua_next(L, -2) != 0) { + const char *key = lua_tostring(L, -2); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + continue; + } + str file_path = str_format("%.*s/%s", str_fmt(&pkg->src), key); + if (access(file_path.data, F_OK) != 0) { + lua_pop(L, 1); + str_free(&file_path); + continue; + } + str_free(&file_path); + if (!lua_try_table(L, "init.lua", "targets")) { + lua_pop(L, 2); + continue; + } + target_success = target_uninstall(L, "init.lua", &pkg->target); + lua_pop(L, 2); + if (target_success) break; + } + lua_pop(L, 1); + return target_success; +} + +static int remove_installed( + const char *src_path, const struct stat *sb, + int typeflag, struct FTW *ftwbuf +) { + (void)sb; + (void)ftwbuf; + + if (typeflag == FTW_F) { + const char *filename = src_path + ftwbuf->base; + const char *ext = strrchr(filename, '.'); + if (!ext) + ext = ""; + + if (strncmp(ext, ".so", 3) == 0) { + char dest[MAX_PATH_LEN]; + snprintf(dest, sizeof(dest), "%s/%s", inst_dirs.lib.data, filename); + if (file_exists(dest)) + remove(dest); + } else if (access(src_path, X_OK) == 0) { + if ( + strcmp(ext, ".sample") != 0 && + strcmp(filename, "bldit") != 0 && + strcmp(filename, "build.sh") != 0 && + strcmp(filename, "compile.sh") != 0 + ) { + char dest[MAX_PATH_LEN]; + snprintf(dest, sizeof(dest), "%s/%s", inst_dirs.bin.data, filename); + if (file_exists(dest)) + remove(dest); + } + } else if (strcmp(ext, ".h") == 0) { + char dest[MAX_PATH_LEN]; + snprintf(dest, sizeof(dest), "%s/%s", inst_dirs.include.data, filename); + if (file_exists(dest)) + remove(dest); + } + } + return 0; +} + +static int remove_tree( + const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf +) { + (void)sb; + (void)ftwbuf; + if (typeflag == FTW_F || typeflag == FTW_SL) { + unlink(fpath); + } else if (typeflag == FTW_DP) { + rmdir(fpath); + } + return 0; +} + +void remove_pkg(package_t *pkg) { + if (!is_directory(pkg->src.data)) { + log_error("%.*s is not installed!", str_fmt(&pkg->name)); + return; + } + chdir(pkg->src.data); + + bool uninstall_available = false; + if (!uninstall_available) if (repo_uninstall(pkg)) + uninstall_available = true; + if (!uninstall_available) if (bldit_uninstall(pkg)) + uninstall_available = true; + if (!uninstall_available) if (config_uninstall(pkg)) + uninstall_available = true; + + if (!uninstall_available) + log_error( + "no uninstall function availible for package: %.*s", + str_fmt(&pkg->name) + ); + + nftw(pkg->src.data, remove_installed, 64, FTW_PHYS); + const char *last_slash = strrchr(pkg->src.data, '/'); + char target[MAX_PATH_LEN]; + if (last_slash && last_slash != pkg->src.data) { + size_t parent_len = last_slash - pkg->src.data; + snprintf(target, sizeof(target), "%.*s", (int)parent_len, pkg->src.data); + } else { + snprintf(target, sizeof(target), "%s", pkg->src.data); + } + nftw(pkg->src.data, remove_tree, 64, FTW_DEPTH | FTW_PHYS); + log_success("removed %s", str_fmt(&pkg->name)); +} -- cgit v1.2.3