diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/check.c | 43 | ||||
| -rw-r--r-- | src/fetch.c | 27 | ||||
| -rw-r--r-- | src/files.c | 187 | ||||
| -rw-r--r-- | src/is_updated.c | 48 | ||||
| -rw-r--r-- | src/lua_globs.c | 69 | ||||
| -rw-r--r-- | src/parse_args.c | 34 | ||||
| -rw-r--r-- | src/pkg_create.c | 36 | ||||
| -rw-r--r-- | src/pkg_exists.c | 8 | ||||
| -rw-r--r-- | src/pkg_install.c | 72 | ||||
| -rw-r--r-- | src/pkg_remove.c | 13 | ||||
| -rw-r--r-- | src/pkg_update.c | 120 |
11 files changed, 537 insertions, 120 deletions
diff --git a/src/check.c b/src/check.c new file mode 100644 index 0000000..366f8a7 --- /dev/null +++ b/src/check.c @@ -0,0 +1,43 @@ +/* +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/fetch.c b/src/fetch.c index 3792a5e..b2c74ef 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -18,7 +18,6 @@ */ -//#include <git2.h> #include <fcntl.h> #include <stdio.h> #include <string.h> @@ -30,31 +29,11 @@ #include "globs.h" #include "log.h" -//bool fetch(package_t *pkg) { -// git_libgit2_init(); -// git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; -// clone_opts.checkout_branch = pkg->version.data; -// clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; -// git_repository *repo = NULL; -// int error = git_clone(&repo, pkg->url.data, pkg->src.data, NULL); -// if (error < 0) { -// const git_error *e = git_error_last(); -// fprintf(stderr, "clone failed: %s\n", -// e && e->message ? e->message : "unknown error"); -// git_libgit2_shutdown(); -// return false; -// } -// git_repository_free(repo); -// git_libgit2_shutdown(); -// return true; -//} - 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; } - pid_t pid = fork(); if (pid < 0) { log_error("fork failed"); @@ -73,26 +52,22 @@ bool fetch(package_t *pkg) { 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); diff --git a/src/files.c b/src/files.c index 7bfc507..ec32ec2 100644 --- a/src/files.c +++ b/src/files.c @@ -19,7 +19,18 @@ */ #include "files.h" + +#include "str.h" + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> #include <sys/stat.h> +#include <unistd.h> bool file_exists(const char *path) { struct stat buffer; @@ -33,3 +44,179 @@ bool is_directory(const char *path) { } 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); +} diff --git a/src/is_updated.c b/src/is_updated.c new file mode 100644 index 0000000..fef759e --- /dev/null +++ b/src/is_updated.c @@ -0,0 +1,48 @@ +/* + + 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; +} diff --git a/src/lua_globs.c b/src/lua_globs.c index 5f333a4..74a7faa 100644 --- a/src/lua_globs.c +++ b/src/lua_globs.c @@ -114,23 +114,6 @@ void bldit_isnt_type(char *variable, char *type) { log_error("bldit.lua: '%s' is not a %s.", variable, type); } -//bool is_bldit_usable() { -// const char* bldit_version = bldit_getver(); -// if ( -// strcmp(bldit_version, "") != 0 && -// strcmp(bldit_version, version) == 0 -// ) return true; -// bool prev_pass = false; -// for (int i = 0; i < strlen(bldit_version); i++) { -// if (bldit_version[i] == '.') continue; -// if ((bldit_version[i] - '0') <= (version[i] - '0')) { -// prev_pass = ((bldit_version[i] - '0') != (version[i] - '0')); -// continue; -// } else return prev_pass; -// } -// return true; -//} - bool lua_try_function(lua_State *L, char *lua_file, char *fname) { lua_getfield(L, -1, fname); if (!lua_isfunction(L, -1)) { @@ -170,3 +153,55 @@ bool lua_try_table(lua_State *L, char *lua_file, char *tname) { } 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 ( + strcmp(bldit_version.data, "") != 0 && + strcmp(bldit_version.data, VERSION) == 0 + ) return true; + 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; + } + } + str_free(&bldit_version); + return true; +} diff --git a/src/parse_args.c b/src/parse_args.c index 0d283b5..26d138f 100644 --- a/src/parse_args.c +++ b/src/parse_args.c @@ -27,7 +27,7 @@ #include "globs.h" #include "log.h" #include "str.h" -// #include "easter_egg.h" +#include "check.h" #include "help.h" #include "pkg.h" #include "pkgit_lua.h" @@ -45,6 +45,7 @@ void cmd_add(char **argv, int i) { 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"); } @@ -59,30 +60,48 @@ void cmd_build(int argc, char **argv, int i) { 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; + 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++) { @@ -91,6 +110,7 @@ void cmd_remove(int argc, char **argv, int i) { 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"); @@ -117,11 +137,11 @@ void flags_cmd(int argc, char **argv, int i) { switch (argv[i][j]) { case 'a': cmd_add(argv, i); break; case 'b': cmd_build(argc, argv, i); break; - case 'c': panic("not implemented"); printf("easter_egg\n"); break; + case 'c': check(); break; case 'd': panic("not implemented"); printf("declare\n"); break; case 'i': cmd_install(argc, argv, i); break; case 'r': cmd_remove(argc, argv, i); break; - case 'u': panic("not implemented"); printf("update\n"); break; + case 'u': cmd_update(argc, argv, i); break; case 'l': panic("not implemented"); printf("list\n"); break; case 's': panic("not implemented"); printf("search\n"); break; case 'v': printf("%s\n", VERSION); break; @@ -151,13 +171,13 @@ void parse_cmds(int argc, char **argv) { 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")) { panic("not implemented"); } + if (COMMAND("--update", "u")) { cmd_update(argc, argv, i); } if (COMMAND("--declare", "d")) { panic("not implemented"); } if (COMMAND("--list", "l")) { panic("not implemented"); } if (COMMAND("--search", "s")) { panic("not implemented"); } if (COMMAND("--version", "v")) { printf(VERSION "\n"); } if (COMMAND("--help", "h")) { help(); } - if (COMMAND("--check", "c")) { panic("not implemented"); } + if (COMMAND("--check", "c")) { check(); } } } diff --git a/src/pkg_create.c b/src/pkg_create.c index df10c46..cf5170f 100644 --- a/src/pkg_create.c +++ b/src/pkg_create.c @@ -13,8 +13,7 @@ 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/>. -*/ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <string.h> #include <unistd.h> @@ -29,10 +28,12 @@ static str get_destdir(str *cwd, str *arg) { str result; - if (str_first(arg) == '.') { + if (str_first(arg) == '.' && arg->len == 1) { result = str_format("%.*s/%.*s", str_fmt(&inst_dirs.src), str_fmt(cwd)); } else { - str name = str_from_after_delim(arg, '/'); + str name; + 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); } @@ -85,13 +86,6 @@ static void assign_pkg_target(package_t *pkg, str *new_arg_str) { package_t pkg_create(str *arg) { package_t pkg = { .is_local = false, }; - 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); assign_pkg_version(&pkg, arg); assign_pkg_target(&pkg, arg); @@ -105,20 +99,24 @@ package_t pkg_create(str *arg) { 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) { - pkg.url = *arg; + str_copy_into(&pkg.url, arg); pkg.name = str_from_after_delim(arg, '/'); } else if (str_equal_cstr(arg, ".")) { - pkg.url = mstr(""); + str_copy_cstr_into(&pkg.url, ""); pkg.name = str_from_after_delim(&cwd_str, '/'); pkg.is_local = true; } else if (pkg_exists(arg)) { - str tmp_url = pkg_get_url(arg); - str_copy_into(&pkg.url, &tmp_url); - str_free(&tmp_url); - pkg.name = *arg; + str_copy_into(&pkg.name, arg); + pkg.url = pkg_get_url(&pkg.name); } else if (is_installed_locally) { - pkg.url = mstr(""); + str_copy_cstr_into(&pkg.url, ""); pkg.name = str_from_after_delim(&dest_dir, '/'); pkg.is_local = true; } else { @@ -126,6 +124,7 @@ package_t pkg_create(str *arg) { str_free(&cwd_str); str_free(&dest_dir); str_free(arg); + free_vars(); exit(EXIT_FAILURE); } @@ -136,5 +135,6 @@ package_t pkg_create(str *arg) { 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 index 05aa238..3ff761a 100644 --- a/src/pkg_exists.c +++ b/src/pkg_exists.c @@ -1,8 +1,7 @@ /* pkgit - package it! - - Copyright (C) 2026 dacctal +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 @@ -27,7 +26,10 @@ bool pkg_exists(str *name) { lua_pop(L, 1); return false; } - if (!lua_try_table(L, "init.lua", name->data)) { + 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; } diff --git a/src/pkg_install.c b/src/pkg_install.c index 6a8f774..b911a71 100644 --- a/src/pkg_install.c +++ b/src/pkg_install.c @@ -18,7 +18,7 @@ */ - +#include <sys/stat.h> #include <unistd.h> #include "pkgit_lua.h" @@ -46,7 +46,7 @@ void install_dependencies(lua_State *L) { const int top = lua_gettop(L); char cwd[MAX_PATH_LEN]; if (getcwd(cwd, sizeof(cwd)) != NULL) { - //install_pkg(pkg); + pkg_install(&pkg); chdir(cwd); } lua_settop(L, top); @@ -92,14 +92,13 @@ bool repo_install(package_t *pkg) { 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; - //} + 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); @@ -145,68 +144,57 @@ void pkg_install(package_t *pkg) { 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)); + if (flags.verbose) log_warn("%.*s is already installed. reinstalling...", str_fmt(&pkg->name)); } + } else { + mkdir(pkg->src.data, 0755); + chdir(inst_dirs.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); - //} else { + 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( + 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( + 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( + 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 && 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"); - //} + if (!pkg_exists(&pkg->name)) { + 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 index bec7a8f..9bc5305 100644 --- a/src/pkg_remove.c +++ b/src/pkg_remove.c @@ -66,11 +66,11 @@ bool bldit_uninstall(package_t *pkg) { 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; - //} + 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); @@ -120,8 +120,7 @@ static int remove_installed( if (typeflag == FTW_F) { const char *filename = src_path + ftwbuf->base; const char *ext = strrchr(filename, '.'); - if (!ext) - ext = ""; + if (!ext) ext = ""; if (strncmp(ext, ".so", 3) == 0) { char dest[MAX_PATH_LEN]; diff --git a/src/pkg_update.c b/src/pkg_update.c new file mode 100644 index 0000000..f778438 --- /dev/null +++ b/src/pkg_update.c @@ -0,0 +1,120 @@ +/* +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 "globs.h" +#include "is_updated.h" +#include "log.h" +#include "pkgit_lua.h" + +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"); +} |
