fix: better way to validate the config, add options to git clone

This commit is contained in:
ngn 2024-05-01 23:07:02 +03:00
parent 5691727d64
commit bdd1ee23d8
7 changed files with 230 additions and 83 deletions

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-01 20:59+0300\n"
"POT-Creation-Date: 2024-05-01 23:04+0300\n"
"PO-Revision-Date: 2024-05-01 13:34+0300\n"
"Last-Translator: <ngn@ngn.tf>\n"
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
@ -23,76 +23,100 @@ msgstr ""
#: src/config.c:18
#, c-format
msgid "Configuration target %s does not have \"dst\" field"
msgid "Configuration target \"%s\" does not have \"dst\" field"
msgstr ""
#: src/config.c:23
#, c-format
msgid "Configuration target %s does not have \"src\" field"
msgid "Configuration target \"%s\" does not have \"src\" field"
msgstr ""
#: src/config.c:53
#: src/config.c:32
msgid "Configuration does not have a name field"
msgstr ""
#: src/config.c:58
#: src/config.c:37
msgid "Configuration does not have an author field"
msgstr ""
#: src/config.c:63
#: src/config.c:42
msgid "Configuration does not have any targets"
msgstr ""
#: src/config.c:117
#: src/config.c:120
#, c-format
msgid "Key %s is unknown"
msgstr ""
#: src/config.c:160
#: src/config.c:156
msgid "Configuration file not found"
msgstr ""
#: src/config.c:170
msgid "Failed to parse configuration file"
msgstr ""
#: src/main.c:66
#: src/log.c:150
msgid "y"
msgstr ""
#: src/log.c:150
msgid "Y"
msgstr ""
#: src/log.c:152
msgid "n"
msgstr ""
#: src/log.c:152
msgid "N"
msgstr ""
#: src/log.c:155
msgid "Please answer with y/n"
msgstr ""
#: src/main.c:74
#, c-format
msgid "Failed to access paths (%s)"
msgstr ""
#: src/main.c:74
#: src/main.c:82
msgid "Failed to lock, mc is already running"
msgstr ""
#: src/main.c:77
#: src/main.c:85
msgid "Failed to lock, did you mess up your directory permissions?"
msgstr ""
#: src/main.c:86
#, c-format
msgid "%s: command failed"
msgstr ""
#: src/main.c:90
#, c-format
msgid "%s: command successful"
msgstr ""
#: src/main.c:94
#, c-format
msgid "MatterLinux Configuration Manager (%s)"
msgstr ""
#: src/main.c:95
msgid "Different operations are done using different commands\n"
msgid "%s: command failed"
msgstr ""
#: src/main.c:98
msgid "pull down a configuration"
#, c-format
msgid "%s: command successful"
msgstr ""
#: src/main.c:101
msgid "build the configuration in the current directory"
#: src/main.c:102
#, c-format
msgid "MatterLinux Configuration Manager (%s)"
msgstr ""
#: src/main.c:103
msgid "Different operations are done using different commands\n"
msgstr ""
#: src/main.c:106
msgid "pull down a configuration"
msgstr ""
#: src/main.c:109
msgid "build the configuration in the current directory"
msgstr ""
#: src/main.c:111
msgid ""
"Licensed under GPLv3, see <https://www.gnu.org/licenses/> for more "
"information"
@ -102,21 +126,58 @@ msgstr ""
msgid "Please specify a config name or a URL"
msgstr ""
#: src/pull.c:55
#: src/pull.c:56
#, c-format
msgid "Cloning %s"
msgstr ""
#: src/pull.c:60
#: src/pull.c:61
#, c-format
msgid "Failed to clone the %s: %s"
msgid "Failed to clone the %s:"
msgstr ""
#: src/pull.c:70
#: src/pull.c:72
#, c-format
msgid "Failed to chdir to %s"
msgstr ""
#: src/pull.c:76
#: src/pull.c:77
msgid "Failed to load the configuration file (mc.cfg):"
msgstr ""
#: src/pull.c:82
msgid "Loaded repository configuration"
msgstr ""
#: src/pull.c:83
msgid "Configuration details:\n"
msgstr ""
#: src/pull.c:84
msgid "Name"
msgstr ""
#: src/pull.c:85
msgid "Author"
msgstr ""
#: src/pull.c:87
msgid "Keywords"
msgstr ""
#: src/pull.c:92
msgid "Do you want to continue?"
msgstr ""
#: src/pull.c:95
msgid "Checking all the targets"
msgstr ""
#: src/pull.c:99
#, c-format
msgid "Failed to access the source for the target \"%s\""
msgstr ""
#: src/pull.c:105
msgid "All the targets are OK"
msgstr ""

