first commit
This commit is contained in:
91
src/args.c
Normal file
91
src/args.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <libmp/all.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "args.h"
|
||||
#include "util.h"
|
||||
|
||||
void args_add(args_t *args, char *name){
|
||||
if(NULL == args->list)
|
||||
args->list = malloc(sizeof(arg_t)*(args->count+1));
|
||||
else
|
||||
args->list = realloc(args->list, sizeof(arg_t)*(args->count+1));
|
||||
|
||||
args->list[args->count].name = name;
|
||||
args->list[args->count++].value = NULL;
|
||||
}
|
||||
|
||||
void args_add_value(args_t *args, char *value){
|
||||
if(NULL != args->list && args->list[args->count-1].value == NULL){
|
||||
args->list[args->count-1].value = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if(NULL == args->list)
|
||||
args->list = malloc(sizeof(arg_t)*(args->count+1));
|
||||
else
|
||||
args->list = realloc(args->list, sizeof(arg_t)*(args->count+1));
|
||||
|
||||
args->list[args->count].name = NULL;
|
||||
args->list[args->count++].value = value;
|
||||
}
|
||||
|
||||
args_t *args_parse(int argc, char *argv[]){
|
||||
args_t *args = malloc(sizeof(args_t));
|
||||
bzero(args, sizeof(args_t));
|
||||
|
||||
if(argc <= 1)
|
||||
return args;
|
||||
|
||||
for(int i = 1; i < argc; i++){
|
||||
if(startswith(argv[i], "--"))
|
||||
args_add(args, argv[i]+2);
|
||||
else
|
||||
args_add_value(args, argv[i]);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void args_free(args_t *args){
|
||||
free(args->list);
|
||||
free(args);
|
||||
}
|
||||
|
||||
char *args_get_string(args_t *args, char *name){
|
||||
for(int i = 0; i < args->count; i++){
|
||||
if(NULL == args->list[i].name)
|
||||
continue;
|
||||
|
||||
if(eq(args->list[i].name, name))
|
||||
return args->list[i].value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool args_get_bool(args_t *args, char *name){
|
||||
for(int i = 0; i < args->count; i++){
|
||||
if(NULL == args->list[i].name)
|
||||
continue;
|
||||
|
||||
if(eq(args->list[i].name, name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int args_get_int(args_t *args, char *name){
|
||||
for(int i = 0; i < args->count; i++){
|
||||
if(NULL == args->list[i].name)
|
||||
continue;
|
||||
|
||||
if(eq(args->list[i].name, name))
|
||||
return atoi(args->list[i].value);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
18
src/args.h
Normal file
18
src/args.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct arg {
|
||||
char *name;
|
||||
char *value;
|
||||
} arg_t;
|
||||
|
||||
typedef struct args {
|
||||
arg_t *list;
|
||||
size_t count;
|
||||
} args_t;
|
||||
|
||||
args_t *args_parse(int argc, char *argv[]);
|
||||
char *args_get_string(args_t *args, char *name);
|
||||
bool args_get_bool(args_t *args, char *name);
|
||||
int args_get_int(args_t *args, char *name);
|
||||
void args_free(args_t *args);
|
20
src/cmd.h
Normal file
20
src/cmd.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <libmp/all.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "args.h"
|
||||
|
||||
typedef bool (*cmd_func_t)(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||
|
||||
typedef struct cmd {
|
||||
char *name;
|
||||
char *desc;
|
||||
cmd_func_t func;
|
||||
} cmd_t;
|
||||
|
||||
bool cmd_sync(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||
bool cmd_install(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||
bool cmd_remove(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||
bool cmd_update(lm_ctx_t *ctx, config_t *config, args_t *args);
|
||||
bool cmd_list(lm_ctx_t *ctx, config_t *config, args_t *args);
|
116
src/cmd/install.c
Normal file
116
src/cmd/install.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <libmp/all.h>
|
||||
#include <libmp/ctx.h>
|
||||
#include <libmp/error.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../util.h"
|
||||
#include "../cmd.h"
|
||||
#include "../log.h"
|
||||
|
||||
bool cmd_install_callback(lm_ctx_t *ctx, lm_pkg_t *pkg, char *file, size_t current, size_t total, void *data){
|
||||
bar(current, total);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmd_download_callback(lm_ctx_t *ctx, lm_pkg_t *pkg, bool is_archive, size_t current, size_t total, void *data){
|
||||
if(!is_archive)
|
||||
bar(current, total);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmd_install(lm_ctx_t *ctx, config_t *config, args_t *args){
|
||||
lm_ctx_resolve_list_t *list = NULL;
|
||||
ssize_t current = 1, size = 0;
|
||||
char ssize[LONGSTR_MAX+3];
|
||||
lm_pkg_t *pkg = NULL;
|
||||
char *name = NULL;
|
||||
bool ret = false;
|
||||
|
||||
if(lm_ctx_sync(ctx, false, NULL, NULL) <= 0){
|
||||
error(_("There are no avaliable pools"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
for(int i = 0; i < args->count; i++){
|
||||
if(NULL != args->list[i].name)
|
||||
continue;
|
||||
|
||||
if(eq((name = args->list[i].value), "install"))
|
||||
continue;
|
||||
|
||||
// find the package
|
||||
if((pkg = lm_ctx_pool_find(ctx, name, NULL)) == NULL){
|
||||
error(_("Failed to find "FG_BOLD"%s"FG_RESET": %s"), name, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
// WEIRD CRASH HERE
|
||||
if(lm_ctx_database_is_installed(ctx, pkg, true)){
|
||||
error(_("Package "FG_BOLD"%s"FG_RESET" ("FG_BLUE"%s"FG_RESET") is already installed"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
// resolve the package and depends
|
||||
if((list = lm_ctx_resolve(ctx, pkg, list)) == NULL){
|
||||
error(_("Failed to resolve "FG_BOLD"%s"FG_RESET": %s"), name, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if(NULL == list){
|
||||
error(_("Please specify at least one package to install"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
while((pkg = lm_ctx_resolve_next(list)) != NULL)
|
||||
size += pkg->size;
|
||||
size_to_human(ssize, size);
|
||||
|
||||
info(_("Following packages will be "FG_BOLD"INSTALLED:"FG_RESET));
|
||||
|
||||
// list all the packages
|
||||
|
||||
info(_("Total of "FG_BOLD"%s"FG_RESET" disk space will be used"), ssize);
|
||||
if(!yesno("Continue?")){
|
||||
error("Operation cancelled");
|
||||
goto end;
|
||||
}
|
||||
|
||||
// download resolved packages
|
||||
while((pkg = lm_ctx_resolve_next(list)) != NULL){
|
||||
info(_("(%d/%d) Downloading "FG_BOLD"%s"FG_RESET" ("FG_BOLD FG_BLUE"%s"FG_RESET")"), current, list->count, pkg->name, pkg->version);
|
||||
|
||||
if(!lm_ctx_download(ctx, pkg, cmd_download_callback, NULL)){
|
||||
error(_("Failed to download "FG_BOLD"%s"FG_RESET": %s"), pkg->name, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
current++;
|
||||
bar_free();
|
||||
}
|
||||
|
||||
current = 1;
|
||||
|
||||
// install resolved packages
|
||||
while((pkg = lm_ctx_resolve_next(list)) != NULL){
|
||||
info(_("(%d/%d) Installing "FG_BOLD"%s"FG_RESET" ("FG_BOLD FG_BLUE"%s"FG_RESET")"), current, list->count, pkg->name, pkg->version);
|
||||
|
||||
if(!lm_ctx_install(ctx, pkg, cmd_install_callback, NULL)){
|
||||
error(_("Failed to install "FG_BOLD"%s"FG_RESET": %s"), pkg->name, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
current++;
|
||||
bar_free();
|
||||
}
|
||||
|
||||
if(current == list->count){
|
||||
success("Installed all of the %d packages", list->count);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
end:
|
||||
bar_free();
|
||||
lm_ctx_resolve_free(list);
|
||||
return ret;
|
||||
}
|
46
src/cmd/list.c
Normal file
46
src/cmd/list.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <libmp/all.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../cmd.h"
|
||||
#include "../log.h"
|
||||
|
||||
bool cmd_list(lm_ctx_t *ctx, config_t *config, args_t *args){
|
||||
ssize_t count = 0;
|
||||
lm_pkg_t pkg;
|
||||
|
||||
if(args_get_bool(args, "help")){
|
||||
info(_("Listing options for the install command:"));
|
||||
printf(_(" "FG_BOLD"--grep"FG_RESET":\tmakes the output \"grepable\"\n"));
|
||||
printf(_(" "FG_BOLD"--desc"FG_RESET":\tshow package descriptions\n"));
|
||||
return true;
|
||||
}
|
||||
|
||||
while(lm_ctx_database_next(ctx, &pkg))
|
||||
count++;
|
||||
lm_ctx_database_next_free(ctx, &pkg);
|
||||
|
||||
if(count <= 0 && !args_get_bool(args, "grep")){
|
||||
info(_("There no installed packages"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!args_get_bool(args, "grep"))
|
||||
info(count > 1 ? _("Listing %d packages") : _("Listing %d package"));
|
||||
|
||||
while(lm_ctx_database_next(ctx, &pkg)){
|
||||
if(args_get_bool(args, "grep")){
|
||||
if(args_get_bool(args, "desc"))
|
||||
printf("%s:%s:%s\n", pkg.name, pkg.version, pkg.desc);
|
||||
else
|
||||
printf("%s:%s\n", pkg.name, pkg.version);
|
||||
}
|
||||
|
||||
if(args_get_bool(args, "desc"))
|
||||
printf(FG_BOLD"%s ("FG_BLUE"%s"FG_RESET"): %s\n", pkg.name, pkg.version, pkg.desc);
|
||||
else
|
||||
printf(FG_BOLD"%s ("FG_BLUE"%s"FG_RESET")\n", pkg.name, pkg.version);
|
||||
}
|
||||
|
||||
lm_ctx_database_next_free(ctx, &pkg);
|
||||
return true;
|
||||
}
|
62
src/cmd/sync.c
Normal file
62
src/cmd/sync.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <libmp/all.h>
|
||||
#include <libmp/error.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../cmd.h"
|
||||
#include "../log.h"
|
||||
|
||||
bool cmd_sync_callback(lm_ctx_t *ctx, lm_pool_t *pool, lm_ctx_sync_state_t state, size_t current, size_t total, void *data){
|
||||
switch (state) {
|
||||
case SYNC_DOWNLOADING_INFO:
|
||||
bar(current, total);
|
||||
break;
|
||||
|
||||
case SYNC_INFO_SUCCESS:
|
||||
bar_free();
|
||||
break;
|
||||
|
||||
case SYNC_INFO_FAIL:
|
||||
bar_free();
|
||||
error(_("Failed to sync "FG_BOLD"%s"FG_RESET": %s"), pool->name, lm_strerror());
|
||||
break;
|
||||
|
||||
case SYNC_DOWNLOADING_LIST:
|
||||
bar(current, total);
|
||||
break;
|
||||
|
||||
case SYNC_LIST_SUCCESS:
|
||||
bar_free();
|
||||
success(_("Synced "FG_BOLD"%s [%s]"FG_RESET), pool->name, pool->info.pubkey);
|
||||
break;
|
||||
|
||||
case SYNC_LIST_FAIL:
|
||||
bar_free();
|
||||
if(LM_ERR_InfoNotLoaded != lm_error())
|
||||
error(_("Failed to sync %s: %s"), pool->name, lm_strerror());
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cmd_sync(lm_ctx_t *ctx, config_t *config, args_t *args){
|
||||
size_t sycned = 0;
|
||||
bool ret = false;
|
||||
|
||||
if(0 == config->pool_count){
|
||||
error(_("There are no pools specified in the configuration"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if((sycned = lm_ctx_sync(ctx, true, cmd_sync_callback, NULL) < 0)){
|
||||
error(_("Failed to sync pools: %s"), lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
info(_("Synced "FG_BOLD"%d/%d"FG_RESET" pools"), sycned, config->pool_count);
|
||||
ret = true;
|
||||
|
||||
end:
|
||||
bar_free();
|
||||
return ret;
|
||||
}
|
122
src/config.c
Normal file
122
src/config.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include <errno.h>
|
||||
#include <ini.h>
|
||||
#include <libmp/all.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "intl.h"
|
||||
#include "log.h"
|
||||
|
||||
bool config_set(config_t *config, char *key, char *value){
|
||||
if(eq(key, "tmpdir"))
|
||||
config->tmpdir = strdup(value);
|
||||
else if(eq(key, "datadir"))
|
||||
config->datadir = strdup(value);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pool_config_t *config_pool_add(config_t *config, char *name) {
|
||||
pool_config_t *pool = malloc(sizeof(pool_config_t));
|
||||
bzero(pool, sizeof(pool_config_t));
|
||||
|
||||
pool->name = strdup(name);
|
||||
pool->next = config->pools;
|
||||
|
||||
config->pools = pool;
|
||||
config->pool_count++;
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
bool config_pool_contains(config_t *config, char *name) {
|
||||
pool_config_t *cur = config->pools;
|
||||
while (NULL != cur) {
|
||||
if (eq(cur->name, name))
|
||||
return true;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int config_load_handler(void *data, const char *_section, const char *_key, const char *_value) {
|
||||
char *section = (char *)_section, *key = (char *)_key, *value = (char *)_value;
|
||||
config_t *config = data;
|
||||
|
||||
if(eq(section, "")){
|
||||
if(config_set(config, key, value))
|
||||
return 1;
|
||||
goto unknown;
|
||||
}
|
||||
|
||||
if (!config_pool_contains(config, section))
|
||||
config_pool_add(config, section);
|
||||
|
||||
if (eq(key, "url")) {
|
||||
free(config->pools->url);
|
||||
config->pools->url = strdup(value);
|
||||
}
|
||||
|
||||
else
|
||||
goto unknown;
|
||||
|
||||
return 1;
|
||||
|
||||
unknown:
|
||||
error(_("Unknown configuration option: %s/%s"), section, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool config_load(lm_ctx_t *ctx, config_t *config, char *file) {
|
||||
bzero(config, sizeof(config_t));
|
||||
|
||||
if (!exists(file) || !can_read(file)) {
|
||||
error(_("Failed to access the configuration file: %s"), file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ini_parse(file, config_load_handler, config) < 0) {
|
||||
error(_("Failed to parse the configuration"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(NULL == config->tmpdir){
|
||||
error(_("Please specify \"tmpdir\" in the configuration"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(NULL == config->datadir){
|
||||
error(_("Please specify \"datadir\" in the configuration"));
|
||||
return false;
|
||||
}
|
||||
|
||||
pool_config_t *pool = config->pools;
|
||||
while (NULL != pool) {
|
||||
if (NULL == pool->url) {
|
||||
error(_("URL not specified for the pool: %s"), pool->name);
|
||||
return false;
|
||||
}
|
||||
pool = pool->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void config_free(config_t *config) {
|
||||
free(config->datadir);
|
||||
free(config->tmpdir);
|
||||
|
||||
pool_config_t *cur = config->pools, *old = NULL;
|
||||
while (NULL != cur) {
|
||||
old = cur;
|
||||
cur = cur->next;
|
||||
|
||||
free(old->name);
|
||||
free(old->url);
|
||||
free(old);
|
||||
}
|
||||
}
|
19
src/config.h
Normal file
19
src/config.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <libmp/ctx.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct pool_config {
|
||||
struct pool_config *next;
|
||||
char *name;
|
||||
char *url;
|
||||
} pool_config_t;
|
||||
|
||||
typedef struct config {
|
||||
pool_config_t *pools;
|
||||
char *datadir, *tmpdir;
|
||||
ssize_t pool_count;
|
||||
} config_t;
|
||||
|
||||
bool config_load(lm_ctx_t *ctx, config_t *config, char *file);
|
||||
void config_free(config_t *config);
|
2
src/intl.h
Normal file
2
src/intl.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include <libintl.h>
|
||||
#define _(x) gettext(x)
|
138
src/log.c
Normal file
138
src/log.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "intl.h"
|
||||
#include "log.h"
|
||||
|
||||
void info(const char *msg, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
printf(FG_BOLD FG_BLUE ">>> " FG_RESET);
|
||||
vprintf(msg, args);
|
||||
printf(FG_RESET "\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void error(const char *msg, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
printf(FG_BOLD FG_RED ">>> " FG_RESET);
|
||||
vprintf(msg, args);
|
||||
printf(FG_RESET "\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void success(const char *msg, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
printf(FG_BOLD FG_GREEN ">>> " FG_RESET);
|
||||
vprintf(msg, args);
|
||||
printf(FG_RESET "\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void input(const char *msg, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
printf(FG_BOLD FG_CYAN ">>> " FG_RESET);
|
||||
vprintf(msg, args);
|
||||
printf(FG_RESET);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool yesno(const char *msg) {
|
||||
char *yes[] = {_("y"), _("Y")};
|
||||
char *no[] = {_("n"), _("N")};
|
||||
|
||||
char question[strlen(msg) + 12], c;
|
||||
sprintf(question, _("%s [y/N] "), msg);
|
||||
|
||||
while (true) {
|
||||
input(question);
|
||||
|
||||
int c = getchar();
|
||||
if (c == '\n')
|
||||
return false;
|
||||
getchar();
|
||||
|
||||
for (int i = 0; i < sizeof(yes) / sizeof(char *); i++) {
|
||||
if (yes[i][0] == c)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(no) / sizeof(char *); i++) {
|
||||
if (no[i][0] == c)
|
||||
return false;
|
||||
}
|
||||
|
||||
error(_("Please answer with y/n"));
|
||||
}
|
||||
}
|
||||
|
||||
bool bar(float cur, float max) {
|
||||
if (cur <= 0 || max <= 0 || cur > max)
|
||||
return false;
|
||||
|
||||
float per = 100 * (cur / max);
|
||||
if (per > 100) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct winsize barwin = {0};
|
||||
char perc[20];
|
||||
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &barwin);
|
||||
sprintf(perc, " %%%.f", per);
|
||||
|
||||
int size = barwin.ws_col - (3 + strlen(perc));
|
||||
if (size <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int prog = size * (cur / max);
|
||||
if (prog > size)
|
||||
return true;
|
||||
|
||||
printf("\e[?25l");
|
||||
|
||||
printf("\r" FG_BOLD "[");
|
||||
for (int i = 0; i < prog; i++) {
|
||||
printf("#");
|
||||
}
|
||||
printf(FG_BLUE "#" FG_RESET FG_BOLD);
|
||||
|
||||
for (int i = prog; i < size; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("]" FG_RESET);
|
||||
|
||||
printf(FG_BOLD FG_BLUE "%s" FG_RESET "\r", perc);
|
||||
return true;
|
||||
}
|
||||
|
||||
void bar_free() {
|
||||
struct winsize barwin = {0};
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &barwin);
|
||||
|
||||
printf("\r");
|
||||
for (int i = 0; i < barwin.ws_col; i++)
|
||||
printf(" ");
|
||||
printf("\r");
|
||||
|
||||
printf("\e[?25h");
|
||||
}
|
18
src/log.h
Normal file
18
src/log.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#define FG_RED "\x1b[31m"
|
||||
#define FG_BOLD "\x1b[1m"
|
||||
#define FG_BLUE "\x1b[34m"
|
||||
#define FG_CYAN "\x1b[36m"
|
||||
#define FG_GREEN "\x1b[32m"
|
||||
#define FG_GRAY "\x1b[37m"
|
||||
#define FG_MAGENTA "\x1b[35m"
|
||||
#define FG_RESET "\x1b[0m"
|
||||
|
||||
void info(const char *msg, ...);
|
||||
void error(const char *msg, ...);
|
||||
void success(const char *msg, ...);
|
||||
bool yesno(const char *msg);
|
||||
bool bar(float cur, float max);
|
||||
void bar_free();
|
137
src/main.c
Normal file
137
src/main.c
Normal file
@@ -0,0 +1,137 @@
|
||||
// clang-format off
|
||||
|
||||
/*
|
||||
|
||||
* matt | MatterLinux package manager
|
||||
* MatterLinux 2023-2024 (https://matterlinux.xyz)
|
||||
|
||||
* 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 3 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/>.
|
||||
|
||||
*/
|
||||
|
||||
// clang-format on
|
||||
|
||||
#include <libmp/all.h>
|
||||
#include <libmp/ctx.h>
|
||||
#include <libmp/error.h>
|
||||
#include <libmp/util.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "args.h"
|
||||
#include "intl.h"
|
||||
#include "cmd.h"
|
||||
#include "log.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
cmd_t commands[] = {
|
||||
{.name="list", .desc="list all the installed packages", .func=cmd_list},
|
||||
{.name="sync", .desc="update the pool info and package lists", .func=cmd_sync},
|
||||
{.name="install", .desc="install package(s) from remote pools", .func=cmd_install},
|
||||
{.name="remove", .desc="remove installed package(s)", .func=NULL},
|
||||
{.name="update", .desc="update installed package(s)", .func=NULL},
|
||||
};
|
||||
|
||||
char *config_file = NULL, *root_dir = NULL;
|
||||
char *full_datadir = NULL, *full_tmpdir = NULL;
|
||||
args_t *args = NULL;
|
||||
bool ret = false;
|
||||
config_t config;
|
||||
lm_ctx_t ctx;
|
||||
|
||||
lm_ctx_init(&ctx);
|
||||
args = args_parse(argc, argv);
|
||||
|
||||
if((config_file = args_get_string(args, "config")) == NULL)
|
||||
config_file = "/etc/matt/config.ini";
|
||||
|
||||
if(!config_load(&ctx, &config, config_file))
|
||||
goto end;
|
||||
|
||||
if(args->count <= 0 || args->list[0].name != NULL)
|
||||
goto help;
|
||||
|
||||
if((root_dir = args_get_string(args, "root")) == NULL)
|
||||
root_dir = "/";
|
||||
|
||||
if(!lm_ctx_set_root(&ctx, root_dir)){
|
||||
if(LM_ERR_CtxRootNoWrite == lm_error())
|
||||
error(_("Failed to access the root directory, are you running as root?"));
|
||||
else
|
||||
error(_("Bad root directory (%s): %s"), root_dir, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
full_datadir = join_alloc(root_dir, config.datadir);
|
||||
full_tmpdir = join_alloc(root_dir, config.tmpdir);
|
||||
|
||||
if(!lm_ctx_set_data(&ctx, full_datadir)){
|
||||
error(_("Bad datadir (%s): %s"), full_datadir, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(!lm_ctx_set_temp(&ctx, full_tmpdir)){
|
||||
error(_("Bad tmpdir (%s): %s"), full_tmpdir, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
|
||||
pool_config_t *pool = config.pools;
|
||||
while (NULL != pool) {
|
||||
if(!lm_ctx_pool_add(&ctx, pool->name, pool->url)){
|
||||
error(_("Failed to add pool "FG_BOLD"%s"FG_RESET" to the list: %s"), pool->name, lm_strerror());
|
||||
goto end;
|
||||
}
|
||||
pool = pool->next;
|
||||
}
|
||||
|
||||
for(int i = 0; i < sizeof(commands)/sizeof(cmd_t); i++){
|
||||
if(eq(commands[i].name, args->list[0].value)){
|
||||
ret = commands[i].func(&ctx, &config, args);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
error(_("Command not found: "FG_BOLD"%s"), args->list[0].value);
|
||||
help:
|
||||
info(_("MatterLinux package manager (version %s)"), VERSION);
|
||||
info(_("Usage: "FG_BOLD"%s [command] <options> <arguments>"), argv[0]);
|
||||
printf("\n");
|
||||
info(_("Here is a list of available commands:"));
|
||||
|
||||
for(int i = 0; i < sizeof(commands)/sizeof(cmd_t); i++)
|
||||
printf(" "FG_BOLD"%s"FG_RESET":\t %s\n", commands[i].name, commands[i].desc);
|
||||
printf("\n");
|
||||
|
||||
info(_("To list different options, use commands with "FG_BOLD"--help"FG_RESET" option"));
|
||||
info(_("Here is a list of available global options:"));
|
||||
|
||||
printf(_(" "FG_BOLD"--config"FG_RESET":\t specify the configuration file (default is /etc/matt/config.ini)\n"));
|
||||
printf(_(" "FG_BOLD"--root"FG_RESET":\t specify a custom root directory (default is /)\n\n"));
|
||||
|
||||
info(_("Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"));
|
||||
|
||||
ret = true;
|
||||
goto end;
|
||||
|
||||
end:
|
||||
free(full_datadir);
|
||||
free(full_tmpdir);
|
||||
|
||||
args_free(args);
|
||||
lm_ctx_free(&ctx);
|
||||
config_free(&config);
|
||||
|
||||
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
30
src/util.c
Normal file
30
src/util.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
bool startswith(char *str, char *sub){
|
||||
size_t strl = strlen(str);
|
||||
size_t subl = strlen(sub);
|
||||
|
||||
if(subl > strl)
|
||||
return false;
|
||||
|
||||
return strncmp(sub, str, subl) == 0;
|
||||
}
|
||||
|
||||
void size_to_human(char *buf, long size) {
|
||||
char *suffix[] = {"B", "KB", "MB", "GB", "TB"};
|
||||
char length = sizeof(suffix) / sizeof(suffix[0]);
|
||||
|
||||
int i = 0;
|
||||
double cursize = size;
|
||||
|
||||
if (size > 1024) {
|
||||
for (i = 0; (size / 1024) > 0 && i < length - 1; i++, size /= 1024)
|
||||
cursize = size / 1024.0;
|
||||
}
|
||||
|
||||
sprintf(buf, "%.02lf%s", cursize, suffix[i]);
|
||||
}
|
7
src/util.h
Normal file
7
src/util.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#define LONGSTR_MAX 30
|
||||
|
||||
bool startswith(char *str, char *sub);
|
||||
void size_to_human(char *buf, long size);
|
Reference in New Issue
Block a user