1
0
mirror of https://github.com/zplug/zplug synced 2025-04-05 15:19:13 +02:00
zplug/base/job/handle.zsh
2017-08-02 00:11:53 +02:00

299 lines
9.3 KiB
Bash

__zplug::job::handle::flock()
{
local -i retry=0 max=15 cant_lock
local is_escape=false
local -a args
local file contents
while (( $#argv > 0 ))
do
case "$argv[1]" in
--escape)
is_escape=true
;;
-*|--*)
;;
*)
args+=( "$argv[1]" )
;;
esac
shift
done
if (( $#args < 2 )); then
return 1
fi
file="$args[1]"
contents="$args[2]"
# TODO: Temporary fix to solve #334
if [[ ! -f $file ]]; then
__zplug::log::write::info \
"create $file because it does not exist"
touch "$file"
fi
(
until zsystem flock -t 3 "$file"
do
cant_lock=$status
if (( (++retry) > max )); then
if (( cant_lock > 0 )); then
{
printf "Can't acquire lock for ${file}."
if (( cant_lock == 2 )); then
printf " timeout."
fi
printf "\n"
} #1> >(__zplug::log::capture::error)
return 1
fi
return 1
fi
done
# Save the status code with LTSV
if $is_escape; then
print -r "$contents" >>|"$file"
else
print "$contents" >>|"$file"
fi >>|"$file"
)
}
__zplug::job::handle::state()
{
local repo="$argv[1]" caller="$argv[2]"
local message
# Save status code for process cache
if [[ -z $status_codes[$repo] ]]; then
status_codes[$repo]="$(__zplug::job::process::get_status_code "$repo" "$caller")"
fi
case $status_codes[$repo] in
$_zplug_status[success])
case "$caller" in
install)
message="Installed!"
;;
update)
message="Updated!"
;;
esac
__zplug::job::message::green "$repo" "$message"
;;
$_zplug_status[up_to_date])
__zplug::job::message::white "$repo" "Up-to-date"
;;
$_zplug_status[skip_local])
__zplug::job::message::yellow "$repo" "Skip local repo"
;;
$_zplug_status[skip_frozen])
__zplug::job::message::yellow "$repo" "Skip frozen repo"
;;
$_zplug_status[skip_if])
__zplug::job::message::yellow "$repo" "Skip due to if"
;;
$_zplug_status[revision_lock])
__zplug::job::message::yellow "$repo" "Revision locked"
;;
$_zplug_status[failure])
__zplug::job::message::red "$repo" "Failed to $caller"
;;
$_zplug_status[out_of_date])
__zplug::job::message::red "$repo" "Local out of date"
;;
$_zplug_status[not_on_branch])
__zplug::job::message::red "$repo" "Not on any branch"
;;
$_zplug_status[not_git_repo])
__zplug::job::message::red "$repo" "Not git repo"
;;
$_zplug_status[repo_not_found])
__zplug::job::message::red "$repo" "Repo not found"
;;
$_zplug_status[unknown] | *)
__zplug::job::message::red "$repo" "Unknown error"
;;
esac
}
__zplug::job::handle::wait()
{
local caller="${${(M)funcstack[@]:#__*__}:gs:_:}"
local -i screen_size=$(($#repo_pids + 2))
local -i spinner_idx=1 sub_spinner_idx=1
local -a spinners sub_spinners
local -F latency=0.1
spinners=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
sub_spinners=(⠁ ⠁ ⠉ ⠙ ⠚ ⠒ ⠂ ⠂ ⠒ ⠲ ⠴ ⠤ ⠄ ⠄ ⠤ ⠠ ⠠ ⠤ ⠦ ⠖ ⠒ ⠐ ⠐ ⠒ ⠓ ⠋ ⠉ ⠈ ⠈)
if __zplug::job::queue::is_overflow || __zplug::job::queue::is_within_range; then
repeat $screen_size; do builtin printf "\n"; done
#
# Multiple progress bars
#
# Use printf command (not builtin) instead of __zplug::io::print::f function,
# because this loop is run the processing by interval of 0.1 second
# and there is a need to be called faster
while __zplug::job::process::is_running "$repo_pids[@]" "$hook_pids[@]" || (( ${(k)#proc_states[(R)running]} > 0 ))
do
sleep "$latency"
__zplug::utils::ansi::cursor_up $screen_size
# Count up within spinners index
if (( ( spinner_idx+=1 ) > $#spinners )); then
spinner_idx=1
fi
# Count up within sub_spinners index
if (( ( sub_spinner_idx+=1 ) > $#sub_spinners )); then
sub_spinner_idx=1
fi
# Processing pids
for repo in "${(k)repo_pids[@]}"
do
if __zplug::job::process::is_running "$repo_pids[$repo]"; then
__zplug::job::handle::running "$repo" "$caller"
proc_states[$repo]="running"
else
if [[ -n $hook_build[$repo] ]]; then
__zplug::job::handle::hook "$repo" "$caller"
# If the repo has a hook-build,
# it can not be said that the processing has ended yet,
# so do not set a flag.
# ==> proc_states[$repo]="terminated"
else
__zplug::job::handle::state "$repo" "$caller"
proc_states[$repo]="terminated"
fi
fi
done
__zplug::utils::ansi::erace_current_line
if __zplug::job::process::is_running "$repo_pids[@]" "$hook_pids[@]"; then
builtin printf "\n"
__zplug::io::print::f \
"Finished: %d/%d plugins\n" \
${(k)#proc_states[(R)terminated]} \
${#proc_states}
else
repo_pids=()
fi
done
fi
}
__zplug::job::handle::running()
{
local repo="$argv[1]" caller="$argv[2]"
local message
case "$caller" in
install)
message="Installing..."
;;
update)
message="Updating..."
;;
status)
message="Fetching..."
;;
esac
__zplug::job::message::spinning "$repo" "$message" "$spinners[$spinner_idx]"
}
__zplug::job::handle::hook()
{
local repo="$argv[1]" caller="$argv[2]"
local -i timeout=60
local message
case "$caller" in
install)
message="Installed!"
;;
update)
message="Updated!"
;;
esac
# Save status code for process cache
if [[ -z $status_codes[$repo] ]]; then
status_codes[$repo]="$(__zplug::job::process::get_status_code "$repo" "$caller")"
fi
# If the installation or updating fails in the first place,
# exits the loop here to stop the hook-build
if [[ $status_codes[$repo] != 0 ]]; then
__zplug::job::handle::state "$repo" "$caller"
proc_states[$repo]="terminated"
continue
fi
if ! $hook_finished[$repo]; then
hook_finished[$repo]=true
# Run the hook-build in background
{
__zplug::job::hook::build "$repo"
if (( $status > 0 )); then
builtin printf "$repo\n" >>|"$_zplug_build_log[failure]"
builtin printf "$repo\n" >>|"$_zplug_build_log[rollback]"
else
builtin printf "$repo\n" >>|"$_zplug_build_log[success]"
fi
} & hook_pids[$repo]=$!
# Run the timeout process in background
{
touch "$_zplug_lock[job]"
# kill the process for hook-build after sleeping
# during the number of seconds that has been set as a timeout
sleep "$timeout"
# Check if $repo_pids don't run
# and check if the process ($hook_pids[$repo]) that has should be killed
if __zplug::job::process::is_running "$hook_pids[$repo]" && ! __zplug::job::process::is_running "$repo_pids[@]"; then
__zplug::job::process::kill "$hook_pids[$repo]"
builtin printf "$repo\n" >>|"$_zplug_build_log[timeout]"
builtin printf "$repo\n" >>|"$_zplug_build_log[rollback]"
fi
rm -f "$_zplug_lock[job]"
} &
fi
__zplug::utils::ansi::erace_current_line
if __zplug::job::process::is_running "$hook_pids[$repo]"; then
__zplug::job::message::green \
"$repo" "$message" "$spinners[$spinner_idx]" "$sub_spinners[$sub_spinner_idx]"
else
if __zplug::job::hook::build_failure "$repo"; then
__zplug::job::message::green \
"$repo" "$message" "" "failure"
elif __zplug::job::hook::build_timeout "$repo"; then
__zplug::job::message::green \
"$repo" "$message" "" "timeout"
else
__zplug::job::message::green \
"$repo" "$message" "" "success"
fi
proc_states[$repo]="terminated"
fi
}
__zplug::job::handle::elapsed_time()
{
local -F elapsed_time="$1"
__zplug::utils::ansi::erace_current_line
builtin printf "\n"
LC_ALL=POSIX __zplug::io::print::f \
--zplug \
"Elapsed time: %.4f sec.\n" \
$elapsed_time
}