#!/usr/bin/env bash # httm is an interactive, file-level Time Machine-like tool for ZFS/btrfs/NILFS2 # at provides wrapper scripts that demonstrate how to use the httm command line: # - bowie.bash displays the difference between unique snapshot versions and the live file. # - equine.bash mount APFS snapshots for use with httm. # - nicotine.bash converts unique snapshot file versions to a $git archive. # - ounce.bash snapshots the datasets of files opened by another programs. only when you have file changes outstanding, uncommitted to a snapshot already # - preview-bootstrap.bash bridges httm to fzf, handles the "Preview" window functionality. # - zdbstat.bash prints the underlying zdb metadata for a ZFS object. DEST=${1:-/etc/skel} set -x URL=raw.githubusercontent.com USER=kimono-koans APP="httm" #TYPES=(deb deb-src) TYPES=(deb) TRANSPORT="https:/" URI="${URL}/${USER}/ppa/main" SUITES="./" COMPONENTS=() ARCHITECTURES=(amd64) KEY_HOME=/usr/share/keyrings KEY=${KEY_HOME}/"${USER}.gpg" packages=(httm two-percent fzf) sudo mkdir -p ${KEY_HOME} wget -qO- ${TRANSPORT}/${URI}/${USER}/${APP}/main/deb.asc | sudo gpg --dearmor -o ${KEY} # echo "deb [signed-by=/etc/apt/trusted.gpg.d/${KEY}] https://${URL}/${USER}/ppa/main ./" | sudo tee /etc/apt/sources.list-available/${APP}-ppa.list # echo "deb-src [signed-by=/etc/apt/trusted.gpg.d/${KEY}] https://${URL}/${USER}/ppa/main ./" | sudo tee -a /etc/apt/sources.list-available/${APP}-ppa.list conf_print_httm_sources() { cat </dev/null sudo ln -sf /etc/apt/sources.list-available/${APP}-ppa.sources /etc/apt/sources.list.d/${APP}-ppa.sources # Bypass apt-proxy for ${APP} packages PROXY_FILE="/etc/apt/apt.conf.d/02proxy" ENTRY="Acquire::http::Proxy { \"${URL}\" DIRECT; };" echo "# Bypass apt-proxy for ${APP} packages" # Check if the entry already exists in the file (if the file exists) if [ -f "$PROXY_FILE" ] && grep -qF "${URL}" "$PROXY_FILE"; then echo "Proxy bypass for ${URL} is already present." else # Append the entry, or create the file if it doesn't exist echo "$ENTRY" | sudo tee -a "$PROXY_FILE" >/dev/null echo "Added proxy bypass for ${URL}." fi sudo apt install -y --no-install-recommends "${packages[@]}" # Using cargo # https://crates.io/crates/httm # curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # latest="(wget -nv -O - "https://api.github.com/repos/kimono-koans/httm/releases/latest" 2>/dev/null | grep tag_name | cut -d: -f2 | cut -d'"' -f2)" # cargo install --locked --git https://github.com/kimono-koans/httm.git --tag "$latest" # httm --install-zsh-hot-keys puts a file in ${HOME} and includes it in the .zshrc # httm: zsh hot keys script: source ~/.httm-key-bindings.zsh # we put in the zshrc.d instead. # Update with :r! curl -s https://raw.githubusercontent.com/kimono-koans/httm/refs/heads/master/scripts/httm-key-bindings.zsh # httm/scripts/httm-key-bindings.zsh cat <<"EOF" | sudo tee "${DEST}/.zshrc.d/008_httm-key-bindings.zsh" # ___ ___ ___ ___ # /\__\ /\ \ /\ \ /\__\ # /:/ / \:\ \ \:\ \ /::| | # /:/__/ \:\ \ \:\ \ /:|:| | # /::\ \ ___ /::\ \ /::\ \ /:/|:|__|__ # /:/\:\ /\__\ /:/\:\__\ /:/\:\__\ /:/ |::::\__\ # \/__\:\/:/ / /:/ \/__/ /:/ \/__/ \/__/~~/:/ / # \::/ / /:/ / /:/ / /:/ / # /:/ / \/__/ \/__/ /:/ / # /:/ / /:/ / # \/__/ \/__/ # # Copyright (c) 2023, Robert Swinford gmail.com> # # For the full copyright and license information, please view the LICENSE file # that was distributed with this source code. # ALT-d - Dynamically snap selected files's dataset __httm-snapshot() { command httm --snap 2>/dev/null "$1" || \ command sudo httm --snap "$1" || \ echo "httm snapshot widget quit with a snapshot error. Check you have the correct permissions to snapshot."; return 1 local ret=$? echo return $ret } httm-snapshot-widget() { local input_file local canonical_path # requires an fzf function sourced to work properly if [[ $( type "__fsel" 2>/dev/null | grep -q "function" ) -eq 0 ]] then # need canonical path for a httm snapshot input_file="$(__fsel)" [[ -z "$input_file" ]] || canonical_path="$(readlink -f $input_file)" else canonical_path="$PWD" fi [[ -z "$canonical_path" ]] || __httm-snapshot "$filename" local ret=$? zle reset-prompt return $ret } zle -N httm-snapshot-widget bindkey '\ed' httm-snapshot-widget # ALT-m - browse for ZFS snapshots interactively httm-lookup-widget() { echo command httm -r -R local ret=$? zle reset-prompt return $ret } zle -N httm-lookup-widget bindkey '\em' httm-lookup-widget # ALT-s - select files on ZFS snapshots interactively __httm-select() { command httm -s -R | \ while read item; do echo -n "${item}" done local ret=$? echo return $ret } httm-select-widget() { LBUFFER="${LBUFFER}$(__httm-select)" local ret=$? zle reset-prompt return $ret } zle -N httm-select-widget bindkey '\es' httm-select-widget EOF # The ounce script (codename: "dimebag") is a wrapper for httm that automates # snapshot creation with minimal mental overhead. It uses seccomp and eBPF to # trace file modifications and automatically takes a snapshot before you edit # a file, effectively providing non-periodic dynamic snapshots "auto-snapshot" # behavior. # To integrate ounce into your workflow, you can set up aliases in your shell # (e.g., .zshrc): conf_print_ounce_aliases() { cat </dev/null # request ZFS snapshot privileges ounce --give-priv