diff --git a/locale/tr/LC_MESSAGES/mc.po b/locale/tr/LC_MESSAGES/mc.po index 7dbf41d..23a78d8 100644 --- a/locale/tr/LC_MESSAGES/mc.po +++ b/locale/tr/LC_MESSAGES/mc.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-02 00:49+0300\n" +"POT-Creation-Date: 2024-05-02 22:51+0300\n" "PO-Revision-Date: 2024-05-01 13:34+0300\n" "Last-Translator: \n" "Language-Team: Turkish \n" @@ -17,45 +17,84 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: src/config.c:13 -msgid "Configuration target is missing a name" -msgstr "" - -#: src/config.c:18 -#, c-format -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" -msgstr "" - -#: src/config.c:32 msgid "Configuration does not have a name field" msgstr "" -#: src/config.c:37 +#: src/config.c:28 msgid "Configuration does not have an author field" msgstr "" -#: src/config.c:42 +#: src/config.c:33 msgid "Configuration does not have any targets" msgstr "" -#: src/config.c:120 +#: src/config.c:91 +msgid "Configuration contains multiple targets with the same name" +msgstr "" + +#: src/config.c:113 #, c-format msgid "Key %s is unknown" msgstr "" -#: src/config.c:156 +#: src/config.c:143 msgid "Configuration file not found" msgstr "" -#: src/config.c:170 +#: src/config.c:158 msgid "Failed to parse configuration file" msgstr "" +#: src/config.c:174 +msgid "Configuration details:\n" +msgstr "" + +#: src/config.c:175 +msgid "Name" +msgstr "" + +#: src/config.c:176 +msgid "Author" +msgstr "" + +#: src/config.c:178 +msgid "Keywords" +msgstr "" + +#: src/gen.c:15 +msgid "Please specify a directory for the repository" +msgstr "" + +#: src/gen.c:20 +msgid "Failed to access the directory" +msgstr "" + +#: src/gen.c:25 +msgid "Failed to change directory to the specified directory" +msgstr "" + +#: src/gen.c:29 src/gen.c:36 src/pull.c:82 +msgid "Loaded repository configuration" +msgstr "" + +#: src/gen.c:31 src/pull.c:77 +msgid "Failed to load the configuration file (mc.cfg):" +msgstr "" + +#: src/gen.c:42 +msgid "Copying all the targets" +msgstr "" + +#: src/gen.c:47 +msgid "Failed to copy the target:" +msgstr "" + +#: src/gen.c:53 +#, c-format +msgid "%s: copy success" +msgstr "" + #: src/log.c:145 msgid "y" msgstr "" @@ -146,43 +185,58 @@ msgstr "" msgid "Failed to chdir to %s" msgstr "" -#: 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 +#: src/pull.c:88 msgid "Checking all the targets" msgstr "" -#: src/pull.c:99 +#: src/pull.c:92 #, c-format msgid "Failed to access the source for the target \"%s\"" msgstr "" -#: src/pull.c:105 +#: src/pull.c:98 msgid "All the targets are OK" msgstr "" + +#: src/target.c:13 +msgid "Configuration target is missing a name" +msgstr "" + +#: src/target.c:18 +#, c-format +msgid "Configuration target \"%s\" does not have \"dst\" field" +msgstr "" + +#: src/target.c:23 +#, c-format +msgid "Configuration target \"%s\" does not have \"src\" field" +msgstr "" + +#: src/target.c:38 +#, c-format +msgid "Failed to open the directory: %s" +msgstr "" + +#: src/target.c:76 +#, c-format +msgid "Source directory \"%s\" does not exist" +msgstr "" + +#: src/util.c:115 src/util.c:126 +#, c-format +msgid "Failed to create directory: %s" +msgstr "" + +#: src/util.c:205 +#, c-format +msgid "Failed to open \"%s\" for reading" +msgstr "" + +#: src/util.c:207 +#, c-format +msgid "Failed to open \"%s\" for writing" +msgstr "" diff --git a/src/config.c b/src/config.c index 37362ed..5d4e8c7 100644 --- a/src/config.c +++ b/src/config.c @@ -8,23 +8,14 @@ #include "log.h" #include "util.h" -bool target_is_valid(target_t *target) { - if (NULL == target->name) { - error_set(_("Configuration target is missing a name")); - return false; +bool config_contains_target(config_t *config, char *name) { + target_t *cur = config->t_last; + while (cur) { + if (eq(cur->name, name)) + return true; + cur = cur->next; } - - if (NULL == target->dst) { - 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); - return false; - } - - return true; + return false; } bool config_is_valid(config_t *config) { @@ -55,13 +46,10 @@ bool config_is_valid(config_t *config) { bool config_add_target(config_t *config, char *name) { target_t *new = malloc(sizeof(target_t)); - clist_init(&new->requires); - - new->next = NULL; + target_init(new); new->name = name; - new->desc = NULL; - new->dst = NULL; - new->src = NULL; + + config->t_len++; if (NULL == config->t_first || NULL == config->t_last) { config->t_first = new; @@ -99,6 +87,11 @@ int config_handler(void *data, const char *section, const char *key, const char if (NULL == config->t_last || (NULL != config->t_last->name && !eq(config->t_last->name, (char *)section))) { debug("adding new target => %s", section); + if (config_contains_target(config, (char *)section)) { + error_set(_("Configuration contains multiple targets with the same name")); + errno = ConfigMultiple; + return 0; + } config_add_target(config, strdup(section)); } @@ -122,15 +115,6 @@ UNKNOWN: return 0; } -void target_free(target_t *target) { - free(target->name); - free(target->desc); - free(target->dst); - free(target->src); - clist_free(&target->requires); - free(target); -} - void config_free(config_t *config) { free(config->name); free(config->author); @@ -139,7 +123,9 @@ void config_free(config_t *config) { while (cur != NULL) { prev = cur; cur = cur->next; + target_free(prev); + free(prev); } clist_free(&config->keywords); @@ -148,6 +134,7 @@ void config_free(config_t *config) { config->author = NULL; config->t_first = NULL; config->t_last = NULL; + config->t_len = 0; clist_init(&config->keywords); } @@ -162,11 +149,12 @@ bool config_load(config_t *config, char *path) { config->author = NULL; config->t_first = NULL; config->t_last = NULL; + config->t_len = 0; clist_init(&config->keywords); if (ini_parse(path, config_handler, config) < 0) { config_free(config); - if (errno != ConfigUnknown) { + if (errno != ConfigUnknown || errno != ConfigMultiple) { error_set(_("Failed to parse configuration file")); errno = ConfigParseFail; } @@ -181,3 +169,14 @@ bool config_load(config_t *config, char *path) { return true; } + +void config_print(config_t *config) { + info(_("Configuration details:\n")); + printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Name"), config->name); + printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Author"), config->author); + + printf(COLOR_BOLD " %s " COLOR_RESET "=> ", _("Keywords")); + for (int i = 0; i < config->keywords.s; i++) + printf("%s ", config->keywords.c[i]); + printf("\n\n"); +} diff --git a/src/config.h b/src/config.h index 6eb27fe..cf066b8 100644 --- a/src/config.h +++ b/src/config.h @@ -1,21 +1,13 @@ #pragma once +#include "target.h" #include "util.h" #include #include -typedef struct target { - struct target *next; - clist_t - requires; - char *name; - char *desc; - char *src; - char *dst; -} target_t; - typedef struct config { target_t *t_first; target_t *t_last; + size_t t_len; char *name; char *author; @@ -24,3 +16,4 @@ typedef struct config { bool config_load(config_t *, char *); void config_free(config_t *); +void config_print(config_t *); diff --git a/src/error.h b/src/error.h index c1a2d8e..02f681c 100644 --- a/src/error.h +++ b/src/error.h @@ -5,6 +5,13 @@ enum ErrorCodes { ConfigNotFound = 954, ConfigInvalid = 953, ConfigParseFail = 952, + ConfigMultiple = 951, + + TargetSrcFail = 950, + + OpendirFail = 948, + MkdirFail = 945, + OpenFail = 944, }; extern int errno; diff --git a/src/gen.c b/src/gen.c index e783188..58f20cd 100644 --- a/src/gen.c +++ b/src/gen.c @@ -1,5 +1,64 @@ #include "gen.h" +#include "args.h" +#include "config.h" +#include "error.h" +#include "intl.h" +#include "log.h" +#include "util.h" +#include bool gen_cmd() { - return true; + bool ret = false; + config_t cfg; + + if (args.count != 2) { + error(_("Please specify a directory for the repository")); + return ret; + } + + if (!exists(args.list[1]) || !is_dir(args.list[1])) { + error(_("Failed to access the directory")); + return ret; + } + + if (chdir(args.list[1]) < 0) { + error(_("Failed to change directory to the specified directory")); + return ret; + } + + success(_("Loaded repository configuration")); + if (!config_load(&cfg, "mc.cfg")) { + error(_("Failed to load the configuration file (mc.cfg):")); + details(errch); + return ret; + } + + success(_("Loaded repository configuration")); + config_print(&cfg); + + target_t *cur = cfg.t_first; + int counter = 0; + + info(_("Copying all the targets")); + bar_init(); + + while (cur && counter++) { + if(!target_copy(cur, true)){ + error(_("Failed to copy the target:")); + details(errch); + bar_free(); + goto END; + } + + success(_("%s: copy success")); + bar(counter, cfg.t_len); + cur = cur->next; + } + + bar_free(); + ret = true; + +END: + config_free(&cfg); + return ret; } diff --git a/src/log.c b/src/log.c index 3de4163..f22d8e9 100644 --- a/src/log.c +++ b/src/log.c @@ -138,31 +138,31 @@ void input(const char *msg, ...) { va_end(args); } -bool yesno(const char *msg){ - if(env_mc_yes()) +bool yesno(const char *msg) { + if (env_mc_yes()) return true; char *yes[] = {_("y"), _("Y")}; char *no[] = {_("n"), _("N")}; - - char question[strlen(msg)+12], c; + + char question[strlen(msg) + 12], c; sprintf(question, _("%s [y/N] "), msg); - while(true){ + while (true) { input(question); - + int c = getchar(); - if(c == '\n') + if (c == '\n') return false; getchar(); - - for(int i = 0; i < sizeof(yes)/sizeof(char*); i++){ - if(yes[i][0] == c) + + 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) + + for (int i = 0; i < sizeof(no) / sizeof(char *); i++) { + if (no[i][0] == c) return false; } diff --git a/src/pull.c b/src/pull.c index 8a26dae..d7a62bc 100644 --- a/src/pull.c +++ b/src/pull.c @@ -80,14 +80,7 @@ COPY: } 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 " %s " COLOR_RESET "=> ", _("Keywords")); - for (int i = 0; i < repo_cfg.keywords.s; i++) - printf("%s ", repo_cfg.keywords.c[i]); - printf("\n\n"); + config_print(&repo_cfg); if (!yesno(_("Do you want to continue?"))) goto END; diff --git a/src/target.c b/src/target.c new file mode 100644 index 0000000..cdeb2bb --- /dev/null +++ b/src/target.c @@ -0,0 +1,110 @@ +#include "target.h" +#include "error.h" +#include "intl.h" +#include "util.h" + +#include +#include +#include +#include + +bool target_is_valid(target_t *t) { + if (NULL == t->name) { + error_set(_("Configuration target is missing a name")); + return false; + } + + if (NULL == t->dst) { + error_set(_("Configuration target \"%s\" does not have \"dst\" field"), t->name); + return false; + } + + if (NULL == t->src) { + error_set(_("Configuration target \"%s\" does not have \"src\" field"), t->name); + return false; + } + + return true; +} + +bool target_copy_dir(char *src, char *dst) { + if (!mksubdirsp(dst, 755)) + return false; + + DIR *dir = opendir(src); + struct dirent *ent = NULL; + + if (NULL == dir) { + error_set(_("Failed to open the directory: %s"), src); + errno = OpendirFail; + return false; + } + + size_t src_len = strlen(src); + size_t dst_len = strlen(dst); + + while ((ent = readdir(dir)) != NULL) { + size_t len = strlen(ent->d_name); + char src_fp[src_len + len + 2], dst_fp[dst_len + len + 2]; + + join(src_fp, src, ent->d_name); + join(dst_fp, dst, ent->d_name); + + if (is_dir(src_fp)) { + if (!target_copy_dir(src_fp, dst_fp)) + return false; + continue; + } + + if (!copyfile(src_fp, dst_fp)) + return false; + } + + return true; +} + +bool target_copy(target_t *t, bool fromdst) { + char *src = t->src, *dst = t->dst; + bool ret = false; + + if (fromdst) { + src = t->dst; + dst = t->src; + } + + if (!exists(t->src)) { + error_set(_("Source directory \"%s\" does not exist"), src); + errno = TargetSrcFail; + return ret; + } + + if (is_dir(src)) + return target_copy_dir(src, dst); + + char *dstcp = strdup(dst); + char *dstdir = dirname(dst); + + if(!mksubdirsp(dstdir, 0755)) + return ret; + + ret = copyfile(src, dstcp); + free(dstcp); + return ret; +} + +void target_init(target_t *t) { + clist_init(&t->requires); + t->next = NULL; + t->name = NULL; + t->desc = NULL; + t->dst = NULL; + t->src = NULL; +} + +void target_free(target_t *t) { + free(t->name); + free(t->desc); + free(t->dst); + free(t->src); + clist_free(&t->requires); +} diff --git a/src/target.h b/src/target.h new file mode 100644 index 0000000..228f585 --- /dev/null +++ b/src/target.h @@ -0,0 +1,17 @@ +#include "util.h" +#include + +typedef struct target { + struct target *next; + clist_t + requires; + char *name; + char *desc; + char *src; + char *dst; +} target_t; + +bool target_is_valid(target_t *); +void target_init(target_t *); +void target_free(target_t *); +bool target_copy(target_t *, bool); diff --git a/src/util.c b/src/util.c index 02d1666..4acee32 100644 --- a/src/util.c +++ b/src/util.c @@ -8,6 +8,8 @@ #include #include +#include "error.h" +#include "intl.h" #include "util.h" bool eq(char *s1, char *s2) { @@ -109,16 +111,22 @@ bool mksubdirsp(char *path, int perms) { for (char *c = path; *c != '\0'; c++) { if (*c == '/' && indx != 0) { cur[indx] = '\0'; - if (!exists(cur) && mkdir(cur, perms) < 0) + if (!exists(cur) && mkdir(cur, perms) < 0){ + error_set(_("Failed to create directory: %s"), cur); + errno = MkdirFail; return false; + } } cur[indx] = *c; indx++; } - if (!exists(cur) && mkdir(cur, perms) < 0) + if (!exists(cur) && mkdir(cur, perms) < 0){ + error_set(_("Failed to create directory: %s"), cur); + errno = MkdirFail; return false; + } return true; } @@ -187,3 +195,29 @@ void clist_add(clist_t *l, char *en) { l->c[l->s] = en; l->s++; } + +bool copyfile(char *src, char *dst){ + FILE *srcf = fopen(src, "r"); + FILE *dstf = fopen(dst, "w"); + + if(NULL == srcf || NULL == dstf){ + if(NULL == srcf) + error_set(_("Failed to open \"%s\" for reading"), srcf); + else + error_set(_("Failed to open \"%s\" for writing"), dstf); + errno = OpenFail; + return false; + } + + char buffer[32]; + int read = -1; + + bzero(buffer, 32); + + while((read = fread(buffer, 1, 32, srcf)) > 0) + fwrite(buffer, 1, read, dstf); + + fclose(srcf); + fclose(dstf); + return true; +} diff --git a/src/util.h b/src/util.h index 03d3cd3..6347ea4 100644 --- a/src/util.h +++ b/src/util.h @@ -18,6 +18,7 @@ int randint(int, int); bool is_dir(char *); bool mksubdirsp(char *, int); bool rmrf(char *); +bool copyfile(char *, char *); void clist_init(clist_t *); void clist_from_str(clist_t *, char *);