Merge branch 'development' into main

This commit is contained in:
PhotoLinux 2021-05-08 21:46:41 +02:00
commit d7a2221941
6 changed files with 474 additions and 498 deletions

View file

@ -1,5 +1,15 @@
# Changelog Backuppy # Changelog Backuppy
## [0.8] - 2021-05-07
### Added
- GUI-mode: Introduce "Browse"-button on directory-selection dialogs
- GUI-mode: Installing necessary PySide2 package if not existing
## [0.7] - 2021-05-06
### Added
- Reworked "install.sh" to call "install.py"
- Launches graphical installer when called with "--gui" option: "install.sh --gui"
## [0.6] - 2021-05-06 ## [0.6] - 2021-05-06
### Added ### Added
- Write alias to Backuppy.sh into .bashrc/.zshrc only if not already existing - Write alias to Backuppy.sh into .bashrc/.zshrc only if not already existing

View file

@ -6,9 +6,9 @@ Name: Backuppy
Description: Make daily backups with Backuppy to avoid losing your data. Description: Make daily backups with Backuppy to avoid losing your data.
Installation: execute `chmod +x install.sh && .\install.sh` Installation: execute `chmod +x install.sh && ./install.sh`
Install. GUI: execute `chmod +x install.sh && .\install.sh --gui` Install. GUI: execute `chmod +x install.sh && ./install.sh --gui`
Usage: execute `backuppy` Usage: execute `backuppy`
@ -16,32 +16,32 @@ Author: Joël Schurter
Licence: GPL3 Licence: GPL3
More infos: see constants and README.md More infos: See README.md and CHANGELOG.md
# ToDo # ToDo
- add a log-file for the rsync errors - add a log-file for the rsync errors
- check user-input for validity
# Dependencies # Dependencies
- rsync (because Backuppy makes its backups with rsync) - rsync (because Backuppy makes its backups with rsync)
execute `sudo pacman -S rsync` on Arch/Manjaro
execute `sudo apt install rsync` on Debian/Ubuntu execute `sudo apt install rsync` on Debian/Ubuntu
execute `sudo pacman -S rsync` on Arch/Manjaro execute `sudo dnf install rsync` on Fedora
execute `sudo zypper install rsync` on openSUSE
# Dependencies for the graphical installer: # Dependencies for the graphical installer:
- pip (the python package manager) - pip (the python package manager)
execute `sudo apt install python3-pip` on Debian/Ubuntu
execute `sudo pacman -S pip` on Arch/Manjaro execute `sudo pacman -S pip` on Arch/Manjaro
- pip package 'PySide2' execute `sudo apt install python3-pip` on Debian/Ubuntu
execute `pip3 install pyside2` on Debian/Ubuntu execute `sudo dnf install pip` on Fedora
execute `pip install pyside2` on Arch/Manjaro execute `sudo zypper install python3-pip` on openSUSE
# IMPORTANT
You have to remove the "backuppy" alias in your .bashrc or .zshrc before reinstall Backuppy.

View file

