update: refactor and rename

This commit is contained in:
ngn 2024-08-01 04:48:11 +03:00
parent 48d177965e
commit 4354fb8b89
30 changed files with 642 additions and 626 deletions

View File

@ -1,20 +1,28 @@
HEADERS = $(wildcard src/*.h) $(wildcard src/*/*.h)
CSRCS = $(wildcard src/*.c) $(wildcard src/*/*.c)
CMDS = mc-pull mc-gen
SRCS = $(wildcard src/*.c) $(wildcard src/*/*.c)
OBJS = $(patsubst src/%.c,dist/%.o,$(SRCS))
HDRS = $(wildcard src/*.h)
PO_SRCS = $(wildcard locale/*/*/*.po)
PO_OUTS = $(patsubst locale/%.po,locale/%.mo,$(PO_SRCS))
PO_DIRS = $(wildcard locale/*/*)
VERSION = 24.02
prefix = /usr
CFLAGS = -O3 -fstack-protector-strong -fcf-protection=full -fstack-clash-protection
LIBS = -linih -lgit2 -lcurl -lcrypto
VERSION = 24.03
PREFIX = /usr
CC = gcc
all: dist/mc $(PO_OUTS)
all: dist dist/confer $(PO_OUTS)
dist/mc: $(CSRCS) $(HEADERS)
mkdir -p dist
$(CC) $(CFLAGS) $(CSRCS) -o $@ -DVERSION=\"${VERSION}\" -linih -lgit2 -lcurl -lcrypto
dist:
mkdir -pv dist/cmd
dist/confer: $(OBJS)
$(CC) -o $@ $^ $(LIBS) $(CFLAGS)
dist/%.o: src/%.c
$(CC) -c -o $@ $^ $(LIBS) $(CFLAGS) -DVERSION=\"${VERSION}\"
locale/%.mo: locale/%.po
msgfmt $^ -o $@
@ -29,36 +37,30 @@ locale/%.po: locale/mc.pot
mv $@.old $@ ; \
fi; \
locale/mc.pot: $(CSRCS)
locale/confer.pot: $(SRCS)
mkdir -p locale
xgettext -k_ -c $^ -o $@
install:
mkdir -pv $(DESTDIR)$(prefix)/bin
install -v -m755 dist/mc $(DESTDIR)$(prefix)/bin/mc
@for cmd in $(CMDS) ; do \
ln -sfv mc $(DESTDIR)$(prefix)/bin/$$cmd ; \
done
mkdir -pv $(DESTDIR)/$(PREFIX)/bin
install -v -m755 dist/confer $(DESTDIR)/$(PREFIX)/bin/confer
@for po in $(PO_DIRS) ; do \
echo "installing locale: $$po/mc.mo" ; \
mkdir -pv $(DESTDIR)/usr/share/$$po ; \
cp $$po/mc.mo $(DESTDIR)/usr/share/$$po ; \
mkdir -pv $(DESTDIR)/$(PREFIX)/share/$$po ; \
cp $$po/mc.mo $(DESTDIR)/$(PREFIX)/share/$$po ; \
done
uninstall:
rm -v $(DESTDIR)$(prefix)/bin/mc
@for cmd in $(CMDS) ; do \
unlink $(DESTDIR)$(prefix)/bin/$$cmd ; \
done
rm -v $(DESTDIR)/$(PREFIX)/bin/confer
clean:
rm dist/mc
rm locale/mc.pot
@for po in $(PO_DIRS) ; do \
rm $$po/mc.mo ; \
rm $$po/confer.mo ; \
done
format:
clang-format -i -style=file $(HEADERS) $(CSRCS)
clang-format -i -style=file $(HDRS) $(SRCS)
.PHONY: install defcfg uninstall clean
.PHONY: install uninstall clean format

View File

@ -1,10 +1,10 @@
# mc | MatterLinux configuration manager
`mc` is a simple tool for managing desktop/window manager configurations,
# confer | MatterLinux configuration manager
`coner` is a simple tool for managing desktop/window manager configurations,
it allows you to easily create configurations from your dot files and
allows you to easily install them
### Installation
To compile `mc` and to use it, you will need the following:
To compile `coner` and to use it, you will need the following:
- gcc
- libgit2
- make
@ -18,10 +18,10 @@ release for a stable build**. Clone the repository only for development.
After downloading the source code, you can compile `mc` using the
`make` tool:
```
```bash
make
```
After compiling it, you can install the binary, locales and the symbolic links:
```
```bash
make install
```

View File

