Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bash history restore #318

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions resurrect.alias
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

alias restore='eval $( while read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_full_command; do
[ x$pane_index = x0 ] && echo "cd ${dir#:} ; tmux new-session -s ${session_name#:} -n ${window_name} \"tar -xzf $HOME/.tmux/resurrect/pane_contents.tar.gz --to-stdout ./pane_contents/pane-${session_name#:}:${window_number}.%${pane_index} ; exec ${pane_command:-/bin/bash}\" ; cd - > /dev/null"
done < $HOME/.tmux/resurrect/last )'

2 changes: 2 additions & 0 deletions scripts/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ _RESURRECT_FILE_PATH=""

d=$'\t'

BASE_INDEX=$( tmux show-option -gv base-index )

# helper functions
get_tmux_option() {
local option="$1"
Expand Down
65 changes: 48 additions & 17 deletions scripts/restore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ d=$'\t'
# is also not restored. That makes the restoration process more idempotent.
EXISTING_PANES_VAR=""

RESTORED_PANE_NUMBERS=""

RESTORING_FROM_SCRATCH="false"

RESTORE_PANE_COUNT=0
RESTORE_PANE_CONTENTS="false"

is_line_type() {
Expand Down Expand Up @@ -60,6 +63,17 @@ is_pane_registered_as_existing() {
[[ "$EXISTING_PANES_VAR" =~ "$pane_custom_id" ]]
}

register_restored_pane() {
local pane_index="$1"
local delimiter=$'\t'
RESTORED_PANE_NUMBERS="${RESTORED_PANE_NUMBERS}${delimiter}${pane_index}"
}

is_pane_registered_as_restored() {
local pane_index="$1"
[[ "$RESTORED_PANE_NUMBERS" =~ "$pane_index" ]]
}

restore_from_scratch_true() {
RESTORING_FROM_SCRATCH="true"
}
Expand Down Expand Up @@ -117,9 +131,10 @@ new_window() {
local window_name="$3"
local dir="$4"
local pane_index="$5"
local pane_id="${session_name}:${window_number}.${pane_index}"
RESTORE_PANE_COUNT=$[$RESTORE_PANE_COUNT+1]
local pane_id="${session_name}:${window_number}.%${pane_index}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "%$pane_index")"
tmux new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir" "$pane_creation_command"
else
tmux new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir"
Expand All @@ -132,9 +147,10 @@ new_session() {
local window_name="$3"
local dir="$4"
local pane_index="$5"
local pane_id="${session_name}:${window_number}.${pane_index}"
RESTORE_PANE_COUNT=$[$RESTORE_PANE_COUNT+1]
local pane_id="${session_name}:${window_number}.%${pane_index}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "%$pane_index")"
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -n "$window_name" -c "$dir" "$pane_creation_command"
else
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -n "$window_name" -c "$dir"
Expand All @@ -152,9 +168,13 @@ new_pane() {
local window_name="$3"
local dir="$4"
local pane_index="$5"
local pane_id="${session_name}:${window_number}.${pane_index}"
RESTORE_PANE_COUNT=$[$RESTORE_PANE_COUNT+1]
if [ $RESTORE_PANE_COUNT -ne $pane_index ] ; then
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
fi
local pane_id="${session_name}:${window_number}.%${pane_index}"
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "%$pane_index")"
tmux split-window -t "${session_name}:${window_number}" -c "$dir" "$pane_creation_command"
else
tmux split-window -t "${session_name}:${window_number}" -c "$dir"
Expand All @@ -171,17 +191,8 @@ restore_pane() {
pane_full_command="$(remove_first_char "$pane_full_command")"
if pane_exists "$session_name" "$window_number" "$pane_index"; then
tmux rename-window -t "$window_number" "$window_name"
if is_restoring_from_scratch; then
# overwrite the pane
# happens only for the first pane if it's the only registered pane for the whole tmux server
local pane_id="$(tmux display-message -p -F "#{pane_id}" -t "$session_name:$window_number")"
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
tmux kill-pane -t "$pane_id"
else
# Pane exists, no need to create it!
# Pane existence is registered. Later, its process also won't be restored.
register_existing_pane "$session_name" "$window_number" "$pane_index"
fi
# Pane existence is registered. Later, its process also won't be restored.
register_existing_pane "$session_name" "$window_number" "$pane_index"
elif window_exists "$session_name" "$window_number"; then
tmux rename-window -t "$window_number" "$window_name"
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
Expand All @@ -190,6 +201,7 @@ restore_pane() {
else
new_session "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
fi
register_restored_pane "$pane_index"
done < <(echo "$pane")
}

Expand Down Expand Up @@ -241,6 +253,16 @@ detect_if_restoring_from_scratch() {
}

detect_if_restoring_pane_contents() {
if [ "$( tmux list-panes -a -F "#{session_name}:#{window_index}.#{pane_id}" )" != 0:${BASE_INDEX}.%0 ] ; then
cat <<-EOF


WARNING : You are not restoring from a fresh tmux session (0:${BASE_INDEX}.0)
Expect unexpected results


EOF
fi
if capture_pane_contents_option_on; then
cache_tmux_default_command
restore_pane_contents_true
Expand All @@ -260,6 +282,15 @@ restore_all_panes() {
restore_pane "$line"
fi
done < $(last_resurrect_file)
# This is a temporary trick, by killing the first pane before saving for proper restore
if ! is_pane_registered_as_existing 0 ${BASE_INDEX} 0; then
tmux kill-pane -t "0:${BASE_INDEX}.%0"
fi
tmux list-panes -a -F "#{session_name} #{window_index} #{pane_id}" | while read session_name window_number pane_id; do
if ! is_pane_registered_as_restored "${pane_id#%}" ; then
tmux kill-pane -t "${session_name}:${window_number}.${pane_id}"
fi
done
if is_restoring_pane_contents; then
rm "$(pane_contents_dir "restore")"/*
fi
Expand Down
21 changes: 18 additions & 3 deletions scripts/save.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pane_format() {
format+="${delimiter}"
format+=":#{window_flags}"
format+="${delimiter}"
format+="#{pane_index}"
format+="#{pane_id}"
format+="${delimiter}"
format+=":#{pane_current_path}"
format+="${delimiter}"
Expand Down Expand Up @@ -80,7 +80,7 @@ state_format() {
}

dump_panes_raw() {
tmux list-panes -a -F "$(pane_format)"
tmux list-panes -a -F "$(pane_format)" | sed -e 's/%//' | sort -n -k 7
}

dump_windows_raw(){
Expand Down Expand Up @@ -257,7 +257,7 @@ dump_pane_contents() {
local pane_contents_area="$(get_tmux_option "$pane_contents_area_option" "$default_pane_contents_area")"
dump_panes_raw |
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_pid history_size; do
capture_pane_contents "${session_name}:${window_number}.${pane_index}" "$history_size" "$pane_contents_area"
capture_pane_contents "${session_name}:${window_number}.%${pane_index}" "$history_size" "$pane_contents_area"
done
}

Expand Down Expand Up @@ -291,6 +291,21 @@ save_all() {
rm "$resurrect_file_path"
fi
if capture_pane_contents_option_on; then
if [[ "$( tmux list-panes -a -F "#{session_name}:#{window_index}.#{pane_id} " )" =~ "0:${BASE_INDEX}.%0 " ]] ; then
cat <<-EOF


WARNING : The initial pane (0:${BASE_INDEX}.0) will not be properly restored by default
You can restore it by defining the alias below and using it to restore your session
Combination with continuum-restore setting allows full recovering with a single command

alias restore='eval \$( while read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command pane_full_command; do
[ x\$pane_index = x0 ] && echo "cd \${dir#:} ; tmux new-session -s \${session_name#:} -n \${window_name} \"tar -xzf \$HOME/.tmux/resurrect/pane_contents.tar.gz --to-stdout ./pane_contents/pane-\${session_name#:}:\${window_number}.%\${pane_index} ; exec \${pane_command:-/bin/bash}\" ; cd - > /dev/null"
done < \$HOME/.tmux/resurrect/last )'


EOF
fi
mkdir -p "$(pane_contents_dir "save")"
dump_pane_contents
pane_contents_create_archive
Expand Down