diff --git a/plugins/history-sync/README.md b/plugins/history-sync/README.md new file mode 100644 index 000000000..d4da2ef67 --- /dev/null +++ b/plugins/history-sync/README.md @@ -0,0 +1,30 @@ +## An Oh My Zsh plugin for GPG encrypted, Internet synchronized Zsh history using Git +
+That is, if you'd like an easy way to securely synchronise your zsh_history across many computers connected to the Internet, this plugin will help you. **Be creative with this - I dare you.** + +### What tooling do I need? +##### 1. GnuPG +history-sync uses GPG to encrypt/decrypt your zsh_history. The [GnuPG documentation](https://www.gnupg.org/documentation/manuals.html) is very good. + +##### 2. Git +history-sync uses Git to push/pull your zsh_history to/from a remote repository.
+ +### How do I use it? +1. Create a Git repo for housing your encrypted zsh_history file. This repo needs to be accessible from all client shells you'd like to synchronize + - Mine is $HOME/.zsh_history_proj +2. Activate history-sync plugin in your .zshrc + - `git clone git@github.com:wulfgarpro/history-sync.git $HOME/.oh-my-zsh/plugins/.` +3. Export environment variables (or use defaults found in the plugin file history-sync.plugin.zsh) +
These are: + - **ZSH_HISTORY_FILE**
+ Your zsh_history file location + - **ZSH_HISTORY_PROJ**
+ Your Git project for housing your zsh_history file + - **ZSH_HISTORY_FILE_ENC**
+ Your encrypted zsh_history file location + - **GIT_COMMIT_MSG**
+ Your default message when pushing to $ZSH_HISTORY_PROJ +4. Ensure your GPG setup is complete and you have a public/private key pair for encrypting/decrypting: `man gpg` +5. Run `zhpl` to pull +6. Run `zhps -r 876T3F78 -r 998A637B -r ...` to encrypt and push +7. Run `zhsync` to pull/push diff --git a/plugins/history-sync/history-sync.plugin.zsh b/plugins/history-sync/history-sync.plugin.zsh new file mode 100644 index 000000000..625d6830f --- /dev/null +++ b/plugins/history-sync/history-sync.plugin.zsh @@ -0,0 +1,133 @@ +### +# James Fraser +# +### + +autoload -U colors +colors + +ZSH_HISTORY_FILE=$HOME/.zsh_history +ZSH_HISTORY_PROJ=$HOME/.zsh_history_proj +ZSH_HISTORY_FILE_ENC=$ZSH_HISTORY_PROJ/zsh_history +GIT_COMMIT_MSG="latest $(date)" + +function print_git_error_msg() { +echo "$bold_color$fg[red]Fix your git repo...${reset_color}"; +} + +function print_gpg_encrypt_error_msg() { +echo "$bold_color$fg[red]GPG failed to encrypt history file... exiting.${reset_color}"; +} + +function print_gpg_decrypt_error_msg() { +echo "$bold_color$fg[red]GPG failed to decrypt history file... exiting.${reset_color}"; +} + +function usage() { +echo "$bold_color$fg[red]Usage: $0 [-r -r ...]${reset_color}" 1>&2; return; +} + +# Pull current master, decrypt, and merge with .zsh_history +function history_sync_pull() { + # Backup + cp -a $HOME/{.zsh_history,.zsh_history.backup} + DIR=$CWD + # Pull + cd $ZSH_HISTORY_PROJ && git pull + if [[ $? != 0 ]]; then + print_git_error_msg + cd $DIR + return + fi + + # Decrypt + gpg --output zsh_history_decrypted --decrypt zsh_history + if [[ $? != 0 ]]; then + print_gpg_decrypt_error_msg + cd $DIR + return + fi + + # Merge + cat $HOME/.zsh_history zsh_history_decrypted | sort -u > $HOME/.zsh_history + rm zsh_history_decrypted + cd $DIR +} + +# Encrypt and push current history to master +function history_sync_push() { + # Get option recipients + local recipients=() + while getopts -r: opt; do + case "$opt" in + r) + recipients+="$OPTARG" + ;; + *) + usage + return + ;; + esac + done + + # Encrypt + if ! [[ ${#recipients[@]} > 0 ]]; then + echo -n "Please enter GPG recipient name: " + read name + recipients+=$name + fi + + ENCRYPT_CMD="gpg -v " + for r in $recipients; do + ENCRYPT_CMD+="-r \"$r\" " + done + + if [[ $ENCRYPT_CMD =~ '.(-r).+.' ]]; then + ENCRYPT_CMD+="--encrypt --sign --armor --output $ZSH_HISTORY_FILE_ENC $ZSH_HISTORY_FILE" + eval ${ENCRYPT_CMD} + if [[ $? != 0 ]]; then + print_gpg_encrypt_error_msg + return + fi + + echo -n "$bold_color$fg[yellow]Do you want to commit current local history file? ${reset_color}" + read commit + if [[ -n $commit ]]; then + case $commit in + [Yy]* ) + DIR=$CWD + cd $ZSH_HISTORY_PROJ && git add * && git commit -am $GIT_COMMIT_MSG + echo -n "$bold_color$fg[yellow]Do you want to push to remote? ${reset_color}" + read push + if [[ -n $push ]]; then + case $push in + [Yy]* ) + git push + if [[ $? != 0 ]]; then + print_git_error_msg + cd $DIR + return + fi + cd $DIR + ;; + esac + fi + + if [[ $? != 0 ]]; then + print_git_error_msg + cd $DIR + return + fi + ;; + [Nn]* ) + ;; + * ) + ;; + esac + fi + fi +} + +alias zhpl=history_sync_pull +alias zhps=history_sync_push +alias zhsync="history_sync_pull && history_sync_push"