@ -0,0 +1,223 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-01 04:31+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/config.c:30
msgid "Configuration does not have a name field"
msgstr "Configuration does not have a name field"
#: src/config.c:35
msgid "Configuration does not have an author field"
msgstr "Configuration does not have an author field"
#: src/config.c:40
msgid "Configuration does not have any targets"
msgstr "Configuration does not have any targets"
#: src/config.c:102
msgid "Configuration contains multiple targets with the same name"
msgstr "Configuration contains multiple targets with the same name"
#: src/config.c:129
#, c-format
msgid "Key %s is unknown"
msgstr "Key %s is unknown"
#: src/config.c:161
msgid "Configuration file not found"
msgstr "Configuration file not found"
#: src/config.c:177
msgid "Failed to parse configuration file"
msgstr "Failed to parse configuration file"
#: src/config.c:193
msgid "Configuration details:\n"
msgstr "Configuration details:\n"
#: src/config.c:194 src/target.c:122
msgid "Name"
msgstr "Name"
#: src/config.c:196
msgid "Desc"
msgstr "Desc"
#: src/config.c:197
msgid "Author"
msgstr "Author"
#: src/config.c:199
msgid "Keywords"
msgstr "Keywords"
#: src/log.c:127
msgid "y"
msgstr "y"
#: src/log.c:127
msgid "Y"
msgstr "Y"
#: src/log.c:128
msgid "n"
msgstr "n"
#: src/log.c:128
msgid "N"
msgstr "N"
#: src/log.c:131
#, c-format
msgid "%s [y/N] "
msgstr "%s [y/N] "
#: src/log.c:151
msgid "Please answer with y/n"
msgstr "Please answer with y/n"
#: src/main.c:48
msgid "Program received a segfault"
msgstr "Program received a segfault"
#: src/main.c:61
msgid "pull down a configuration"
msgstr "pull down a configuration"
#: src/main.c:62
msgid "build the configuration in the current directory"
msgstr "build the configuration in the current directory"
#: src/main.c:73
msgid "Please specify the homedir with "
msgstr "Please specify the homedir with "
#: src/main.c:84
msgid "Failed to lock, confer is already running"
msgstr "Failed to lock, confer is already running"
#: src/main.c:88
msgid "Failed to lock, are you root?"
msgstr "Failed to lock, are you root?"
#: src/main.c:100
msgid "Command not found: "
msgstr "Command not found: "
#: src/main.c:102
#, c-format
msgid "MatterLinux configuration manager (version %s)"
msgstr "MatterLinux configuration manager (version %s)"
#: src/main.c:103
msgid "Usage: "
msgstr "Usage: "
#: src/main.c:105
msgid "Here is a list of available commands:"
msgstr "Here is a list of available commands:"
#: src/main.c:111
msgid "Here is a list of available options:"
msgstr "Here is a list of available options:"
#: src/main.c:114 src/main.c:115
#, c-format
msgid " "
msgstr " "
#: src/main.c:117
msgid ""
"Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"
msgstr ""
"Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"
#: src/target.c:15
msgid "Configuration target is missing a name"
msgstr "Configuration target is missing a name"
#: src/target.c:20
#, c-format
msgid "Configuration target \"%s\" does not have \"dst\" field"
msgstr "Configuration target \"%s\" does not have \"dst\" field"
#: src/target.c:25
#, c-format
msgid "Configuration target \"%s\" does not have \"src\" field"
msgstr "Configuration target \"%s\" does not have \"src\" field"
#: src/target.c:40
#, c-format
msgid "Failed to open the directory: %s"
msgstr "Failed to open the directory: %s"
#: src/target.c:84
#, c-format
msgid "Source directory \"%s\" does not exist"
msgstr "Source directory \"%s\" does not exist"
#: src/target.c:121
msgid "Target details:\n"
msgstr "Target details:\n"
#: src/target.c:123
msgid "Description"
msgstr "Description"
#: src/url.c:44
msgid "Failed to open /dev/null"
msgstr "Failed to open /dev/null"
#: src/url.c:51
msgid "Failed to init curl"
msgstr "Failed to init curl"
#: src/url.c:63
msgid "Request failed"
msgstr "Request failed"
#: src/url.c:70
msgid "Failed to get the response code"
msgstr "Failed to get the response code"
#: src/url.c:76
msgid "Response is not a redirect"
msgstr "Response is not a redirect"
#: src/url.c:83
msgid "Failed to get the location header"
msgstr "Failed to get the location header"
#: src/url.c:89
msgid "Invalid location header"
msgstr "Invalid location header"
#: src/util.c:105 src/util.c:116
#, c-format
msgid "Failed to create directory: %s"
msgstr "Failed to create directory: %s"
#: src/util.c:195
#, c-format
msgid "Failed to open \"%s\" for reading"
msgstr "Failed to open \"%s\" for reading"
#: src/util.c:197
#, c-format
msgid "Failed to open \"%s\" for writing"
msgstr "Failed to open \"%s\" for writing"

