diff options
| author | Jack Jamison <jackqjamison@gmail.com> | 2026-07-20 15:16:13 -0400 |
|---|---|---|
| committer | Jack Jamison <jackqjamison@gmail.com> | 2026-07-20 15:16:13 -0400 |
| commit | 0ad03c0647b94683c26045bbc143b0d6450d914f (patch) | |
| tree | 8aae29f86cebd7d567bca274e8fa43c388c89cea | |
| parent | 3ae746e5ac3f8feb80a8619127956fb93ba47ca0 (diff) | |
read package info into snag
| -rw-r--r-- | TODO | 3 | ||||
| -rwxr-xr-x | snag/getpkginfo.sh | 17 | ||||
| -rw-r--r-- | snag/main.c | 81 | ||||
| -rw-r--r-- | snag/readme.txt | 9 | ||||
| -rwxr-xr-x | snag/snagpkginfo.sh | 19 |
5 files changed, 107 insertions, 22 deletions
@@ -1,2 +1,3 @@ Things to come back to - - [ ] Optional package info attributes
\ No newline at end of file + - [ ] Optional package info attributes + - [ ] better memory allocation strategies for snag (temporary, arena)
\ No newline at end of file diff --git a/snag/getpkginfo.sh b/snag/getpkginfo.sh deleted file mode 100755 index 0650740..0000000 --- a/snag/getpkginfo.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# reads a package description script and outputs the attributes in a format easy -# for the snag program to read - -if [ -z "$1" ]; then - echo "Usage: $0 <description script>" >&2 - exit 1 -fi - -# load the description script -. $1 - -# echo package properties -echo ID $pkg_id -echo NAME $pkg_name -echo DESC $pkg_desc diff --git a/snag/main.c b/snag/main.c index 9eacf33..10a5f86 100644 --- a/snag/main.c +++ b/snag/main.c @@ -1,12 +1,17 @@ #include <stdio.h> #include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> -#define DESC_DIR "../snaggies" +#define PKG_DB "../snaggies" +#define PKG_INFO_CMD "./snagpkginfo.sh" typedef struct { char* id; char* name; char* desc; + char* script_path; } package_info_t; void subcmd_install(char* pkgs[], size_t count); @@ -25,9 +30,79 @@ void subcmd_install(char* pkgs[], size_t count) { // install each package listed for (int i = 0; i < count; ++i) { - char* package = pkgs[i]; - printf("Installing '%s'\n", package); + char* pkgid = pkgs[i]; // load package description + package_info_t info; + if (load_package_info(&info, pkgid)) { + printf("Installing '%s'\n", info.name); + } } } + +bool load_package_info(package_info_t* info, char* pkgid) { + + // construct package description directory path and ensure it exists + size_t pkg_dir_len = strlen(PKG_DB) + strlen(pkgid) + 1; + char* pkg_dir = malloc(pkg_dir_len + 1); + snprintf(pkg_dir, pkg_dir_len + 1, "%s/%s", PKG_DB, pkgid); + if (access(pkg_dir, F_OK) != 0) { + fprintf(stderr, "Package '%s' not found in database\n", pkgid); + free(pkg_dir); + return false; + } + + // construct package description script path and ensure it exists + size_t script_path_len = pkg_dir_len + strlen(pkgid) + 4; + info->script_path = malloc(script_path_len + 1); + snprintf(info->script_path, script_path_len + 1, "%s/%s.sh", pkg_dir, pkgid); + free(pkg_dir); + if (access(info->script_path, F_OK) != 0) { + fprintf(stderr, "Package '%s' broken, doesn't have description script\n", pkgid); + free(info->script_path); + return false; + } + + // run getpkginfo script that outputs package attributes + size_t cmd_len = strlen(PKG_INFO_CMD) + script_path_len + 3; + char* cmd = malloc(cmd_len + 1); + snprintf(cmd, cmd_len + 1, "%s '%s'", PKG_INFO_CMD, info->script_path); + FILE* getinfo_fp = popen(cmd, "r"); + if (getinfo_fp == NULL) { + perror("failed to popen getpkginfo"); + exit(1); // fatal error + } + + // go through each NULL delimited section of the output + size_t n = 0; + char* line = NULL; + ssize_t read; + while ((read = getdelim(&line, &n, '\0', getinfo_fp)) != -1) { + // read in property based on first attribute type character + char atype = line[0]; + char* avalue = line+1; + switch (atype) { + case 'i': + // id + info->id = strdup(avalue); + break; + case 'n': + // name + info->name = strdup(avalue); + break; + case 'd': + // description + info->desc = strdup(avalue); + break; + } + } + free(line); + + // close the getpkginfo process + if (pclose(getinfo_fp) != 0) { + perror("failed to pclose getpkginfo"); + exit(1); // fatal error + } + + return true; +} diff --git a/snag/readme.txt b/snag/readme.txt index ef15404..d93431d 100644 --- a/snag/readme.txt +++ b/snag/readme.txt @@ -9,7 +9,7 @@ `files` - list the installed files of the specified package(s) `log` - open your pager to the build log of the specified package -`reason` - list why this package is installed (manually installed, as a dependency, from a group) +`why` - list why this package is installed (manually installed, as a dependency, from a group) ## Terminology "Package Database" - the directory containing package descriptions @@ -29,3 +29,10 @@ Packages have the following attributes: `id` - the identifier name of the package. everything uses this `name` - the display name of package `desc` - the short description of the package + +## Interesting Features +- switch between cli and tui mode mid run +- build packages that aren't in the database + +## Developer Subcommands +`validate` - check a package description and check for format errors or warnings diff --git a/snag/snagpkginfo.sh b/snag/snagpkginfo.sh new file mode 100755 index 0000000..bb80418 --- /dev/null +++ b/snag/snagpkginfo.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# reads a package description script and outputs the attributes in a format easy +# for the snag program to read. it does not do any other validation, and should +# not be used by other programs + +if [ -z "$1" ]; then + echo "Usage: $0 <description script>" >&2 + exit 1 +fi + +# load the description script +. $1 + +# output package attributes (type char, value, null delimiter) +echoatt() { [ -n "$2" ] && printf "$1$2\0"; } +echoatt i "$pkg_id" +echoatt n "$pkg_name" +echoatt d "$pkg_desc" |
