aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/check.c43
-rw-r--r--src/fetch.c27
-rw-r--r--src/files.c187
-rw-r--r--src/is_updated.c48
-rw-r--r--src/lua_globs.c69
-rw-r--r--src/parse_args.c34
-rw-r--r--src/pkg_create.c36
-rw-r--r--src/pkg_exists.c8
-rw-r--r--src/pkg_install.c72
-rw-r--r--src/pkg_remove.c13
-rw-r--r--src/pkg_update.c120
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");
+}