View File

@ -1,297 +0,0 @@
# Turkish translations for PACKAGE package.
# Copyright (C) 2024 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# <ngn@ngn.tf>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-09 23:28+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"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/config.c:24
msgid "Configuration does not have a name field"
msgstr ""
#: src/config.c:29
msgid "Configuration does not have an author field"
msgstr ""
#: src/config.c:34
msgid "Configuration does not have any targets"
msgstr ""
#: src/config.c:95
msgid "Configuration contains multiple targets with the same name"
msgstr ""
#: src/config.c:122
#, c-format
msgid "Key %s is unknown"
msgstr ""
#: src/config.c:154
msgid "Configuration file not found"
msgstr ""
#: src/config.c:170
msgid "Failed to parse configuration file"
msgstr ""
#: src/config.c:186
msgid "Configuration details:\n"
msgstr ""
#: src/config.c:187 src/target.c:122
msgid "Name"
msgstr ""
#: src/config.c:189
msgid "Desc"
msgstr ""
#: src/config.c:190
msgid "Author"
msgstr ""
#: src/config.c:192
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:95
msgid "Loaded repository configuration"
msgstr ""
#: src/gen.c:31 src/pull.c:90
msgid "Failed to load the configuration file (mc.cfg):"
msgstr ""
#: src/gen.c:42 src/pull.c:122
msgid "Copying all the targets"
msgstr ""
#: src/gen.c:48 src/pull.c:136
msgid "Failed to copy the target:"
msgstr ""
#: src/log.c:145
msgid "y"
msgstr ""
#: src/log.c:145
msgid "Y"
msgstr ""
#: src/log.c:146
msgid "n"
msgstr ""
#: src/log.c:146
msgid "N"
msgstr ""
#: src/log.c:149
#, c-format
msgid "%s [y/N] "
msgstr ""
#: src/log.c:169
msgid "Please answer with y/n"
msgstr ""
#: src/main.c:62
msgid "Program received a segfault"
msgstr ""
#: src/main.c:81
#, c-format
msgid "Failed to access paths (%s)"
msgstr ""
#: src/main.c:89
msgid "Failed to lock, mc is already running"
msgstr ""
#: src/main.c:92
msgid "Failed to lock, did you mess up your directory permissions?"
msgstr ""
#: src/main.c:101
#, c-format
msgid "%s: command failed"
msgstr ""
#: src/main.c:105
#, c-format
msgid "%s: command successful"
msgstr ""
#: src/main.c:109
#, c-format
msgid "MatterLinux Configuration Manager (%s)"
msgstr ""
#: src/main.c:110
msgid "Different operations are done using different commands\n"
msgstr ""
#: src/main.c:113
msgid "pull down a configuration"
msgstr ""
#: src/main.c:116
msgid "build the configuration in the current directory"
msgstr ""
#: src/main.c:118
msgid ""
"Licensed under GPLv3, see <https://www.gnu.org/licenses/> for more "
"information"
msgstr ""
#: src/pull.c:28
msgid "Please specify a config name or a URL"
msgstr ""
#: src/pull.c:69
#, c-format
msgid "Cloning %s"
msgstr ""
#: src/pull.c:74
#, c-format
msgid "Failed to clone the %s:"
msgstr ""
#: src/pull.c:85
#, c-format
msgid "Failed to chdir to %s"
msgstr ""
#: src/pull.c:98
msgid "Do you want to continue?"
msgstr ""
#: src/pull.c:104
msgid "Checking all the targets"
msgstr ""
#: src/pull.c:110
#, c-format
msgid "Failed to access the source for the target \"%s\""
msgstr ""
#: src/pull.c:119
msgid "All the target checks were successful"
msgstr ""
#: src/pull.c:130
msgid "Install the target?"
msgstr ""
#: src/pull.c:131
msgid "Skipping target"
msgstr ""
#: src/pull.c:169
msgid "Installing all the requirements"
msgstr ""
#: src/pull.c:172
msgid "Failed to run the mp-install command"
msgstr ""
#: src/target.c:15
msgid "Configuration target is missing a name"
msgstr ""
#: src/target.c:20
#, c-format
msgid "Configuration target \"%s\" does not have \"dst\" field"
msgstr ""
#: src/target.c:25
#, c-format
msgid "Configuration target \"%s\" does not have \"src\" field"
msgstr ""
#: src/target.c:40
#, c-format
msgid "Failed to open the directory: %s"
msgstr ""
#: src/target.c:84
#, c-format
msgid "Source directory \"%s\" does not exist"
msgstr ""
#: src/target.c:121
msgid "Target details:\n"
msgstr ""
#: src/target.c:123
msgid "Description"
msgstr ""
#: src/url.c:44
msgid "Failed to open /dev/null"
msgstr ""
#: src/url.c:51
msgid "Failed to init curl"
msgstr ""
#: src/url.c:63
msgid "Request failed"
msgstr ""
#: src/url.c:70
msgid "Failed to get the response code"
msgstr ""
#: src/url.c:76
msgid "Response is not a redirect"
msgstr ""
#: src/url.c:83
msgid "Failed to get the location header"
msgstr ""
#: src/url.c:89
msgid "Invalid location header"
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 ""

