Skip to content
Snippets Groups Projects
Verified Commit 1d4d8117 authored by Volker Schukai's avatar Volker Schukai :alien:
Browse files

fix: setting the paths does not always work smoothly #9

parent 4746b5f3
No related branches found
No related tags found
No related merge requests found
# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL
# DO NOT EDIT THIS FILE MANUALLY
# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix
# AND OPEN A SHELL WITH THE COMMAND devenv shell
#
image: docker-registry.schukai.com:443/nixos-ci-devenv:latest
services:
- docker:dind
variables:
# The repo name as used in
# https://github.com/nix-community/NUR/blob/master/repos.json
......@@ -13,7 +19,6 @@ variables:
DOCKER_DRIVER: overlay2
GIT_DEPTH: 10
stages:
- test
- deploy
......
# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL
# DO NOT EDIT THIS FILE MANUALLY
# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix
# AND OPEN A SHELL WITH THE COMMAND devenv shell
#
# Information about the task runner can be found here:
# https://taskfile.dev
version: '3'
......@@ -5,7 +12,7 @@ version: '3'
tasks:
default:
cmds:
- task --list-all
- task --list
silent: true
test:
......@@ -13,39 +20,40 @@ tasks:
cmds:
- echo "Execute unit tests in Go."
- go test -cover -v ./...
- go test -bench .
- go test -race .
- go test -bench -v ./...
- go test -race -v ./...
test-fuzz:
desc: Conduct fuzzing tests.#
cmds:
- echo "Conduct fuzzing tests."
- go test -v -fuzztime=10s -fuzz=Fuzz ./...
- go test -v -fuzztime=30s -fuzz=Fuzz ./...
add-licenses:
desc: Attach license headers to Go files.
cmds:
- echo "Attach license headers to Go files."
- go install github.com/google/addlicense@latest
- addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go
silent: true
check-licenses:
desc: Check license headers of Go files.
silent: true
cmds:
- go-licenses save "$(get-go-default-packages)" --ignore "gitlab.schukai.com" --force --save_path ${DEVENV_ROOT}/licenses/
check:
desc: Confirm repository status.
cmds:
- git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1)
silent: true
build:
desc: Compile the application,
commit:
desc: Commit changes to the repository.
aliases:
- b
vars:
DEVENV_ROOT:
sh: echo "$DEVENV_ROOT"
- c
- ci
- git-commit
cmds:
- devenv shell build-app
sources:
- source/**/*.go
- source/**/*.mod
- dist/**
- do-git-commit
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true">
<buildTags>
<option name="customFlags">
<array>
<option value="" />
</array>
</option>
</buildTags>
</component>
<module type="JAVA_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/licenses" />
<sourceFolder url="file://$MODULE_DIR$/.devenv/state/go/pkg/mod/github.com/google/addlicense@v1.1.1/testdata/expected" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/.devenv/state/go/pkg/mod/github.com/google/addlicense@v1.1.1/testdata/initial" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
......
{ pkgs, inputs, phps, lib, config, modulesPath, ... }:
{
# https://devenv.sh/packages/
packages = with pkgs; [
inputs.version.defaultPackage."${builtins.currentSystem}"
git
gcc12
go-task
appimage-run
blackbox
blackbox-terminal
jq
coreutils-full
dbeaver
delve
dialog
drill
exa
fd
fd
gcc12
gdlv
wget
git
glab
unixtools.xxd
libffi
zlib
procps
php81Extensions.xdebug
ranger
meld
gnused
coreutils-full
gnugrep
gnumake
util-linux
gnused
go-licenses
go-task
gum
httpie
netcat
hurl
jq
libffi
logrotate
meld
memcached
fd
netcat
nixfmt
procps
ranger
unixtools.xxd
unzip
util-linux
wget
zlib
];
# https://devenv.sh/languages/
# languages.nix.enable = true;
languages = {
go = { enable = true; };
};
languages = { go = { enable = true; }; };
difftastic.enable = true;
scripts.get-go-default-packages.exec = ''
#!${pkgs.bash}/bin/bash
echo $(awk -F ' ' '/^module / { print $2 }' go.mod)
'';
# This script is executed when the app is built
# You can use it to build the app
......@@ -63,7 +74,9 @@ PATH="''${PATH}":${pkgs.procps}/bin/
PATH="''${PATH}":${pkgs.exa}/bin/
PATH="''${PATH}":${pkgs.git}/bin/
PATH="''${PATH}":${pkgs.gnugrep}/bin/
PATH="''${PATH}":${inputs.version.defaultPackage."${builtins.currentSystem}"}/bin/
PATH="''${PATH}":${
inputs.version.defaultPackage."${builtins.currentSystem}"
}/bin/
export PATH
......@@ -85,7 +98,9 @@ PATH="''${PATH}":${pkgs.gnutar}/bin
PATH="''${PATH}":${pkgs.gzip}/bin/
PATH="''${PATH}":${pkgs.exa}/bin/
PATH="''${PATH}":${pkgs.git}/bin/
PATH="''${PATH}":${inputs.version.defaultPackage."${builtins.currentSystem}"}/bin/
PATH="''${PATH}":${
inputs.version.defaultPackage."${builtins.currentSystem}"
}/bin/
export PATH
......@@ -145,5 +160,479 @@ echo "done"
'';
enterShell = ''
cat <<'EOF' > Taskfile.yml
# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL
# DO NOT EDIT THIS FILE MANUALLY
# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix
# AND OPEN A SHELL WITH THE COMMAND devenv shell
#
# Information about the task runner can be found here:
# https://taskfile.dev
version: '3'
tasks:
default:
cmds:
- task --list
silent: true
test:
desc: Execute unit tests in Go.
cmds:
- echo "Execute unit tests in Go."
- go test -cover -v ./...
- go test -bench -v ./...
- go test -race -v ./...
test-fuzz:
desc: Conduct fuzzing tests.#
cmds:
- echo "Conduct fuzzing tests."
- go test -v -fuzztime=30s -fuzz=Fuzz ./...
add-licenses:
desc: Attach license headers to Go files.
cmds:
- echo "Attach license headers to Go files."
- go install github.com/google/addlicense@latest
- addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go
silent: true
check-licenses:
desc: Check license headers of Go files.
silent: true
cmds:
- go-licenses save "$(get-go-default-packages)" --ignore "gitlab.schukai.com" --force --save_path ''${DEVENV_ROOT}/licenses/
check:
desc: Confirm repository status.
cmds:
- git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1)
silent: true
commit:
desc: Commit changes to the repository.
aliases:
- c
- ci
- git-commit
cmds:
- do-git-commit
EOF
cat <<'EOF' > .gitlab-ci.yml
# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL
# DO NOT EDIT THIS FILE MANUALLY
# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix
# AND OPEN A SHELL WITH THE COMMAND devenv shell
#
image: docker-registry.schukai.com:443/nixos-ci-devenv:latest
services:
- docker:dind
variables:
# The repo name as used in
# https://github.com/nix-community/NUR/blob/master/repos.json
NIXOS_VERSION: "23.05"
NIXPKGS_ALLOW_UNFREE: "1"
NIXPKGS_ALLOW_INSECURE: "1"
DOCKER_DRIVER: overlay2
GIT_DEPTH: 10
stages:
- test
- deploy
before_script:
- nix shell nixpkgs#coreutils-full -c mkdir -p /certs/client/
- nix shell nixpkgs#coreutils-full -c ln -fs /etc/ssl/certs/ca-bundle.crt /certs/client/ca.pem
- echo > .env-gitlab-ci
- variables=("HOME=$HOME" "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME" "CI_REPOSITORY_URL=$CI_REPOSITORY_URL" "GITLAB_TOKEN=$GITLAB_TOKEN" "CI_JOB_TOKEN=$CI_JOB_TOKEN" "GITLAB_USER_EMAIL=$GITLAB_USER_EMAIL" "GITLAB_USER_NAME=\"$GITLAB_USER_NAME\"" "CI_REGISTRY_USER=$CI_REGISTRY_USER" "CI_PROJECT_ID=$CI_PROJECT_ID" "CI_PROJECT_DIR=$CI_PROJECT_DIR" "CI_API_V4_URL=$CI_API_V4_URL" "CI_PROJECT_NAME=$CI_PROJECT_NAME" "CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA"); for var in "''${variables[@]}"; do echo "$var" >> .env-gitlab-ci; done
- cat .env-gitlab-ci
after_script:
- if [ -f .env-gitlab-ci ]; then rm .env-gitlab-ci; fi
test:
stage: test
tags:
- nixos
script:
- devenv shell test-lib
cache:
- key: nixos
paths:
- /nix/store
artifacts:
paths:
- dist
deploy:
stage: deploy
tags:
- nixos
script:
- devenv shell -c deploy-lib
when: on_success
cache:
- key: nixos
paths:
- /nix/store
artifacts:
paths:
- dist
EOF
'';
scripts.do-git-commit.exec = ''
#!/usr/bin/env bash
# Define colors if the terminal supports it
if [ -t 1 ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
RESET='\033[0m'
BOLD='\033[1m'
else
RED=""
GREEN=""
RESET=""
fi
step=1
reset
clear
# create random log file
LOGFILE="$(mktemp)"
if [ $? -ne 0 ]; then
echo -e "''${RED}✖ Could not create temporary log file. Exiting.''${RESET}"
exit 1
fi
log_and_display() {
echo -e "''${GREEN}==> $step. $1''${RESET}" | tee -a $LOGFILE
step=$((step + 1))
}
log_error_and_display() {
echo -e "''${RED}==> $step. $1''${RESET}" | tee -a $LOGFILE
}
printLogfileAndExit() {
exit_code=$1
echo -e "\n\n========================================\n\n\n"
echo -e "\n\n''${BOLD}Git and GitLab Automation Script''${RESET}\n\nI have performed the following actions:\n\n"
cat "$LOGFILE"
# Optional: Remove log file
rm -f "$LOGFILE"
if [ $exit_code -eq 0 ]; then
echo -e "\n''${GREEN}✔''${RESET} All actions were successful" | tee -a $LOGFILE
elif [ $exit_code -eq -1 ]; then
echo -e "\n''${RED}✖''${RESET} The script was manually cancelled" | tee -a $LOGFILE
exit_code=0
else
echo -e "\n''${RED}✖''${RESET} Some actions failed" | tee -a $LOGFILE
fi
exit $exit_code
}
print_headline() {
local title=$1
local underline=$(printf '─%.0s' $(seq 1 ''${#title}))
echo -e "\n\n''${BOLD}''${title}\n''${underline}''${RESET}\n"
}
do_cancel() {
echo -e "''${RED}==> ✖ Cancelled.''${RESET}" | tee -a $LOGFILE
printLogfileAndExit -1
}
# Function for unified logging and display
log_action() {
if [ $? -eq 0 ]; then
echo -e " ''${GREEN}✔''${RESET} $1: Successful" | tee -a $LOGFILE
else
echo -e " ''${RED}✖''${RESET} $1: Failed" | tee -a $LOGFILE
printLogfileAndExit 1
fi
}
print_what_to_do() {
echo -e "\n\nWhat do you want to do?\n"
}
git_status=$(git status --porcelain)
if [[ -z "$git_status" ]]; then
log_error_and_display "No changes to commit. Exiting."
printLogfileAndExit 0
fi
print_headline "Choose commit type"
selection=$(gum choose "feat: (new feature for the user, not a new feature for build script)" "fix: (bug fix for the user, not a fix to a build script)" "chore: (updating grunt tasks etc.; no production code change)" "docs: (changes to the documentation)" "style: (formatting, missing semi colons, etc; no production code change)" "refactor: (refactoring production code, eg. renaming a variable)" "test: (adding missing tests, refactoring tests; no production code change)" "Cancel")
commit_type=$(echo "$selection" | awk -F':' '{print $1}')
if [[ "$commit_type" == "Cancel" ]]; then
do_cancel
fi
log_and_display "You chose the commit type: $commit_type"
# NEXT STEP ISSUE HANDLING ############################################################################################################
#log_and_display "Issue handling"
gitlabIssues=()
while IFS= read -r line; do
if [[ $line =~ ^# ]]; then
id=$(echo "$line" | awk '{print substr($1, 2)}')
title=$(echo "$line" | awk -F'about' '{print $1}' | awk '{$1=$2=""; print substr($0, 3)}')
gitlabIssues+=("$id > $title")
fi
done < <(gum spin --spinner dot --show-output --title "Ask gitlab ..." -- glab issue list --output-format=details)
## if issues are available, ask if user wants to use an existing issue or create a new one
createOption="Create new issue"
existingOption="Use existing issue"
cancelOption="Cancel"
print_headline "Choose issue handling"
if [ ''${#gitlabIssues[@]} -eq 0 ]; then
log_and_display "There are no issues available."
print_what_to_do
choice=$(gum choose "$createOption" "$cancelOption")
else
log_and_display "There are ''${#gitlabIssues[@]} issues available."
print_what_to_do
choice=$(gum choose "$createOption" "$existingOption" "$cancelOption")
fi
if [[ "$choice" == "$cancelOption" ]]; then
do_cancel
fi
## array of issue ids
work_on_issue_ids=()
issue_text=""
if [[ "$choice" == "$createOption" ]]; then
print_headline "Create new issue"
issue_text=$(gum input --placeholder "Enter issue title")
echo -e "Enter issue description. ''${RED}End with Ctrl+D''${RESET}\n"
issue_description=$(gum write --placeholder "Enter issue description. End with Ctrl+D")
if [[ -z "$issue_text" ]]; then
log_error_and_display "Issue title is empty. Exiting."
printLogfileAndExit 1
fi
log_and_display "You entered the issue title: $issue_text"
log_and_display "You entered the issue description: $issue_description"
echo -e "\n"
gum confirm "Do you want to create this issue?"
# gum confirm exits with status 0 if confirmed and status 1 if cancelled.
if [ $? -eq 1 ]; then
do_cancel
fi
issue_output=$(glab issue create -t"$issue_text" --no-editor --description "$issue_description")
issue_id=$(echo "$issue_output" | grep -oP '(?<=/issues/)\d+')
work_on_issue_ids+=("$issue_id")
log_action "glab issue with id $issue_id created"
else
print_headline "Use existing issue"
echo -e "Select issue with arrow keys and press tab or space to select. Press enter to confirm.\n"
issue_ids=$(gum choose --no-limit "''${gitlabIssues[@]}")
# assign issue_ids to work_on_issue_ids. iterate over lines and take integer from beginning of line
while IFS= read -r line; do
work_on_issue_ids+=($(echo "$line" | grep -oP '^\d+'))
done <<<"$issue_ids"
fi
if [ ''${#work_on_issue_ids[@]} -eq 0 ]; then
log_and_display "No issue selected. Exiting."
printLogfileAndExit 0
fi
# NEXT STEP COMMIT MESSAGE ############################################################################################################
# print work_on_issue_ids
work_on_issue_ids_string=""
for i in "''${work_on_issue_ids[@]}"; do
work_on_issue_ids_string+="#$i "
done
log_and_display "You chose to work on the following issues: ''${work_on_issue_ids_string}"
print_headline "Check for changes to commit"
# ' ' = unmodified
# M = modified
# T = file type changed (regular file, symbolic link or submodule)
# A = added
# D = deleted
# R = renamed
# C = copied (if config option status.renames is set to "copies")
# U = updated but unmerged
# https://man.freebsd.org/cgi/man.cgi?query=git-status&sektion=1&manpath=freebsd-release-ports
count_all_changes=$(echo "$git_status" | wc -l)
count_staged_changes=$(echo "$git_status" | grep -c '^M')
count_new_staged_files=$(echo "$git_status" | grep -c '^A')
count_staged_changes=$((count_staged_changes + count_new_staged_files))
git_options_all="All $count_all_changes changes"
git_options_staged="Only the $count_staged_changes staged changes"
git_options_select_files="Select files"
git_options_cancel="Cancel"
git_options_array=()
if [[ $count_all_changes -gt 0 ]]; then
git_options_array+=("$git_options_all")
fi
if [[ $count_staged_changes -gt 0 ]]; then
git_options_array+=("$git_options_staged")
fi
git_options_array+=( "$git_options_select_files" )
git_options_array+=( "$git_options_cancel" )
selection=$(gum choose "''${git_options_array[@]}")
if [[ "$selection" == "$git_options_cancel" ]]; then
do_cancel
fi
if [[ "$selection" == "$git_options_all" ]]; then
git add -A
echo "1"
elif [[ "$selection" == "$git_options_select_files" ]]; then
files=()
while IFS= read -r line; do
files+=("$line")
done <<<"$git_status"
selected_files=$(gum choose --no-limit "''${files[@]}")
# no files selected
if [[ -z "$selected_files" ]]; then
log_and_display "No files selected. Exiting."
printLogfileAndExit 0
fi
# add selected files
while IFS= read -r line; do
## git proclimne could have letter, ? or ! at the beginning of the line
file=$(echo "$line" | awk '{print $2}')
if [[ -z "$file" || ! -f "$file" ]]; then
log_and_display "No file found in line: $line"
continue
fi
git add "$file"
done <<<"$selected_files"
fi
## count staged changes again and print
count_staged_changes=$(echo "$git_status" | grep -c '^M')
count_new_staged_files=$(echo "$git_status" | grep -c '^A')
count_staged_changes=$((count_staged_changes + count_new_staged_files))
log_and_display "You have $count_staged_changes staged changes to commit."
# NEXT STEP COMMIT MESSAGE ############################################################################################################
print_headline "Enter commit message"
commit_message=$(gum input --placeholder "Enter commit message" --value "$commit_type: $issue_text $work_on_issue_ids_string")
if [[ -z "$commit_message" ]]; then
log_error_and_display "Commit message is empty. Exiting."
printLogfileAndExit 1
fi
log_and_display "You entered the commit message: $commit_message"
gum confirm "Do you want to commit with this message?"
if [ $? -eq 1 ]; then
do_cancel
fi
# NEXT STEP COMMIT ####################################################################################################################
print_headline "Committing changes"
if ! git commit -m "$commit_message" ; then
log_error_and_display "Commit failed. Exiting."
printLogfileAndExit 1
fi
log_and_display "Commit successful."
# NEXT STEP PUSH ######################################################################################################################
print_headline "Pushing changes"
if ! git push ; then
log_error_and_display "Push failed. Exiting."
printLogfileAndExit 1
fi
log_and_display "Push successful."
# Close issue ######################################################################################################################
print_headline "Closing issues"
for issue_id in "''${work_on_issue_ids[@]}"; do
gum confirm "Do you want to close issue #$issue_id?"
if [ $? -eq 1 ]; then
continue
fi
if ! glab issue close "$issue_id" ; then
log_error_and_display "Closing issue $issue_id failed. Exiting."
else
log_and_display "Closing issue $issue_id successful."
fi
done
printLogfileAndExit 0
'';
}
......@@ -66,6 +66,26 @@ gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.3.1 h1:oyElaqEiyr2Xg
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.3.1/go.mod h1:UvdD4NAf3gLKYafabJD7e9ZCOetzM9JZ9y4GkZukPVU=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.2 h1:R+dL2NJCM+AQNPK4DPDmfvx1eomi1Xb1dl0XKEFj7Ek=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.2/go.mod h1:UvdD4NAf3gLKYafabJD7e9ZCOetzM9JZ9y4GkZukPVU=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.3 h1:pl5XnGS6lxBCI98pnqNU0D0qt19X7g7/Qf/ycM4Do44=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.5.3/go.mod h1:0vlu9GwsHHuFTm49FSOs60UN3KDgcrcfDeCxsG3Ygyg=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.6.0 h1:1edcW7HB2VvTqzFUEGnnJih316sJvBvwGxBwMP8m3ho=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.6.0/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.0 h1:ReofKz+Ys4d2l4y4Whwfbtj7CQPEL1ew46QTf1kPW7A=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.0/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.1 h1:NRlSHy8DlWhkmZkHzjjdPj7hQMrpL8K8V9an9JW9UAk=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.2 h1:LF9b1UiWpShxld9Re4VnvkRt3oi3KqTqpSaU21F9tKg=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.7.2/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.0 h1:jG/kDUsBgaqIHLoMiF4cJA627neqf9BwaoKFMaMMB6U=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.0/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1 h1:A3KvLvu4rV3OstgEn6xHulhQaXawVvzFzbafYHWHUfs=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.2 h1:Gs06CcP/pvywyO86dAsv2fmJfwPoJrTjN9fX7CqT/54=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.8.2/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.0 h1:YJHX4IDO+1c+AufidfYBcfZA8OlvLsqs8K9Hq4R8icY=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.0/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.1 h1:WpM6PcFqQZWPBGDEuMILWHq98dPVBLAxi8ae9QMWWbM=
gitlab.schukai.com/oss/libraries/go/utilities/pathfinder v0.9.1/go.mod h1:MqCBFv7DXKoBE2rZDc51LGvl2QI7Kz0D+XkQ0izj+ws=
gitlab.schukai.com/oss/libraries/go/utilities/watch v0.1.0 h1:FAKHmf9p3NKyzuM0cIXYBxmhdQ7zJ+6wj5qqeoIMbGc=
gitlab.schukai.com/oss/libraries/go/utilities/watch v0.1.0/go.mod h1:tMFl68peRKHgFQLltrTN3JLredofMqvGi3C0SEAj73Y=
gitlab.schukai.com/oss/libraries/go/utilities/watch v0.2.0 h1:tLjN9Wyv+LJhtiiQDzdzaDelEq2LVCDP3Ndo7ZPIWfQ=
......
......@@ -6,15 +6,16 @@ package configuration
import (
"bytes"
"encoding/json"
"reflect"
"fmt"
"github.com/imdario/mergo"
"github.com/magiconair/properties"
"github.com/pelletier/go-toml/v2"
"gitlab.schukai.com/oss/libraries/go/utilities/pathfinder"
"gopkg.in/yaml.v3"
"io"
"os"
"path"
"reflect"
)
func importJson[C any](config *C, reader io.Reader) error {
......@@ -94,82 +95,60 @@ func (s *Settings[C]) importStreams() {
}
}
func replacePath(p string, c interface{}) {
cValue := reflect.ValueOf(c)
var typeOfPathValue PathValue
// If c is of type PathValue (which implements pathInterface), modify the path
if cValue.Type() == reflect.TypeOf(PathValue("")) {
pathVal := cValue.Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
if cValue.CanSet() {
cValue.Set(reflect.ValueOf(newPath))
}
}
return
}
// replacePath replaces all relative paths with absolute paths
func replacePath[C any](basePath string, c C) error {
// If c is not a struct, simply return
if cValue.Kind() != reflect.Ptr || cValue.Elem().Kind() != reflect.Struct {
return
}
paths := []string{}
fields := reflect.VisibleFields(cValue.Elem().Type())
for _, field := range fields {
r := cValue.Elem().FieldByName(field.Name)
handleField(p, r)
}
}
top := reflect.TypeOf(typeOfPathValue)
toc := reflect.ValueOf(c)
ptp := &paths
func handleField(p string, r reflect.Value) {
switch r.Kind() {
case reflect.Struct:
if r.CanAddr() {
replacePath(p, r.Addr().Interface())
}
case reflect.Slice:
for i := 0; i < r.Len(); i++ {
elem := r.Index(i)
if elem.Type() == reflect.TypeOf(PathValue("")) {
pathVal := elem.Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
if elem.CanSet() {
elem.Set(reflect.ValueOf(newPath))
}
}
} else if elem.CanAddr() {
replacePath(p, elem.Addr().Interface())
}
}
case reflect.Map:
for _, k := range r.MapKeys() {
elem := r.MapIndex(k)
if elem.Type() == reflect.TypeOf(PathValue("")) {
pathVal := elem.Interface().(PathValue)
if !path.IsAbs(pathVal.String()) {
newPath := PathValue(path.Join(p, pathVal.String()))
r.SetMapIndex(k, reflect.ValueOf(newPath))
pathfinder.FindPaths(toc, top, []string{}, ptp)
for _, px := range paths {
p, err := pathfinder.GetValue[C](c, px)
if err != nil {
return err
}
} else if elem.CanAddr() {
replacePath(p, elem.Addr().Interface())
switch p.(type) {
case PathValue:
tp, ok := p.(PathValue)
if !ok {
return fmt.Errorf("type assertion failed")
}
if !path.IsAbs(p.(PathValue).String()) {
newPath := PathValue(path.Join(basePath, tp.String()))
switch reflect.TypeOf(p).Kind() {
case reflect.Ptr:
err = pathfinder.SetValue[C](c, px, &newPath)
case reflect.String:
if px == "G.I.key1GI.A" {
}
err = pathfinder.SetValue[C](c, px, newPath.String())
default:
// Check for pathInterface
if v, ok := r.Interface().(pathInterface); ok {
// Check if r is nil
if r.Kind() == reflect.Ptr && r.IsNil() {
return
err = pathfinder.SetValue[C](c, px, newPath)
}
currentPath := v.String()
if r.CanSet() && !path.IsAbs(currentPath) {
if r.Type() == reflect.TypeOf(PathValue("")) {
r.Set(reflect.ValueOf(PathValue(path.Join(p, currentPath))))
if err != nil {
return err
}
}
}
}
return nil
}
func (s *Settings[C]) importFiles() {
......@@ -190,7 +169,7 @@ func (s *Settings[C]) importFiles() {
r := (io.Reader)(f)
s.importStream(reader{s.files.format, r}, func(c *C) {
replacePath(d, c)
replacePath[*C](d, c)
})
_ = f.Close()
}
......@@ -206,7 +185,10 @@ func (s *Settings[C]) importFiles() {
s.importStream(reader{f.format, r}, func(c *C) {
d := path.Dir(f.path)
replacePath(d, c)
err := replacePath[*C](d, c)
if err != nil {
return
}
})
_ = r.Close()
......
// Copyright 2022 schukai GmbH
// Copyright 2023 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
package configuration
import (
"github.com/stretchr/testify/assert"
"path/filepath"
"testing"
)
......@@ -27,3 +28,85 @@ func TestReadExample3(t *testing.T) {
assert.Equal(t, c.Config().Host, "localhost")
}
type TestStruct struct {
Path1 PathValue
Path2 string
Path3 []PathValue
}
func TestReplacePath2(t *testing.T) {
testData := TestStruct{
Path1: "relative/path1",
Path2: "relative/path2",
Path3: []PathValue{"relative/path3", "relative/path4"},
}
basePath := "/base"
err := replacePath[*TestStruct](basePath, &testData)
assert.Nil(t, err)
expectedPath1 := PathValue(filepath.Join(basePath, "relative/path1"))
if testData.Path1 != expectedPath1 {
t.Errorf("Expected %s, got %s", expectedPath1, testData.Path1)
}
// no pathValue
expectedPath2 := "relative/path2"
if testData.Path2 != expectedPath2 {
t.Errorf("Expected %s, got %s", expectedPath2, testData.Path2)
}
expectedPath3 := []PathValue{PathValue(filepath.Join(basePath, "relative/path3")), PathValue(filepath.Join(basePath, "relative/path4"))}
if testData.Path3[0] != expectedPath3[0] {
t.Errorf("Expected %s, got %s", expectedPath3[0], testData.Path3[0])
}
if testData.Path3[1] != expectedPath3[1] {
t.Errorf("Expected %s, got %s", expectedPath3[1], testData.Path3[1])
}
}
type SubTestSubPaths struct {
Template PathValue
Definitions []PathValue
}
type SubTest2Def struct {
Paths SubTestSubPaths
}
type SubTestStruct1 map[string]SubTest2Def
type MainTestStruct struct {
Sub SubTestStruct1
}
func TestReplacePathForConfig(t *testing.T) {
config := MainTestStruct{
Sub: SubTestStruct1{
"Default": SubTest2Def{
Paths: SubTestSubPaths{
Template: "../../../default.html",
Definitions: []PathValue{"../../../legacy.yaml"},
},
},
},
}
basePath := "/base/1/2/3/"
err := replacePath[*MainTestStruct](basePath, &config)
if err != nil {
t.Error(err)
}
expectedTemplatePath := PathValue(filepath.Join(basePath, "../../../default.html"))
if config.Sub["Default"].Paths.Template != expectedTemplatePath {
t.Errorf("Expected %s, got %s", expectedTemplatePath, config.Sub["Default"].Paths.Template)
}
expectedDefinitionPath := PathValue(filepath.Join(basePath, "../../../legacy.yaml"))
if config.Sub["Default"].Paths.Definitions[0] != expectedDefinitionPath {
t.Errorf("Expected %s, got %s", expectedDefinitionPath, config.Sub["Default"].Paths.Definitions[0])
}
}
......@@ -4,7 +4,6 @@
package configuration
import (
"fmt"
"os"
"testing"
)
......@@ -21,7 +20,6 @@ func Fuzz1Test(f *testing.F) {
s := New(config)
fmt.Println("A:", a, "B:", b, "F:", f)
if s == nil {
t.Error("Expected not nil")
......
......@@ -5,7 +5,6 @@ package configuration
import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"path"
"path/filepath"
......@@ -26,7 +25,7 @@ type Issue7Config struct {
}
func createIssue7TempFile(content string) (string, error) {
file, err := ioutil.TempFile("", "tempfile")
file, err := os.CreateTemp("", "tempfile")
if err != nil {
return "", err
}
......@@ -100,7 +99,8 @@ func TestIssue7ReplacePath(t *testing.T) {
C: 42,
}
replacePath(basePath, &ts1)
err := replacePath[*Issue7TestStruct1](basePath, &ts1)
assert.Nil(t, err)
if ts1.A != PathValue(path.Join(basePath, "relative/path")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "relative/path"), ts1.A)
......@@ -118,7 +118,8 @@ func TestIssue7ReplacePath(t *testing.T) {
E: "justastring",
}
replacePath(basePath, &ts2)
err = replacePath[*Issue7TestStruct2](basePath, &ts2)
assert.Nil(t, err)
if ts2.A != PathValue(path.Join(basePath, "another/relative/path")) {
t.Errorf("Expected '%s', got '%s'", path.Join(basePath, "another/relative/path"), ts2.A)
......@@ -220,7 +221,8 @@ func TestReplacePath(t *testing.T) {
// Copy the struct to compare later
original := *s
replacePath(basePath, s)
err := replacePath[*MyStruct](basePath, s)
assert.Nil(t, err)
// Checking each field to ensure replacePath works as expected
if s.A != original.A && !path.IsAbs(s.A.String()) {
......
The MIT License (MIT)
Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton
go-toml v2
Copyright (c) 2021 - 2023 Thomas Pelletier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment