diff options
| -rw-r--r-- | include/files.h | 5 | ||||
| -rw-r--r-- | include/lua_state.h | 13 | ||||
| -rw-r--r-- | include/pkg.h | 2 | ||||
| -rw-r--r-- | src/cli.c | 17 | ||||
| -rw-r--r-- | src/files.c | 52 | ||||
| -rw-r--r-- | src/pkg.c | 25 | ||||
| -rw-r--r-- | src/recipes.c | 83 |
7 files changed, 155 insertions, 42 deletions
diff --git a/include/files.h b/include/files.h index 24712e9..052c5f4 100644 --- a/include/files.h +++ b/include/files.h @@ -23,7 +23,12 @@ #include <stdbool.h> +#include "str.h" + bool file_exists(const char *path); bool is_directory(const char *path); +bool rmrf(str *path); +bool file_write(str *content, str *path); +str file_read(str *path); #endif diff --git a/include/lua_state.h b/include/lua_state.h index 6c36f37..97740e7 100644 --- a/include/lua_state.h +++ b/include/lua_state.h @@ -25,19 +25,6 @@ void free_lua_config(void); } \ } while (0) -#define lua_get_table(name, file, pop_num) \ - do { \ - lua_pushstring(L, name); \ - lua_gettable(L, -2); \ - lua_pop(L, 1); \ - if (!lua_istable(L, -1)) { \ - log_error("lua: expected type 'table' for '%s' in '%.*s'", \ - name, str_fmt(file)); \ - /*lua_pop(L, pop_num);*/ \ - return false; \ - } \ - } while (0) - #define lua_run_function(name, file, params, returns, pop_num) \ do { \ if (lua_pcall(L, params, returns, 0)) { \ diff --git a/include/pkg.h b/include/pkg.h index af720d5..d6e6cf0 100644 --- a/include/pkg.h +++ b/include/pkg.h @@ -4,7 +4,7 @@ #include "str.h" typedef struct package_t { - str name, version, url, src; + str name, version, url, src, root; unsigned int dep_count; bool is_local; } package_t; @@ -52,6 +52,10 @@ void cmd_build(int argc, char **argv, int i) { if (argv[j][0] == '-') continue; str arg = mstr(argv[j]); + package_t pkg = pkg_create(&arg); + if (!pkg_build(&pkg)) log_error( + "failed to build '%.*s'", str_fmt(&pkg.name)); + pkg_free(&pkg); if (str_is_valid(&arg)) str_free(&arg); } @@ -69,9 +73,8 @@ void cmd_install(int argc, char **argv, int i) { continue; str arg = mstr(argv[j]); package_t pkg = pkg_create(&arg); - if (!pkg_install(&pkg)) { - log_error("failed to install"); - } + if (!pkg_install(&pkg)) log_error( + "failed to install '%.*s'", str_fmt(&pkg.name)); pkg_free(&pkg); if (str_is_valid(&arg)) str_free(&arg); @@ -87,6 +90,10 @@ void cmd_update(int argc, char **argv, int i) { if (argv[j][0] == '-') continue; str arg = mstr(argv[j]); + package_t pkg = pkg_create(&arg); + if (!pkg_update(&pkg)) log_error( + "failed to update '%.*s'", str_fmt(&pkg.name)); + pkg_free(&pkg); if (str_is_valid(&arg)) str_free(&arg); } @@ -100,6 +107,10 @@ void cmd_remove(int argc, char **argv, int i) { if (argv[j][0] == '-') continue; str arg = mstr(argv[j]); + package_t pkg = pkg_create(&arg); + if (!pkg_remove(&pkg)) log_error( + "failed to remove '%.*s'", str_fmt(&pkg.name)); + pkg_free(&pkg); if (str_is_valid(&arg)) str_free(&arg); } diff --git a/src/files.c b/src/files.c index 5eaa459..67a327a 100644 --- a/src/files.c +++ b/src/files.c @@ -4,8 +4,7 @@ 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 + 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, @@ -18,9 +17,18 @@ */ +#define _XOPEN_SOURCE 500 +#include <stdio.h> +#include <ftw.h> +#include <unistd.h> + #include <stdbool.h> #include <sys/stat.h> +#include "log.h" +#include "state.h" +#include "str.h" + bool file_exists(const char *path) { struct stat buffer; return (stat(path, &buffer) == 0); @@ -30,4 +38,42 @@ bool is_directory(const char *path) { struct stat statbuf; if (stat(path, &statbuf) != 0) return false; return S_ISDIR(statbuf.st_mode); -}
\ No newline at end of file +} + +bool file_write(str *content, str *path) { + FILE *fileptr = fopen(path->data, "a"); + str_write_to_file(content, fileptr); + fclose(fileptr); + if (!file_exists(path->data)) { +// if (!flags.quiet) log_error( +// "could not write file: '%.*s'", str_fmt(path)); + return false; + } + return true; +} + +str file_read(str *path) { + if (!file_exists(path->data)) { +// if (!flags.quiet) log_error( +// "could not open file: '%.*s'", str_fmt(path)); + return str_new(); + } + FILE *fileptr = fopen(path->data, "r"); + str content = str_read_entire_file(fileptr); + fclose(fileptr); + return content; +} + +static int unlink_cb(const char *fpath, const struct stat *sb, +int typeflag, struct FTW *ftwbuf) { + (void)sb; + (void)typeflag; + (void)ftwbuf; + int rv = remove(fpath); + if (rv) perror(fpath); + return rv; +} + +bool rmrf(str *path) { + return nftw(path->data, unlink_cb, 64, FTW_DEPTH | FTW_PHYS) == 0; +} @@ -31,22 +31,26 @@ 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(&config.inst_dirs.src), str_fmt(cwd)); + result = str_format("%.*s/%.*s", + str_fmt(&config.inst_dirs.src), str_fmt(cwd)); } else { str name = {0}; - if (str_find_char(arg, '/') != 0) name = str_from_after_delim(arg, '/'); + 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(&config.inst_dirs.src), str_fmt(&name)); + result = str_format("%.*s/%.*s", + str_fmt(&config.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(&config.inst_dirs.src), str_fmt(&pkg->name)); - else - return str_format("%.*s/%.*s/%.*s", str_fmt(&config.inst_dirs.src), - str_fmt(&pkg->name), str_fmt(&pkg->version)); +static void set_pkgsrc(package_t *pkg) { + pkg->root = str_format("%.*s/%.*s", + str_fmt(&config.inst_dirs.src), str_fmt(&pkg->name)); + if (pkg->is_local) pkg->src = pkg->root; + else pkg->src = str_format("%.*s/%.*s/%.*s", + str_fmt(&config.inst_dirs.src), str_fmt(&pkg->name), + str_fmt(&pkg->version)); } static void assign_pkg_version(package_t *pkg, str *new_arg_str) { @@ -89,7 +93,7 @@ package_t pkg_create(str *arg) { abort(); } - pkg.src = get_pkgsrc(&pkg); + set_pkgsrc(&pkg); str_free(&cwd); str_free(&destdir); @@ -101,4 +105,5 @@ void pkg_free(package_t *pkg) { str_free(&pkg->version); str_free(&pkg->url); str_free(&pkg->src); + str_free(&pkg->root); } diff --git a/src/recipes.c b/src/recipes.c index 5f387b4..b84a026 100644 --- a/src/recipes.c +++ b/src/recipes.c @@ -24,14 +24,59 @@ #include "files.h" #include "log.h" #include "pkg.h" +#include "state.h" + +#define try_pkg_fn(fn, pkg, operation) \ + do { \ + log_info("attempting to %s '%.*s'", operation, str_fmt(&(pkg)->name)); \ + if (!(fn((pkg)))) { \ + log_error("%s failed", operation); \ + return false; \ + } \ + } while (0) + +static bool pkg_write_status(const char *status, package_t *pkg) { + bool success = false; + str status_str = mstr(status); + str pkgit_status = str_format("%.*s/.pkgit_status", str_fmt(&pkg->src)); + success = file_write(&status_str, &pkgit_status); + str_free(&pkgit_status); + str_free(&status_str); + return success; +} + +static bool pkg_read_status(const char desired, package_t *pkg) { + bool success = false; + str pkgit_status = str_format("%.*s/.pkgit_status", + str_fmt(&pkg->src)); + str status = file_read(&pkgit_status); + success = str_find_char(&status, desired); + str_free(&pkgit_status); + str_free(&status); + return success; +} + +static bool is_pkg_installed(package_t *pkg) { + if (pkg_read_status('i', pkg)) { + if (flags.force) log_warn( + "%.*s is already installed", + str_fmt(&pkg->name)); + else log_info( + "%.*s is already installed", + str_fmt(&pkg->name)); + return true; + } else return false; +} static bool pkg_fetch_sources(package_t *pkg) { + bool success = false; if (!pkg_hook_fetch_sources(pkg)) { log_error(GREEN "%.*s" COLOR_RESET " fetch failed", str_fmt(&pkg->name)); return false; } - return true; + success = pkg_write_status("f", pkg); + return success; } static bool pkg_enter(package_t *pkg) { @@ -41,38 +86,52 @@ static bool pkg_enter(package_t *pkg) { return false; } chdir(pkg->src.data); + if (!pkg_write_status("e", pkg)) return false; return true; } bool pkg_setup(package_t *pkg) { - if (!pkg_enter(pkg)) return false; - if (!pkg_hook_setup(pkg)) return false; + if (pkg_read_status('s', pkg)) return true; + try_pkg_fn(pkg_enter, pkg, "enter"); + try_pkg_fn(pkg_hook_setup, pkg, "setup"); + if (!pkg_write_status("s", pkg)) return false; return true; } bool pkg_build(package_t *pkg) { - if (!pkg_enter(pkg)) return false; - if (!pkg_hook_build(pkg)) return false; + if (pkg_read_status('b', pkg)) return true; + try_pkg_fn(pkg_enter, pkg, "enter"); + try_pkg_fn(pkg_hook_build, pkg, "build"); + if (!pkg_write_status("b", pkg)) return false; return true; } bool pkg_install(package_t *pkg) { - if (!pkg_fetch_sources(pkg)) return false; - if (!pkg_enter(pkg)) return false; - if (!pkg_hook_setup(pkg)) return false; - if (!pkg_hook_build(pkg)) return false; + if (is_pkg_installed(pkg) && !flags.force) return true; + log_info("fetching '%.*s'", str_fmt(&pkg->name)); + if (!pkg_read_status('f', pkg) && !pkg_fetch_sources(pkg)) return false; + log_info("entering '%.*s'", str_fmt(&pkg->src)); + if (!pkg_read_status('e', pkg) && !pkg_enter(pkg)) return false; + log_info("setting up '%.*s'", str_fmt(&pkg->name)); + if (!pkg_read_status('s', pkg) && !pkg_hook_setup(pkg)) return false; + log_info("building '%.*s'", str_fmt(&pkg->name)); + if (!pkg_read_status('b', pkg) && !pkg_hook_build(pkg)) return false; + log_info("installing '%.*s'", str_fmt(&pkg->name)); if (!pkg_hook_install(pkg)) return false; + if (!pkg_write_status("i", pkg)) return false; + log_success("installed '%.*s'", str_fmt(&pkg->name)); return true; } bool pkg_remove(package_t *pkg) { if (!pkg_enter(pkg)) return false; - if (!pkg_hook_setup(pkg)) return false; + if (!pkg_hook_remove(pkg)) return false; + if (!rmrf(&pkg->root)) return false; + log_success("removed '%.*s'", str_fmt(&pkg->name)); return true; } bool pkg_update(package_t *pkg) { - if (!pkg_enter(pkg)) return false; - if (!pkg_hook_setup(pkg)) return false; + pkg_install(pkg); return true; } |