View File

@ -1,8 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "args.h"
#include "util.h"
args_t args;
void args_add_name(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));
void args_load(int argc, char *argv[]) {
args.count = argc;
args.list = argv;
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 = 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;
}
void args_set_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;
}
args_add_value(args, value);
}
bool args_split(args_t *args, char *name) {
char *value = NULL;
for (int i = 0; i < args->count; i++) {
if (NULL == args->list[i].name || !eq(args->list[i].name, name))
continue;
value = args->list[i].value;
args->list[i].value = NULL;
break;
}
if (NULL == value)
return false;
args_add_value(args, value);
return true;
}
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_name(args, argv[i] + 2);
else
args_set_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;
}

View File

@ -1,9 +1,20 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
typedef struct Args {
int count;
char **list;
typedef struct arg {
char *name;
char *value;
} arg_t;
typedef struct args {
arg_t *list;
size_t count;
} args_t;
extern args_t args;
void args_load(int, char *[]);
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);
bool args_split(args_t *args, char *name);
void args_free(args_t *args);

18
src/cmd.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <libmp/all.h>
#include <stdbool.h>
#include "args.h"
#include "ctx.h"
typedef bool (*cmd_func_t)(ctx_t *ctx, args_t *args);
typedef struct cmd {
char *name;
char *desc;
cmd_func_t func;
bool lock;
} cmd_t;
bool cmd_pull(ctx_t *ctx, args_t *args);
bool cmd_gen(ctx_t *ctx, args_t *args);

View File

