diff options
| author | dacctal <donotcontactmevia@email.invalid> | 2026-07-21 21:32:27 +0000 |
|---|---|---|
| committer | dacctal <donotcontactmevia@email.invalid> | 2026-07-21 21:32:27 +0000 |
| commit | 184bd50e2ea12b4bf40f4ae1b0d685f0bfa1c995 (patch) | |
| tree | bfe4f0a8fb39def302bdc807308c30b60dd18a92 /src | |
| parent | c251d37c98efba534766e914f7392cc7a0470351 (diff) | |
started 2.0 refactor. Co-authored-by: ezntek <eason@ezntek.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/add_repo.c | 56 | ||||
| -rw-r--r-- | src/build.c | 170 | ||||
| -rw-r--r-- | src/check.c | 43 | ||||
| -rw-r--r-- | src/cli.c | 246 | ||||
| -rw-r--r-- | src/debug.c | 35 | ||||
| -rw-r--r-- | src/fetch.c | 95 | ||||
| -rw-r--r-- | src/files.c | 246 | ||||
| -rw-r--r-- | src/globs.c | 64 | ||||
| -rw-r--r-- | src/help.c | 7 | ||||
| -rw-r--r-- | src/is_updated.c | 48 | ||||
| -rw-r--r-- | src/log.c | 2 | ||||
| -rw-r--r-- | src/lua_globs.c | 213 | ||||
| -rw-r--r-- | src/lua_state.c | 146 | ||||
| -rw-r--r-- | src/lua_vars.c | 66 | ||||
| -rw-r--r-- | src/main.c | 28 | ||||
| -rw-r--r-- | src/parse_args.c | 206 | ||||
| -rw-r--r-- | src/pkg_create.c | 140 | ||||
| -rw-r--r-- | src/pkg_exists.c | 56 | ||||
| -rw-r--r-- | src/pkg_free.c | 10 | ||||
| -rw-r--r-- | src/pkg_install.c | 213 | ||||
| -rw-r--r-- | src/pkg_remove.c | 189 | ||||
| -rw-r--r-- | src/pkg_update.c | 174 | ||||
| -rw-r--r-- | src/search.c | 70 | ||||
| -rw-r--r-- | src/state.c | 27 | ||||
| -rw-r--r-- | src/str.c | 34 |
25 files changed, 477 insertions, 2107 deletions
diff --git a/src/add_repo.c b/src/add_repo.c deleted file mode 100644 index 1c41f3b..0000000 --- a/src/add_repo.c +++ /dev/null @@ -1,56 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdio.h> -#include <string.h> -#include <stdbool.h> - -#include "add_repo.h" - -#include "files.h" -#include "globs.h" - -void add_repo(package_t *pkg) { - bool is_previous_repos = false; - char rfile_line[1024]; - char rfile_contents[8192] = {0}; - - if (file_exists(cfg.repos.data)) { - FILE *rfile = fopen(cfg.repos.data, "r"); - if (rfile) { - while (fgets(rfile_line, sizeof(rfile_line), rfile)) { - strcat(rfile_contents, rfile_line); - } - fclose(rfile); - is_previous_repos = true; - } - } - - char *previous_repos = is_previous_repos ? rfile_contents : ""; - - FILE *wfile = fopen(cfg.repos.data, "w"); - if (wfile) { - fprintf(wfile, - "%srepositories[\"%s\"] = { url = \"%s\" }\n", - previous_repos, pkg->name.data, pkg->url.data - ); - fclose(wfile); - } -} diff --git a/src/build.c b/src/build.c deleted file mode 100644 index 1974846..0000000 --- a/src/build.c +++ /dev/null @@ -1,170 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdio.h> -#include <unistd.h> - -#include "build.h" - -#include "globs.h" -#include "log.h" -#include "lua.h" -#include "pkg.h" -#include "pkgit_lua.h" - -bool target_build(lua_State *L, char *lua_file, str *target) { - if (!lua_try_table(L, lua_file, target->data)) - return false; - if (lua_try_table(L, lua_file, "dependencies")) { - lua_pushnil(L); - install_dependencies(L); - } - lua_pop(L, 1); - if (!lua_try_function(L, lua_file, "build")) - return false; - lua_pop(L, 1); - return true; -} - -bool repo_build(package_t *pkg) { - lua_getglobal(L, "repositories"); - if (!lua_try_table(L, "init.lua", pkg->name.data)) { - lua_pop(L, 2); - return false; - } - if (lua_try_table(L, "init.lua", "dependencies")) { - lua_pushnil(L); - install_dependencies(L); - } - lua_pop(L, 1); - if (!lua_try_table(L, "init.lua", "targets")) { - lua_pop(L, 3); - return false; - } - bool target_success = target_build(L, "init.lua", &pkg->target); - lua_pop(L, 4); - return target_success; -} - -bool bldit(package_t *pkg) { - init_bldit_state(); - if (!bldit_loaded) - return false; - lua_getglobal(B, "dependencies"); - if (!lua_istable(B, -1)) { - bldit_isnt_type("dependencies", "table"); - lua_pop(B, 1); - } else { - lua_pushnil(B); - install_dependencies(B); - lua_pop(B, 1); - } - lua_getglobal(B, "targets"); - if (!lua_istable(B, -1)) { - bldit_isnt_type("targets", "table"); - lua_pop(B, 1); - lua_close(B); - B = NULL; - bldit_loaded = false; - return false; - } - bool target_success = target_build(B, "bldit.lua", &pkg->target); - lua_pop(B, 1); - return target_success; -} - -bool config_build(package_t *pkg) { - lua_getglobal(L, "build_systems"); - if (!lua_istable(L, -1)) { - lua_isnt_type("build_systems", "table"); - lua_pop(L, 1); - return false; - } - bool target_success = false; - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - str key = mstr(lua_tostring(L, -2)); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - str_free(&key); - continue; - } - str file_path = str_format("%.*s/%s", str_fmt(&pkg->src), key.data); - if (access(file_path.data, F_OK) != 0) { - lua_pop(L, 1); - str_free(&file_path); - str_free(&key); - continue; - } - str_free(&file_path); - str_free(&key); - if (!lua_try_table(L, "init.lua", "targets")) - continue; - target_success = target_build(L, "init.lua", &pkg->target); - if (target_success) - break; - lua_pop(L, 1); - } - lua_pop(L, 1); - return target_success; -} - -bool build_loop(package_t *pkg) { - if (flags.verbose) - log_info("attempting init.lua: 'repositories.%.*s.build'", - str_fmt(&pkg->name)); - if (repo_build(pkg)) { - return true; - } - if (flags.verbose) - log_warn("failed init.lua: 'repositories.%.*s.build'", - str_fmt(&pkg->name)); - - if (flags.verbose) - log_info("attempting bldit.lua"); - if (bldit(pkg)) { - return true; - } - if (flags.verbose) - log_warn("failed bldit.lua"); - - if (flags.verbose) - log_info("attempting init.lua: 'build_systems'"); - if (config_build(pkg)) { - return true; - } - if (flags.verbose) - log_warn("failed init.lua: 'build_systems'"); - return false; -} - -bool build(package_t *pkg) { - char cwd[MAX_PATH_LEN]; - if (getcwd(cwd, sizeof(cwd)) == NULL) { - log_error("getcwd failed"); - return false; - } - 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)); - return false; -} diff --git a/src/check.c b/src/check.c deleted file mode 100644 index 366f8a7..0000000 --- a/src/check.c +++ /dev/null @@ -1,43 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdio.h> -#include <unistd.h> - -#include "check.h" - -void check(void) { - const char *frame_top = " (c _c)"; - const char *frame1_bot = "_/ \\-"; - const char *frame2_bot = "-/ \\_"; - - printf("\033[2J\033[H"); - printf("Unfortunately due to budget issues, we could not afford a progress bar. Enjoy this instead:\n\n"); - - for (int i = 0; i < 16; i++) { - printf("%s\n%s\n", frame_top, i % 2 == 0 ? frame1_bot : frame2_bot); - for (int j = 0; j <= i; j++) printf("."); - printf("\n"); - fflush(stdout); - sleep(1); - if (i < 15) printf("\033[3A"); - } - printf("\n"); - printf("Dependencies resolved! (this does nothing)\n"); -} diff --git a/src/cli.c b/src/cli.c new file mode 100644 index 0000000..c4499ff --- /dev/null +++ b/src/cli.c @@ -0,0 +1,246 @@ +/* + + 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 <https://www.gnu.org/licenses/>. + +*/ + +#include <stdio.h> +#include <string.h> + +#include "cli.h" +#include "common.h" +#include "help.h" +#include "log.h" +#include "state.h" +#include "str.h" + +#define COMMAND(large, small) \ + (!strcmp(argv[i], large) || !strcmp(argv[i], small)) + +#define NOT_ENOUGH_ARGS(arg, next) \ + log_error("Not enough arguments! Try: pkgit %s [%s]", (arg), (next)) + +void cmd_add(char **argv, int i) { + if (argv[i + 1]) { + str arg = mstr(argv[i + 1]); + if (str_is_valid(&arg)) + str_free(&arg); + } else { + NOT_ENOUGH_ARGS(argv[i], "url"); + } +} + +void cmd_build(int argc, char **argv, int i) { + if (argv[i + 1]) { + for (int j = i + 1; j < argc; j++) { + if (argv[j][0] == '-') + continue; + str arg = mstr(argv[j]); + if (str_is_valid(&arg)) + str_free(&arg); + } + } else { + str arg = mstr("."); + if (str_is_valid(&arg)) + str_free(&arg); + } +} + +void cmd_install(int argc, char **argv, int i) { + if (argv[i + 1]) { + for (int j = i + 1; j < argc; j++) { + if (argv[j][0] == '-') + continue; + str arg = mstr(argv[j]); + if (str_is_valid(&arg)) + str_free(&arg); + } + } else { + NOT_ENOUGH_ARGS(argv[i], "url/pkg"); + } +} + +void cmd_update(int argc, char **argv, int i) { + if (argv[i + 1]) { + for (int j = i + 1; j < argc; j++) { + if (argv[j][0] == '-') + continue; + str arg = mstr(argv[j]); + if (str_is_valid(&arg)) + str_free(&arg); + } + } else { + } +} + +void cmd_remove(int argc, char **argv, int i) { + if (argv[i + 1]) { + for (int j = i + 1; j < argc; j++) { + if (argv[j][0] == '-') + continue; + str arg = mstr(argv[j]); + if (str_is_valid(&arg)) + str_free(&arg); + } + } else { + NOT_ENOUGH_ARGS(argv[i], "url/pkg"); + } +} + +void cmd_search(int argc, char **argv, int i) { + if (argv[i + 1]) { + for (int j = i + 1; j < argc; j++) { + if (argv[j][0] == '-') + continue; + } + } else { + } +} + +void flags_mod(char **argv, int i) { + for (size_t j = 1; j < strlen(argv[i]); j++) { + switch (argv[i][j]) { + case 'q': + flags.quiet = true; + break; + case 'f': + flags.force = true; + break; + default: + break; + } + } +} + +cli_result_t flags_cmd(int argc, char **argv, int i) { + for (size_t j = 1; j < strlen(argv[i]); j++) { + switch (argv[i][j]) { + case 'a': + cmd_add(argv, i); + break; + case 'b': + cmd_build(argc, argv, i); + break; + case 'c': + // check(); + break; + case 'd': + // declare(); + break; + case 'i': + cmd_install(argc, argv, i); + break; + case 'r': + cmd_remove(argc, argv, i); + break; + case 'u': + cmd_update(argc, argv, i); + break; + case 'l': + // list_installed(); + break; + case 's': + cmd_search(argc, argv, i); + break; + case 'v': + printf("%s\n", VERSION); + break; + case 'h': + print_help(); + return CLI_HELP_CALLED; + break; + default: + break; + } + } + return CLI_SUCCESS; +} + +cli_result_t parse_flags(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '-') + continue; + if (argv[i][1] == '-') { + if (COMMAND("--quiet", "-q")) + flags.quiet = true; + if (COMMAND("--force", "-f")) + flags.force = true; + } else { + flags_mod(argv, i); + cli_result_t status = flags_cmd(argc, argv, i); + if (status != CLI_SUCCESS) + return status; + } + } + return CLI_SUCCESS; +} + +cli_result_t parse_cmds(int argc, char **argv) { + for (int i = 1; i < argc; i++) { + if (COMMAND("--add", "a")) { + cmd_add(argv, i); + } + if (COMMAND("--build", "b")) { + cmd_build(argc, argv, i); + } + if (COMMAND("--install", "i")) { + cmd_install(argc, argv, i); + } + if (COMMAND("--remove", "r")) { + cmd_remove(argc, argv, i); + } + if (COMMAND("--update", "u")) { + cmd_update(argc, argv, i); + } + if (COMMAND("--declare", "d")) { + // declare(); + } + if (COMMAND("--list", "l")) { + // list_installed(); + } + if (COMMAND("--search", "s")) { + cmd_search(argc, argv, i); + } + if (COMMAND("--version", "v")) { + printf(VERSION "\n"); + } + if (COMMAND("--help", "h")) { + print_help(); + return CLI_HELP_CALLED; + } + if (COMMAND("--check", "c")) { + // check(); + } + } + return CLI_SUCCESS; +} + +cli_result_t cli(int argc, char **argv) { + flags.force = false; + flags.quiet = false; + if (argc == 1) { + print_help(); + return CLI_HELP_CALLED; + } + if (!parse_flags(argc, argv)) + return CLI_FAIL; + + if (!parse_cmds(argc, argv)) + return CLI_FAIL; + + return CLI_SUCCESS; +} diff --git a/src/debug.c b/src/debug.c deleted file mode 100644 index 0a580df..0000000 --- a/src/debug.c +++ /dev/null @@ -1,35 +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 <https://www.gnu.org/licenses/>. - -*/ - - -#include "globs.h" - -void debug_print_inst_dirs(void) { - printf("PREFIX:\t"); - str_println(&inst_dirs.prefix); - printf("ID_BIN:\t"); - str_println(&inst_dirs.bin); - printf("ID_LIB:\t"); - str_println(&inst_dirs.lib); - printf("ID_INCLUDE:\t"); - str_println(&inst_dirs.include); - printf("ID_SRC:\t"); - str_println(&inst_dirs.src); -} diff --git a/src/fetch.c b/src/fetch.c deleted file mode 100644 index 2666f78..0000000 --- a/src/fetch.c +++ /dev/null @@ -1,95 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <fcntl.h> -#include <sys/wait.h> -#include <unistd.h> - -#include "fetch.h" -#include "files.h" -#include "globs.h" -#include "log.h" -#include "str.h" - -bool fetch(package_t *pkg) { - if (pkg->url.data == NULL || pkg->src.data == NULL) { - if (flags.verbose) - log_warn("invalid pkg: url or src is NULL"); - return false; - } - - str s = str_dupe(&pkg->src); - s.len -= pkg->version.len + 1; - s.data[s.len] = 0; - - if (is_directory(s.data) && flags.force) { - if (remove_tree(s.data)) { - log_error("could not remove %.*s", str_fmt(&s)); - return false; - } - } - - str_free(&s); - - pid_t pid = fork(); - if (pid < 0) { - log_error("fork failed"); - return false; - } - - if (pid == 0) { - if (!flags.verbose) { - int nullfd = open("/dev/null", O_WRONLY); - if (nullfd >= 0) { - dup2(nullfd, STDOUT_FILENO); - dup2(nullfd, STDERR_FILENO); - close(nullfd); - } - } - - const char *argv[12]; - int i = 0; - argv[i++] = "git"; - argv[i++] = "-c"; - argv[i++] = "advice.detachedHead=false"; - argv[i++] = "clone"; - if (pkg->version.data != NULL && - !str_equal_cstr(&pkg->version, "HEAD")) { - argv[i++] = "--branch"; - argv[i++] = pkg->version.data; - } - - argv[i++] = "--recursive"; - argv[i++] = pkg->url.data; - argv[i++] = pkg->src.data; - argv[i] = NULL; - execvp("git", (char *const *)argv); - _exit(127); - } - int status; - waitpid(pid, &status, 0); - - bool result = (WEXITSTATUS(status) == 0); - if (!result) { - log_error("git clone failed"); - } - - return result; -} diff --git a/src/files.c b/src/files.c deleted file mode 100644 index 0ce64b4..0000000 --- a/src/files.c +++ /dev/null @@ -1,246 +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 <https://www.gnu.org/licenses/>. - -*/ - -#define _XOPEN_SOURCE 700 - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <ftw.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "files.h" -#include "log.h" -#include "str.h" - -bool file_exists(const char *path) { - struct stat buffer; - return (stat(path, &buffer) == 0); -} - -bool is_directory(const char *path) { - struct stat statbuf; - if (stat(path, &statbuf) != 0) { - return false; - } - return S_ISDIR(statbuf.st_mode); -} - -FILE *popen(const char *command, const char *type); -int pclose(FILE *stream); - -str cmd_out(const char *cmd) { - FILE *pipe = popen(cmd, "r"); - if (!pipe) - return mstr(""); - - char buffer[128]; - size_t total_size = 0; - size_t capacity = 256; - char *result = malloc(capacity); - if (!result) { - pclose(pipe); - return mstr(""); - } - result[0] = '\0'; - - while (fgets(buffer, sizeof(buffer), pipe) != NULL) { - size_t len = strlen(buffer); - // Ensure enough space for the new chunk + 1 byte for '\0' - if (total_size + len + 1 > capacity) { - capacity *= 2; - char *new_result = realloc(result, capacity); - if (!new_result) { - free(result); - pclose(pipe); - return mstr(""); - } - result = new_result; - } - - snprintf(result + total_size, capacity - total_size, "%s", buffer); - total_size += len; - } - - pclose(pipe); - str str_result = mstr(result); - free(result); - return str_result; -} - -const char *get_filename_ext(const char *filename) { - const char *dot = strrchr(filename, '.'); - if (!dot || dot == filename) - return ""; - return dot + 1; -} - -static int write_all(int fd, const void *buf, size_t size) { - while (size) { - ssize_t written = write(fd, buf, size); - if (written < 0) { - return -1; - } - - size -= written; - buf = (const char *)buf + written; - } - - return 0; -} - -static int copy_file_content(int src_fd, int dst_fd) { - char buf[4096]; - ssize_t readed; - while ((readed = read(src_fd, buf, sizeof(buf))) > 0) { - if (write_all(dst_fd, buf, readed) < 0) { - perror("write_all"); - return -1; - } - } - - if (readed < 0) { - perror("read"); - return -1; - } - - return 0; -} - -static int copy_at(int src_dir_fd, const char *src_path, int dst_dir_fd, - const char *dst_path); - -static int copy_dir_content(int src_fd, int dst_fd) { - int ret = -1; - // duplicate the descriptor to prevent closedir from closing original one - src_fd = dup(src_fd); - if (src_fd < 0) { - perror("dup"); - goto cleanup0; - } - - DIR *src_dir = fdopendir(src_fd); - if (!src_dir) { - perror("fdopendir"); - close(src_fd); - goto cleanup0; - } - - for (struct dirent *ent; (errno = 0, ent = readdir(src_dir));) { - if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { - continue; - } - - if (copy_at(src_fd, ent->d_name, dst_fd, ent->d_name) < 0) { - goto cleanup1; - } - } - - if (errno != 0) { - perror("readdir"); - goto cleanup1; - } - - ret = 0; - -cleanup1: - closedir(src_dir); -cleanup0: - return ret; -} - -static int copy_at(int src_dir_fd, const char *src_path, int dst_dir_fd, - const char *dst_path) { - int ret = -1; - int src_fd = openat(src_dir_fd, src_path, O_NOFOLLOW | O_RDONLY); - if (src_fd < 0) { - perror("openat"); - goto cleanup0; - } - - struct stat stat; - if (fstat(src_fd, &stat) < 0) { - perror("fstat"); - goto cleanup1; - } - - int dst_oflag = O_NOFOLLOW; - if (S_ISDIR(stat.st_mode)) { - if (mkdirat(dst_dir_fd, dst_path, stat.st_mode) < 0) { - perror("mkdirat"); - goto cleanup1; - } - - dst_oflag |= O_RDONLY | O_DIRECTORY; - } else { - dst_oflag |= O_WRONLY | O_CREAT | O_EXCL; - } - - int dst_fd = openat(dst_dir_fd, dst_path, dst_oflag, stat.st_mode); - if (dst_fd < 0) { - perror("openat"); - goto cleanup1; - } - - switch (stat.st_mode & S_IFMT) { - case S_IFDIR: - ret = copy_dir_content(src_fd, dst_fd); - break; - case S_IFREG: - ret = copy_file_content(src_fd, dst_fd); - break; - default: - fprintf(stderr, "copy_at: unsupported file inode type\n"); - } - goto cleanup2; - -cleanup2: - close(dst_fd); -cleanup1: - close(src_fd); -cleanup0: - return ret; -} - -void cpdir(const char *src_path, const char *dst_path) { - copy_at(AT_FDCWD, src_path, AT_FDCWD, dst_path); -} - -static int _remove_callback(const char *fpath, const struct stat *sb, - int typeflag, struct FTW *ftwbuf) { - (void)sb; - (void)typeflag; - (void)ftwbuf; - - int res = remove(fpath); - if (res) { - log_warn("could not remove: %s", fpath); - } - return 0; -} - -int remove_tree(const char *path) { - return nftw(path, _remove_callback, 256, FTW_DEPTH | FTW_PHYS); -} diff --git a/src/globs.c b/src/globs.c deleted file mode 100644 index cdb9df8..0000000 --- a/src/globs.c +++ /dev/null @@ -1,64 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdlib.h> - -#include "globs.h" - -#include "files.h" -#include "log.h" -#include "pkgit_lua.h" -#include "str.h" - -install_dirs_t inst_dirs = {0}; -cli_flags_t flags = {0}; -config_t cfg = {0}; - -void init_vars(void) { - if (file_exists("/etc/pkgit/repos.lua")) { - cfg.dir = mstr("/etc/pkgit"); - cfg.name = mstr("/etc/pkgit/repos.lua"); - } else { - const char *tmp = getenv("XDG_CONFIG_HOME"); - if (tmp) { - cfg.dir = str_format("%s/pkgit", tmp); - } else { - cfg.dir = str_format("%s/.config/pkgit", getenv("HOME")); - } - cfg.name = str_concat_cstr(&cfg.dir, "/init.lua"); - } - // TODO: read into cfg.content - - cfg.repos = str_format("%.*s/repos.lua", str_fmt(&cfg.dir)); - init_install_directories(); - init_prefix_directory(); -} - -void free_vars(void) { - str_free(&cfg.dir); - str_free(&cfg.name); - str_free(&cfg.content); - str_free(&cfg.repos); - str_free(&inst_dirs.prefix); - str_free(&inst_dirs.bin); - str_free(&inst_dirs.lib); - str_free(&inst_dirs.include); - str_free(&inst_dirs.src); -} @@ -20,10 +20,11 @@ #include <stdio.h> +#include "common.h" #include "help.h" -#include "globs.h" +#include "state.h" -void help(void) { +void print_help(void) { typedef struct { const char *short_flag; const char *long_flag; @@ -50,7 +51,7 @@ void help(void) { {"-f", "--force", "", "build a package"}, }; - if (flags.verbose) { + if (!flags.quiet) { printf(BOLD_MAGENTA " , \n"); printf(BOLD_MAGENTA " / \\ \n"); printf(BOLD_MAGENTA "_.--' '--._ \n"); diff --git a/src/is_updated.c b/src/is_updated.c deleted file mode 100644 index fef759e..0000000 --- a/src/is_updated.c +++ /dev/null @@ -1,48 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <string.h> -#include <stdbool.h> -#include <unistd.h> - -#include "is_updated.h" - -#include "files.h" -#include "str.h" -#include "pkgit_lua.h" - -bool is_updated(str *src) { - bool result = false; - if (str_is_valid(src) && src->len > 0 && chdir(src->data) != 0) return result; - str bldit_pkgver = bldit_pkg_getver(); - str git_tag = cmd_out("git tag | tail -n 1"); - result = (strstr(git_tag.data, bldit_pkgver.data) != NULL && bldit_pkgver.len != 0); - if (result) { - str_free(&bldit_pkgver); - str_free(&git_tag); - return result; - } - str git_pull = cmd_out("git pull"); - result = (strstr(git_pull.data, "Already up to date.") != NULL); - str_free(&git_tag); - str_free(&git_pull); - str_free(&bldit_pkgver); - return result; -} @@ -2,7 +2,7 @@ #include <stdarg.h> #include <stdio.h> -#include "globs.h" +#include "common.h" #include "log.h" #define X(n, N) \ diff --git a/src/lua_globs.c b/src/lua_globs.c deleted file mode 100644 index 3f8ac2a..0000000 --- a/src/lua_globs.c +++ /dev/null @@ -1,213 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdlib.h> -#include <string.h> - -#include "lua.h" -#include "pkgit_lua.h" - -#include "files.h" -#include "globs.h" -#include "log.h" -#include "str.h" - -lua_State *L = NULL; -lua_State *B = NULL; -bool config_loaded = false; -bool bldit_loaded = false; - -void push_lua_path(lua_State *L, const char *new_path) { - lua_getglobal(L, "package"); - lua_getfield(L, -1, "path"); - const char *current_path = lua_tostring(L, -1); - if (!current_path) - current_path = ""; - lua_pop(L, 1); - lua_pushfstring(L, "%s;%s", current_path, new_path); - lua_setfield(L, -2, "path"); - lua_pop(L, 1); -} - -void init_lua_state(void) { - if (L != NULL) - return; - L = luaL_newstate(); - luaL_openlibs(L); - str lua_path = str_format("%.*s/?.lua", str_fmt(&cfg.dir)); - push_lua_path(L, lua_path.data); - if (luaL_loadfile(L, cfg.name.data) || lua_pcall(L, 0, 0, 0)) { - log_error("cannot run configuration script: %s", lua_tostring(L, -1)); - log_pkgit("to generate a configuration file, head into the"); - log_pkgit( - "root directory of the pkgit source and run `make defconfig`"); - exit(EXIT_FAILURE); - } - if (file_exists(cfg.repos.data)) { - if (luaL_loadfile(L, cfg.repos.data) || lua_pcall(L, 0, 0, 0)) { - if (flags.verbose) - log_warn("cannot load repository file: %s", - lua_tostring(L, -1)); - lua_pop(L, 1); - } - } - str_free(&lua_path); - config_loaded = true; -} - -void init_bldit_state(void) { - if (B != NULL) - return; - B = luaL_newstate(); - 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)); - return; - } - lua_pushfstring(B, "%s", inst_dirs.prefix.data); - lua_setglobal(B, "prefix"); - bldit_loaded = true; -} - -void free_lua_state(void) { - if (L != NULL) { - lua_close(L); - L = NULL; - } - config_loaded = false; -} - -void free_bldit_state(void) { - if (B != NULL) { - lua_close(B); - B = NULL; - } - bldit_loaded = false; -} - -lua_State *get_lua_state(void) { - return L; -} - -lua_State *get_bldit_state(void) { - return B; -} - -void lua_isnt_type(char *variable, char *type) { - if (flags.verbose) - log_error("init.lua: '%s' is not a %s.", variable, type); -} - -void bldit_isnt_type(char *variable, char *type) { - if (flags.verbose) - log_error("bldit.lua: '%s' is not a %s.", variable, type); -} - -bool lua_try_function(lua_State *L, char *lua_file, char *fname) { - lua_getfield(L, -1, fname); - if (!lua_isfunction(L, -1)) { - if (!strcmp(lua_file, "bldit.lua")) - bldit_isnt_type(fname, "function"); - else - lua_isnt_type(fname, "function"); - lua_pop(L, 1); - return false; - } else if (lua_pcall(L, 0, 1, 0) != LUA_OK) { - if (flags.verbose) - log_warn("%s: '%s' function borked: %s", lua_file, fname, - lua_tostring(L, -1)); - lua_pop(L, 1); - return false; - } - if (!lua_isnumber(L, -1) || lua_tonumber(L, -1) != 0) { - if (flags.verbose) - log_warn("%s: '%s' failed: %s", lua_file, fname, - lua_tostring(L, -1)); - lua_pop(L, 1); - return false; - } - lua_pop(L, 1); - return true; -} - -bool lua_try_table(lua_State *L, char *lua_file, char *tname) { - lua_getfield(L, -1, tname); - if (!lua_istable(L, -1)) { - if (!strcmp(lua_file, "bldit.lua")) - bldit_isnt_type(tname, "table"); - else - lua_isnt_type(tname, "table"); - return false; - } - return true; -} - -str bldit_getver(void) { - init_bldit_state(); - if (!bldit_loaded) { - return mstr(""); - } - lua_getglobal(B, "bldit_version"); - if (!lua_isstring(B, -1)) { - if (flags.verbose) - log_warn("bldit.lua: 'bldit_version' is not a string."); - lua_pop(B, 1); - return mstr(""); - } - str bldit_version = mstr(lua_tostring(B, -1)); - lua_pop(B, 1); - return bldit_version; -} - -str bldit_pkg_getver(void) { - init_bldit_state(); - lua_getglobal(B, "package_version"); - if (!lua_isstring(B, -1)) { - if (flags.verbose) - log_warn("bldit.lua: 'package_version' is not a string."); - lua_pop(B, 1); - return mstr(""); - } - str package_version = mstr(lua_tostring(B, -1)); - lua_pop(B, 1); - return package_version; -} - -bool is_bldit_usable(void) { - str bldit_version = bldit_getver(); - if (bldit_version.len && str_equal_cstr(&bldit_version, VERSION)) - goto done; - bool prev_pass = false; - for (size_t i = 0; i < bldit_version.len; i++) { - if (bldit_version.data[i] == '.') - continue; - if ((bldit_version.data[i] - '0') <= (VERSION[i] - '0')) { - prev_pass = ((bldit_version.data[i] - '0') != (VERSION[i] - '0')); - continue; - } else { - str_free(&bldit_version); - return prev_pass; - } - } -done: - str_free(&bldit_version); - return true; -} diff --git a/src/lua_state.c b/src/lua_state.c new file mode 100644 index 0000000..7e9dd18 --- /dev/null +++ b/src/lua_state.c @@ -0,0 +1,146 @@ +#include <lua.h> +#include <stdlib.h> +#include <unistd.h> + +#include "log.h" +#include "lua_state.h" +#include "state.h" +#include "str.h" + +lua_State *L = NULL; +bool L_is_loaded = false; + +static void lua_path_push(const char *new_path) { + lua_getglobal(L, "package"); + lua_getfield(L, -1, "path"); + + const char *current_path = lua_tostring(L, -1); + if (!current_path) + current_path = ""; + lua_pop(L, 1); + + lua_pushfstring(L, "%s;%s", current_path, new_path); + lua_setfield(L, -2, "path"); + + lua_pop(L, 1); +} + +bool init_lua_state(void) { + if (L_is_loaded) + return true; + + L = luaL_newstate(); + luaL_openlibs(L); + + str lua_path = str_format("%.*s/?.lua", str_fmt(&config.dir)); + lua_path_push(lua_path.data); + + if (luaL_loadfile(L, config.init_path.data) || lua_pcall(L, 0, 1, 0)) { + log_error("cannot run configuration script: %s", lua_tostring(L, -1)); + log_pkgit("to generate a configuration file, head into the"); + log_pkgit( + "root directory of the pkgit source and run `make defconfig`"); + lua_close(L); + return false; + } + + if (!lua_istable(L, -1)) { + log_error("top-level configuration is not a table"); + lua_pop(L, 1); + lua_close(L); + return false; + } + + str_free(&lua_path); + L_is_loaded = true; + return true; +} + +static void setup_base_dirs(void) { + int uid = getuid(), euid = geteuid(); + + config.is_root = false; + + if (uid < 0 || uid != euid) { + config.is_root = true; + config.dir = mstr("/etc/pkgit"); + } else { + char *tmp = getenv("XDG_CONFIG_HOME"); + if (tmp) { + config.dir = str_format("%s/pkgit", tmp); + } else { + config.dir = str_format("%s/.config/pkgit", getenv("HOME")); + } + } + + config.init_path = str_concat_cstr(&config.dir, "/init.lua"); + config.autogenerated_path = + str_concat_cstr(&config.dir, "/autogenerated.lua"); +} + +#define HANDLE_LUA_ERROR \ + do { \ + log_error("lua: %s", lua_tostring(L, -1)); \ + lua_pop(L, 1); \ + return false; \ + } while (0) + +#define lua_get_field_type(name, type, file) \ + do { \ + lua_getfield(L, -1, name); \ + if (!lua_is##type(L, -1)) { \ + log_error("lua: expected type " #type " for " name " in %.*s", \ + str_fmt(file)); \ + lua_pop(L, 1); \ + return false; \ + } \ + } while (0) + +static bool load_init_lua(void) { + if (luaL_loadfile(L, config.init_path.data)) + HANDLE_LUA_ERROR; + + lua_setglobal(L, "__PkgitUserConfig"); + + lua_getglobal(L, "__PkgitUserConfig"); + lua_get_field_type("dirs", table, &config.init_path); + +#define X(field) \ + do { \ + lua_get_field_type(#field, string, &config.init_path); \ + config.inst_dirs.field = str_adopt((char *)lua_tostring(L, -1)); \ + lua_pop(L, -1); \ + } while (0) + + X(prefix); + X(bin); + X(include); + X(lib); + X(src); + +#undef X + + lua_getfield(L, -1, "prefix"); + + return true; +} + +bool init_lua_config(void) { + if (!init_lua_state()) + return false; + + setup_base_dirs(); + + if (!load_init_lua()) + return false; + + return true; +} + +void free_lua_state(void) { + if (L != NULL) { + lua_close(L); + L = NULL; + } + L_is_loaded = false; +} diff --git a/src/lua_vars.c b/src/lua_vars.c deleted file mode 100644 index 7420ae0..0000000 --- a/src/lua_vars.c +++ /dev/null @@ -1,66 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include "pkgit_lua.h" - -#include "globs.h" - -void init_install_directories(void) { - init_lua_state(); - if (!lua_istable(L, -1)) { - lua_getglobal(L, "install_directories"); - } - if (!lua_istable(L, -1)) { - lua_isnt_type("install_directories", "table"); - return; - } - -#define SETUP_INST_DIRS \ - X(bin) \ - X(lib) \ - X(include) \ - X(src) - -#define X(dir) \ - do { \ - lua_getfield(L, -1, #dir); \ - if (!lua_isstring(L, -1)) { \ - lua_isnt_type("install_directories." #dir, "string"); \ - } else { \ - str_copy_cstr_into(&inst_dirs.dir, lua_tostring(L, -1)); \ - } \ - lua_pop(L, 1); \ - } while (0); - - SETUP_INST_DIRS -#undef X - - lua_pop(L, 1); -} - -void init_prefix_directory(void) { - lua_getglobal(L, "prefix"); - if (!lua_isstring(L, -1)) { - lua_isnt_type("prefix", "string."); - return; - } - inst_dirs.prefix = mstr(lua_tostring(L, -1)); - lua_pop(L, 1); -} @@ -18,12 +18,28 @@ */ -#include "parse_args.h" -#include "globs.h" +#include "cli.h" +#include "lua_state.h" int main(int argc, char **argv) { - init_vars(); - parse_args(argc, argv); - free_vars(); - return 0; + // if (!init_vars()) + // return 1; + + int retval = 0; + cli_result_t result = cli(argc, argv); + if (!result) { + retval = 1; + goto done; + } + + if (result != CLI_HELP_CALLED) { + init_lua_state(); + // if (!init_vars()) + // return 1; + } + +done: + free_lua_state(); + // free_vars(); + return retval; } diff --git a/src/parse_args.c b/src/parse_args.c deleted file mode 100644 index ff72334..0000000 --- a/src/parse_args.c +++ /dev/null @@ -1,206 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <stdio.h> -#include <string.h> - -#include "parse_args.h" - -#include "build.h" -#include "globs.h" -#include "log.h" -#include "str.h" -#include "check.h" -#include "help.h" -#include "pkg.h" -#include "pkgit_lua.h" -#include "add_repo.h" -#include "search.h" - -#define COMMAND(large, small) \ - (!strcmp(argv[i], large) || !strcmp(argv[i], small)) - -#define NOT_ENOUGH_ARGS(arg, next) \ - log_error("Not enough arguments! Try: pkgit %s [%s]", (arg), (next)) - -void cmd_add(char **argv, int i) { - if (argv[i + 1]) { - str arg = mstr(argv[i + 1]); - package_t pkg = pkg_create(&arg); - add_repo(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } else { - NOT_ENOUGH_ARGS(argv[i], "url"); - } -} - -void cmd_build(int argc, char **argv, int i) { - if (argv[i + 1]) { - for (int j = i + 1; j < argc; j++) { - if (argv[j][0] == '-') - continue; - str arg = mstr(argv[j]); - package_t pkg = pkg_create(&arg); - build(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } - } else { - str arg = mstr("."); - package_t pkg = pkg_create(&arg); - build(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } -} - -void cmd_install(int argc, char **argv, int i) { - if (argv[i + 1]) { - for (int j = i + 1; j < argc; j++) { - if (argv[j][0] == '-') continue; - str arg = mstr(argv[j]); - package_t pkg = pkg_create(&arg); - if (flags.force) pkg_remove(&pkg); - pkg_install(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } - } else { - NOT_ENOUGH_ARGS(argv[i], "url/pkg"); - } -} - -void cmd_update(int argc, char **argv, int i) { - if (argv[i + 1]) { - for (int j = i + 1; j < argc; j++) { - if (argv[j][0] == '-') continue; - str arg = mstr(argv[j]); - package_t pkg = pkg_create(&arg); - pkg_update(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } - } else { - all_update(); - } -} - -void cmd_remove(int argc, char **argv, int i) { - if (argv[i + 1]) { - for (int j = i + 1; j < argc; j++) { - if (argv[j][0] == '-') continue; - str arg = mstr(argv[j]); - package_t pkg = pkg_create(&arg); - pkg_remove(&pkg); - pkg_free(&pkg); - if (str_is_valid(&arg)) str_free(&arg); - } - } else { - NOT_ENOUGH_ARGS(argv[i], "url/pkg"); - } -} - -void cmd_search(int argc, char **argv, int i) { - if (argv[i + 1]) { - for (int j = i + 1; j < argc; j++) { - if (argv[j][0] == '-') continue; - search(argv[j]); - } - } else { - search(""); - } -} - -void flags_mod(char **argv, int i) { - for (size_t j = 1; j < strlen(argv[i]); j++) { - switch (argv[i][j]) { - case 'q': - flags.verbose = false; - break; - case 'f': - flags.force = true; - break; - default: - break; - } - } -} - -void flags_cmd(int argc, char **argv, int i) { - for (size_t j = 1; j < strlen(argv[i]); j++) { - switch (argv[i][j]) { - case 'a': cmd_add(argv, i); break; - case 'b': cmd_build(argc, argv, i); break; - case 'c': check(); break; - case 'd': declare(); break; - case 'i': cmd_install(argc, argv, i); break; - case 'r': cmd_remove(argc, argv, i); break; - case 'u': cmd_update(argc, argv, i); break; - case 'l': list_installed(); break; - case 's': cmd_search(argc, argv, i); break; - case 'v': printf("%s\n", VERSION); break; - case 'h': help(); break; - default: break; - } - } -} - -void parse_flags(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - if (argv[i][0] != '-') continue; - if (argv[i][1] == '-') { - if (COMMAND("--quiet", "-q")) flags.verbose = false; - if (COMMAND("--force", "-f")) flags.force = true; - } else { - flags_mod(argv, i); - flags_cmd(argc, argv, i); - } - } - return; -} - -void parse_cmds(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - if (COMMAND("--add", "a")) { cmd_add(argv, i); } - if (COMMAND("--build", "b")) { cmd_build(argc, argv, i); } - if (COMMAND("--install", "i")) { cmd_install(argc, argv, i); } - if (COMMAND("--remove", "r")) { cmd_remove(argc, argv, i); } - if (COMMAND("--update", "u")) { cmd_update(argc, argv, i); } - if (COMMAND("--declare", "d")) { declare(); } - if (COMMAND("--list", "l")) { list_installed(); } - if (COMMAND("--search", "s")) { cmd_search(argc, argv, i); } - if (COMMAND("--version", "v")) { printf(VERSION "\n"); } - if (COMMAND("--help", "h")) { help(); } - if (COMMAND("--check", "c")) { check(); } - } -} - -void parse_args(int argc, char **argv) { - flags.force = false; - flags.verbose = true; - if (argc == 1) { - help(); - return; - } - parse_flags(argc, argv); - parse_cmds(argc, argv); - return; -} diff --git a/src/pkg_create.c b/src/pkg_create.c deleted file mode 100644 index 5afd1b0..0000000 --- a/src/pkg_create.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - - pkgit - package_t 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 <https://www.gnu.org/licenses/>. */ - -#include <string.h> -#include <unistd.h> - -#include "pkg.h" - -#include "files.h" -#include "globs.h" -#include "log.h" -#include "pkgit_lua.h" -#include "str.h" - -static str get_destdir(str *cwd, str *arg) { - str result = {0}; - if (str_first(arg) == '.' && arg->len == 1) { - result = str_format("%.*s/%.*s", str_fmt(&inst_dirs.src), str_fmt(cwd)); - } else { - str name = {0}; - if (str_find_char(arg, '/') != 0) name = str_from_after_delim(arg, '/'); - else str_copy_into(&name, arg); - result = str_format("%.*s/%.*s", str_fmt(&inst_dirs.src), str_fmt(&name)); - str_free(&name); - } - return result; -} - -static str get_pkgsrc(package_t pkg) { - if (pkg.is_local == 1) - return str_format("%.*s/%.*s", str_fmt(&inst_dirs.src), str_fmt(&pkg.name)); - else - return str_format("%.*s/%.*s/%.*s", str_fmt(&inst_dirs.src), - str_fmt(&pkg.name), str_fmt(&pkg.version)); -} - -static void assign_pkg_version(package_t *pkg, str *new_arg_str) { - if (str_find_char(new_arg_str, '@')) { - str tmp_arg = str_from_after_delim(new_arg_str, '@'); - if (str_find_char(new_arg_str, ',')) { - str tmp_trg = str_from_after_delim(&tmp_arg, ','); - pkg->version = str_from_after_delim(new_arg_str, '@'); - pkg->version.len -= tmp_trg.len; - str_free(&tmp_trg); - } else { - pkg->version = str_from_after_delim(new_arg_str, '@'); - } - if (str_find_char(&pkg->version, ',')) pkg->version.len--; - str_free(&tmp_arg); - pkg->name.len -= pkg->version.len + 1; - } else str_copy_cstr_into(&pkg->version, "HEAD");; -} - -static void assign_pkg_target(package_t *pkg, str *new_arg_str) { - if (str_find_char(new_arg_str, ',')) { - str tmp_arg = str_from_after_delim(new_arg_str, ','); - if (str_find_char(new_arg_str, '@')) { - str tmp_ver = str_from_after_delim(&tmp_arg, '@'); - pkg->target = str_from_after_delim(new_arg_str, ','); - pkg->target.len -= tmp_ver.len; - str_free(&tmp_ver); - } else { - pkg->target = str_from_after_delim(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) { - str_copy_cstr_into(&pkg->target, "quiet"); - } else str_copy_cstr_into(&pkg->target, "quiet"); -} - -package_t pkg_create(str *arg) { - package_t pkg = { .is_local = false, }; - - assign_pkg_version(&pkg, arg); - assign_pkg_target(&pkg, arg); - if (str_find_char(arg, '@')) { - str tmp = str_from_after_delim(arg, '@'); - arg->len -= tmp.len + 1; - str_free(&tmp); - } if (str_find_char(arg, ',')) { - str tmp = str_from_after_delim(arg, ','); - arg->len -= tmp.len + 1; - str_free(&tmp); - } - - char cwd[MAX_PATH_LEN]; - getcwd(cwd, MAX_PATH_LEN); - str cwd_str = mstr(cwd); - str dest_dir = get_destdir(&cwd_str, arg); - bool is_installed_locally = is_directory(dest_dir.data); - - if (strncmp(arg->data, "http", 4) == 0 || strncmp(arg->data, "ssh", 3) == 0) { - str_copy_into(&pkg.url, arg); - pkg.name = str_from_after_delim(arg, '/'); - } else if (str_equal_cstr(arg, ".")) { - str_copy_cstr_into(&pkg.url, ""); - pkg.name = str_from_after_delim(&cwd_str, '/'); - pkg.is_local = true; - } else if (pkg_exists(arg)) { - str_copy_into(&pkg.name, arg); - pkg.url = pkg_get_url(&pkg.name); - } else if (is_installed_locally) { - str_copy_cstr_into(&pkg.url, ""); - pkg.name = str_from_after_delim(&dest_dir, '/'); - 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(arg); - free_vars(); - exit(EXIT_FAILURE); - } - - if (str_find_char(arg, ',') - && str_find_char(arg, '@') - ) pkg.name.len--; - pkg.src = get_pkgsrc(pkg); - - str_free(&cwd_str); - str_free(&dest_dir); - if (pkg.is_local) str_free(arg); - return pkg; -} diff --git a/src/pkg_exists.c b/src/pkg_exists.c deleted file mode 100644 index 3ff761a..0000000 --- a/src/pkg_exists.c +++ /dev/null @@ -1,56 +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 <https://www.gnu.org/licenses/>. - -*/ - -#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; - } - str_slc new_name = {name->data, name->len}; - char* name_cstr = (char*)new_name.data; - name_cstr[new_name.len] = '\0'; - if (!lua_try_table(L, "init.lua", name_cstr)) { - 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 deleted file mode 100644 index 5944c4d..0000000 --- a/src/pkg_free.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "pkg.h" -#include "globs.h" - -void pkg_free(package_t *pkg) { - str_free(&pkg->name); - str_free(&pkg->url); - str_free(&pkg->version); - str_free(&pkg->target); - str_free(&pkg->src); -} diff --git a/src/pkg_install.c b/src/pkg_install.c deleted file mode 100644 index 0a1f427..0000000 --- a/src/pkg_install.c +++ /dev/null @@ -1,213 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <sys/stat.h> -#include <unistd.h> - -#include "lua.h" -#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 dep_url = mstr(lua_tostring(L, -1)); - lua_pop(L, 1); - package_t pkg = pkg_create(&dep_url); - str_free(&dep_url); - lua_getfield(L, -1, "version"); - str_free(&pkg.version); - const char *ver = lua_tostring(L, -1); - pkg.version = ver ? mstr(ver) : mstr("HEAD"); - lua_pop(L, 1); - const int top = lua_gettop(L); - char cwd[MAX_PATH_LEN]; - if (getcwd(cwd, sizeof(cwd)) != NULL) { - pkg_install(&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; - } - if (!lua_try_function(L, lua_file, "install")) { - lua_pop(L, 1); - return false; - } - 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) { - 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_getglobal(B, "targets"); - if (!lua_istable(B, -1)) { - log_error("targets is not a table in bldit.lua!"); - return false; - } - bool target_success = target_install(B, "bldit.lua", &pkg->target); - lua_pop(B, 1); - 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. reinstalling...", - str_fmt(&pkg->name)); - } - } else { - mkdir(pkg->src.data, 0755); - chdir(pkg->src.data); - } - 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.data); - } else { - log_pkgit("fetching " GREEN "%.*s" COLOR_RESET, str_fmt(&pkg->name)); - if (!fetch(pkg)) - return; - if (flags.verbose) - 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; - if (flags.verbose) - log_pkgit("built " GREEN "%.*s" COLOR_RESET, str_fmt(&pkg->name)); - - bool install_success = false; - if (flags.verbose) - log_info("attempting init.lua: 'repositories.%.*s.install'", - str_fmt(&pkg->name)); - if (!install_success && repo_install(pkg)) - install_success = true; - if (flags.verbose) - log_info("attempting bldit.lua: 'repositories.%.*s.install'", - str_fmt(&pkg->name)); - if (!install_success && bldit_install(pkg)) - install_success = true; - if (flags.verbose) - 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)); - - if (!pkg_exists(&pkg->name)) { - log_pkgit("adding " GREEN "%.*s" COLOR_RESET, str_fmt(&pkg->name)); - if (pkg->url.len > 0) { - add_repo(pkg); - log_pkgit("added " GREEN "%.*s" COLOR_RESET, str_fmt(&pkg->name)); - } - } else { - log_info("repo already exists, done"); - } -} diff --git a/src/pkg_remove.c b/src/pkg_remove.c deleted file mode 100644 index 20105c2..0000000 --- a/src/pkg_remove.c +++ /dev/null @@ -1,189 +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 <https://www.gnu.org/licenses/>. - -*/ -#define _XOPEN_SOURCE 700 - -#include <ftw.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "files.h" -#include "globs.h" -#include "log.h" -#include "pkgit_lua.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"); - if (!lua_try_table(B, "bldit.lua", "targets")) - return false; - bool target_success = target_uninstall(B, "bldit.lua", &pkg->target); - lua_pop(B, 1); - 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; -} - -void pkg_remove(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)); - return; - } - - 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); - } - remove_tree(pkg->src.data); - log_success("removed %.*s", str_fmt(&pkg->name)); -} diff --git a/src/pkg_update.c b/src/pkg_update.c deleted file mode 100644 index 3441db0..0000000 --- a/src/pkg_update.c +++ /dev/null @@ -1,174 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <dirent.h> -#include <string.h> - -#include "files.h" -#include "globs.h" -#include "is_updated.h" -#include "log.h" -#include "pkgit_lua.h" - -lua_State *U = NULL; - -void init_update_state(void) { - if (U != NULL) - return; - U = luaL_newstate(); - luaL_openlibs(U); - str lua_path = str_format("%.*s/?.lua", str_fmt(&cfg.dir)); - push_lua_path(U, lua_path.data); - if (luaL_loadfile(U, cfg.name.data) || lua_pcall(U, 0, 0, 0)) { - log_error("cannot run configuration script: %s", lua_tostring(U, -1)); - log_pkgit("to generate a configuration file, head into the"); - log_pkgit( - "root directory of the pkgit source and run `make defconfig`"); - exit(EXIT_FAILURE); - } - if (file_exists(cfg.repos.data)) { - if (luaL_loadfile(U, cfg.repos.data) || lua_pcall(U, 0, 0, 0)) { - if (flags.verbose) log_warn("cannot load repository file: %s", lua_tostring(U, -1)); - lua_pop(U, 1); - } - } - str_free(&lua_path); - config_loaded = true; -} - -bool on_pkg_update(lua_State *L, package_t *pkg) { - lua_getglobal(L, "repositories"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return false; - } - if (!lua_try_table(L, "init.lua", pkg->name.data)) { - lua_pop(L, 2); - return false; - } - if (!lua_try_table(L, "init.lua", "targets")) { - lua_pop(L, 3); - return false; - } - if (!lua_try_table(L, "init.lua", pkg->target.data)) { - lua_pop(L, 4); - return false; - } - if (!lua_try_function(L, "init.lua", "on_update")) { - lua_pop(L, 4); - return false; - } - lua_pop(L, 4); - return true; -} - -void pkg_update(package_t *pkg) { - if (is_updated(&pkg->src)) { - if (flags.verbose) log_info( - "%.*s is already up to date.", - str_fmt(&pkg->name) - ); - return; - } - flags.force = true; - str_copy_cstr_into(&pkg->version, "HEAD"); - pkg_install(pkg); - if (!on_pkg_update(L, pkg)) log_warn( - "init.lua: 'repositories.%.*s.%.*s.on_update' function failed", - str_fmt(&pkg->name), str_fmt(&pkg->target) - ); - pkg_free(pkg); -} - -bool on_all_update(lua_State *L) { - char* fname = "on_update"; - char* lua_file = "init.lua"; - lua_getglobal(L, fname); - if (!lua_isfunction(L, -1)) { - if (flags.verbose) lua_isnt_type(fname, "function"); - lua_pop(L, 1); - } else if (lua_pcall(L, 0, 1, 0) != LUA_OK) { - if (flags.verbose) log_warn( - "%s: '%s' function borked: %s", - lua_file, fname, lua_tostring(L, -1) - ); - lua_pop(L, 1); - return false; - } - if (!lua_isnumber(L, -1) || lua_tonumber(L, -1) != 0) { - if (flags.verbose) log_warn( - "%s: '%s' failed: %s", - lua_file, fname, lua_tostring(L, -1) - ); - lua_pop(L, 1); - return false; - } - lua_pop(L, 1); - return true; -} - -void all_update(void) { - struct dirent* dirent_ptr; - DIR* dir_ptr; - if ((dir_ptr = opendir(inst_dirs.src.data)) == NULL) { - log_error("could not open %s", str_fmt(&inst_dirs.src)); - } - while ((dirent_ptr = readdir(dir_ptr)) != NULL) { - if ( - strcmp(dirent_ptr->d_name, "..") == 0 || - strcmp(dirent_ptr->d_name, ".") == 0 - ) continue; - str pkg_name = mstr(dirent_ptr->d_name); - if (!pkg_exists(&pkg_name)) { - str_free(&pkg_name); - continue; - } - package_t pkg = pkg_create(&pkg_name); - pkg_update(&pkg); - pkg_free(&pkg); - if (str_is_valid(&pkg_name)) str_free(&pkg_name); - } - closedir(dir_ptr); - if (!on_all_update(L)) - log_warn("init.lua: 'on_update' function failed"); -} - -void declare(void) { - init_update_state(); - lua_getglobal(U, "repositories"); - if (!lua_istable(U, -1)) { - lua_isnt_type("repositories", "table"); - lua_pop(U, 1); - return; - } - lua_pushnil(U); - while (lua_next(U, -2) != 0) { - str key = mstr(lua_tostring(U, -2)); - if (!lua_istable(U, -1)) { - lua_pop(U, 1); - str_free(&key); - continue; - } - package_t pkg = pkg_create(&key); - pkg_install(&pkg); - pkg_free(&pkg); - if (str_is_valid(&key)) str_free(&key); - lua_pop(U, 1); - } - if (!on_all_update(L)) - log_warn("init.lua: 'on_update' function failed"); - lua_pop(U, 1); -} diff --git a/src/search.c b/src/search.c deleted file mode 100644 index 20d3e8c..0000000 --- a/src/search.c +++ /dev/null @@ -1,70 +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 <https://www.gnu.org/licenses/>. - -*/ - -#include <dirent.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> - -#include "search.h" - -#include "globs.h" -#include "log.h" -#include "pkgit_lua.h" - -void search(char *arg) { - lua_getglobal(L, "repositories"); - if (!lua_istable(L, -1)) { - lua_isnt_type("repositories", "table"); - lua_pop(L, 1); - return; - } - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - str key = mstr(lua_tostring(L, -2)); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - str_free(&key); - continue; - } - if (key.len <= 1) str_println(&key); - else if (strstr(key.data, arg)) str_println(&key); - if (str_is_valid(&key)) str_free(&key); - lua_pop(L, 1); - } -} - -void list_installed(void) { - struct dirent* dirent_ptr; - DIR* dir_ptr = opendir(inst_dirs.src.data); - - if (dir_ptr == NULL) { - log_error("could not open %.*s", str_fmt(&inst_dirs.src)); - return; - } - - while ((dirent_ptr = readdir(dir_ptr)) != NULL) { - if ( - strcmp(dirent_ptr->d_name, "..") == 0 || - strcmp(dirent_ptr->d_name, ".") == 0 - ) continue; - printf("%s\n", dirent_ptr->d_name); - } -} diff --git a/src/state.c b/src/state.c new file mode 100644 index 0000000..ec05250 --- /dev/null +++ b/src/state.c @@ -0,0 +1,27 @@ +/* + + 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 <https://www.gnu.org/licenses/>. + +*/ + +#include <lua.h> + +#include "state.h" + +cli_flags_t flags = {0}; +user_config_t config = {0}; +install_dirs_t inst_dirs = {0}; @@ -27,7 +27,7 @@ along with this program.If not, see <https://www.gnu.org/licenses/>. #include <stdlib.h> #include <string.h> -#include "globs.h" +#include "common.h" #include "str.h" // NOTE: only use this assertion in functions where you don't depend @@ -76,6 +76,15 @@ str mstr(const char *s) { return str_from_str_slc(_cstrslc(s)); } +str str_adopt(char *s) { + str adopted = { + .data = s, + .len = strlen(s), + }; + adopted.cap = adopted.len; + return adopted; +} + str str_from_str_slc(const str_slc s) { str res = str_new_with_capacity(s.len + 1); str_copy_str_slc_into(&res, s); @@ -207,13 +216,32 @@ void str_append_str_slc(str *src, const str_slc new) { size_t len_after_append = src->len + new.len; if (len_after_append + 1 > src->cap) { src->cap = len_after_append + 1; - str_reserve(src, src->cap); + str_reserve_exact(src, src->cap); } memcpy(src->data + src->len, new.data, new.len + 1); src->len = len_after_append; src->data[len_after_append] = 0; } +void str_append_format(str *src, const char *format, ...) { + assert_str_is_valid(dest); + + va_list args, args_copy; + va_start(args, format); + va_copy(args_copy, args); + + size_t len = vsnprintf(NULL, 0, format, args_copy); + if (src->len + len + 1 > src->cap) { + src->cap = 1 + src->len + len; + str_reserve_exact(src, src->cap); + } + + vsnprintf(src->data + src->len, len + 1, format, args); + src->len += len; + + va_end(args); +} + char str_pop_last(str *src) { char c = str_last(src); src->len--; @@ -502,7 +530,7 @@ str_slc str_slc_from_cstr(const char *s) { return _cstrslc(s); } -str_slc mstrslc(const char *s) { +str_slc mslc(const char *s) { return (str_slc){s, strlen(s)}; } |
