From 30b1ced97d655f888bb2d7dde6e58131ffa72822 Mon Sep 17 00:00:00 2001 From: Ivan Yarcev Date: Thu, 6 Jul 2023 11:43:15 +0600 Subject: [PATCH] Repomanager back --- ubl-settings-repo-back/Makefile | 146 ++++++++++++++++++ .../com.ublinux.ubl-settings-repo-back.policy | 24 +++ ubl-settings-repo-back/source/CMakeLists.txt | 31 ++++ .../source/ubl-settings-repo-back.c | 141 +++++++++++++++++ .../source/ubl-settings-repo-back.h | 32 ++++ ubl-settings-repo-back/source/ubl-strings.h | 1 + ubl-settings-repo-back/ubl-settings-repo-back | Bin 0 -> 21832 bytes 7 files changed, 375 insertions(+) create mode 100644 ubl-settings-repo-back/Makefile create mode 100644 ubl-settings-repo-back/com.ublinux.ubl-settings-repo-back.policy create mode 100644 ubl-settings-repo-back/source/CMakeLists.txt create mode 100644 ubl-settings-repo-back/source/ubl-settings-repo-back.c create mode 100644 ubl-settings-repo-back/source/ubl-settings-repo-back.h create mode 100644 ubl-settings-repo-back/source/ubl-strings.h create mode 100755 ubl-settings-repo-back/ubl-settings-repo-back diff --git a/ubl-settings-repo-back/Makefile b/ubl-settings-repo-back/Makefile new file mode 100644 index 0000000..f84e9df --- /dev/null +++ b/ubl-settings-repo-back/Makefile @@ -0,0 +1,146 @@ +#!/usr/bin/make -f + +#SHELL := /bin/bash +MAKEFILE_FILEPATH := $(abspath $(lastword $(MAKEFILE_LIST))) +MAKEFILE_DIR := $(notdir $(patsubst %/,%,$(dir $(MAKEFILE_FILEPATH)))) +MAKEFILE_PATH := $(dir $(MAKEFILE_FILEPATH)) + +CMAKE_COMMAND = cmake +CMAKE_SOURCE_DIR = $(MAKEFILE_PATH)source +CMAKE_BUILD_DIR = $(MAKEFILE_PATH)compile +#CMAKE_SOURCE_DIR = ./source +#CMAKE_BUILD_DIR = ./compile +DEPENDS = /bin/cmake +PREFIX ?= /usr +PKGNAME = $(MAKEFILE_DIR) +#PKGNAME = ubl-settings-manager +LATEST_TAG= +default_target: all + +.PHONY: all init depend debug prepare check build uninstall install clean help + +all: init build + +init: + @echo "Initialize ..."; \ + if [ -d ".git" ]; then \ + LATEST_TAG=$$(git describe --tags | sed 's/^v//'|grep -oE "^[0-9]{1,}.[0-9]{1,}"); \ + else \ + LATEST_TAG="0.0"; \ + fi; \ + sed -r "s/^(string version_application).*/\1=\"$${LATEST_TAG}\";/" -i source/${PKGNAME}.h; \ + echo "-- Build path: ${CMAKE_BUILD_DIR}" + +depend: + @echo "Check depends ..." + @for FILE_DEPEND in $(DEPENDS); do \ + if [ ! -f $${FILE_DEPEND} ]; then \ + echo "ERROR: Depend '$${FILE_DEPEND}' not found !"; \ + exit 1; \ + fi; \ + done; \ + echo "Check depends: OK" +# $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 + +debug: init build + @echo "Debug ..."; \ + if [ ! -d ${CMAKE_BUILD_DIR} ]; then \ + $(CMAKE_COMMAND) -S${CMAKE_SOURCE_DIR} -B${CMAKE_BUILD_DIR} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="${PREFIX}"; \ + fi; \ + echo "${CMAKE_BUILD_DIR}/${PKGNAME}"; \ + cp ${CMAKE_BUILD_DIR}/${PKGNAME} ./; \ + echo "Debug: OK" + +prepare: + @echo "Prepare ..."; \ + if [ ! -d ${CMAKE_BUILD_DIR} ]; then \ + $(CMAKE_COMMAND) -S${CMAKE_SOURCE_DIR} -B${CMAKE_BUILD_DIR} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="${PREFIX}"; \ + fi; \ + echo "Prepare: OK" + +check: + @echo "Check ..."; \ + if [ -f ${CMAKE_BUILD_DIR}/${PKGNAME} ]; then \ + echo "Check: OK"; \ + else \ + echo "Check: ${CMAKE_BUILD_DIR}/${PKGNAME} not found !"; \ + exit 1; \ + fi + +build: depend prepare + @echo "Build ..."; \ + make --directory=${CMAKE_BUILD_DIR}; \ + echo "Build: OK" + +uninstall: + @echo "Uninstall ..." + @for FILE_PO in $(wildcard *.po); do \ + LANG=$${FILE_PO##*_};LANG=$${LANG%.*}; \ + FILE_MO=$${FILE_PO##*/}; FILE_MO="$${FILE_MO%_*.po}.mo"; \ + PATH_FILE_MO="${DESTDIR}${PREFIX}/share/locale/$${LANG}/LC_MESSAGES/$${FILE_MO}"; \ + $(RM) "$${PATH_FILE_MO}"; \ + done + @$(RM) "${DESTDIR}${PREFIX}/bin/${PKGNAME}" + @$(RM) "${DESTDIR}${PREFIX}/share/polkit-1/actions/com.ublinux.${PKGNAME}.policy" + @if [ -z ${DESTDIR} ]; then \ + [ -d "${DESTDIR}${PREFIX}/share/icons/hicolor/" ] && gtk-update-icon-cache -fiq "${DESTDIR}${PREFIX}/share/icons/hicolor/" &>/dev/null || true; \ + update-desktop-database --quiet &>/dev/null || true; \ + [ -d "${DESTDIR}${PREFIX}/share/applications" ] && touch "${DESTDIR}${PREFIX}/share/applications" &>/dev/null || true; \ + fi + @echo "Uninstall: OK" + +install: check uninstall + @echo "Install ..." +#################################################### УДАЛИТЬ ПЕРЕД КОММИТОМ ################################################################################ + @gcc source/ubl-settings-repo-back.c source/ubl-settings-repo-back.h source/ubl-strings.h -o ubl-settings-repo-back `pkg-config --cflags --libs gtk+-3.0 vte-2.91 webkit2gtk-4.0 webkit2gtk-web-extension-4.0` -g +#################################################### УДАЛИТЬ ПЕРЕД КОММИТОМ ################################################################################ + @for FILE_PO in $(wildcard *.po); do \ + LANG=$${FILE_PO##*_};LANG=$${LANG%.*}; \ + install -dm755 "${DESTDIR}${PREFIX}/share/locale/$${LANG}/LC_MESSAGES"; \ + FILE_MO=$${FILE_PO##*/}; FILE_MO="$${FILE_MO%_*.po}.mo"; \ + PATH_FILE_MO="${DESTDIR}${PREFIX}/share/locale/$${LANG}/LC_MESSAGES/$${FILE_MO}"; \ + echo "$${FILE_PO}"; \ + msgfmt "$${FILE_PO}" -v -f -o "$${PATH_FILE_MO}"; \ + done + @install -dm755 "${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/apps" + @install -dm755 "${DESTDIR}${PREFIX}/share/polkit-1/actions" + @install -Dm644 -t "${DESTDIR}${PREFIX}/share/polkit-1/actions/" "com.ublinux.${PKGNAME}.policy" + @install -Dm755 -t "${DESTDIR}${PREFIX}/bin/" "${CMAKE_BUILD_DIR}/${PKGNAME}" + @install -dm755 "${DESTDIR}/etc/xdg" + @install -dm755 "${DESTDIR}${PREFIX}/share/applications" + @if [ -z ${DESTDIR} ]; then \ + [ -d "${DESTDIR}${PREFIX}/share/icons/hicolor/" ] && gtk-update-icon-cache -fiq "${DESTDIR}${PREFIX}/share/icons/hicolor/" &>/dev/null || true; \ + update-desktop-database --quiet &>/dev/null || true; \ + [ -d "${DESTDIR}${PREFIX}/share/applications" ] && touch "${DESTDIR}${PREFIX}/share/applications" &>/dev/null || true; \ + fi + @echo "Install: OK" + @sed -r "s/^(string version_application=\"*\").*/string version_application;/" -i source/${PKGNAME}.h; \ + +clean: + @echo "Clean ..." + @$(RM) -rd ${CMAKE_BUILD_DIR} + @if [ -d ${CMAKE_BUILD_DIR} ]; then \ + echo "Clean: error, compile directory exist ${CMAKE_BUILD_DIR}"; \ + else \ + echo "Clean: OK"; \ + fi + +up_ver: + @CURRENT=$$(grep 'VERSION' ${FILE_VERSION} | cut -d" " -f2); \ + MAJOR=$$(cut -d. -f1 <<< $${CURRENT}); \ + MINOR=$$(cut -d. -f2 <<< $${CURRENT}); \ + VER="$${MAJOR}.$$(($${MINOR}+1))"; \ + sed "s/VERSION *[[:digit:]]*.*/VERSION $${VER}/" -i ${FILE_VERSION}; \ + echo "Updated version to VERSION.md: $${CURRENT} to $${VER}" + +help: + @echo "The following are some of the valid targets for this Makefile:"; \ + echo "... all (the default if no target is provided)"; \ + echo "... init"; \ + echo "... debug"; \ + echo "... prepare"; \ + echo "... compile"; \ + echo "... install"; \ + echo "... uninstall"; \ + echo "... clean"; \ + echo "... up_ver" diff --git a/ubl-settings-repo-back/com.ublinux.ubl-settings-repo-back.policy b/ubl-settings-repo-back/com.ublinux.ubl-settings-repo-back.policy new file mode 100644 index 0000000..2dd9623 --- /dev/null +++ b/ubl-settings-repo-back/com.ublinux.ubl-settings-repo-back.policy @@ -0,0 +1,24 @@ + + + + + UBLinux + https://ublinux.ru + + + Run ubl-settings-repo-back as root + Запуск утилиты ubl-settings-repo-back с правами root + Authentication is required to run ubl-settings-repo-back + Требуется авторизация для запуска утилиты ubl-settings-repo-back с правами root + + auth_admin + auth_admin + auth_admin + + /usr/bin/ubl-settings-repo-back + true + + + diff --git a/ubl-settings-repo-back/source/CMakeLists.txt b/ubl-settings-repo-back/source/CMakeLists.txt new file mode 100644 index 0000000..9ed448b --- /dev/null +++ b/ubl-settings-repo-back/source/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.7) +project(ubl-settings-repo-back) + +find_package(PkgConfig REQUIRED) + +pkg_check_modules(GTK REQUIRED glib-2.0) +include_directories(${GTK_INCLUDE_DIRS}) +link_directories(${GTK_LIBRARY_DIRS}) +add_definitions(${GTK_CFLAGS_OTHER}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Werror -Wmissing-declarations -fdiagnostics-color=always \ + -O2 -pipe -fno-plt -fexceptions \ + -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security \ + -fstack-clash-protection -fcf-protection") + + +set(SOURCE_FILES + ubl-settings-repo-back.c + ubl-settings-repo-back.h + # ubl-strings.h + ) + +set(LIBRARIES + ${GTK_LIBRARIES} + pthread) + + +add_executable(${PROJECT_NAME} ${SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${LIBRARIES}) +target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR}) +install(TARGETS ${PROJECT_NAME} DESTINATION bin) \ No newline at end of file diff --git a/ubl-settings-repo-back/source/ubl-settings-repo-back.c b/ubl-settings-repo-back/source/ubl-settings-repo-back.c new file mode 100644 index 0000000..f8a7dee --- /dev/null +++ b/ubl-settings-repo-back/source/ubl-settings-repo-back.c @@ -0,0 +1,141 @@ +#include "ubl-settings-repo-back.h" + + +dict_simple *yon_dict_new(){ + dict_simple *dict = (dict_simple*)malloc(sizeof(dict_simple)); + dict->first=dict; + dict->next=NULL; + dict->data=NULL; + return dict; +} + +dict_simple *yon_dict_append(dict_simple *dictionary_to_append){ + dict_simple *dict = (dict_simple*)malloc(sizeof(dict_simple)); + dictionary_to_append->next=dict; + dict->first=dictionary_to_append->first; + dict->next=NULL; + dict->data=NULL; + return dict; +} + +repo_operation *yon_operation_new(){ + repo_operation *operation = (repo_operation*)malloc(sizeof(repo_operation)); + operation->package_add=NULL; + operation->package_remove=NULL; + operation->rename=NULL; + operation->target=NULL; + operation->create=0; + return operation; +} + +char *yon_string_append(char *source, char *append){ + int size = (strlen(source)+strlen(append)+2); + char *n_source = (char*)malloc(sizeof(char)*size); + memset(n_source,0,size); + memcpy(n_source,source,strlen(source)); + memcpy(n_source+strlen(source)," ",1); + memcpy(n_source+strlen(source)+1,append,strlen(append)); + return n_source; +} + +char *yon_string_copy(char *string){ + if (string){ + char *str = malloc(sizeof(char)*strlen(string)+1); + memset(str,0,strlen(string)+1); + memcpy(str,string,strlen(string)); + return str; + } else return NULL; +} + +char *yon_string_find_last(char *source, char *find){ + + for (char *found = strstr(source,find);found;found=strstr(found,find)){ + if (found); + } +} + +int yon_repo_proceed(int argc, char *argv[]){ + int option_index=0; + int show_help=0; + { + struct option long_options[] = { + {"repo-new", 1, 0, 1}, + {"package-add", 1, 0, 2}, + {"package-remove", 1, 0, 3}, + {"repo-rename", 1, 0, 4}, + {"origin", 1, 0, 'o'}, + { NULL, 0, NULL, 0 } + }; + dict_simple *dict = yon_dict_new(); + repo_operation *operation = yon_operation_new(); + dict->data=(void*)operation; + #define curpack(dict) ((repo_operation*)dict->data) + for (int i=0;ipackage_add = yon_string_append(curpack(dict)->package_add,yon_string_copy(optarg)); + break; + case 3: curpack(dict)->package_remove = yon_string_append(curpack(dict)->package_add,yon_string_copy(optarg)); + break; + case 4: curpack(dict)->rename=yon_string_copy(optarg); + case 1: + if (!((repo_operation*)dict->data)->target) ((repo_operation*)dict->data)->target=yon_string_copy(optarg); + else { + dict = yon_dict_append(dict); + operation = yon_operation_new(); + dict->data=(void*)operation; + ((repo_operation*)dict->data)->target=yon_string_copy(optarg); + } + ((repo_operation*)dict->data)->create=1; + break; + case 'o': + if (!((repo_operation*)dict->data)->target) ((repo_operation*)dict->data)->target=yon_string_copy(optarg); + else { + dict = yon_dict_append(dict); + operation = yon_operation_new(); + dict->data=(void*)operation; + ((repo_operation*)dict->data)->target=yon_string_copy(optarg); + } + break; + case '?': printf("%s: %c\n",UNKNOWN_ARGUMENT_LABEL,argument); + break; + } + } + for (dict_simple *dct=dict->first;dct;dct=dct->next){ + if (curpack(dct)->target){ + if (curpack(dct)->create){ + GKeyFile *file = g_key_file_new(); + g_key_file_load_from_file(file,"/etc/pacman.conf",G_KEY_FILE_KEEP_COMMENTS,NULL); + g_key_file_set_string(file,curpack(dct)->target,"Server",curpack(dct)->target); + char *command = yon_string_append("repo-add ",curpack(dct)->target); + if (curpack(dct)->package_add){ + command = yon_string_append(command," "); + command = yon_string_append(command,curpack(dct)->package_add); + } + system(command); + + } else if (curpack(dct)->package_remove){ + char *command = yon_string_append("repo-remove ",curpack(dct)->target); + command = yon_string_append(command," "); + command = yon_string_append(command,curpack(dct)->package_remove); + system(command); + } + if (curpack(dct)->package_add){ + char *command = yon_string_append("repo-add ",curpack(dct)->target); + command = yon_string_append(command," "); + command = yon_string_append(command,curpack(dct)->package_add); + } + system(command); + + + } + } + } +} + +int main(int argc, char *argv[]){ + char *local=setlocale(LC_ALL, ""); + textdomain (LocaleName); + yon_repo_proceed(argc, argv); + +} diff --git a/ubl-settings-repo-back/source/ubl-settings-repo-back.h b/ubl-settings-repo-back/source/ubl-settings-repo-back.h new file mode 100644 index 0000000..fcc8d86 --- /dev/null +++ b/ubl-settings-repo-back/source/ubl-settings-repo-back.h @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ubl-strings.h" + +#define LocaleName "ubl-settings-repo-back" + + +#define _(String) gettext(String) + +typedef struct { + char *target; + char *package_add; + char *package_remove; + char *rename; + int create; + +} repo_operation; + +typedef struct { + struct dict_simple *first; + struct dict_simple *next; + void *data; +} dict_simple; + +char *yon_string_append(char *source, char *append); +char *yon_string_copy(char *string); \ No newline at end of file diff --git a/ubl-settings-repo-back/source/ubl-strings.h b/ubl-settings-repo-back/source/ubl-strings.h new file mode 100644 index 0000000..290f02c --- /dev/null +++ b/ubl-settings-repo-back/source/ubl-strings.h @@ -0,0 +1 @@ +#define UNKNOWN_ARGUMENT_LABEL _("Unknown argument has been given") \ No newline at end of file diff --git a/ubl-settings-repo-back/ubl-settings-repo-back b/ubl-settings-repo-back/ubl-settings-repo-back new file mode 100755 index 0000000000000000000000000000000000000000..28783d805f095677b4fd97de885378ea367ccade GIT binary patch literal 21832 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 literal 0 HcmV?d00001