@ -1,34 +1,49 @@
#include "gen.h"
#include "args.h"
#include "config.h"
#include "error.h"
#include "intl.h"
#include "log.h"
#include "util.h"
#include "../args.h"
#include "../cmd.h"
#include "../config.h"
#include "../error.h"
#include "../intl.h"
#include "../log.h"
#include "../util.h"
#include <unistd.h>
bool gen_cmd() {
bool cmd_gen(ctx_t *ctx, args_t *args) {
bool ret = false;
char *dir = NULL;
config_t cfg;
if (args.count != 2) {
error(_("Please specify a directory for the repository"));
return ret;
for (size_t i = 0; i < args->count; i++) {
if (NULL != args->list[i].name || eq(args->list[i].value, "gen"))
continue;
if (NULL == dir) {
dir = args->list[i].value;
continue;
}
error(_("Please specify only a signle directory for the repository"));
return false;
}
if (!exists(args.list[1]) || !is_dir(args.list[1])) {
if (NULL == dir) {
error(_("Please specify a directory for the repository"));
return false;
}
if (!exists(dir) || !is_dir(dir)) {
error(_("Failed to access the directory"));
return ret;
}
if (chdir(args.list[1]) < 0) {
if (chdir(dir) < 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):"));
if (!config_load(ctx, &cfg, "confer.ini")) {
error(_("Failed to load the configuration file (confer.ini):"));
details(errch);
return ret;
}

View File

@ -1,12 +1,11 @@
#include "pull.h"
#include "args.h"
#include "config.h"
#include "error.h"
#include "log.h"
#include "paths.h"
#include "run.h"
#include "url.h"
#include "util.h"
#include "../args.h"
#include "../cmd.h"
#include "../config.h"
#include "../error.h"
#include "../log.h"
#include "../run.h"
#include "../url.h"
#include "../util.h"
#include <git2.h>
#include <git2/global.h>
@ -23,41 +22,54 @@ int pull_progress(const git_indexer_progress *stats, void *data) {
return 0;
}
bool pull_cmd() {
if (args.count != 2) {
bool cmd_pull(ctx_t *ctx, args_t *args) {
char *repo_url = NULL, *repo_root = NULL, *url = NULL;
config_t repo_cfg = {.name = NULL};
bool ret = false;
for (size_t i = 0; i < args->count; i++) {
if (NULL != args->list[i].name || eq(args->list[i].value, "pull"))
continue;
if (NULL == url) {
url = args->list[i].value;
continue;
}
error(_("Please specify only a single config name or a URL"));
return false;
}
if (NULL == url) {
error(_("Please specify a config name or a URL"));
return false;
}
char *repo_url = NULL, *repo_root = NULL;
config_t repo_cfg = {.name = NULL};
bool ret = false;
if (url_is_local(args.list[1])) {
repo_root = args.list[1];
if (url_is_local(url)) {
repo_root = url;
goto COPY;
}
else if (url_is_name(args.list[1]))
repo_url = url_complete(args.list[1]);
else if (url_is_name(url))
repo_url = url_complete(url);
else
repo_url = url_ensure_protocol(args.list[1]);
repo_url = url_ensure_protocol(url);
if (NULL == repo_url) {
switch (errno) {
case UrlReqBadCode:
error("Specified configuration is not found");
error(_("Specified configuration is not found"));
break;
default:
error("Failed to access the URL");
error(_("Failed to access the URL"));
details(errch);
}
goto END;
}
rmrf(mc_tmp_path);
repo_root = mc_tmp_path;
rmrf(ctx->tmp_path);
repo_root = ctx->tmp_path;
git_libgit2_init();
@ -86,7 +98,7 @@ COPY:
goto END;
}
if (!config_load(&repo_cfg, "mc.cfg")) {
if (!config_load(ctx, &repo_cfg, "mc.cfg")) {
error(_("Failed to load the configuration file (mc.cfg):"));
details(errch);
goto END;

View File

@ -1,14 +1,20 @@
#include <ini.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "ctx.h"
#include "error.h"
#include "intl.h"
#include "log.h"
#include "paths.h"
#include "util.h"
struct __config_args {
config_t *config;
ctx_t *ctx;
};
bool config_contains_target(config_t *config, char *name) {
target_t *cur = config->t_last;
while (cur) {
@ -70,7 +76,9 @@ int config_handler(void *data, const char *section, const char *key, const char
if (strlen(section) == 0)
return 1;
config_t *config = data;
struct __config_args *args = data;
config_t *config = args->config;
ctx_t *ctx = args->ctx;
if (MATCH("details", "name")) {
config->name = strdup(value);
@ -90,7 +98,6 @@ 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;
@ -103,9 +110,9 @@ int config_handler(void *data, const char *section, const char *key, const char
config->t_last->desc = strdup(value);
return 1;
} else if (MATCHKEY("dst")) {
int len = strlen(value) + strlen(mc_root) + 2;
int len = strlen(value) + strlen(ctx->home_path) + 2;
config->t_last->dst = malloc(len);
join(config->t_last->dst, mc_root, value);
join(config->t_last->dst, ctx->home_path, value);
return 1;
} else if (MATCHKEY("src")) {
config->t_last->src = strdup(value);
@ -149,22 +156,22 @@ void config_free(config_t *config) {
clist_init(&config->keywords);
}
bool config_load(config_t *config, char *path) {
bool config_load(ctx_t *ctx, config_t *config, char *path) {
if (!exists(path) || is_dir(path)) {
error_set(_("Configuration file not found"));
errno = ConfigNotFound;
return false;
}
config->name = NULL;
config->desc = NULL;
config->author = NULL;
config->t_first = NULL;
config->t_last = NULL;
config->t_len = 0;
bzero(config, sizeof(config_t));
clist_init(&config->keywords);
if (ini_parse(path, config_handler, config) < 0) {
struct __config_args args = {
.config = config,
.ctx = ctx,
};
if (ini_parse(path, config_handler, &args) < 0) {
config_free(config);
if (errno != ConfigUnknown || errno != ConfigMultiple) {
error_set(_("Failed to parse configuration file"));
@ -184,12 +191,12 @@ bool config_load(config_t *config, char *path) {
void config_print(config_t *config) {
info(_("Configuration details:\n"));
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Name"), config->name);
printf(FG_BOLD " %s " FG_RESET "=> %s\n", _("Name"), config->name);
if (NULL != config->desc)
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Desc"), config->desc);
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Author"), config->author);
printf(FG_BOLD " %s " FG_RESET "=> %s\n", _("Desc"), config->desc);
printf(FG_BOLD " %s " FG_RESET "=> %s\n", _("Author"), config->author);
printf(COLOR_BOLD " %s " COLOR_RESET "=> ", _("Keywords"));
printf(FG_BOLD " %s " FG_RESET "=> ", _("Keywords"));
for (int i = 0; i < config->keywords.s; i++)
printf("%s ", config->keywords.c[i]);
printf("\n\n");

View File

@ -1,6 +1,7 @@
#pragma once
#include "ctx.h"
#include "target.h"
#include "util.h"
#include <stdbool.h>
#include <stddef.h>
@ -15,6 +16,6 @@ typedef struct config {
clist_t keywords;
} config_t;
bool config_load(config_t *, char *);
void config_free(config_t *);
void config_print(config_t *);
bool config_load(ctx_t *ctx, config_t *config, char *path);
void config_free(config_t *config);
void config_print(config_t *config);

33
src/ctx.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "ctx.h"
#include "util.h"
bool ctx_init(ctx_t *ctx, char *homedir) {
bzero(ctx, sizeof(ctx_t));
if (NULL == homedir)
return false;
size_t home_len = strlen(homedir);
ctx->dir_path = malloc(home_len + 20);
ctx->tmp_path = malloc(home_len + 25);
ctx->lock_path = malloc(home_len + 25);
ctx->home_path = strdup(homedir);
join(ctx->dir_path, homedir, ".local/share/mc");
join(ctx->lock_path, ctx->dir_path, "lock");
join(ctx->tmp_path, ctx->dir_path, "tmp");
return true;
}
void ctx_free(ctx_t *ctx) {
free(ctx->dir_path);
free(ctx->tmp_path);
free(ctx->lock_path);
free(ctx->home_path);
bzero(ctx, sizeof(ctx_t));
}

12
src/ctx.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <stdbool.h>
typedef struct ctx {
char *home_path;
char *lock_path;
char *tmp_path;
char *dir_path;
} ctx_t;
bool ctx_init(ctx_t *ctx, char *homedir);
void ctx_free(ctx_t *ctx);

View File

@ -1,23 +0,0 @@
#include "env.h"
#include <pwd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
char *env_mc_root() {
char *env = getenv("MC_ROOT");
if (env == NULL) {
struct passwd *pw = getpwuid(getuid());
return pw->pw_dir;
}
return env;
}
bool env_mc_yes() {
return NULL != getenv("MC_YES");
}
bool env_mc_debug() {
return NULL != getenv("MC_DEBUG");
}

View File

@ -1,6 +0,0 @@
#pragma once
#include <stdbool.h>
char *env_mc_root();
bool env_mc_yes();
bool env_mc_debug();

View File

@ -1,4 +0,0 @@
#pragma once
#include <stdbool.h>
bool gen_cmd();

View File

@ -4,14 +4,14 @@
#include <fcntl.h>
#include <unistd.h>
lock_st lock() {
if (exists(mc_lock_path))
lock_st lock(char *lock_path) {
if (exists(lock_path))
return ALREADY_LOCKED;
if (creat(mc_lock_path, 0600) == -1)
if (creat(lock_path, 0600) == -1)
return LOCK_ERROR;
return LOCK_SUCCESS;
}
void unlock() {
unlink(mc_lock_path);
void unlock(char *lock_path) {
unlink(lock_path);
}

View File

@ -5,5 +5,5 @@ typedef enum lock_state {
LOCK_ERROR = 3,
} lock_st;
lock_st lock();
void unlock();
lock_st lock(char *lock_path);
void unlock(char *lock_path);

View File

@ -1,5 +1,4 @@
#include "log.h"
#include "env.h"
#include "intl.h"
#include "util.h"
@ -54,18 +53,18 @@ bool bar(float cur, float max) {
return true;
lastprog = prog;
printf("\r" COLOR_BOLD "[");
printf("\r" FG_BOLD "[");
for (int i = 0; i < prog; i++) {
printf("#");
}
printf(COLOR_BLUE "#" COLOR_RESET COLOR_BOLD);
printf(FG_BLUE "#" FG_RESET FG_BOLD);
for (int i = prog; i < size; i++) {
printf(" ");
}
printf("]" COLOR_RESET);
printf("]" FG_RESET);
printf(COLOR_BOLD COLOR_BLUE "%s" COLOR_RESET "\r", perc);
printf(FG_BOLD FG_BLUE "%s" FG_RESET "\r", perc);
return true;
}
@ -73,9 +72,9 @@ void info(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_BLUE ">>> " COLOR_RESET COLOR_BOLD);
printf(FG_BOLD FG_BLUE ">>> " FG_RESET);
vprintf(msg, args);
printf(COLOR_RESET "\n");
printf(FG_RESET "\n");
va_end(args);
}
@ -84,9 +83,9 @@ void error(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_RED ">>> " COLOR_RESET COLOR_BOLD);
printf(FG_BOLD FG_RED ">>> " FG_RESET);
vprintf(msg, args);
printf(COLOR_RESET "\n");
printf(FG_RESET "\n");
va_end(args);
}
@ -95,9 +94,9 @@ void details(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(" " COLOR_RESET);
printf(" " FG_RESET);
vprintf(msg, args);
printf(COLOR_RESET "\n");
printf(FG_RESET "\n");
va_end(args);
}
@ -106,23 +105,9 @@ void success(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_GREEN ">>> " COLOR_RESET COLOR_BOLD);
printf(FG_BOLD FG_GREEN ">>> " FG_RESET);
vprintf(msg, args);
printf(COLOR_RESET "\n");
va_end(args);
}
void debug(const char *msg, ...) {
if (!env_mc_debug())
return;
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_MAGENTA "DEBUG: " COLOR_RESET COLOR_BOLD);
vprintf(msg, args);
printf(COLOR_RESET "\n");
printf(FG_RESET "\n");
va_end(args);
}
@ -131,17 +116,14 @@ void input(const char *msg, ...) {
va_list args;
va_start(args, msg);
printf(COLOR_BOLD COLOR_CYAN ">>> " COLOR_RESET COLOR_BOLD);
printf(FG_BOLD FG_CYAN ">>> " FG_RESET);
vprintf(msg, args);
printf(COLOR_RESET);
printf(FG_RESET);
va_end(args);
}
bool yesno(const char *msg) {
if (env_mc_yes())
return true;
char *yes[] = {_("y"), _("Y")};
char *no[] = {_("n"), _("N")};

View File

@ -1,14 +1,14 @@
#pragma once
#include <stdbool.h>
#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"
#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_MAGENTA "\x1b[35m"
#define FG_UNDERLINE "\x1b[4m"
#define FG_RESET "\x1b[0m"
void bar_init();
bool bar(float, float);
@ -18,6 +18,5 @@ 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

@ -22,6 +22,7 @@
// clang-format on
#include <libmp/util.h>
#include <locale.h>
#include <signal.h>
#include <stdbool.h>
@ -30,92 +31,100 @@
#include <string.h>
#include "args.h"
#include "gen.h"
#include "cmd.h"
#include "ctx.h"
#include "intl.h"
#include "lock.h"
#include "log.h"
#include "paths.h"
#include "pull.h"
#include "util.h"
typedef bool (*cmd)();
struct CmdMap {
char *name;
bool lock;
cmd func;
};
ctx_t ctx;
struct CmdMap cmdmap[] = {
{.name = "mc-pull", .lock = true, .func = pull_cmd},
{.name = "mc-gen", .lock = false, .func = gen_cmd },
};
void handler_int(int sig){
unlock();
printf("\e[?25h");
exit(1);
}
void handler_seg(int sig){
unlock();
printf("\e[?25h");
error(_("Program received a segfault"));
void handler(int sig){
unlock(ctx.lock_path);
printf("\e[?25h\n");
if(SIGSEGV == sig)
error(_("Program received a segfault"));
exit(1);
}
int main(int argc, char *argv[]) {
signal(SIGINT, handler_int);
signal(SIGSEGV, handler_seg);
signal(SIGINT, handler);
signal(SIGSEGV, handler);
setbuf(stdout, NULL);
setlocale(LC_ALL, "");
textdomain("mc");
textdomain("confer");
for (int i = 0; i < sizeof(cmdmap) / sizeof(struct CmdMap); i++) {
if (strcmp(argv[0], cmdmap[i].name) != 0)
cmd_t commands[] = {
{.name = "pull", .lock = true, .desc = _("pull down a configuration"), .func = cmd_pull },
{.name = "gen", .lock = false, .desc = _("build the configuration in the current directory"), .func = cmd_gen },
};
args_t *args = NULL;
char *homedir = NULL;
bool ret = false;
args = args_parse(argc, argv);
if (args->count <= 0 || args->list[0].name != NULL)
goto help;
if((homedir = args_get_string(args, "home")) == NULL)
homedir = getenv("HOME");
if(!ctx_init(&ctx, homedir)){
error(_("Please specify the homedir with "FG_BOLD"--home"FG_RESET" option or specify the "FG_BOLD"HOME"FG_RESET" environment variable"));
goto end;
}
for (int i = 0; i < sizeof(commands) / sizeof(cmd_t); i++) {
if (!eq(commands[i].name, args->list[0].value))
continue;
args_load(argc, argv);
if(!paths_load()){
error(_("Failed to access paths (%s)"), mc_dir);
return EXIT_FAILURE;
}
if (cmdmap[i].lock) {
int st = lock();
switch (st) {
if (commands[i].lock) {
switch (lock(ctx.lock_path)) {
case ALREADY_LOCKED:
error(_("Failed to lock, mc is already running"));
return EXIT_FAILURE;
error(_("Failed to lock, confer is already running"));
goto end;
case LOCK_ERROR:
error(_("Failed to lock, did you mess up your directory permissions?"));
return EXIT_FAILURE;
error(_("Failed to lock, are you root?"));
goto end;
default:
break;
}
}
bool ret = cmdmap[i].func();
unlock();
if (!ret) {
error(_("%s: command failed"), cmdmap[i].name);
return EXIT_FAILURE;
}
success(_("%s: command successful"), cmdmap[i].name);
return EXIT_SUCCESS;
ret = commands[i].func(&ctx, args);
goto end;
}
info(_("MatterLinux Configuration Manager (%s)"), VERSION);
info(_("Different operations are done using different commands\n"));
error(_("Command not found: " FG_BOLD "%s"), args->list[0].value);
help:
info(_("MatterLinux configuration manager (version %s)"), VERSION);
info(_("Usage: " FG_BOLD "%s [command] <options> <arguments>"), argv[0]);
printf("\n");
info(_("Here is a list of available commands:"));
printf(COLOR_BOLD " mc-pull" COLOR_RESET ": ");
printf(" %s\n", _("pull down a configuration"));
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");
printf(COLOR_BOLD " mc-gen" COLOR_RESET ": ");
printf(" %s\n\n", _("build the configuration in the current directory"));
info(_("Here is a list of available options:"));
info(_("Licensed under GPLv3, see <https://www.gnu.org/licenses/> for more "
"information"));
return EXIT_SUCCESS;
printf(
_(" " FG_BOLD "--yes" FG_RESET ":\t skip the confirmation\n"));
printf(_(" " FG_BOLD "--home" FG_RESET ":\t path to your home directory\n\n"));
info(_("Licensed under GPLv3, see https://www.gnu.org/licenses/ for more information"));
ret = true;
end:
unlock(ctx.lock_path);
args_free(args);
ctx_free(&ctx);
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -1,32 +0,0 @@
#include <string.h>
#include <sys/stat.h>
#include "env.h"
#include "paths.h"
#include "util.h"
char *mc_lock_path;
char *mc_tmp_path;
char *mc_root;
char *mc_home;
char *mc_dir;
char *append_root(char *pth) {
char fp[strlen(mc_root) + strlen(pth) + 10];
join(fp, mc_root, pth);
return strdup(fp);
}
bool paths_load() {
mc_root = env_mc_root();
if (!exists(mc_root) || !is_dir(mc_root))
return false;
mc_dir = append_root(MC_DIR);
mc_lock_path = append_root(LOCK_PATH);
mc_tmp_path = append_root(TMP_PATH);
if (!mksubdirsp(mc_dir, 0700))
return false;
return true;
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <stdbool.h>
#define MC_DIR ".local/share/mc"
#define TMP_PATH MC_DIR "/tmp"
#define LOCK_PATH MC_DIR "/lock"
bool paths_load();
extern char *mc_lock_path;
extern char *mc_tmp_path;
extern char *mc_root;
extern char *mc_dir;

View File

@ -1,4 +0,0 @@
#pragma once
#include <stdbool.h>
bool pull_cmd();

View File

@ -1,26 +0,0 @@
#include "log.h"
#include "util.h"
#include <git2.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TMP_PATH "/tmp/confer"
char *repo_clone(char *url) {
git_libgit2_init();
git_repository *repo = NULL;
int random = randint(100, 999);
char path[strlen(TMP_PATH) + 4];
sprintf(path, "%s_%d", TMP_PATH, random);
if (git_clone(&repo, url, path, NULL) != 0) {
error("Failed to clone the repository: " COLOR_RESET "%s", git_error_last()->message);
return NULL;
}
git_libgit2_shutdown();
return strdup(path);
}

View File

@ -1 +0,0 @@
char *repo_clone(char *);

View File

@ -56,6 +56,8 @@ bool run_cmd_root(char *cmd, char **args) {
return false;
RUN:
errno = 0;
int arg_count = 0;
while (args[arg_count] != NULL)
arg_count++;

View File

@ -119,7 +119,7 @@ void target_free(target_t *t) {
void target_print(target_t *t) {
info(_("Target details:\n"));
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Name"), t->name);
printf(COLOR_BOLD " %s " COLOR_RESET "=> %s\n", _("Description"), t->desc);
printf(FG_BOLD " %s " FG_RESET "=> %s\n", _("Name"), t->name);
printf(FG_BOLD " %s " FG_RESET "=> %s\n", _("Description"), t->desc);
printf("\n");
}

View File

@ -18,16 +18,6 @@ bool eq(char *s1, char *s2) {
return strcmp(s1, s2) == 0;
}
bool joinhome(char *res, char *path) {
char *homedir = getenv("HOME");
if (NULL == homedir)
return false;
snprintf(res, PATH_MAX, "%s/%s", homedir, path);
return true;
}
bool exists(char *path) {
return access(path, F_OK) == 0;
}

View File

@ -10,7 +10,6 @@ typedef struct clist {
bool eq(char *, char *);
bool exists(char *);
char *check_path(char *);
bool joinhome(char *, char *);
bool startswith(char *, char *);
bool endswith(const char *, const char *);
int join(char *, const char *, const char *);