@ -1,343 +1,187 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
project: Backuppy project: Backuppy
version: 0.6 version: 0.8
file: install.py file: install.py
summary: main entry python file summary: python installer-script in CLI-mode
""" """
# Standard library imports # Standard library imports
import sys
import os import os
import time
# Third party imports
from PySide2 import QtWidgets
# local imports # local imports
from languages import english from languages import english
from languages import german from languages import german
# local globals # local globals
VERSION: str = "0.6" # ----------------------
EMAIL: str = "fotocoder@joschu.ch" VERSION: str = "0.8"
TARGET_SCRIPT: str = "Backuppy.sh" EMAIL = "fotocoder@joschu.ch"
EXCLUDE_FILE: str = "exclude.txt" EXCLUDE_FILE = "exclude.txt"
LANG_EN: str = "English" BACKUPPY_SCRIPT = "Backuppy.sh"
LANG_DE: str = "German" # ----------------------
LANGUAGE: str = LANG_EN MYDIR = os.getcwd()
MYDIR: str = os.environ.get("mydir") EXCLUDE: bool = False
if not MYDIR: SHELL = os.environ.get("SHELL")
MYDIR = os.getcwd() HOME = os.environ.get("HOME")
SOURCEDIR: str = None LANG_EN = "English"
EXCLUDE: bool = True LANG_DE = "German"
TARGETDIR: str = None LANGUAGE = LANG_EN
RSYNC_CMD: str = None RSYNC_CMD: str = None
def set_language(language):
global LANGUAGE
LANGUAGE = language
def trace(message_txt):
""" Print a formatted message to std out. """
print("[ OK ] " + message_txt)
def get_lang_text(search_str: str): def get_lang_text(search_str: str):
global LANGUAGE
""" Returns a string from the appropriate language file. """ """ Returns a string from the appropriate language file. """
return_str: str = eval("english." + search_str) return_str: str = eval("english." + search_str)
global LANGUAGE
if LANGUAGE == LANG_DE: if LANGUAGE == LANG_DE:
return_str = eval("german." + search_str) return_str = eval("german." + search_str)
return return_str return return_str
def trace(message_txt: str): def main_install_cli():
""" Print a formatted message to std out. """ language = input("Hello, first of all, which language do you prefer: German [DE] or English [EN]?\n> ")
print("[ OK ]" + message_txt) if language.upper() == "DE":
set_language(LANG_DE)
class BackuppyWizard(QtWidgets.QWizard): print("Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen!\n")
def __init__(self, parent=None):
super().__init__(parent)
self.addPage(Page01(self))
self.addPage(Page02(self))
self.addPage(Page03(self))
self.addPage(Page04(self))
self.addPage(Page05(self))
self.addPage(Page06(self))
self.addPage(Page07(self))
self.addPage(Page08(self))
self.addPage(Page09(self))
self.addPage(Page10(self))
self.setWindowTitle(english.intromsg1)
self.resize(640, 480)
class Page01(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel("Hello, first of all, which language do you prefer: English or German?")
# self.comboBox = QIComboBox(self)
self.comboBox = QtWidgets.QComboBox(self)
self.comboBox.addItem(LANG_EN, LANG_EN)
self.comboBox.addItem(LANG_DE, LANG_DE)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.comboBox)
self.setLayout(layout)
def validatePage(self):
global LANGUAGE
if self.comboBox.currentText() == LANG_DE:
LANGUAGE = LANG_DE
else: else:
LANGUAGE = LANG_EN print("Perfect, the English language package is now activated. Welcome!.\n")
return True
time.sleep(1)
class Page02(QtWidgets.QWizardPage): print("\n" + get_lang_text("intromsg1") + "\n")
def __init__(self, parent=None): time.sleep(1)
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout() print("\n" + get_lang_text("intromsg2") + "\n")
layout.addWidget(self.label1) time.sleep(1)
layout.addWidget(self.label2)
self.setLayout(layout)
def initializePage(self): # which Rsync options are available and which one you want to use
self.label1.setText(get_lang_text("languagepack")) print(get_lang_text("rsyncopt") + "\n")
self.label2.setText(get_lang_text("intromsg2")) time.sleep(1)
# asks if you want to exclude files/directories from backup and creates an exclude file in case of Yes
class Page03(QtWidgets.QWizardPage): exclude = input(get_lang_text("excludefile1") + "\n> ")
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel()
self.groupbox = QtWidgets.QGroupBox()
self.groupbox.setFlat(True)
self.radio1 = QtWidgets.QRadioButton()
self.radio2 = QtWidgets.QRadioButton()
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.radio1)
vbox.addWidget(self.radio2)
vbox.addStretch(1)
self.groupbox.setLayout(vbox)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.groupbox)
self.setLayout(layout)
def initializePage(self):
self.label.setText(get_lang_text("excludefile1"))
self.radio1.setText(get_lang_text("Yes"))
self.radio2.setText(get_lang_text("No"))
self.radio1.setChecked(True)
def validatePage(self):
global EXCLUDE global EXCLUDE
if self.radio1.isChecked(): if exclude.upper() in ("J", "Y"):
EXCLUDE = True EXCLUDE = True
print(get_lang_text("excludefile2") + "\n")
else: else:
EXCLUDE = False EXCLUDE = False
return True print(get_lang_text("excludefile3") + "\n")
time.sleep(1)
class Page04(QtWidgets.QWizardPage): # Asks for the source directory which should be saved
def __init__(self, parent=None): print(get_lang_text("srcdir1"))
super().__init__(parent) time.sleep(1)
self.label = QtWidgets.QLabel() sourcedir = input(get_lang_text("srcdir2") + "\n> ")
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
def initializePage(self): print(f"{get_lang_text('srcdir3_1')} {sourcedir} {get_lang_text('srcdir3_2')}")
global EXCLUDE time.sleep(1)
if EXCLUDE:
self.label.setText(get_lang_text("excludefile2"))
else:
self.label.setText(get_lang_text("excludefile3"))
class Page05(QtWidgets.QWizardPage): # asks for the destination directory in which the backup should be saved
def __init__(self, parent=None): targetdir = input(get_lang_text("targetdir1") + "\n> ")
super().__init__(parent) print(f"{get_lang_text('targetdir2_1')} {targetdir} {get_lang_text('targetdir2_2')}")
self.label1 = QtWidgets.QLabel() time.sleep(1)
self.label2 = QtWidgets.QLabel()
self.edit = QtWidgets.QLineEdit()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.edit)
self.setLayout(layout)
def initializePage(self): # collects all the information needed to execute the rsync command and creates it.
self.label1.setText(get_lang_text("srcdir1")) print(get_lang_text("collect") + "\n")
self.label2.setText(get_lang_text("srcdir2")) time.sleep(1)
exclude_file = os.path.join(MYDIR, EXCLUDE_FILE)
def validatePage(self): RSYNC_CMD = f"rsync -aqp --exclude-from={exclude_file} {sourcedir} {targetdir}"
global SOURCEDIR
SOURCEDIR = self.edit.text()
return True print(f"{RSYNC_CMD}")
time.sleep(1)
# Outro
print(get_lang_text("outro1"))
time.sleep(2)
print(get_lang_text("outro2") + " " + EMAIL)
class Page06(QtWidgets.QWizardPage): return True, EXCLUDE, RSYNC_CMD
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
def initializePage(self): def create_exclude_file(directory, exclude_file):
self.label1.setText(get_lang_text("srcdir3_1")) exclude_file = os.path.join(directory, exclude_file)
bold_text = f"<p><strong>{SOURCEDIR}</strong></p>" with open(exclude_file, "w") as fExclude:
self.label2.setText(bold_text) trace(f"creating exclude-file '{exclude_file}'.")
self.label3.setText(get_lang_text("srcdir3_2")) fExclude.write("\n")
def create_alias(shell, home_dir, directory, backuppy_script):
# alias entry in .bashrc or .zshrc
backuppy_script = os.path.join(directory, backuppy_script)
alias_str = f"alias backuppy='sudo {backuppy_script}'"
class Page07(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.edit = QtWidgets.QLineEdit()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.edit)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("targetdir1"))
def validatePage(self):
global TARGETDIR
TARGETDIR = self.edit.text()
return True
class Page08(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("targetdir2_1"))
bold_text = f"<p><strong>{TARGETDIR}</strong></p>"
self.label2.setText(bold_text)
self.label3.setText(get_lang_text("targetdir2_2"))
def validatePage(self):
global RSYNC_CMD, MYDIR, SOURCEDIR, TARGETDIR
RSYNC_CMD = f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {SOURCEDIR} {TARGETDIR}"
return True
class Page09(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("collect"))
global RSYNC_CMD
#self.label2.setText(f"{RSYNC_CMD}")
bold_text = f"<p><strong>{RSYNC_CMD}</strong></p>"
self.label2.setText(bold_text)
class Page10(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
self.setFinalPage(True)
def initializePage(self):
self.label1.setText(get_lang_text("outro1"))
self.label2.setText(get_lang_text("outro2"))
urlLink = f"<a href='mailto: {EMAIL}'>{EMAIL}</a>"
self.label3.setText(urlLink)
self.label3.setOpenExternalLinks(True)
def validatePage(self):
# create shell script with rsync command
create_shell_script(RSYNC_CMD)
return True
def create_shell_script(command_str: str):
rc_filepath: str = None
global MYDIR, EXCLUDE, TARGET_SCRIPT
TARGET_SCRIPT = os.path.join(MYDIR, TARGET_SCRIPT)
ALIAS_STR = f"alias backuppy='sudo {TARGET_SCRIPT}'"
current_shell = os.environ.get("SHELL")
user_home = os.environ.get("HOME")
## STEP 1: update shell config scripts with alias for backuppy
# Check for installed ZSH # Check for installed ZSH
if current_shell.upper().find("ZSH") > 0: if shell.upper().find("ZSH") > 0:
rc_filepath = os.path.join(user_home, ".zshrc") rc_filepath = os.path.join(home_dir, ".zshrc")
# Check for installed BASH # Check for installed BASH
if current_shell.upper().find("BASH") > 0: if shell.upper().find("BASH") > 0:
rc_filepath = os.path.join(user_home, ".bashrc") rc_filepath = os.path.join(home_dir, ".bashrc")
# Append our alias if not already existing # Append our alias if not already existing
if os.path.isfile(rc_filepath): if os.path.isfile(rc_filepath):
fileRc = open(rc_filepath, "r") # open file in read mode fileRc = open(rc_filepath, "r") # open file in read mode
backuppy_entry_exists = False backuppy_entry_exists = False
for line in fileRc: for line in fileRc:
if "alias backuppy=" in line: if "alias backuppy=" in line:
backuppy_entry_exists = True backuppy_entry_exists = True
break break
if not backuppy_entry_exists: if not backuppy_entry_exists:
trace(f"Writing {ALIAS_STR} to config file '{rc_filepath}'.") trace(f"Writing {alias_str} to config file '{rc_filepath}'.")
fileRc = open(rc_filepath, "a") # open file in append mode fileRc = open(rc_filepath, "a") # open file in append mode
fileRc.write("\n# Following line was created by Backuppy\n" + ALIAS_STR + "\n") fileRc.write("\n# Following line was created by Backuppy\n" + alias_str + "\n")
fileRc.close() fileRc.close()
## STEP 2: Create the exclude script if desired def create_backuppy_script(directory, backuppy_script, rsync_cmd):
if EXCLUDE: # creates the file 'Backuppy.sh'
global EXCLUDE_FILE backuppy_file = os.path.join(directory, backuppy_script)
EXCLUDE_FILE = os.path.join(MYDIR, EXCLUDE_FILE) with open(backuppy_file, "w") as fBackuppy:
with open(EXCLUDE_FILE, "w") as file2: trace(f"creating backuppy-file '{backuppy_file}'.")
trace(f"creating exclude-file '{EXCLUDE_FILE}'.") fBackuppy.write("#!/bin/bash\n" + rsync_cmd + "\n")
file2.writelines("\n")
## STEP 3: enter the rsync command in Backuppy.sh os.chmod(backuppy_file, 0o777) # make file executable
with open(TARGET_SCRIPT, "w") as file3:
trace(f"Writing rsync-command to file '{TARGET_SCRIPT}':\n {command_str}")
file3.writelines("#!/bin/bash" + "\n")
file3.writelines(command_str + "\n")
def do_the_install(is_exclude: bool, rsync_cmd: str):
""" Creates scripts and entries based on environment variables. """
if __name__ == '__main__': if is_exclude:
create_exclude_file(MYDIR, EXCLUDE_FILE)
if rsync_cmd:
create_backuppy_script(MYDIR, BACKUPPY_SCRIPT, rsync_cmd)
create_alias(SHELL, HOME, MYDIR, BACKUPPY_SCRIPT)
def main(argv):
trace(f"Starting Backuppy install.py v{VERSION}") trace(f"Starting Backuppy install.py v{VERSION}")
app = QtWidgets.QApplication() is_finalized = False
wizard = BackuppyWizard()
wizard.show()
app.exec_() if argv and argv[0] == "--gui":
from install_gui import main_install_gui
trace("Starting GUI-version.")
is_finalized, is_exclude, rsync_cmd = main_install_gui() # collect user input via GUI and store in env. variables
else:
trace("Starting CLI-version.\n")
is_finalized, is_exclude, rsync_cmd = main_install_cli() # collect user input via CLI and store in env. variables
if is_finalized:
print("CLI finalized.")
if is_exclude:
print("exclude is true.")
if rsync_cmd:
print("rsync command returned: " + rsync_cmd)
if is_finalized:
do_the_install(is_exclude, rsync_cmd)
trace("Ending Backuppy install.py") trace("Ending Backuppy install.py")
if __name__ == '__main__':
# sys.argv.append("--gui") # TODO: disable for production
sys.exit(main(sys.argv[1:]))

View file

@ -1,107 +1,29 @@
#!/bin/bash #!/bin/bash
# """
# Variables # project: Backuppy
mydir=$PWD # version: 0.8
langDE="./languages/german.py" # file: install.sh
langEN="./languages/english.py" # summary: main entry shell script
# """
# Check if graphical installer should be executed # Check if graphical installer should be executed
if [ "$1" == "--gui" ]; then if [ "$1" == "--gui" ]; then
python3 -B install.py # Check if PIP ist installed
exit 0 if ! command -v pip3> /dev/null
then
echo "Please install PIP on your system for the graphical version of Backuppy!"
exit
fi
# Check if PIP module "PySide2" is installed
if ! pip list | grep PySide2> /dev/null
then
# Install PySide2
echo -e "Installing necessary PySide2 package for GUI-mode."
pip3 install PySide2
fi
# Launch python installer in GUI mode
python3 -B install.py "$1"
else else
# Intro # Launch python installer in CLI mode
# language python3 -B install.py
echo -e "Hello, first of all, which language do you prefer: German [DE] or English [EN]?"
read language
if [ $language = "DE" ]; then
echo -e "Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen! \n"
. $langDE
sleep 1
fi
if [ $language = "EN" ]; then
echo -e "Perfect, the English language package is now activated. Welcome!. \n"
. $langEN
sleep 1
fi
echo -e "\n$intromsg1 \n"
sleep 1
echo -e " \n$intromsg2\n"
sleep 1
# Installer
# creates the file 'Backuppy.sh'
touch Backuppy.sh
echo "#!/bin/bash" >> Backuppy.sh
chmod +x Backuppy.sh
# which Rsync options are available and which one you want to use
echo -e "$rsyncopt \n"
sleep 1
# asks if you want to exclude files/directories from backup and creates an exclude file in case of Yes
echo -e "$excludefile1"
read exclude
if [ $exclude = "J" ]; then
echo -e "$excludefile2 \n"
touch exclude.txt
sleep 1
elif [ $exclude = "Y" ]; then
echo -e "$excludefile2 \n"
touch exclude.txt
sleep 1
fi
if [ $exclude = "N" ]; then
echo -e "$excludefile3 \n"
sleep 1
fi
# Asks for the source directory which should be saved
echo -e "$srcdir1"
sleep 1
echo -e "$srcdir2"
read sourcedir
echo -e "$srcdir3_1 $sourcedir $srcdir3_2"
sleep 1
# asks for the destination directory in which the backup should be saved
echo -e "$targetdir1"
read targetdir
echo -e "$targetdir2_1 $targetdir $targetdir2_2"
sleep 1
# alias entry in .bashrc or .zshrc
# .zshrc case 1
echo $SHELL
if [ $SHELL = "/usr/bin/zsh" ]; then
echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc
fi
# zshrc case 2
echo $SHELL
if [ $SHELL = "/bin/zsh" ]; then
echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.zshrc
fi
#bashrc case 1
if [ $SHELL = "/usr/bin/bash" ]; then
echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc
fi
# bashrc case 2
if [ $SHELL = "/bin/bash" ]; then
echo "alias backuppy='sudo $mydir/Backuppy.sh'" >> ~/.bashrc
fi
# collects all the information needed to execute the rsync command and creates it.
echo -e "$collect \n"
sleep 1
echo -e "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir \n"
sleep 1
# enter the rsync command in Backuppy.sh
echo "rsync -aqp --exclude-from=$mydir/exclude.txt $sourcedir $targetdir" >> Backuppy.sh
# Outro
echo -e "$outro1"
sleep 2
echo "$outro2"
exit 0
fi fi

View file

@ -1,95 +0,0 @@
#!/usr/bin/env python3
# Dependencies
import os
import time
# Variables
MYDIR = os.getcwd()
SHELL = os.environ.get("SHELL")
HOME = os.environ.get("HOME")
# Intro
# language
language = input("Hello, first of all, which language do you prefer: German [DE] or English [EN]?\n> ")
if language.upper() == "DE":
from languages.german import *
print("Perfekt, nun ist das deutsche Sprachpaket aktiviert. Willkommen!\n")
else:
from languages.english import *
print("Perfect, the English language package is now activated. Welcome!.\n")
time.sleep(1)
print("\n" + intromsg1 + "\n")
time.sleep(1)
print("\n" + intromsg2 + "\n")
time.sleep(1)
# Installer
# creates the file 'Backuppy.sh'
fBackuppy = open("Backuppy.sh", "w")
fBackuppy.write("#!/bin/bash")
os.chmod("Backuppy.sh", 0o777) # make file executable
# which Rsync options are available and which one you want to use
print(rsyncopt + "\n")
time.sleep(1)
# asks if you want to exclude files/directories from backup and creates an exclude file in case of Yes
exclude = input(excludefile1 + "\n> ")
if exclude.upper() in ("J", "Y"):
print(excludefile2 + "\n")
fExclude = open("exclude.txt", "w")
fExclude.close()
else:
print(excludefile3 + "\n")
time.sleep(1)
# Asks for the source directory which should be saved
print(srcdir1)
time.sleep(1)
sourcedir = input(srcdir2 + "\n> ")
print(f"{srcdir3_1} {sourcedir} {srcdir3_2}")
time.sleep(1)
# asks for the destination directory in which the backup should be saved
targetdir = input(targetdir1 + "\n> ")
print(f"{targetdir2_1} {targetdir} {targetdir2_2}")
time.sleep(1)
# alias entry in .bashrc or .zshrc
print(SHELL)
# .zshrc case1 and case2
if SHELL.upper().find("ZSH") >0:
# Appending to bash config file
fRc = open(os.path.join(HOME, ".zshrc"), "a") # append mode
fRc.write("\n" + f"alias backuppy='sudo {MYDIR}/Backuppy.sh'" + "\n")
fRc.close()
# .bashrc case1 and case2
elif SHELL.upper().find("BASH") >0:
# Appending to zsh config file
fRc = open(os.path.join(HOME, ".bashrc"), "a") # append mode
fRc.write("\n" + f"alias backuppy='sudo {MYDIR}/Backuppy.sh'" + "\n")
fRc.close()
# collects all the information needed to execute the rsync command and creates it.
print(collect + "\n")
time.sleep(1)
print(f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {sourcedir} {targetdir}\n")
time.sleep(1)
# enter the rsync command in Backuppy.sh
fBackuppy.write("\n" + f"rsync -aqp --exclude-from={MYDIR}/exclude.txt {sourcedir} {targetdir}" + "\n")
fBackuppy.close()
# Outro
print(outro1)
time.sleep(2)
print(outro2 + " fotocoder@joschu.ch")

295
install_gui.py Normal file
View file

@ -0,0 +1,295 @@
#!/usr/bin/env python3
"""
project: Backuppy
version: 0.8
file: install_gui.py
summary: python installer-script in GUI-mode (needs PySide2)
"""
# Standard library imports
import os
# Third party imports
from PySide2 import QtWidgets
# local imports
from install import *
class BackuppyWizard(QtWidgets.QWizard):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle(get_lang_text("intromsg1"))
self.addPage(Page01(self))
self.addPage(Page02(self))
self.addPage(Page03(self))
self.addPage(Page04(self))
self.addPage(Page05(self))
self.addPage(Page06(self))
self.addPage(Page07(self))
self.addPage(Page08(self))
self.addPage(Page09(self))
self.addPage(Page10(self))
self.resize(640, 480)
class Page01(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel("Hello, first of all, which language do you prefer: English or German?")
self.comboBox = QtWidgets.QComboBox(self)
self.comboBox.addItem(LANG_EN, LANG_EN)
self.comboBox.addItem(LANG_DE, LANG_DE)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.comboBox)
self.setLayout(layout)
def validatePage(self):
if self.comboBox.currentText() == LANG_DE:
set_language(LANG_DE)
return True
class Page02(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
self.setLayout(layout)
def initializePage(self):
self.setWindowTitle(get_lang_text("intromsg1"))
self.label1.setText(get_lang_text("languagepack"))
self.label2.setText(get_lang_text("intromsg2"))
class Page03(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel()
self.groupbox = QtWidgets.QGroupBox()
self.groupbox.setFlat(True)
self.radio1 = QtWidgets.QRadioButton()
self.radio2 = QtWidgets.QRadioButton()
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.radio1)
vbox.addWidget(self.radio2)
vbox.addStretch(1)
self.groupbox.setLayout(vbox)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.groupbox)
self.setLayout(layout)
def initializePage(self):
self.label.setText(get_lang_text("excludefile1"))
self.radio1.setText(get_lang_text("Yes"))
self.radio2.setText(get_lang_text("No"))
self.radio1.setChecked(True)
def validatePage(self):
global EXCLUDE
if self.radio1.isChecked():
EXCLUDE = True
else:
EXCLUDE = False
return True
class Page04(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
def initializePage(self):
global EXCLUDE
if EXCLUDE:
self.label.setText(get_lang_text("excludefile2"))
else:
self.label.setText(get_lang_text("excludefile3"))
class Page05(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.efSourceDir = QtWidgets.QLineEdit()
self.pbBrowse = QtWidgets.QPushButton("Browse")
self.pbBrowse.clicked.connect(self.on_pbBrowse_clicked)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
hLayout = QtWidgets.QHBoxLayout()
hLayout.addWidget(self.efSourceDir)
hLayout.addWidget(self.pbBrowse)
layout.addLayout(hLayout)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("srcdir1"))
self.label2.setText(get_lang_text("srcdir2"))
def on_pbBrowse_clicked(self):
options = QtWidgets.QFileDialog.Options() | QtWidgets.QFileDialog.ShowDirsOnly
dirName = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Directory", None, options)
self.efSourceDir.setText(dirName)
def validatePage(self):
global SOURCEDIR
SOURCEDIR = self.efSourceDir.text()
return True
class Page06(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("srcdir3_1"))
bold_text = f"<p><strong>{SOURCEDIR}</strong></p>"
self.label2.setText(bold_text)
self.label3.setText(get_lang_text("srcdir3_2"))
class Page07(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.efTargetDir = QtWidgets.QLineEdit()
self.pbBrowse = QtWidgets.QPushButton("Browse")
self.pbBrowse.clicked.connect(self.on_pbBrowse_clicked)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
hLayout = QtWidgets.QHBoxLayout()
hLayout.addWidget(self.efTargetDir)
hLayout.addWidget(self.pbBrowse)
layout.addLayout(hLayout)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("targetdir1"))
def on_pbBrowse_clicked(self):
options = QtWidgets.QFileDialog.Options() | QtWidgets.QFileDialog.ShowDirsOnly
dirName = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Directory", None, options)
self.efTargetDir.setText(dirName)
def validatePage(self):
global TARGETDIR
TARGETDIR = self.efTargetDir.text()
return True
class Page08(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("targetdir2_1"))
bold_text = f"<p><strong>{TARGETDIR}</strong></p>"
self.label2.setText(bold_text)
self.label3.setText(get_lang_text("targetdir2_2"))
def validatePage(self):
global RSYNC_CMD, MYDIR, SOURCEDIR, TARGETDIR
exclude_file = os.path.join(MYDIR, EXCLUDE_FILE)
RSYNC_CMD = f"rsync -aqp --exclude-from={exclude_file} {SOURCEDIR} {TARGETDIR}"
return True
class Page09(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
self.setLayout(layout)
def initializePage(self):
self.label1.setText(get_lang_text("collect"))
global RSYNC_CMD
#self.label2.setText(f"{RSYNC_CMD}")
bold_text = f"<p><strong>{RSYNC_CMD}</strong></p>"
self.label2.setText(bold_text)
class Page10(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.label1 = QtWidgets.QLabel()
self.label2 = QtWidgets.QLabel()
self.label3 = QtWidgets.QLabel()
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.label1)
layout.addWidget(self.label2)
layout.addWidget(self.label3)
self.setLayout(layout)
self.setFinalPage(True)
def initializePage(self):
self.label1.setText(get_lang_text("outro1"))
self.label2.setText(get_lang_text("outro2"))
urlLink = f"<a href='mailto: {EMAIL}'>{EMAIL}</a>"
self.label3.setText(urlLink)
self.label3.setOpenExternalLinks(True)
def validatePage(self):
return True
def main_install_gui():
app = QtWidgets.QApplication()
wizard = BackuppyWizard()
wizard.show()
app.exec_()
return True, EXCLUDE, RSYNC_CMD
if __name__ == '__main__':
is_finalized, is_exclude, rsync_cmd = main_install_gui()