View File

@ -15,18 +15,44 @@ bool target_is_valid(target_t *target) {
}
if (NULL == target->dst) {
error_set(_("Configuration target %s does not have \"dst\" field"), target->name);
error_set(_("Configuration target \"%s\" does not have \"dst\" field"), target->name);
return false;
}
if (NULL == target->src) {
error_set(_("Configuration target %s does not have \"src\" field"), target->name);
error_set(_("Configuration target \"%s\" does not have \"src\" field"), target->name);
return false;
}
return true;
}
bool config_is_valid(config_t *config) {
if (NULL == config->name) {
error_set(_("Configuration does not have a name field"));
return false;
}
if (NULL == config->author) {
error_set(_("Configuration does not have an author field"));
return false;
}
if (NULL == config->t_last) {
error_set(_("Configuration does not have any targets"));
return false;
}
target_t *cur = config->t_first;
while(cur){
if(!target_is_valid(cur))
return false;
cur = cur->next;
}
return true;
}
bool config_add_target(config_t *config, char *name) {
target_t *new = malloc(sizeof(target_t));
clist_init(&new->requires);
@ -48,25 +74,6 @@ bool config_add_target(config_t *config, char *name) {
return true;
}
bool config_is_valid(config_t *config) {
if (NULL == config->name) {
error_set(_("Configuration does not have a name field"));
return false;
}
if (NULL == config->author) {
error_set(_("Configuration does not have an author field"));
return false;
}
if (NULL == config->t_last) {
error_set(_("Configuration does not have any targets"));
return false;
}
return true;
}
int config_handler(void *data, const char *section, const char *key, const char *value) {
#define MATCH(s, k) eq((char *)section, s) && eq((char *)key, k)
#define MATCHKEY(k) eq((char *)key, k)
@ -85,17 +92,12 @@ int config_handler(void *data, const char *section, const char *key, const char
} else if (MATCH("details", "keywords")) {
clist_from_str(&config->keywords, (char *)value);
return 1;
}else if(eq((char*)section, "details")) {
goto UNKNOWN;
return 1;
}
if(NULL == config->t_last || (NULL != config->t_last->name && !eq(config->t_last->name, (char*)section))){
if (NULL != config->t_last) {
if (!target_is_valid(config->t_last)) {
errno = ConfigInvalid;
debug("invalid %s %s", config->t_last->name, section);
return 0;
}
}
debug("adding new target => %s", section);
config_add_target(config, strdup(section));
}
@ -107,13 +109,14 @@ int config_handler(void *data, const char *section, const char *key, const char
config->t_last->dst = strdup(value);
return 1;
} else if (MATCHKEY("src")) {
config->t_last->dst = strdup(value);
config->t_last->src = strdup(value);
return 1;
} else if (MATCHKEY("requires")) {
clist_from_str(&config->t_last->requires, strdup(value));
return 1;
}
UNKNOWN:
error_set(_("Key %s is unknown"), key);
errno = ConfigUnknown;
return 0;
@ -140,10 +143,17 @@ void config_free(config_t *config) {
}
clist_free(&config->keywords);
config->name = NULL;
config->author = NULL;
config->t_first = NULL;
config->t_last = NULL;
clist_init(&config->keywords);
}
bool config_load(config_t *config, char *path) {
if (!exists(path) || is_dir(path)) {
error_set(_("Configuration file not found"));
errno = ConfigNotFound;
return false;
}
@ -156,7 +166,7 @@ bool config_load(config_t *config, char *path) {
if (ini_parse(path, config_handler, config) < 0) {
config_free(config);
if (errno != ConfigUnknown && errno != ConfigInvalid) {
if (errno != ConfigUnknown) {
error_set(_("Failed to parse configuration file"));
errno = ConfigParseFail;
}

View File

@ -23,3 +23,4 @@ typedef struct config {
} config_t;
bool config_load(config_t *, char *);
void config_free(config_t *);

View File

@ -1,5 +1,8 @@
#include "log.h"
#include "env.h"
#include "intl.h"
#include "util.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
@ -88,6 +91,17 @@ void error(const char *msg, ...) {
va_end(args);
}
void details(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(" "COLOR_RESET);
vprintf(msg, args);
printf(COLOR_RESET "\n");
va_end(args);
}
void success(const char *msg, ...) {
va_list args;
va_start(args, msg);
@ -112,3 +126,32 @@ void debug(const char *msg, ...) {
va_end(args);
}
void input(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_CYAN ">>> " COLOR_RESET COLOR_BOLD);
vprintf(msg, args);
printf(COLOR_RESET);
va_end(args);
}
bool yesno(const char *msg){
char question[strlen(msg)+12], inp[2] = {'n','\0'}, c;
sprintf(question, "%s [y/n]? ", msg);
while(true){
input(question);
scanf("%c", &c);
inp[0] = c;
if(eq(inp, _("y")) || eq(inp, _("Y")))
return true;
else if(eq(inp, _("n")) || eq(inp, _("N")))
return false;
error(_("Please answer with y/n"));
}
}

View File

@ -4,15 +4,20 @@
#define COLOR_RED "\x1b[31m"
#define COLOR_BOLD "\x1b[1m"
#define COLOR_BLUE "\x1b[34m"
#define COLOR_CYAN "\x1b[36m"
#define COLOR_GREEN "\x1b[32m"
#define COLOR_MAGENTA "\x1b[35m"
#define COLOR_UNDERLINE "\x1b[4m"
#define COLOR_RESET "\x1b[0m"
void bar_init();
bool bar(float, float);
void bar_free();
void info(const char *msg, ...);
void error(const char *msg, ...);
void success(const char *msg, ...);
void info(const char *, ...);
void error(const char *, ...);
void details(const char *, ...);
void success(const char *, ...);
void debug(const char *, ...);
void input(const char *, ...);
bool yesno(const char *);

View File

@ -24,6 +24,7 @@
#include <libintl.h>
#include <locale.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -51,7 +52,14 @@ struct CmdMap cmdmap[] = {
{.name = "mc-gen", .lock = false, .func = gen_cmd },
};
void handler(int sig){
unlock();
printf("\e[?25h");
exit(1);
}
int main(int argc, char *argv[]) {
signal(SIGINT, handler);
setbuf(stdout, NULL);
setlocale(LC_ALL, "");
textdomain("mc");

View File

@ -17,7 +17,7 @@
#define _(x) gettext(x)
int fetch_progress(const git_indexer_progress *stats, void *data) {
int pull_progress(const git_indexer_progress *stats, void *data){
bar(stats->indexed_objects, stats->total_objects);
return 0;
}
@ -29,6 +29,7 @@ bool pull_cmd() {
}
char *repo_url = NULL, *repo_root = NULL;
config_t repo_cfg = {.name = NULL};
bool ret = false;
if (url_is_local(args.list[1])) {
@ -49,15 +50,16 @@ bool pull_cmd() {
git_repository *repo = NULL;
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.fetch_opts.callbacks.transfer_progress = fetch_progress;
opts.fetch_opts.callbacks.transfer_progress = pull_progress;
opts.fetch_opts.callbacks.payload = NULL;
info(_("Cloning %s"), repo_url);
bar_init();
if (git_clone(&repo, repo_url, repo_root, NULL) < 0) {
if (git_clone(&repo, repo_url, repo_root, &opts) < 0) {
const git_error *e = git_error_last();
error(_("Failed to clone the %s: %s"), repo_url, e->message);
error(_("Failed to clone the %s:"), repo_url);
details(e->message);
bar_free();
goto END;
}
@ -71,23 +73,40 @@ COPY:
goto END;
}
config_t repo_cfg;
if (!config_load(&repo_cfg, "mc.cfg")) {
error(_("Failed to load the configuration file (mc.cfg):"));
printf(" %s\n", errch);
details(errch);
goto END;
}
info("Configuration details:");
printf(COLOR_BOLD " Name" COLOR_RESET ": %s\n", repo_cfg.name);
printf(COLOR_BOLD " Author" COLOR_RESET ": %s\n", repo_cfg.author);
success(_("Loaded repository configuration"));
info(_("Configuration details:\n"));
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Name"), repo_cfg.name);
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Author"), repo_cfg.author);
printf(COLOR_BOLD " Keywords" COLOR_RESET ":");
printf(COLOR_BOLD " %s " COLOR_RESET "=> ", _("Keywords"));
for (int i = 0; i < repo_cfg.keywords.s; i++)
printf("%s ", repo_cfg.keywords.c[i]);
printf("\n");
printf("\n\n");
if(!yesno(_("Do you want to continue?")))
goto END;
info(_("Checking all the targets"));
target_t *cur = repo_cfg.t_first;
while(NULL != cur){
if(!exists(cur->src)){
error(_("Failed to access the source for the target \"%s\""), cur->name);
goto END;
}
cur = cur->next;
}
success(_("All the targets are OK"));
END:
if(repo_cfg.name != NULL)
config_free(&repo_cfg);
free(repo_url);
return ret;
}