diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index ffc3649..b391e40 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -56,4 +56,5 @@ env: VALIDATE_ALL_CODEBASE: false DEFAULT_BRANCH: master - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VALIDATE_JSCPD: false \ No newline at end of file diff --git a/.github/workflows/opencommit.yml b/.github/workflows/opencommit.yml index 4580c83..d482941 100644 --- a/.github/workflows/opencommit.yml +++ b/.github/workflows/opencommit.yml @@ -4,7 +4,7 @@ on: push: # this list of branches is often enough, # but you may still ignore other public branches - branches-ignore: [master, main] + branches-ignore: [master, main, dev] paths: - "src/**" - "scripts/**" diff --git a/.gitignore b/.gitignore index 6804318..83219eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ user_profile.cfg user_config.cfg -logs/* \ No newline at end of file +logs/* +src/**.service +log4bash.sh \ No newline at end of file diff --git a/README.md b/README.md index ba7a3fa..e451662 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,17 @@ # PrintCFG Klipper Suite +[![GitHub Super-Linter](https://github.com/rootiest/printcfg/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) + ![header](docs/pretty_header.png) This set of macros is a full suite of features for Klipper. It is designed to be fully customizable to fit any printer or configuration. All without having to edit or understand the macros themselves. All configuration for the macros is done in the [user_profile.cfg](profiles/default/variables.cfg) file. -[Documentation is available in the Wiki](https://github.com/rootiest/printcfg/wiki) +## Documentation + +### [Documentation is available in the Wiki](https://github.com/rootiest/printcfg/wiki) ## Features diff --git a/profiles/hephaestus/README.md b/profiles/hephaestus/README.md index 4527942..60c08e5 100644 --- a/profiles/hephaestus/README.md +++ b/profiles/hephaestus/README.md @@ -35,18 +35,20 @@ To change to this profile, run: ## Features -- 300mm build volume -- Voron TAP probe -- Nozzle brush -- Nevermore Filter -- Exhaust Fan -- Bed fans -- Chamber sensor -- Filament sensor on toolhead (load detection possible) -- Door sensor -- Case lights (125 RGBW LEDs) -- StealthBurner LEDs (rainbow barf + RGBW LEDs) -- Beeper (for notifications) +- 300mm build volume: The printer has a build volume of 300mm. +- Voron TAP probe: The printer uses a Voron TAP probe for bed leveling. +- Nozzle brush: The printer has a nozzle brush attached to it. +- Nevermore Filter: The printer has a Nevermore filter installed. +- Exhaust Fan: The printer has an exhaust fan installed. +- Bed fans: The printer has bed fans installed. +- Chamber sensor: The printer has a chamber sensor installed. +- Filament sensor on toolhead (load detection possible): The printer has a filament sensor installed on the toolhead that can detect when filament is loaded. +- Door sensor: The printer has a door sensor installed. +- Case lights (125 RGBW LEDs): The printer has 125 RGBW LEDs installed for lighting. +- StealthBurner LEDs (rainbow barf + RGBW LEDs): The printer has StealthBurner LEDs installed. +- Beeper (for notifications): The printer has a beeper installed for notifications. +- Sensorless homing: The printer uses sensorless homing. +- Adaptive meshing: The printer uses adaptive meshing. ## Notes diff --git a/profiles/v2tap300/README.md b/profiles/v2tap300/README.md index d777cc2..5ed6f87 100644 --- a/profiles/v2tap300/README.md +++ b/profiles/v2tap300/README.md @@ -38,3 +38,5 @@ To change to this profile, run: - 300mm build volume - Voron TAP probe - StealthBurner LEDs +- No Sensorless Homing +- Adaptive Meshing diff --git a/profiles/v2tap300/config.cfg b/profiles/v2tap300/config.cfg index 600b073..7ad3d85 100644 --- a/profiles/v2tap300/config.cfg +++ b/profiles/v2tap300/config.cfg @@ -265,17 +265,17 @@ gcode: ######## Door Configs ########## ################################ -[gcode_button doors] +#[gcode_button left_door] ########## IMPORTANT ########### ## ---------------------------- ## # Set pin to match your machine: # -pin: !PG15 # +#pin: !PG15 # ## ---------------------------- ## ########## IMPORTANT ########### -press_gcode: - _close_door ; DO NOT CHANGE -release_gcode: - _open_door ; DO NOT CHANGE +#press_gcode: +# _close_door ; DO NOT CHANGE +#release_gcode: +# _open_door ; DO NOT CHANGE #[gcode_button right_door] ########## IMPORTANT ########### diff --git a/profiles/v2tap300/variables.cfg b/profiles/v2tap300/variables.cfg index e1bdfb9..a49ad2f 100644 --- a/profiles/v2tap300/variables.cfg +++ b/profiles/v2tap300/variables.cfg @@ -160,7 +160,7 @@ variable_home_travel_speed: 10000 variable_home_z_speed: 1000 variable_home_retract: 10 variable_home_retract_speed: 1200 -variable_sensorless_home: True +variable_sensorless_home: False variable_home_current: 0.7 ## Homing Macros @@ -388,7 +388,7 @@ variable_telegram_runout: 'TELEGRAM_FILAMENT_RUNOUT' ## Each door must have a name (e.g. variable_door1_name: 'left_door') ## Each door may optionally have custom macros for open and closed (e.g. variable_door1_open: 'M116') -variable_doors: 1 ; Number of doors (0, 1 or 2) (set to 0 to disable) +variable_doors: 0 ; Number of doors (0, 1 or 2) (set to 0 to disable) variable_door1_name: 'Left' ; Name of first door switch variable_door1_open: 'M116' ; Custom macro for open door1 (set to 'M116' to disable) diff --git a/scripts/change_profile.sh b/scripts/change_profile.sh index 9c54f03..51f38ec 100644 --- a/scripts/change_profile.sh +++ b/scripts/change_profile.sh @@ -25,39 +25,30 @@ # This script will change the user profile to the specified profile. # Arguments: # $1: (mandatory) - -#################################################################################################### - +# The name of the profile to change to. # Example: # ./change_profile.sh default # This will change the user profile to the default profile. -#################################################################################################### - -# Set the dev and repo name -dev="rootiest" +# Set the repo name repo="printcfg" -branch="master" # Get home directory -home=$(eval echo ~$USER) +home=$(eval echo ~"$USER") # Define the klipper config file config=$home/printer_data/config -# Define the printer.cfg and moonraker.conf files -printer=$home/printer_data/config/printer.cfg -moonraker=$home/printer_data/config/moonraker.conf -# Set the default profile -default_src=default user_vars=$config/user_profile.cfg -old_user_vars=$config/$repo/user_profile.cfg user_cfg=$config/user_config.cfg -old_user_cfg=$config/$repo/user_config.cfg profile_pattern="# Profile:(.*)" +LOGFILE="$home/$repo/logs/change_profile.log" +exec 3>&1 1>"$LOGFILE" 2>&1 +trap "echo 'ERROR: An error occurred during execution, check log for details.' >&3" ERR +trap '{ set +x; } 2>/dev/null; echo -n "[$(date -Is)] "; set -x' DEBUG # Check if any parameters were provided if [ $# -eq 0 ] then - echo -e "\n\e[31mERROR: No profile name provided.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: No profile name provided.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 else # Set the profile name @@ -76,13 +67,20 @@ else fi fi -echo -e "\nChanging profile to $1..." +echo -e "\nChanging profile to $1..." >&3 # Check if the profile exists if [ ! -d "$src_path" ] then - echo -e "\n\e[31mERROR: Profile $1 does not exist.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile $1 does not exist.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 + exit 1 +fi +# Check if the profile directory is empty +if [ ! "$(ls -A "$src_path")" ] +then + echo -e "\n\e[31mERROR: Profile $1 is empty.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi @@ -94,8 +92,10 @@ then # Verify that the profile marker was found if [ -z "$vars_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $user_vars.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $user_vars.\e[0m" >&3 + echo "The profile marker should be near the top of the file." >&3 + echo "It should look like this: # Profile: " >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Search for the profile_pattern in the src_vars using grep @@ -103,15 +103,17 @@ then # Verify that the profile marker was found if [ -z "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $src_vars.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $src_vars.\e[0m" >&3 + echo "The profile marker should be near the top of the file." >&3 + echo "It should look like this: # Profile: " >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Check if the profile is already active if [ "$vars_profile" == "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile $1 is already active.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile $1 is already active.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -124,8 +126,8 @@ then # Verify that the profile marker was found if [ -z "$cfg_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $user_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $user_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Search for the profile_pattern in the src_cfg using grep @@ -133,15 +135,15 @@ then # Verify that the profile marker was found if [ -z "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $src_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $src_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Check if the profile is already active if [ "$cfg_profile" == "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile $1 is already active.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile $1 is already active.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -167,22 +169,16 @@ then if [ -f "$user_vars.bak" ] then # Rename the backup - cp "$user_vars.bak" "$user_vars.old" - # Verify that the rename was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to rename $user_vars.bak to $user_vars.old.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$user_vars.bak" "$user_vars.old";then + echo -e "\n\e[31mERROR: Failed to rename $user_vars.bak to $user_vars.old.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi # Backup the current user profile - cp "$user_vars" "$user_vars.bak" - # Verify that the backup was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to backup $user_vars.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$user_vars" "$user_vars.bak"; then + echo -e "\n\e[31mERROR: Failed to backup $user_vars.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -194,22 +190,16 @@ then if [ -f "$user_cfg.bak" ] then # Rename the backup - cp "$user_cfg.bak" "$user_cfg.old" - # Verify that the rename was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to rename $user_cfg.bak to $user_cfg.old.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$user_cfg.bak" "$user_cfg.old"; then + echo -e "\n\e[31mERROR: Failed to rename $user_cfg.bak to $user_cfg.old.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi # Backup the current user config - cp "$user_cfg" "$user_cfg.bak" - # Verify that the backup was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to backup $user_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$user_cfg" "$user_cfg.bak"; then + echo -e "\n\e[31mERROR: Failed to backup $user_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -218,12 +208,9 @@ fi if [ -f "$user_vars" ] then # Copy the new profile to the user profile - cp "$src_vars" "$user_vars" - # Verify that the copy was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to copy $src_vars to $user_vars.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$src_vars" "$user_vars"; then + echo -e "\n\e[31mERROR: Failed to copy $src_vars to $user_vars.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -232,12 +219,9 @@ fi if [ -f "$user_cfg" ] then # Copy the new config to the user config - cp "$src_cfg" "$user_cfg" - # Verify that the copy was successful - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to copy $src_cfg to $user_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + if ! cp "$src_cfg" "$user_cfg"; then + echo -e "\n\e[31mERROR: Failed to copy $src_cfg to $user_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -250,8 +234,7 @@ then # Verify that the profile marker was found if [ -z "$vars_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $user_vars.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $user_vars.\e[0m" >&3 exit 1 fi # Search for the profile_pattern in the src_vars using grep @@ -259,15 +242,13 @@ then # Verify that the profile marker was found if [ -z "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $src_vars.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $src_vars.\e[0m" >&3 exit 1 fi # Check if the profile is already active if [ "$vars_profile" != "$src_profile" ] then - echo -e "\n\e[31mERROR: Failed to apply profile $1.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Failed to apply profile $1.\e[0m" >&3 exit 1 fi fi @@ -280,8 +261,8 @@ then # Verify that the profile marker was found if [ -z "$cfg_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $user_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $user_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Search for the profile_pattern in the src_cfg using grep @@ -289,15 +270,15 @@ then # Verify that the profile marker was found if [ -z "$src_profile" ] then - echo -e "\n\e[31mERROR: Profile marker not found in $src_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Profile marker not found in $src_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi # Check if the profile is already active if [ "$cfg_profile" != "$src_profile" ] then - echo -e "\n\e[31mERROR: Failed to apply profile $1.\e[0m" - echo "Usage: ./change_profile.sh " + echo -e "\n\e[31mERROR: Failed to apply profile $1.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -308,12 +289,9 @@ fi if [ "${src_vars: -4}" == ".tmp" ] then # Remove the temp file - rm "$src_vars" - # Verify that the file was removed - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to remove $src_vars.\e[0m" - echo "Usage: ./change_profile.sh " + if ! rm "$src_vars"; then + echo -e "\n\e[31mERROR: Failed to remove $src_vars.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi @@ -322,15 +300,12 @@ fi if [ "${src_cfg: -4}" == ".tmp" ] then # Remove the temp file - rm "$src_cfg" - # Verify that the file was removed - if [ $? -ne 0 ] - then - echo -e "\n\e[31mERROR: Failed to remove $src_cfg.\e[0m" - echo "Usage: ./change_profile.sh " + if ! rm "$src_cfg"; then + echo -e "\n\e[31mERROR: Failed to remove $src_cfg.\e[0m" >&3 + echo "Usage: ./change_profile.sh " >&3 exit 1 fi fi # Success -echo -e "\n\e[32mSuccessfully applied profile $1.\e[0m" +echo -e "\n\e[32mSuccessfully applied profile $1.\e[0m" >&3 diff --git a/scripts/install.sh b/scripts/install.sh index 8e46193..d14e4ec 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -41,14 +41,12 @@ #################################################################################################### -# List required packages -PKGLIST="git python3-pip bc" # Set the dev and repo name dev="rootiest" repo="printcfg" branch="master" # Get home directory -home=$(eval echo ~$USER) +home=$(eval echo ~"$USER") # Define the klipper config paths printer_data=$home/printer_data config=$printer_data/config @@ -58,6 +56,11 @@ moonraker=$config/moonraker.conf # Set the default profile default_src=default +LOGFILE="$home/$repo/logs/install.log" +exec 3>&1 1>"$LOGFILE" 2>&1 +trap "echo 'ERROR: An error occurred during execution, check log for details.' >&3" ERR +trap '{ set +x; } 2>/dev/null; echo -n "[$(date -Is)] "; set -x' DEBUG + # Check if any parameters were provided if [ $# -eq 0 ] then @@ -76,68 +79,75 @@ else fi # Welcome message -echo "Welcome to the $repo install script." -echo "This script will download and install the $repo package from GitHub." +echo "Welcome to the $repo install script." >&3 +echo "This script will download and install the $repo package from GitHub." >&3 -echo -echo "Checking dependencies..." +echo >&3 +echo "Checking dependencies..." >&3 if ! which git > /dev/null; then need_git=true - echo "Missing git." + echo "Missing git." >&3 fi if ! which pip > /dev/null; then need_pip=true - echo "Missing pip." + echo "Missing pip." >&3 sudo apt-get install python3-pip fi if ! which bc > /dev/null; then need_bc=true - echo "Missing bc." + echo "Missing bc." >&3 sudo apt-get install bc fi +if ! which wget > /dev/null; then + need_wget=true + echo "Missing wget." >&3 + sudo apt-get install wget +fi + ## Install missing dependencies -if [ -n "$need_git" ] || [ -n "$need_pip" ] || [ -n "$need_bc" ]; then - echo "Installing missing dependencies..." +if [ -n "$need_git" ] || [ -n "$need_pip" ] || [ -n "$need_bc" ] || [ -n "$need_wget" ]; then + echo "Installing missing dependencies..." >&3 sudo apt update - sudo apt-get install -y git python3-pip bc + sudo apt-get install -y git python3-pip bc wget else - echo -e "\e[32mAll dependencies are installed.\e[0m" + echo -e "\e[32mAll dependencies are installed.\e[0m" >&3 fi -echo "Installing $repo..." + +echo "Installing $repo..." >&3 # Check if the repo exists if ! git ls-remote https://github.com/"$dev"/"$repo" >/dev/null; then - echo "The repo does not exist." + echo "The repo does not exist." >&3 exit 1 fi # Change to the home directory -cd $home +cd "$home" || exit # Check if printcfg is already installed -if [ -d $home/$repo ]; +if [ -d "$home"/$repo ]; then - echo -e "\e[33m$repo repo is already installed.\e[0m" - echo "Updating $repo repo..." + echo -e "\e[33m$repo repo is already installed.\e[0m" >&3 + echo "Updating $repo repo..." >&3 # Change to the repo directory - cd $home/$repo + cd "$home"/$repo || exit # Pull the latest changes git pull else - echo "Installing $repo repo..." + echo "Installing $repo repo..." >&3 # Clone the repo git clone https://github.com/"$dev"/"$repo" # Check if the repo was cloned - if [ ! -d $home/$repo ]; then - echo -e "\e[31mError: Repo not cloned.\e[0m" + if [ ! -d "$home"/$repo ]; then + echo -e "\e[31mError: Repo not cloned.\e[0m" >&3 exit 1 else - echo "Repo cloned successfully." + echo "Repo cloned successfully." >&3 fi fi # Change to the repo directory -cd $home/$repo +cd "$home"/$repo || exit # Find the current branch current_branch=$(git branch --show-current) @@ -145,27 +155,25 @@ current_branch=$(git branch --show-current) # Check if the branch was provided if [ -n "$2" ] then - echo "Checking out branch $branch..." + echo "Checking out branch $branch..." >&3 # Check if the branch exists if ! git ls-remote --heads then - echo -e "\e[31mError: Branch $branch does not exist.\e[0m" + echo -e "\e[31mError: Branch $branch does not exist.\e[0m" >&3 exit 1 fi else - echo "Staying on branch $current_branch..." + echo "Staying on branch $current_branch..." >&3 branch=$current_branch fi # Check if the branch is already checked out if [ "$current_branch" != "$branch" ]; then - git switch $branch - # Check if the branch was switched - if [ $? -ne 0 ]; then - echo -e "\e[31mError: Branch not switched.\e[0m" + if ! git switch "$branch"; then + echo -e "\e[31mError: Branch $branch does not exist.\e[0m" >&3 exit 1 else - echo -e "\e[32mBranch switched successfully.\e[0m" + echo -e "\e[32mBranch switched successfully.\e[0m" >&3 pull_branch=true fi else @@ -174,43 +182,50 @@ fi # Pull the latest changes if [ -n "$pull_branch" ]; then - echo "Pulling latest changes..." + echo "Pulling latest changes..." >&3 git pull fi ### Run any setup scripts ### # Install the dependencies -echo "Installing dependencies..." +echo "Installing dependencies..." >&3 if [ -f requirements.txt ]; then pip3 install -r requirements.txt - echo -e "\e[32mDependencies installed successfully.\e[0m" + echo -e "\e[32mDependencies installed successfully.\e[0m" >&3 else - echo -e "\e[33mNo dependencies to install.\e[0m" + echo -e "\e[33mNo dependencies to install.\e[0m" >&3 fi # Check if the service is enabled -echo "Checking if the ${repo} service is enabled..." +echo "Checking if the ${repo} service is enabled..." >&3 if systemctl is-enabled "${repo}" >/dev/null 2>&1; then - echo "The ${repo} service is enabled." + echo "The ${repo} service is enabled." >&3 else - echo "Installing the ${repo} service..." - echo "Acquiring root privileges..." + echo "Installing the ${repo} service..." >&3 + echo "Acquiring root privileges..." >&3 # Acquire root privileges - sudo -v &3 fi fi # Create printcfg bin if [ ! -f /usr/local/bin/$repo ]; then - echo "Creating $repo bin..." - sudo ln -s $home/$repo/src/$repo.py /usr/local/bin/$repo + echo "Creating $repo bin..." >&3 + sudo ln -s "$home"/$repo/src/$repo.py /usr/local/bin/$repo sudo chmod +x /usr/local/bin/$repo - echo -e "\e[32m$repo bin created successfully.\e[0m" + echo -e "\e[32m$repo bin created successfully.\e[0m" >&3 +fi + +# Check if log4bash is installed in local directory +if [ ! -f log4bash.sh ]; then + echo "Installing log4bash." >&3 + # Download log4bash library + wget https://raw.githubusercontent.com/fredpalmer/log4bash/master/log4bash.sh -O "$home"/$repo/src/log4bash.sh fi ### Install into klippers config ### @@ -218,106 +233,106 @@ fi # Check if config directory exists if [ ! -d "$config" ] then - echo -e "\e[31mError: Directory '$config' not found.\e[0m" - echo "Please make sure you have klipper installed and your config is located in $config" + echo -e "\e[31mError: Directory '$config' not found.\e[0m" >&3 + echo "Please make sure you have klipper installed and your config is located in $config" >&3 exit 1 fi # Check if the file exists if [ ! -f "$printer" ] then - echo -e "\e[31mError: File '$printer' not found.\e[0m" - echo "Please make sure you have klipper installed and your config is located in $printer" + echo -e "\e[31mError: File '$printer' not found.\e[0m" >&3 + echo "Please make sure you have klipper installed and your config is located in $printer" >&3 exit 1 fi # Check if user_config file exists -if [ ! -f $config/user_config.cfg ] +if [ ! -f "$config"/user_config.cfg ] then # Check if profile config exists - if [ ! -f $home/$repo/profiles/$src/config.cfg ] + if [ ! -f "$home"/$repo/profiles/"$src"/config.cfg ] then - echo -e "\e[31mError: Config Profile '$src' not found.\e[0m" - echo "Using default config profile: $default_src" + echo -e "\e[31mError: Config Profile '$src' not found.\e[0m" >&3 + echo "Using default config profile: $default_src" >&3 src=$default_src fi # Copy user profile to config directory - echo -e "\e[36mUsing config profile: $src\e[0m" - echo "Creating user_config in config directory..." - cp -r $home/$repo/profiles/$src/config.cfg $config/user_config.cfg + echo -e "\e[36mUsing config profile: $src\e[0m" >&3 + echo "Creating user_config in config directory..." >&3 + cp -r "$home"/$repo/profiles/"$src"/config.cfg "$config"/user_config.cfg else - echo -e "\e[32mUser config already exists.\e[0m" + echo -e "\e[32mUser config already exists.\e[0m" >&3 fi # Check if user profile file exists -if [ ! -f $config/user_profile.cfg ] +if [ ! -f "$config"/user_profile.cfg ] then # Check if profile exists - if [ ! -f $home/$repo/profiles/$src/variables.cfg ] + if [ ! -f "$home"/$repo/profiles/"$src"/variables.cfg ] then - echo -e "\e[31mError: Profile '$src' not found.\e[0m" - echo "Using default variables profile: $default_src" + echo -e "\e[31mError: Profile '$src' not found.\e[0m" >&3 + echo "Using default variables profile: $default_src" >&3 src=$default_src fi # Copy user profile to config directory - echo -e "\e[36mUsing variables profile: $src\e[0m" - echo "Creating user profile in config directory..." - cp -r $home/$repo/profiles/$src/variables.cfg $config/user_profile.cfg + echo -e "\e[36mUsing variables profile: $src\e[0m" >&3 + echo "Creating user profile in config directory..." >&3 + cp -r "$home"/$repo/profiles/"$src"/variables.cfg "$config"/user_profile.cfg else - echo -e "\e[32mUser profile already exists.\e[0m" + echo -e "\e[32mUser profile already exists.\e[0m" >&3 fi # Check if link already exists -if [ ! -L $config/$repo ] +if [ ! -L "$config"/$repo ] then # Link printcfg to the printer config directory - echo "Linking $repo to the printer config directory..." - ln -s $home/$repo $config/$repo + echo "Linking $repo to the printer config directory..." >&3 + ln -s "$home"/$repo "$config"/$repo # Check if the link was created - if [ ! -L $config/$repo ] + if [ ! -L "$config"/$repo ] then - echo -e "\e[31mError: Link not created.\e[0m" + echo -e "\e[31mError: Link not created.\e[0m" >&3 exit 1 fi else - echo -e "\e[33m$repo symlink already exists.\e[0m" + echo -e "\e[33m$repo symlink already exists.\e[0m" >&3 fi # Check if include line exists in printer.cfg uconfig_pattern="[include user_config.cfg]" if grep -qFx "$uconfig_pattern" "$printer" then - echo -e "\e[33m$repo config already included.\e[0m" + echo -e "\e[33m$repo config already included.\e[0m" >&3 else - echo "Adding $repo config to $printer..." + echo "Adding $repo config to $printer..." >&3 # Add printcfg config to beginning of file - python3 $home/$repo/scripts/search_replace.py "$uconfig_pattern" "$uconfig_pattern" "$printer" + python3 "$home"/$repo/src/search_replace.py "$uconfig_pattern" "$uconfig_pattern" "$printer" fi # Verify moonraker is installed if [ ! -f "$moonraker" ] then - echo -e "\e[31mError: File '$moonraker' not found.\e[0m" - echo "Please make sure you have moonraker installed and your config is located in $moonraker" + echo -e "\e[31mError: File '$moonraker' not found.\e[0m" >&3 + echo "Please make sure you have moonraker installed and your config is located in $moonraker" >&3 exit 1 fi # Check if the moonraker-printcfg.conf file exists -if [ ! -f $config/moonraker-$repo.conf ] +if [ ! -f "$config"/moonraker-$repo.conf ] then # Copy moonraker config to config directory - echo "Creating moonraker config in config directory..." - cp -r $home/$repo/src/mooncfg.conf $config/moonraker-$repo.conf + echo "Creating moonraker config in config directory..." >&3 + cp -r "$home"/$repo/src/mooncfg.conf "$config"/moonraker-$repo.conf else - echo -e "\e[32mMoonraker config already exists.\e[0m" + echo -e "\e[32mMoonraker config already exists.\e[0m" >&3 fi # Set branch in moonraker-printcfg.conf -echo "Setting branch in moonraker config..." +echo "Setting branch in moonraker config..." >&3 # Define search pattern branch_pattern="primary_branch:" # Set branch to current branch -python3 $home/$repo/scripts/search_replace.py "$branch_pattern" "$branch_pattern $branch" "$config/moonraker-$repo.conf" +python3 "$home"/$repo/src/search_replace.py "$branch_pattern" "$branch_pattern $branch" "$config/moonraker-$repo.conf" # Check if the moonraker config already contains the old printcfg config moon_pattern="[include $repo/moonraker-$repo.conf]" @@ -325,123 +340,123 @@ new_moon="[include moonraker-$repo.conf]" if grep -qFx "$new_moon" "$moonraker" then - echo -e "\e[33m$repo moonraker already included.\e[0m" + echo -e "\e[33m$repo moonraker already included.\e[0m" >&3 else - echo "Adding $repo config to $moonraker..." + echo "Adding $repo config to $moonraker..." >&3 # Add printcfg config to moonraker - python3 $home/$repo/scripts/search_replace.py "$moon_pattern" "$new_moon" "$moonraker" + python3 "$home"/$repo/src/search_replace.py "$moon_pattern" "$new_moon" "$moonraker" fi # Add printcfg to moonraker.asvc -echo "Checking for $repo service in moonraker allowlist..." +echo "Checking for $repo service in moonraker allowlist..." >&3 # Define allowlist file allowlist="$printer_data/moonraker.asvc" # Verify printcfg is in allowlist if grep -qFx "$repo" "$allowlist" then - echo -e "\e[33m$repo service already in allowlist.\e[0m" + echo -e "\e[33m$repo service already in allowlist.\e[0m" >&3 else - echo "Adding $repo service to moonraker allowlist..." + echo "Adding $repo service to moonraker allowlist..." >&3 # Add printcfg service to moonraker allowlist - echo "$repo" >> $allowlist + echo "$repo" >> "$allowlist" if grep -qFx "$repo" "$allowlist" then - echo -e "\e[32m$repo service added to allowlist successfully.\e[0m" + echo -e "\e[32m$repo service added to allowlist successfully.\e[0m" >&3 else - echo -e "\e[31mError: $repo service not added to allowlist.\e[0m" + echo -e "\e[31mError: $repo service not added to allowlist.\e[0m" >&3 exit 1 fi fi -echo -e "\e[32mInstall complete.\e[0m" -echo +echo -e "\e[32mInstall complete.\e[0m" >&3 +echo >&3 # Perform all checks to make sure printcfg is installed correctly -echo "Checking $repo installation..." +echo "Checking $repo installation..." >&3 # Check if the repo exists -if [ ! -d $home/$repo ]; then - echo -e "\e[31mError: Repo not cloned.\e[0m" +if [ ! -d "$home"/$repo ]; then + echo -e "\e[31mError: Repo not cloned.\e[0m" >&3 exit 1 fi # Check if the printer.cfg exists if [ ! -f "$printer" ] then - echo -e "\e[31mError: File '$printer' not found.\e[0m" - echo "Please make sure you have klipper installed and your config is located in $printer" + echo -e "\e[31mError: File '$printer' not found.\e[0m" >&3 + echo "Please make sure you have klipper installed and your config is located in $printer" >&3 exit 1 fi # Check if moonraker config exists if [ ! -f "$moonraker" ] then - echo -e "\e[31mError: File '$moonraker' not found.\e[0m" - echo "Please make sure you have moonraker installed and your config is located in $moonraker" + echo -e "\e[31mError: File '$moonraker' not found.\e[0m" >&3 + echo "Please make sure you have moonraker installed and your config is located in $moonraker" >&3 exit 1 fi # Check if printcfg is included in the printer.cfg file if ! grep -qFx "$uconfig_pattern" "$printer" then - echo -e "\e[31mError: $repo config not included in $printer\e[0m" + echo -e "\e[31mError: $repo config not included in $printer\e[0m" >&3 exit 1 fi # Check if the moonraker config contains printcfg config if ! grep -qFx "$new_moon" "$moonraker" then - echo -e "\e[31mError: $repo config not included in $moonraker\e[0m" + echo -e "\e[31mError: $repo config not included in $moonraker\e[0m" >&3 exit 1 fi # Check if printcfg symlink exists -if [ ! -L $config/$repo ] +if [ ! -L "$config"/$repo ] then - echo -e "\e[31mError: $repo symlink not created.\e[0m" + echo -e "\e[31mError: $repo symlink not created.\e[0m" >&3 exit 1 fi # Check if user config exists -if [ ! -f $config/user_config.cfg ] +if [ ! -f "$config"/user_config.cfg ] then - echo -e "\e[31mError: $repo user config not found.\e[0m" + echo -e "\e[31mError: $repo user config not found.\e[0m" >&3 exit 1 fi # Check if user profile exists -if [ ! -f $config/user_profile.cfg ] +if [ ! -f "$config"/user_profile.cfg ] then - echo -e "\e[31mError: $repo user profile not found.\e[0m" + echo -e "\e[31mError: $repo user profile not found.\e[0m" >&3 exit 1 fi # Acknowledge that the installation checks passed -echo -e "\e[32m$repo installation checks passed.\e[0m" +echo -e "\e[32m$repo installation checks passed.\e[0m" >&3 echo # Success! -echo -echo -e "\e[32mPrintcfg has been successfully downloaded and installed.\e[0m" -echo +echo >&3 +echo -e "\e[32mPrintcfg has been successfully downloaded and installed.\e[0m" >&3 +echo >&3 # Perform setup checks -echo "Performing Setup Checks..." -echo +echo "Performing Setup Checks..." >&3 +echo >&3 -bash $home/$repo/scripts/setup.sh $src +bash "$home"/$repo/scripts/setup.sh "$src" -echo -e "\e[32mSetup checks passed.\e[0m" +echo -e "\e[32mSetup checks passed.\e[0m" >&3 -echo +echo >&3 # Restart klipper -echo "Restarting klipper..." +echo "Restarting klipper..." >&3 systemctl restart klipper # Restart moonraker -echo "Restarting moonraker..." +echo "Restarting moonraker..." >&3 systemctl restart moonraker -echo -echo -e "\e[32mInstallation completed successfully.\e[0m" +echo >&3 +echo -e "\e[32mInstallation completed successfully.\e[0m" >&3 diff --git a/scripts/patch.sh b/scripts/patch.sh index 5e6b890..c92aaa3 100644 --- a/scripts/patch.sh +++ b/scripts/patch.sh @@ -39,20 +39,14 @@ #################################################################################################### # Set the dev and repo name -dev="rootiest" repo="printcfg" -branch="master" # Get home directory -home=$(eval echo ~$USER) +home=$(eval echo ~"$USER") # Define the klipper config file config=$home/printer_data/config # Define the printer.cfg and moonraker.conf files printer=$home/printer_data/config/printer.cfg -moonraker=$home/printer_data/config/moonraker.conf -# Set the default profile -default_src=default user_vars=$config/user_profile.cfg -old_user_vars=$config/$repo/user_profile.cfg user_cfg=$config/user_config.cfg old_user_cfg=$config/$repo/user_config.cfg # Patterns to identify profile name and version @@ -62,11 +56,16 @@ uconfig_pattern_old="[include $repo/user_config.cfg]" uconfig_pattern_new="[include user_config.cfg]" ver_patch="# Patch: *" +LOGFILE="$home/$repo/logs/patch.log" +exec 3>&1 1>"$LOGFILE" 2>&1 +trap "echo 'ERROR: An error occurred during execution, check log for details.' >&3" ERR +trap '{ set +x; } 2>/dev/null; echo -n "[$(date -Is)] "; set -x' DEBUG + # Check if any parameters were provided if [ $# -eq 0 ] then # Get the user profile version - user_vars_version=$(grep -oP '(variable_version: ).*' $user_vars) + user_vars_version=$(grep -oP '(variable_version: ).*' "$user_vars") user_vars_version=${user_vars_version#variable_version: } else # Set the user profile version @@ -76,179 +75,179 @@ else fi fi -echo "Checking user config path..." +echo "Checking user config path..." >&3 # Check that user config exists -if [ ! -f $user_cfg ] +if [ ! -f "$user_cfg" ] then # Check if old user config exists - if [ -f $old_user_cfg ] + if [ -f "$old_user_cfg" ] then - echo -e "\e[31mUser config location is out of date.\e[0m" - mv $old_user_cfg $user_cfg + echo -e "\e[31mUser config location is out of date.\e[0m" >&3 + mv "$old_user_cfg" "$user_cfg" # Verify move was successful - if [ -f $user_cfg ] + if [ -f "$user_cfg" ] then - echo "User config moved to $config/user_config.cfg" + echo "User config moved to $config/user_config.cfg" >&3 else - echo -e "\e[31mUser config move failed.\e[0m" + echo -e "\e[31mUser config move failed.\e[0m" >&3 exit 1 fi # Check if old include line exists in printer.cfg - echo "Checking printer.cfg include line..." + echo "Checking printer.cfg include line..." >&3 if grep -qFx "$uconfig_pattern_old" "$printer" then echo -e "\e[31mInclude line is out of date.\e[0m" # Replace old include line with new include line - python3 $home/$repo/scripts/search_replace.py "$uconfig_pattern_old" "$uconfig_pattern_new" "$printer" + python3 "$home"/$repo/src/search_replace.py "$uconfig_pattern_old" "$uconfig_pattern_new" "$printer" # Verify include line was added if grep -qFx "$uconfig_pattern_new" "$printer" then - echo "Include line updated." + echo "Include line updated." >&3 # User config is up to date - echo -e "\e[32mUser config is now up to date.\e[0m" + echo -e "\e[32mUser config is now up to date.\e[0m" >&3 else - echo -e "\e[31mInclude line update failed.\e[0m" + echo -e "\e[31mInclude line update failed.\e[0m" >&3 exit 1 fi else if grep -qFx "$uconfig_pattern_new" "$printer" then - echo -e "\e[32mUser config is up to date.\e[0m" + echo -e "\e[32mUser config is up to date.\e[0m" >&3 else - echo -e "\e[31mInclude line does not exist.\e[0m" + echo -e "\e[31mInclude line does not exist.\e[0m" >&3 exit 1 fi fi else - echo -e "\e[31mUser config does not exist.\e[0m" + echo -e "\e[31mUser config does not exist.\e[0m" >&3 exit 1 fi else # User config is up to date - echo -e "\e[32mUser config path is up to date.\e[0m" + echo -e "\e[32mUser config path is up to date.\e[0m" >&3 fi # Check user config profile marker -echo "Checking user config: profile..." +echo "Checking user config: profile..." >&3 # Search for the profile_pattern in the user_cfg using grep config_profile=$(grep -oP "$profile_pattern" "$user_cfg" | cut -d':' -f2) if [ -n "$config_profile" ]; then - echo "Profile: $config_profile" + echo "Profile: $config_profile" >&3 else - echo -e "\e[31mUser config profile marker not found.\e[0m" + echo -e "\e[31mUser config profile marker not found.\e[0m" >&3 exit 1 fi # Check user config patch version marker -echo "Checking user config: version..." +echo "Checking user config: version..." >&3 # Search for the patch pattern in the user_cfg config_ver=$(grep -oP "$patch_pattern" "$user_cfg" | cut -d':' -f2) if [ -n "$config_ver" ]; then # Extract the version number using sed - echo "Version: $config_ver" + echo "Version: $config_ver" >&3 else - echo -e "\e[31mUser config version marker not found.\e[0m" + echo -e "\e[31mUser config version marker not found.\e[0m" >&3 exit 1 fi # Check user profile profile marker -echo "Checking user profile: profile..." +echo "Checking user profile: profile..." >&3 # Search for the profile_pattern in the user_vars using grep vars_profile=$(grep -oP "$profile_pattern" "$user_vars" | cut -d':' -f2) if [ -n "$vars_profile" ]; then - echo "Profile: $vars_profile" + echo "Profile: $vars_profile" >&3 else - echo -e "\e[31mUser profile profile marker not found.\e[0m" + echo -e "\e[31mUser profile profile marker not found.\e[0m" >&3 exit 1 fi # Check user profile patch version marker -echo "Checking user profile: version..." +echo "Checking user profile: version..." >&3 # Search for the patch pattern in the user_vars vars_ver=$(grep -oP "$patch_pattern" "$user_vars" | cut -d':' -f2) if [ -n "$vars_ver" ]; then # Extract the version number using sed - echo "Version: $vars_ver" + echo "Version: $vars_ver" >&3 else - echo -e "\e[31mUser profile version marker not found.\e[0m" + echo -e "\e[31mUser profile version marker not found.\e[0m" >&3 exit 1 fi # Find the latest version in the patch_notes. -echo "Checking patch notes..." +echo "Checking patch notes..." >&3 # Search for the patch pattern in the patch_notes patch_notes="$home/$repo/profiles/$vars_profile/patch_notes.txt" # Read version from patch notes -highest_version=$(python3 $home/$repo/scripts/read_patch_notes.py "$patch_notes") +highest_version=$(python3 "$home"/$repo/src/read_patch_notes.py "$patch_notes") # Print the highest version number -echo "Latest patch is: $highest_version" +echo "Latest patch is: $highest_version" >&3 # Check if the user config version is the same as the highest version if [ "$config_ver" = "$highest_version" ]; then - echo -e "\e[32mUser config is up to date.\e[0m" + echo -e "\e[32mUser config is up to date.\e[0m" >&3 update_config=False else - echo -e "\e[31mUser config is out of date.\e[0m" + echo -e "\e[31mUser config is out of date.\e[0m" >&3 update_config=True fi # Check if the user profile version is the same as the highest version if [ "$vars_ver" = "$highest_version" ]; then - echo -e "\e[32mUser profile is up to date.\e[0m" + echo -e "\e[32mUser profile is up to date.\e[0m" >&3 update_profile=False else - echo -e "\e[31mUser profile is out of date.\e[0m" + echo -e "\e[31mUser profile is out of date.\e[0m" >&3 update_profile=True fi if [ "$update_config" = "False" ] && [ "$update_profile" = "False" ]; then - echo -e "\e[32mUser config and profile are up to date.\e[0m" - echo -e "\e[32mNo action required.\e[0m" + echo -e "\e[32mUser config and profile are up to date.\e[0m" >&3 + echo -e "\e[32mNo action required.\e[0m" >&3 exit 0 else # Search for patch files matching the user profile version - echo "Searching for patch files..." + echo "Searching for patch files..." >&3 vars_patch=$home/$repo/profiles/$vars_profile/patches/$highest_version/vars.patch config_patch=$home/$repo/profiles/$config_profile/patches/$highest_version/config.patch # Check if the config needs to be updated if [ "$update_config" = "True" ]; then # Check if the patch file exists - if [ -f $config_patch ]; then - echo "Patch file found." + if [ -f "$config_patch" ]; then + echo "Patch file found." >&3 # Append the contents of the patch file to the user config - echo "Applying config patch file..." - cat $config_patch >> $user_cfg - echo "Config patch file applied." + echo "Applying config patch file..." >&3 + cat "$config_patch" >> "$user_cfg" + echo "Config patch file applied." >&3 # Update version number in user config - echo "Updating version number..." + echo "Updating version number..." >&3 # Replace the version number using sed - python3 $home/$repo/scripts/search_replace.py "$ver_patch" "$ver_patch$highest_version" "$user_cfg" + python3 "$home"/$repo/src/search_replace.py "$ver_patch" "$ver_patch$highest_version" "$user_cfg" # Verify that the version number has been updated if grep -qFx "$ver_patch$highest_version" "$user_cfg" then - echo -e "\e[32mVersion number updated.\e[0m" + echo -e "\e[32mVersion number updated.\e[0m" >&3 else - echo -e "\e[31mVersion number update failed.\e[0m" + echo -e "\e[31mVersion number update failed.\e[0m" >&3 exit 1 fi - echo "Version number updated." + echo "Version number updated." >&3 else - echo -e "\e[31mConfig patch file not found.\e[0m" - echo "Patch file: $config_patch" + echo -e "\e[31mConfig patch file not found.\e[0m" >&3 + echo "Patch file: $config_patch" >&3 exit 1 fi fi @@ -256,65 +255,64 @@ else # Check if the profile needs to be updated if [ "$update_profile" = "True" ]; then # Check if the patch file exists - if [ -f $vars_patch ]; then - echo "Patch file found." + if [ -f "$vars_patch" ]; then + echo "Patch file found." >&3 # Append the contents of the patch file to the user config - echo "Applying profile patch file..." + echo "Applying profile patch file..." >&3 # Find the line containing '# End Custom Variables #' - vars_end=$(grep -n '# End Custom Variables #' $user_vars | cut -d':' -f1) + vars_end=$(grep -n '# End Custom Variables #' "$user_vars" | cut -d':' -f1) # Make sure the line number is not empty if [ -z "$vars_end" ]; then - echo -e "\e[31mEnd of custom variables marker not found.\e[0m" - echo "Marker: # End Custom Variables #" - echo - echo "Using 'gcode:' instead." - vars_end=$(grep -n 'gcode:' $user_vars | cut -d':' -f1) + echo -e "\e[31mEnd of custom variables marker not found.\e[0m" >&3 + echo "Marker: # End Custom Variables #" >&3 + echo >&3 + echo "Using 'gcode:' instead." >&3 + vars_end=$(grep -n 'gcode:' "$user_vars" | cut -d':' -f1) fi # Add the patch before the line - sed -i "$vars_end r $vars_patch" $user_vars + sed -i "$vars_end r $vars_patch" "$user_vars" # Add a newline after the patch - sed -i "$vars_end a \ " $user_vars - echo "Profile patch file applied." + sed -i "$vars_end a \ " "$user_vars" + echo "Profile patch file applied." >&3 # Update version number in user profile - echo "Updating version number..." + echo "Updating version number..." >&3 # Replace the version number using sed - python3 $home/$repo/scripts/search_replace.py "$ver_patch" "$ver_patch$highest_version" "$user_vars" + python3 "$home"/$repo/src/search_replace.py "$ver_patch" "$ver_patch$highest_version" "$user_vars" # Verify that the version number has been updated if grep -qFx "$ver_patch$highest_version" "$user_vars" then - echo -e "\e[32mVersion number updated.\e[0m" + echo -e "\e[32mVersion number updated.\e[0m" >&3 else - echo -e "\e[31mVersion number update failed.\e[0m" + echo -e "\e[31mVersion number update failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mProfile patch file not found.\e[0m" - echo "Patch file: $vars_patch" + echo -e "\e[31mProfile patch file not found.\e[0m" >&3 + echo "Patch file: $vars_patch" >&3 exit 1 fi fi # Summarize results - echo - echo "Summary:" + echo >&3 + echo "Summary:" >&3 if [ "$update_config" = "True" ]; then - echo -e "\e[32mUser config was successfully patched.\e[0m" - echo -e "Version: $highest_version" + echo -e "\e[32mUser config was successfully patched.\e[0m" >&3 + echo -e "Version: $highest_version" >&3 else - echo -e "\e[32mUser config patch was not needed.\e[0m" - echo -e "Version: $config_ver" + echo -e "\e[32mUser config patch was not needed.\e[0m" >&3 + echo -e "Version: $config_ver" >&3 fi if [ "$update_profile" = "True" ]; then - echo -e "\e[32mUser profile was successfully patched.\e[0m" - echo -e "Version: $highest_version" + echo -e "\e[32mUser profile was successfully patched.\e[0m" >&3 + echo -e "Version: $highest_version" >&3 else - echo -e "\e[32mUser profile patch was not needed.\e[0m" - echo -e "Version: $vars_ver" + echo -e "\e[32mUser profile patch was not needed.\e[0m" >&3 + echo -e "Version: $vars_ver" >&3 fi - echo - echo -e "\e[32mPatching completed successfully.\e[0m" + echo >&3 + echo -e "\e[32mPatching completed successfully.\e[0m" >&3 exit 0 -fi - +fi \ No newline at end of file diff --git a/scripts/remove_printcfg.sh b/scripts/remove_printcfg.sh index eebf5ab..09cb243 100644 --- a/scripts/remove_printcfg.sh +++ b/scripts/remove_printcfg.sh @@ -1,40 +1,32 @@ #!/bin/bash # Copyright (C) 2023 Chris Laprade (chris@rootiest.com) -# +# # This file is part of printcfg. -# +# # printcfg is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # printcfg is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with printcfg. If not, see . # This script will remove printcfg from your system. -# Set the dev and repo name -dev="rootiest" +# Set the repo name repo="printcfg" -branch="master" # Get home directory -home=$(eval echo ~$USER) +home=$(eval echo ~"$USER") # Define the klipper config file config=$home/printer_data/config # Define the printer.cfg and moonraker.conf files printer=$home/printer_data/config/printer.cfg moonraker=$home/printer_data/config/moonraker.conf -# Set the default profile -default_src=default -user_vars=$config/user_profile.cfg -old_user_vars=$config/$repo/user_profile.cfg -user_cfg=$config/user_config.cfg -old_user_cfg=$config/$repo/user_config.cfg # Check if any parameters were provided if [ "$1" ]; then @@ -49,71 +41,53 @@ if [ "$1" ]; then # Exit the script exit 1 fi + fi fi # Stop the printcfg service -sudo systemctl stop $repo.service - -# Verify that the printcfg service was stopped -if [ "$(systemctl is-active $repo.service)" = "active" ]; then - echo -e "\e[31mFailed to stop the printcfg service.\e[0m" - exit 1 -fi +systemctl stop $repo.service || { echo -e "\e[31mFailed to stop $repo service.\e[0m"; exit 1; } # Remove the printcfg service -sudo rm /etc/systemd/system/$repo.service - -# Verify that the printcfg service was removed -if [ -f /etc/systemd/system/$repo.service ]; then - echo -e "\e[31mFailed to remove the printcfg service.\e[0m" - exit 1 +service_file="/etc/systemd/system/$repo.service" +if [ -f "$service_file" ]; then + sudo systemctl disable $repo.service || { echo -e "\e[31mFailed to disable $repo service.\e[0m"; exit 1; } + sudo rm "$service_file" || { echo -e "\e[31mFailed to remove $service_file.\e[0m"; exit 1; } +else + echo -e "\e[31m$service_file does not exist.\e[0m" fi # Remove the [include user_config.cfg] line from printer.cfg include_line="[include user_config.cfg]" replace_line="#[include user_config.cfg]" -python3 $home/$repo/scripts/search_replace.py $include_line $replace_line $printer +python3 "$SCRIPT_DIR/search_replace.py" "$include_line" "$replace_line" "$printer" || { echo -e "\e[31mFailed to remove [include user_config.cfg] from printer.cfg.\e[0m"; exit 1; } + +# Remove the [include printcfg-moonraker.conf] line from moonraker.conf +include_line="[include printcfg-moonraker.conf]" +replace_line="#[include printcfg-moonraker.conf]" +python3 "$SCRIPT_DIR/search_replace.py" "$include_line" "$replace_line" "$moonraker" || { echo -e "\e[31mFailed to remove [include printcfg-moonraker.conf] from moonraker.conf.\e[0m"; exit 1; } # Remove the printcfg directory -sudo rm -r $home/$repo +sudo rm -rf "$home"/$repo # Verify that the printcfg directory was removed -if [ -d $home/$repo ]; then +if [ -d "$home"/$repo ]; then echo -e "\e[31mFailed to remove the printcfg directory.\e[0m" exit 1 fi -# Remove the printcfg symlink from the klipper config directory -sudo rm $config/$repo +# Remove the printcfg directory +sudo rm -rf "$home/$repo" +# Verify that the printcfg directory was removed +if [ -d "$home/$repo" ]; then + echo -e "\e[31mFailed to remove $home/$repo.\e[0m" + exit 1 +fi # Verify that the printcfg symlink was removed -if [ -L $config/$repo ]; then +if [ -L "$config"/$repo ]; then echo -e "\e[31mFailed to remove the printcfg symlink.\e[0m" exit 1 fi # Success -echo -e "\e[32mSuccessfully removed $repo.\e[0m" - - - - - - - - - - - - - - - -# Get the current script directory -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Remove the script directory -rm -r "$SCRIPT_DIR" - -# Remove the script file -rm "$0" \ No newline at end of file +echo -e "\e[32mSuccessfully removed $repo.\e[0m" \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh index 87e75a9..37ff1bc 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -40,16 +40,13 @@ #################################################################################################### # Set the dev and repo name -dev="rootiest" repo="printcfg" -branch="master" # Get home directory -home=$(eval echo ~$USER) +home=$(eval echo ~"$USER") # Define the klipper config file config=$home/printer_data/config # Define the printer.cfg and moonraker.conf files printer=$home/printer_data/config/printer.cfg -moonraker=$home/printer_data/config/moonraker.conf # Set the default profile default_src=default user_vars=$config/user_profile.cfg @@ -57,12 +54,18 @@ old_user_vars=$config/$repo/user_profile.cfg user_cfg=$config/user_config.cfg old_user_cfg=$config/$repo/user_config.cfg +LOGFILE="$home/$repo/logs/setup.log" +exec 3>&1 1>"$LOGFILE" 2>&1 +trap "echo 'ERROR: An error occurred during execution, check log for details.' >&3" ERR +trap '{ set +x; } 2>/dev/null; echo -n "[$(date -Is)] "; set -x' DEBUG + # Check if any parameters were provided if [ $# -eq 0 ] then src_cfg=$config/$repo/profiles/$default_src/config.cfg src_vars=$config/$repo/profiles/$default_src/variables.cfg src_path=$config/$repo/profiles/$default_src + profile_used=$default_src else # Set the src_vars file if [ -n "$1" ] @@ -70,6 +73,7 @@ else src_cfg=$config/$repo/profiles/$1/config.cfg src_vars=$config/$repo/profiles/$1/variables.cfg src_path=$config/$repo/profiles/$1 + profile_used=$1 fi fi @@ -77,230 +81,233 @@ echo "Checking $repo executable..." # Check if bin exists if [ ! -f /usr/local/bin/$repo ] then - echo "Creating $repo bin..." - sudo ln -s $home/$repo/src/$repo.py /usr/local/bin/$repo + echo "Creating $repo bin..." >&3 + sudo ln -s "$home"/$repo/src/$repo.py /usr/local/bin/$repo sudo chmod +x /usr/local/bin/$repo - echo -e "\e[32m$repo bin created successfully.\e[0m" + echo -e "\e[32m$repo bin created successfully.\e[0m" >&3 else # Check if bin is executable if [ ! -x /usr/local/bin/$repo ] then - echo "Making $repo bin executable..." + echo "Making $repo bin executable..." >&3 sudo chmod +x /usr/local/bin/$repo - echo -e "\e[32m$repo bin made executable.\e[0m" + echo -e "\e[32m$repo bin made executable.\e[0m" >&3 else - echo -e "\e[32m$repo bin is up to date.\e[0m" + echo -e "\e[32m$repo bin is up to date.\e[0m" >&3 fi fi # Check for force parameter if [ "$2" == "force" ] then - echo -e "\e[31mChanging user profile to $default_src.\e[0m" + echo -e "\e[31mChanging user profile to $default_src.\e[0m" >&3 echo - echo "Updating user config..." + echo "Updating user config..." >&3 # Check if src_cfg exists - if [ -f $src_cfg ] + if [ -f "$src_cfg" ] then # Check if user config exists - if [ -f $user_cfg ] + if [ -f "$user_cfg" ] then # Remove old user config - rm $user_cfg + rm "$user_cfg" # Verify removal was successful - if [ ! -f $user_cfg ] + if [ ! -f "$user_cfg" ] then - echo "Old user config removed." + echo "Old user config removed." >&3 # Copy new user config - cp $src_cfg $user_cfg + cp "$src_cfg" "$user_cfg" # Verify copy was successful - if [ -f $user_cfg ] + if [ -f "$user_cfg" ] then echo "New user config copied." # User config is up to date - echo -e "\e[32mUser config is now up to date.\e[0m" + echo -e "\e[32mUser config is now up to date.\e[0m" >&3 else - echo -e "\e[31mUser config copy failed.\e[0m" + echo -e "\e[31mUser config copy failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mOld user config removal failed.\e[0m" + echo -e "\e[31mOld user config removal failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mUser config does not exist.\e[0m" + echo -e "\e[31mUser config does not exist.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mSource config does not exist.\e[0m" + echo -e "\e[31mSource config does not exist.\e[0m" >&3 exit 1 fi # Check if src_vars exists - if [ -f $src_vars ] + if [ -f "$src_vars" ] then # Check if user vars exists - if [ -f $user_vars ] + if [ -f "$user_vars" ] then # Remove old user vars - rm $user_vars + rm "$user_vars" # Verify removal was successful - if [ ! -f $user_vars ] + if [ ! -f "$user_vars" ] then echo "Old user vars removed." # Copy new user vars - cp $src_vars $user_vars + cp "$src_vars" "$user_vars" # Verify copy was successful - if [ -f $user_vars ] + if [ -f "$user_vars" ] then echo "New user vars copied." # User vars is up to date - echo -e "\e[32mUser vars is now up to date.\e[0m" + echo -e "\e[32mUser vars is now up to date.\e[0m" >&3 else - echo -e "\e[31mUser vars copy failed.\e[0m" + echo -e "\e[31mUser vars copy failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mOld user vars removal failed.\e[0m" + echo -e "\e[31mOld user vars removal failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mUser vars does not exist.\e[0m" + echo -e "\e[31mUser vars does not exist.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mSource vars does not exist.\e[0m" + echo -e "\e[31mSource vars does not exist.\e[0m" >&3 exit 1 fi else - echo "Checking user config..." + echo "Checking user config..." >&3 # Check that user config exists - if [ ! -f $user_cfg ] + if [ ! -f "$user_cfg" ] then # Check if old user config exists - if [ -f $old_user_cfg ] + if [ -f "$old_user_cfg" ] then - echo -e "\e[31mUser config location is out of date.\e[0m" - mv $old_user_cfg $user_cfg + echo -e "\e[31mUser config location is out of date.\e[0m" >&3 + mv "$old_user_cfg" "$user_cfg" # Verify move was successful - if [ -f $user_cfg ] + if [ -f "$user_cfg" ] then - echo "User config moved to $config/user_config.cfg" + echo "User config moved to $config/user_config.cfg" >&3 else - echo -e "\e[31mUser config move failed.\e[0m" + echo -e "\e[31mUser config move failed.\e[0m" >&3 exit 1 fi # Check if old include line exists in printer.cfg - echo "Checking printer.cfg include line..." + echo "Checking printer.cfg include line..." >&3 if grep -qFx "[include $repo/user_config.cfg]" "$printer" then - echo -e "\e[31mInclude line is out of date.\e[0m" + echo -e "\e[31mInclude line is out of date.\e[0m" >&3 # Remove old include line - sed -i '/\[include $repo\/user_config.cfg\]/d' "$printer" + sed -i "/\[include $repo\/user_config.cfg\]/d" "$printer" # Add new include line - sed -i '1s/^/[include user_config.cfg]\n/' "$printer" + sed -i "1s/^/[include user_config.cfg]\n/" "$printer" # Verify include line was added if grep -qFx "[include user_config.cfg]" "$printer" then - echo "Include line updated." + echo "Include line updated." >&3 # User config is up to date - echo -e "\e[32mUser config is now up to date.\e[0m" + echo -e "\e[32mUser config is now up to date.\e[0m" >&3 else - echo -e "\e[31mInclude line update failed.\e[0m" + echo -e "\e[31mInclude line update failed.\e[0m" >&3 exit 1 fi else if grep -qFx "[include user_config.cfg]" "$printer" then - echo -e "\e[32mUser config is up to date.\e[0m" + echo -e "\e[32mUser config is up to date.\e[0m" >&3 else - echo -e "\e[31mInclude line does not exist.\e[0m" + echo -e "\e[31mInclude line does not exist.\e[0m" >&3 exit 1 fi fi else - echo -e "\e[31mUser config does not exist.\e[0m" + echo -e "\e[31mUser config does not exist.\e[0m" >&3 exit 1 fi else # User config is up to date - echo -e "\e[32mUser config is up to date.\e[0m" + echo -e "\e[32mUser config is up to date.\e[0m" >&3 fi - echo - echo "Checking user profile..." + echo >&3 + echo "Checking user profile..." >&3 # Check that user profile exists - if [ ! -f $user_vars ] + if [ ! -f "$user_vars" ] then # Check if old user profile exists - if [ -f $old_user_vars ] + if [ -f "$old_user_vars" ] then - echo -e "\e[31mUser profile location is out of date.\e[0m" - mv $old_user_vars $user_vars + echo -e "\e[31mUser profile location is out of date.\e[0m" >&3 + mv "$old_user_vars" "$user_vars" # Verify move was successful - if [ -f $user_vars ] + if [ -f "$user_vars" ] then - echo "User profile moved to $config/user_profile.cfg" + echo "User profile moved to $config/user_profile.cfg" >&3 else - echo -e "\e[31mUser profile move failed.\e[0m" + echo -e "\e[31mUser profile move failed.\e[0m" >&3 exit 1 fi else - echo -e "\e[31mUser profile does not exist.\e[0m" + echo -e "\e[31mUser profile does not exist.\e[0m" >&3 exit 1 fi fi # Find version of user profile - user_vars_version=$(grep -oP '(variable_version: ).*' $user_vars) - user_vars_version=${user_vars_version#variable_version: } - src_vars_version=$(grep -oP '(variable_version: ).*' $src_vars) - src_vars_version=${src_vars_version#variable_version: } + #user_vars_version=$(grep -oP '(variable_version: ).*' $user_vars) + #user_vars_version=${user_vars_version#variable_version: } + #src_vars_version=$(grep -oP '(variable_version: ).*' $src_vars) + #src_vars_version=${src_vars_version#variable_version: } + user_vars_version=$(python3 "$home"/$repo/src/find_string.py "variable_version: " "$user_vars") + src_vars_version=$(python3 "$home"/$repo/src/find_string.py "variable_version: " "$src_vars") # Check if user profile is up to date if [ "$user_vars_version" != "$src_vars_version" ]; then - echo - echo -e "\e[31mUser profile is not up to date.\e[0m" - echo "User version: $user_vars_version" - echo "Source version: $src_vars_version" - echo - echo -e "\033[1;31mVersion mismatch: [$user_vars]\e[0m" - echo - echo "Attempting to patch user profile..." - echo - if [ -f $src_path/patch_notes.txt ]; then - echo -e "\e[31mPatch notes:" - cat $src_path/patch_notes.txt - echo -e "\e[0m" + echo >&3 + echo -e "\e[31mUser profile is not up to date.\e[0m" >&3 + echo "User profile: $profile_used" >&3 + echo "User version: $user_vars_version" >&3 + echo "Source version: $src_vars_version" >&3 + echo >&3 + echo -e "\033[1;31mVersion mismatch: [$user_vars]\e[0m" >&3 + echo >&3 + echo "Attempting to patch user profile..." >&3 + echo >&3 + if [ -f "$src_path"/patch_notes.txt ]; then + echo -e "\e[31mPatch notes:" >&3 + cat "$src_path"/patch_notes.txt + echo -e "\e[0m" >&3 fi - echo - bash $home/$repo/scripts/patch.sh + echo >&3 + bash "$home"/$repo/scripts/patch.sh exit 1 else - echo -e "\e[32mUser profile is up to date.\e[0m" - echo "User version: $user_vars_version" + echo -e "\e[32mUser profile is up to date.\e[0m" >&3 + echo "User profile: $profile_used" >&3 + echo "Profile version: $user_vars_version" >&3 fi fi - # Check that printcfg service is enabled -echo -echo "Checking $repo service..." +echo >&3 +echo "Checking $repo service..." >&3 if systemctl is-enabled $repo.service | grep -q "enabled" then # Check if printcfg service is running if systemctl is-active $repo.service | grep -q "active" then - echo -e "\e[32m$repo service is active.\e[0m" + echo -e "\e[32m$repo service is active.\e[0m" >&3 else - echo -e "\e[31m$repo service is not running.\e[0m" + echo -e "\e[31m$repo service is not running.\e[0m" >&3 exit 1 fi else - echo -e "\e[31m$repo service is not enabled.\e[0m" + echo -e "\e[31m$repo service is not enabled.\e[0m" >&3 exit 1 fi -echo +echo >&3 exit 0 \ No newline at end of file diff --git a/src/find_string.py b/src/find_string.py new file mode 100644 index 0000000..a0338bc --- /dev/null +++ b/src/find_string.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +# Copyright (C) 2023 Chris Laprade (chris@rootiest.com) +# +# This file is part of printcfg. +# +# printcfg is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# printcfg is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with printcfg. If not, see . + +import datetime +import getpass +import logging +import os +import sys + +S_TEXT = sys.argv[1] +F_NAME = sys.argv[2] + +logger: logging.Logger = logging.getLogger(__name__) + +# Get the current user name +current_user = getpass.getuser() +user_home = os.path.expanduser("~") +# Set the logfile +logfile = f"{user_home}/printcfg/logs/find_string.log" + +# Check the date of the first log entry +# If it is older than 30 days, delete the logfile +if os.path.exists(logfile): + with open(logfile, "r", encoding="utf-8") as file: + first_line = file.readline() + if first_line: + first_line = first_line.split(" - ")[0] + first_date = datetime.datetime.strptime(first_line, "%Y-%m-%d %H:%M:%S,%f") + thirty_days_ago = datetime.datetime.now() - datetime.timedelta(days=30) + if first_date < thirty_days_ago: + os.remove(logfile) + +# Set the logging level +logger.setLevel(logging.DEBUG) +formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") +handler = logging.FileHandler(logfile) +handler.setFormatter(formatter) +logger.addHandler(handler) + +# Log start of script +logger.info("Starting script: %s", __file__) + + +def check_file(file_name: str) -> bool: + # Check if the file exists + if not os.path.exists(file_name): + logger.error("File not found: %s", file_name) + return False + # Check if the file is readable + if not os.access(file_name, os.R_OK): + logger.error("File is not readable: %s", file_name) + return False + # Check if the file is writable + if not os.access(file_name, os.W_OK): + logger.error("File is not writable: %s", file_name) + return False + return True + + +def find_string(search_text: str, file_name: str) -> str: + """Search for a string in a file. + + Arguments: + search_text: The text to search for. + file_name: The name of the file to search. + + Returns: + The rest of the line containing the search_text. + """ + # Check if the file is accessible + if not check_file(file_name): + return "File not accessible." + # Open the file in read mode + with open(file_name, "r", encoding="utf-8") as sfile: + # Read each line + for line in sfile: + # Strip the newline character at the end + line = line.rstrip("\n") + # Check if the search text is in the line + if search_text in line: + # Return the rest of the line + # after the search text + logger.info("Search text found: %s", search_text) + logger.info("File name: %s", file_name) + logger.info("Line: %s", line) + logger.info("Rest of line: %s", line.split(search_text)[1]) + return line.split(search_text)[1] + # If the search text was not found, return an error + logger.error("Search text not found: %s", search_text) + logger.info("File name: %s", file_name) + return "Search text not found." + + +def string_exists(search_text: str, file_name: str) -> bool: + """Search for a string in a file. + + Arguments: + search_text: The text to search for. + file_name: The name of the file to search. + + Returns: + The rest of the line containing the search_text. + """ + # Check if the file is accessible + if not check_file(file_name): + return False + # Open the file in read mode + with open(file_name, "r", encoding="utf-8") as filee: + # Read each line + for line in filee: + # Strip the newline character at the end + line = line.rstrip("\n") + # Check if the search text is in the line + if search_text in line: + # Return the rest of the line + # after the search text + logger.info("Search text found: %s", search_text) + logger.info("File name: %s", file_name) + logger.info("Line: %s", line) + return True + # If the search text was not found, return an error + logger.error("Search text not found: %s", search_text) + logger.info("File name: %s", file_name) + return False + + +# Check if the script was run from the command line +if __name__ == "__main__": + # Log the current user + logger.info("Current user: %s", current_user) + # Log arguments + logger.info("Arguments: %s", sys.argv) + # Check for help argument + if len(sys.argv) == 2 and sys.argv[1] == "--help" or sys.argv[1] == "-h": + print("Usage: find_string.py [options]") + print("Search for a string in a file.") + print("Example: find_string.py 'hello world' hello.txt") + print("Options:") + print(" --exists, -e Search for the string and return True or False.") + print(" --help, -h Show this help message and exit.") + exit(0) + if len(sys.argv) == 3: + # Call the find_string function + result = find_string(S_TEXT, F_NAME) + # Return the result + print(result) + elif len(sys.argv) == 4 and sys.argv[3] == "--exists" or sys.argv[3] == "-e": + # Call the find_string function + if string_exists(S_TEXT, F_NAME): + exists = "True" + else: + exists = "False" + # Return the result + print(exists) + else: + # Print an error message + print("Usage: find_string.py ") + # Exit with an error code + exit(1) +else: + # Print an error message + print("This script must be run from the command line.") + # Exit with an error code + sys.exit(1) diff --git a/src/gen_service.py b/src/gen_service.py index ff1b55d..26f7998 100644 --- a/src/gen_service.py +++ b/src/gen_service.py @@ -1,33 +1,29 @@ #!/usr/bin/env python3 - # Copyright (C) 2023 Chris Laprade (chris@rootiest.com) -# +# # This file is part of printcfg. -# +# # printcfg is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # printcfg is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with printcfg. If not, see . -# This script generates a service file for printcfg. - -#!/usr/bin/env python3 +"""Generate a service file for printcfg.""" import os import sys -import subprocess if len(sys.argv) < 3: USER = os.environ["USER"] GROUP = os.environ["USER"] - HOME= os.path.expanduser('~') + HOME = os.path.expanduser("~") else: USER = sys.argv[1] GROUP = sys.argv[1] @@ -35,8 +31,9 @@ # Service name and configuration file SERVICE_NAME = "printcfg" -SERVICE_FILE = f"/etc/systemd/system/{SERVICE_NAME}.service" +SERVICE_LINK = f"/etc/systemd/system/{SERVICE_NAME}.service" SERVICE_PATH = f"{HOME}/{SERVICE_NAME}" +SERVICE_FILE = f"{HOME}/{SERVICE_NAME}/src/{SERVICE_NAME}.service" # Path to the Python script PYTHON_SCRIPT = f"{SERVICE_PATH}/src/{SERVICE_NAME}.py" @@ -46,60 +43,50 @@ MODE = sys.argv[1] elif len(sys.argv) < 0: print("Please provide the 'install' argument to install the service.") -else: - if sys.argv[3] == "install": - if not PYTHON_SCRIPT: - print("Please provide the path to the Python script as an argument.") - sys.exit(1) - - # Create the service file - service_content = f"""\ - [Unit] - Description=Print Configuration Service - Requires=klipper.service - After=klipper.service - - [Service] - Mode=oneshot - User={USER} - Group={GROUP} - RemainAfterExit=yes - ExecStart={PYTHON_EXECUTABLE} {PYTHON_SCRIPT} - WorkingDirectory={os.path.dirname(SERVICE_PATH)} - TimeoutStartSec=0 +elif len(sys.argv) == 4 and sys.argv[3] == "install": + # Create the service file + service_content = f"""\ + [Unit] + Description=Print Configuration Service + Requires=klipper.service + After=klipper.service - [Install] - WantedBy=default.target - """ - - print("Installing service...") - print(f"Service file: {SERVICE_FILE}") - print(f"Python script: {PYTHON_SCRIPT}") - print(f"Python executable: {PYTHON_EXECUTABLE}") - print(f"Working directory: {os.path.dirname(SERVICE_PATH)}") + [Service] + Mode=oneshot + User={USER} + Group={GROUP} + RemainAfterExit=yes + ExecStart={PYTHON_EXECUTABLE} {PYTHON_SCRIPT} + WorkingDirectory={os.path.dirname(SERVICE_PATH)} + TimeoutStartSec=0 - os.makedirs(os.path.dirname(SERVICE_FILE), exist_ok=True) - with open(SERVICE_FILE, "w", encoding="utf-8") as service: - service.write(service_content) + [Install] + WantedBy=default.target + """ + print("Installing service...") + print(f"Service file: {SERVICE_FILE}") + print(f"Python script: {PYTHON_SCRIPT}") + print(f"Python executable: {PYTHON_EXECUTABLE}") + print(f"Working directory: {os.path.dirname(SERVICE_PATH)}") + os.makedirs(os.path.dirname(SERVICE_FILE), exist_ok=True) + with open(SERVICE_FILE, "w", encoding="utf-8") as service: + service.write(service_content) + # Set the appropriate permissions for the service configuration file + os.chmod(SERVICE_FILE, 0o644) + # Symbolic link to the service file + os.symlink(SERVICE_FILE, SERVICE_LINK) + # Reload systemd to recognize the new service + os.system("systemctl daemon-reload") + # Enable and start the service + os.system(f"systemctl enable {SERVICE_NAME}") + os.system(f"systemctl start {SERVICE_NAME}") + # Check the status of the service + os.system(f"systemctl status {SERVICE_NAME}") - # Set the appropriate permissions for the service configuration file - os.chmod(SERVICE_FILE, 0o644) - - # Reload systemd to recognize the new service - os.system("systemctl daemon-reload") - - # Enable and start the service - os.system(f"systemctl enable {SERVICE_NAME}") - os.system(f"systemctl start {SERVICE_NAME}") - - # Check the status of the service - os.system(f"systemctl status {SERVICE_NAME}") - - # Symbolic link to the executable - os.symlink(PYTHON_SCRIPT, f"/usr/local/bin/{SERVICE_NAME}") - # Set the appropriate permissions for the executable - os.chmod(f"/usr/local/bin/{SERVICE_NAME}", 0o755) - - else: - print("Please provide the 'install' argument to install the service.") - sys.exit(1) \ No newline at end of file + # Symbolic link to the executable + os.symlink(PYTHON_SCRIPT, f"/usr/local/bin/{SERVICE_NAME}") + # Set the appropriate permissions for the executable + os.chmod(f"/usr/local/bin/{SERVICE_NAME}", 0o755) +else: + print("Please provide the 'install' argument to install the service.") + sys.exit(1) diff --git a/src/printcfg.py b/src/printcfg.py index 9f586ce..888f959 100755 --- a/src/printcfg.py +++ b/src/printcfg.py @@ -26,28 +26,38 @@ # remove: Remove the printcfg service # update: Update printcfg -#!/usr/bin/env python3 - -import os -import sys +""" printcfg - A configuration manager for Klipper printers.""" +import datetime import getpass -import subprocess import logging -import datetime +import os +import subprocess +import sys logger: logging.Logger = logging.getLogger(__name__) # Set the repo name REPO = "printcfg" - +# Set arguments +ARGUMENTS_LIST = [ + "help", + "install", + "restart", + "change", + "remove", + "update", + "repair", + "branch", + "status", +] # Get the current user name current_user = getpass.getuser() user_home = os.path.expanduser("~") -profile_path = f"{user_home}/printer_data/user_profile.cfg" -setup_script = f"{user_home}/printcfg/scripts/setup.sh" +profile_path = f"{user_home}/printer_data/config/user_profile.cfg" +setup_script = f"{user_home}/{REPO}/scripts/setup.sh" # Set the logfile -logfile = f"{user_home}/printcfg/logs/printcfg.log" +logfile = f"{user_home}/{REPO}/logs/{REPO}.log" # Check the date of the first log entry # If it is older than 30 days, delete the logfile @@ -56,18 +66,26 @@ first_line = file.readline() if first_line: first_line = first_line.split(" - ")[0] - first_line = datetime.datetime.strptime(first_line, "%Y-%m-%d %H:%M:%S,%f") + first_date = datetime.datetime.strptime(first_line, "%Y-%m-%d %H:%M:%S,%f") thirty_days_ago = datetime.datetime.now() - datetime.timedelta(days=30) - if first_line < thirty_days_ago: + if first_date < thirty_days_ago: os.remove(logfile) # Check if the logfile exists -if not os.path.exists(f"{user_home}/printcfg/logs/"): - # Create the log directory - os.mkdir(f"{user_home}/printcfg/logs/") +log_dir = f"{user_home}/{REPO}/logs/" +if not os.path.exists(log_dir): + try: + # Create the log directory + os.makedirs(log_dir) + except OSError as err: + print(f"Error creating log directory: {err}") # Create the logfile - with open(logfile, "w", encoding="utf-8") as file: - pass + try: + with open(logfile, "w", encoding="utf-8") as file: + pass + logging.info("Created log file: %s", logfile) + except OSError as err: + logging.error("Error creating log file: %s", err) # Set the logging level logger.setLevel(logging.DEBUG) @@ -77,99 +95,131 @@ logger.addHandler(handler) -def find_profile(path): - logger.debug("Searching for profile name in file: {}".format(path)) +def show_help(): + """Show the help message.""" + logger.info("Showing help message...") + print(f"Usage: {sys.argv[0]} [install|change|remove|update|help]") + print(f" install: Install the {REPO} service") + print(f" restart: Restart the {REPO} service") + print(" change: Change the current profile") + print(f" branch: Change the current {REPO} branch") + print(f" remove: Remove {REPO} service") + print(f" update: Update {REPO}") + print(f" status: Show the status of the {REPO} service") + print(f" repair: Repair the {REPO} service") + print(" help: Show this help message") + logger.info("Help message shown.") + sys.exit(0) + + +def find_profile(path: str): + """Find the profile name in the given file.""" + logger.debug("Searching for profile name in file: %s", path) # Find the profile name (Eg: '# Profile: default' = 'default') - with open(path, "r", encoding="utf-8") as file: - for line in file: - if line.startswith("# Profile: "): - logger.debug("Found profile name: {}".format(line[11:].strip())) + with open(path, "r", encoding="utf-8") as p_file: + for line in p_file: + if line.startswith("# Profile:"): + the_profile = line[10:].strip() + logger.debug("Found profile name: %s", the_profile) # Return the profile name - return line[11:].strip() + return the_profile # If no profile was found, raise an error - logger.error("Profile not found in file: {}".format(path)) - raise ValueError("Profile not found in file: {}".format(path)) + logger.error("Profile not found in file: %s", path) + raise ValueError(f"Profile not found in file: {path}") def normal_ops(): + """Run the script normally.""" logger.info("Starting normal operations...") + try: + profile_name = find_profile(profile_path) + except ValueError as errnorm: + logger.error("Error: %s", str(errnorm)) + profile_name = "default" + logger.info("Using default profile.") try: # Run the shell script at startup - subprocess.Popen(["/bin/bash", setup_script]) + subprocess.Popen(["/bin/bash", setup_script, profile_name]) logger.info("Startup script complete.") - except Exception as e: + except subprocess.CalledProcessError as errsetscript: # Log the error - logger.error("Error running startup script: {}".format(str(e))) + logger.error("Error running startup script: %s", str(errsetscript)) # Exit with error - exit(1) - # Exit successfully + sys.exit(1) + # Exit gracefully logger.info("Startup script complete, exiting.") - exit(0) + sys.exit(0) def generate_service(): - logger.info("Generating service...") + """Generate the printcfg service.""" + logger.info("Generating %s service...", REPO) # Define the path to the second script script_dir = f"{user_home}/{REPO}/" - logger.debug("Script directory: {}".format(script_dir)) + logger.debug("Script directory: %s", script_dir) mode = sys.argv[1] - logger.debug("Mode: {}".format(mode)) + logger.debug("Mode: %s", mode) # Define the path to the second script - script_path = f"{script_dir}/src/gen_service.py" - logger.debug("Script path: {}".format(script_path)) + script_path = f"{script_dir}src/gen_service.py" + logger.debug("Script path: %s", script_path) # Check if the second script exists if not os.path.isfile(script_path): print(f"Error: The script '{script_path}' does not exist.") - logger.error("Error: The script '{}' does not exist.".format(script_path)) + logger.error("Error: The script '%s' does not exist.", script_path) return # Start the second script as root with the current user name as the first argument - command = ["sudo", "python3", script_path, current_user, user_home, mode] - logger.debug("Executing command: {}".format(command)) + command = f"sudo python3 {script_path} {current_user} {user_home} {mode}" + logger.debug("Executing command: %s", command) print(f"Executing command: {command}") try: - result = subprocess.run(command, capture_output=True) - except subprocess.CalledProcessError as e: - print(f"Error: The subprocess returned an error.") - print(e.stderr) - logger.error("Error: The subprocess returned an error: {}".format(e.stderr)) + result = subprocess.run(command, capture_output=True, check=False) + except subprocess.CalledProcessError as errgen: + print("Error: The subprocess returned an error.") + print(errgen.stderr) + logger.error("Error: The subprocess returned an error: %s", errgen.stderr) return - logger.debug("Command output: {}".format(result.stdout.decode("utf-8"))) + logger.debug("Command output: %s", result.stdout.decode("utf-8")) if result.returncode != 0: print(f"Error: The command '{command}' failed with code {result.returncode}.") - logger.error("Error: The command '{}' failed with code {}.".format(command, result.returncode)) + logger.error( + "Error: The command '%s' failed with code %s.", command, result.returncode + ) print(f"Output from command: {result.stdout.decode('utf-8')}") print(f"Error from command: {result.stderr.decode('utf-8')}") return - # Exit successfully - logger.info("Service generated successfully.") - exit(0) + # Exit gracefully + logger.info("%s service generated successfully.", REPO) + sys.exit(0) -def change_profile(profile): +def change_profile(profile_name: str): + """Change the profile.""" # Define the path to the second script script_path = f"{user_home}/{REPO}/scripts/change_profile.sh" - logger.debug("Script path: {}".format(script_path)) + logger.debug("Script path: %s", script_path) # Check if the second script exists if not os.path.isfile(script_path): print(f"Error: The script '{script_path}' does not exist.") - logger.error("Error: The script '{}' does not exist.".format(script_path)) + logger.error("Error: The script '%s' does not exist.", script_path) return # Start the change profile script - command = ["bash", script_path, profile] - logger.debug("Executing command: {}".format(command)) + command = ["bash", script_path, profile_name] + logger.debug("Executing command: %s", command) try: subprocess.run(command, check=True) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError as errprofile: print("Error: The subprocess returned an error.") - print(e.stderr) - logger.error("Error: The subprocess returned an error: {}".format(e.stderr)) - # Exit successfully - logger.info("Profile changed successfully.") - exit(0) + print(errprofile.stderr) + logger.error("Error: The subprocess returned an error: %s", errprofile.stderr) + # Exit gracefully + logger.info("Profile changed to %s successfully.", profile_name) + print(f"Profile changed to {profile_name} successfully.") + sys.exit(0) def update_printcfg(): + """Update printcfg.""" # Define the path to the second script script_path = f"{user_home}/{REPO}/scripts/install.sh" # Check if the second script exists @@ -177,42 +227,158 @@ def update_printcfg(): print(f"Error: The script '{script_path}' does not exist.") return # Find the current profile - profile = find_profile(profile_path) + profile_name = find_profile(profile_path) # Start the update script - command = ["bash", script_path, profile] - logger.debug("Executing command: {}".format(command)) + command = ["bash", script_path, profile_name] + logger.debug("Executing command: %s", command) try: - subprocess.run(command) - except subprocess.CalledProcessError as e: + subprocess.run(command, check=True) + except subprocess.CalledProcessError as errr: print("Error: The subprocess returned an error.") - print(e.stderr) - logger.error("Error: The subprocess returned an error: {}".format(e.stderr)) - # Exit successfully - logger.info("Update complete.") - exit(0) + print(errr.stderr) + logger.error("Error: The subprocess returned an error: %s", errr.stderr) + # Exit gracefully + logger.info("%s updated successfully.", REPO) + print(f"{REPO} updated successfully.") + sys.exit(0) + + +def restart_service(service_name: str): + """Restarts a systemctl service. + + Args: + service_name: The name of the systemctl service to restart. + + Returns: + True if the service was restarted successfully, False otherwise. + """ + command = ["systemctl", "restart", f"{service_name}.service"] + logger.debug("Executing command: %s", command) + try: + subprocess.check_call(command) + logger.info("Service '%s' restarted successfully.", service_name) + print(f"Service '{service_name}' restarted successfully.") + return True + except subprocess.CalledProcessError as errserv: + logger.error("Error restarting %s service: %s", service_name, errserv) + print(f"Error restarting {service_name} service: {errserv}") + return False + + +def change_branch(branch_name: str): + """Changes the branch of the printcfg repo.""" + logger.info("Changing to branch '%s'.", branch_name) + # Define the path to the second script + script_path = f"{user_home}/{REPO}/scripts/install.sh" + logger.debug("Script: %s", script_path) + # Check if the second script exists + if not os.path.isfile(script_path): + print(f"Error: The script '{script_path}' does not exist.") + return + # Find the current profile + profile_name = find_profile(profile_path) + # Start the change branch script + command = ["bash", script_path, profile_name, branch_name] + logger.debug("Executing command: %s", command) + logger.debug( + "Changing to branch '%s' with profile '%s'.", branch_name, profile_name + ) + print(f"Changing to branch '{branch_name}' with profile '{profile_name}'.") + try: + subprocess.run(command, check=False) + except subprocess.CalledProcessError as errbranch: + print("Error: The subprocess returned an error.") + print(errbranch.stderr) + logger.error("Error: The subprocess returned an error: %s", errbranch.stderr) + # Exit gracefully + logger.info("Succesfully changed to branch '%s'.", branch_name) + print(f"Succesfully changed to branch '{branch_name}'.") + sys.exit(0) + + +def repair_printcfg(): + """Repairs printcfg.""" + # Define the path to the second script + script_path = f"{user_home}/{REPO}/scripts/setup.sh" + # Check if the second script exists + if not os.path.isfile(script_path): + print(f"Error: The script '{script_path}' does not exist.") + return + # Find the current profile + profile_name = find_profile(profile_path) + # Start the update script + command = ["bash", script_path, profile_name, "force"] + logger.debug("Executing command: %s", command) + try: + subprocess.run(command, check=True) + except subprocess.CalledProcessError as errepair: + print("Error: The subprocess returned an error.") + print(errepair.stderr) + logger.error("Error: The subprocess returned an error: %s", errepair.stderr) + # Exit gracefully + logger.info("Repairing %s completed successfully.", REPO) + print(f"Repairing {REPO} completed successfully.") + sys.exit(0) def remove_printcfg(): + """Remove printcfg from the system.""" # Define the path to the second script script_path = f"{user_home}/{REPO}/scripts/remove_{REPO}.sh" - logger.debug("Script path: {}".format(script_path)) + logger.debug("Script path: %s", script_path) # Check if the second script exists if not os.path.isfile(script_path): print(f"Error: The script '{script_path}' does not exist.") - logger.error("Error: The script '{}' does not exist.".format(script_path)) + logger.error("Error: The script '%s' does not exist.", script_path) return # Start the second script as root with the current user name as the first argument command = ["bash", script_path] - logger.debug("Executing command: {}".format(command)) + logger.debug("Executing command: %s", command) try: - subprocess.run(command) - except subprocess.CalledProcessError as e: + subprocess.run(command, check=True) + except subprocess.CalledProcessError as erremove: print("Error: The subprocess returned an error.") - print(e.stderr) - logger.error("Error: The subprocess returned an error: {}".format(e.stderr)) - # Exit successfully - logger.info("Printcfg removed successfully.") - exit(0) + print(erremove.stderr) + logger.error("Error: The subprocess returned an error: %s", erremove.stderr) + # Exit gracefully + logger.info("%s removed successfully.", REPO) + print(f"{REPO} removed successfully.") + sys.exit(0) + + +def show_status(service_name: str): + """Show the status of a systemctl service. + + Args: + service_name: The name of the systemctl service to restart. + + Returns: + True if the status was displayed successfully, False otherwise. + """ + # Get the systemctl status + command = ["systemctl", "status", f"{service_name}.service"] + logger.debug("Executing command: %s", command) + try: + result = subprocess.run(command, capture_output=True, check=False) + except subprocess.CalledProcessError as errstat: + print("Error: The subprocess returned an error.") + print(errstat.stderr) + logger.error("Error: The subprocess returned an error: %s", errstat.stderr) + return False + logger.debug("Command output: %s", result.stdout.decode("utf-8")) + if result.returncode != 0: + print(f"Error: The command '{command}' failed with code {result.returncode}.") + logger.error( + "Error: The command '%s' failed with code %s.", command, result.returncode + ) + print(f"Output from command: {result.stdout.decode('utf-8')}") + print(f"Error from command: {result.stderr.decode('utf-8')}") + return False + # Print the status + print(result.stdout.decode("utf-8")) + # Exit gracefully + logger.info("Status shown successfully.") + return True if __name__ == "__main__": @@ -222,11 +388,10 @@ def remove_printcfg(): normal_ops() sys.exit(1) # Check the argument - if sys.argv[1] not in ["install", "change", "remove", "update", "default"]: - print( - "Error: The argument must be either install, change, remove, update, or default." - ) - logger.error("Error: The argument must be either install, change, remove, update, or default.") + if sys.argv[1] not in ARGUMENTS_LIST: + print(f"Error: Invalid Argument: {sys.argv[1]}") + logger.error("Error: Invalid Argument: %s", sys.argv[1]) + show_help() sys.exit(1) # If the argument is 'install' start the script as root if sys.argv[1] == "install": @@ -244,7 +409,7 @@ def remove_printcfg(): profile = sys.argv[2] logger.info("Running change operations.") profile_path = f"{user_home}/{REPO}/profiles/{profile}" - logger.debug("Profile path: {}".format(profile_path)) + logger.debug("Profile path: %s", profile_path) print(f"Changing to profile '{profile}'") # If the profile is 'backup' then skip the check if profile == "backup": @@ -254,10 +419,10 @@ def remove_printcfg(): # If the profile path does not exist, exit if not os.path.isdir(profile_path): print(f"Error: The profile '{profile}' does not exist.") - logger.error("Error: The profile '{}' does not exist.".format(profile)) + logger.error("Error: The profile '%s' does not exist.", profile) sys.exit(1) else: - logger.info("Changing to profile '{}'.".format(profile)) + logger.info("Changing to profile '%s'.", profile) change_profile(profile) # If the argument is 'remove' elif sys.argv[1] == "remove": @@ -266,7 +431,33 @@ def remove_printcfg(): elif sys.argv[1] == "update": logger.info("Running update operations.") update_printcfg() - + elif sys.argv[1] == "status": + logger.info("Running status operations.") + show_status(REPO) + elif sys.argv[1] == "restart": + logger.info("Running restart operations.") + restart_service(REPO) + elif sys.argv[1] == "repair": + logger.info("Running repair operations.") + repair_printcfg() + elif sys.argv[1] == "branch": + logger.info("Running branch operations.") + # Make sure the branch was provided + if len(sys.argv) != 3: + print("Error: The branch script requires two arguments.") + print(f"Usage: python3 {REPO}.py branch ") + logger.error("Error: The branch script requires two arguments.") + sys.exit(1) + else: + branch_arg = sys.argv[2] + change_branch(branch_arg) + elif sys.argv[1] == "help": + logger.info("Running help operations.") + show_help() else: logger.info("Running normal operations.") normal_ops() + + # Exit gracefully + logger.info("%s completed successfully.", REPO) + exit(0) diff --git a/scripts/read_patch_notes.py b/src/read_patch_notes.py similarity index 91% rename from scripts/read_patch_notes.py rename to src/read_patch_notes.py index 69f74a0..3f6646c 100644 --- a/scripts/read_patch_notes.py +++ b/src/read_patch_notes.py @@ -1,37 +1,35 @@ #!/usr/bin/env python3 - # Copyright (C) 2023 Chris Laprade (chris@rootiest.com) -# +# # This file is part of printcfg. -# +# # printcfg is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # printcfg is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with printcfg. If not, see . -#!/usr/bin/env python3 - # This script reads the patch notes file and returns the highest version number. -import sys import re +import sys + def find_highest_version(file_name): """Finds highest version in patch notes.""" highest_version = None - with open(file_name, 'r', encoding="utf-8") as file: + with open(file_name, "r", encoding="utf-8") as file: content = file.read() - pattern = r'(\d+\.\d+\.\d+):' + pattern = r"(\d+\.\d+\.\d+):" versions = re.findall(pattern, content) for version in versions: diff --git a/src/requirements.txt b/src/requirements.txt index b2ef71f..1edbc5c 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,4 +1,5 @@ python-apt==0.7.8 python-dateutil==2.8.2 requests==2.30.0 -watchdog==3.0.0 \ No newline at end of file +watchdog==3.0.0 +GitPython==3.1.31 \ No newline at end of file diff --git a/scripts/search_replace.py b/src/search_replace.py similarity index 88% rename from scripts/search_replace.py rename to src/search_replace.py index d04eda6..e645395 100644 --- a/scripts/search_replace.py +++ b/src/search_replace.py @@ -17,8 +17,6 @@ # You should have received a copy of the GNU General Public License # along with printcfg. If not, see . -#!/usr/bin/env python3 - # This code searches for a string in a file and replaces the whole line # containing the string with a different string. # The search is case sensitive. @@ -40,12 +38,12 @@ # Example: # python3 search_replace.py "version" "version: 1.0.0" "patch_notes.txt" -import sys -import os +import datetime import getpass -import re import logging -import datetime +import os +import re +import sys logger: logging.Logger = logging.getLogger(__name__) @@ -62,9 +60,9 @@ first_line = file.readline() if first_line: first_line = first_line.split(" - ")[0] - first_line = datetime.datetime.strptime(first_line, "%Y-%m-%d %H:%M:%S,%f") + first_date = datetime.datetime.strptime(first_line, "%Y-%m-%d %H:%M:%S,%f") thirty_days_ago = datetime.datetime.now() - datetime.timedelta(days=30) - if first_line < thirty_days_ago: + if first_date < thirty_days_ago: os.remove(logfile) # Set the logging level @@ -76,7 +74,10 @@ def simple_search_and_replace(search_text, replace_text, file_name): - """Searches for the line containing the search_text and replaces the whole line with the replace_text and saves the updated file over the original. + """ + Searches for the line containing the search_text + and replaces the whole line with the replace_text + and saves the updated file over the original. Args: search_text: The text to search for. @@ -86,7 +87,7 @@ def simple_search_and_replace(search_text, replace_text, file_name): Returns: A status indicating whether the change was successful. """ - + # Log the input logger.debug( "search_and_replace() called with: search_text=%s, replace_text=%s, file_name=%s", @@ -94,7 +95,7 @@ def simple_search_and_replace(search_text, replace_text, file_name): replace_text, file_name, ) - + if search_text is None or replace_text is None or file_name is None: logger.error( "search_and_replace() failed due to invalid input: search_text=%s, replace_text=%s, file_name=%s", @@ -111,13 +112,17 @@ def simple_search_and_replace(search_text, replace_text, file_name): found = False for i, line in enumerate(lines): if search_text in line: - lines[i] = replace_text + '\n' + lines[i] = replace_text + "\n" found = True - logger.debug("search_and_replace() found the search_text %s", search_text) - break + logger.debug( + "search_and_replace() did not find the search_text %s", search_text + ) + break if not found: - logger.debug("search_and_replace() did not find the search_text %s", search_text) + logger.debug( + "search_and_replace() did not find the search_text %s", search_text + ) lines.insert(0, replace_text + "\n") logger.debug("search_and_replace() inserted the replace_text %s", replace_text) @@ -129,7 +134,10 @@ def simple_search_and_replace(search_text, replace_text, file_name): def search_and_replace(search_text: str, replace_text: str, file_name: str) -> bool: - """Searches for the line containing the search_text and replaces the whole line with the replace_text and saves the updated file over the original. + """ + Searches for the line containing the search_text + and replaces the whole line with the replace_text + and saves the updated file over the original. Args: search_text: The text to search for. @@ -200,4 +208,4 @@ def search_and_replace(search_text: str, replace_text: str, file_name: str) -> b if status: print("The change was successful.") else: - print("The text to search for was not found.") + print("The text was added.")