Compare commits
26
Commits
3bd4128229
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2b11f7e5c | ||
|
|
5cfbb620fb | ||
|
|
60bf635a0c | ||
|
|
8b8be02912 | ||
|
|
6c746797e9 | ||
|
|
8edee10703 | ||
|
|
ae6b0b227b | ||
|
|
444ca8c57d | ||
|
|
e12d3d42cb | ||
|
|
deb879b6c4 | ||
|
|
7a1e432231 | ||
|
|
f1fb649e98 | ||
|
|
1f17b19f1e | ||
|
|
3305f5a543 | ||
|
|
f88dbcc6f4 | ||
|
|
65c3034b91 | ||
|
|
485d8768f9 | ||
|
|
275121a638 | ||
|
|
65ebd5e171 | ||
|
|
9ed74e1028 | ||
|
|
a3f0b42353 | ||
|
|
318420eba6 | ||
|
|
995f03b9bd | ||
|
|
e6785a24a7 | ||
|
|
95183069ce | ||
|
|
dd0bc6a77c |
@@ -0,0 +1,4 @@
|
||||
complete -c copytime -f -a '(__fish_complete_path)' -d 'Source file'
|
||||
complete -c copytime -f -a '(__fish_complete_path)' -d 'Destination file'
|
||||
complete -c copytime -s d -l date -x -d 'Set container creation date directly (e.g. 2020-01-02 03:04:05)'
|
||||
complete -c copytime -s h -l help -d 'Show help'
|
||||
@@ -0,0 +1,5 @@
|
||||
complete -c vrot -f -a '(__fish_complete_suffix .mp4 .mkv .mov .m4v .webm .avi .ts .mts .m2ts .flv .wmv .mpg .mpeg .vob .3gp)' -d 'Video file'
|
||||
complete -c vrot -s h -l help -d 'Show help'
|
||||
complete -c vrot -s r -l reencode -d 'Re-encode the video (rotate pixels, works everywhere)'
|
||||
complete -c vrot -s a -l angle -x -a '90 180 270' -d 'Rotation angle (degrees clockwise)'
|
||||
complete -c vrot -s p -l preset -x -a 'ultrafast superfast veryfast faster fast medium slow slower veryslow' -d 'x264/x265 encoder preset'
|
||||
@@ -52,8 +52,4 @@ if status is-interactive
|
||||
source $HOME/.config/fish/configs/default_config.fish
|
||||
end
|
||||
end
|
||||
|
||||
if test -e /usr/bin/fastfetch
|
||||
fastfetch
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,9 +3,16 @@
|
||||
#
|
||||
|
||||
alias mount_all='sudo $HOME/.config/fish/scripts/mount.sh'
|
||||
alias umount_all='sudo $HOME/.config/fish/scripts/umount.sh'
|
||||
|
||||
function mkdir
|
||||
command mkdir $argv
|
||||
and cd -- $argv[-1]
|
||||
end
|
||||
|
||||
################ COMMON ALIASES ################################################
|
||||
|
||||
alias rm='rm -r'
|
||||
alias remount='sudo mount -a'
|
||||
alias mount_config='sudo nano /etc/fstab'
|
||||
alias own='sudo chown -R "$USER":"$USER"'
|
||||
@@ -71,6 +78,7 @@ if test -e /usr/bin/nano
|
||||
echo "Usage: nanorm {FILE}"
|
||||
return 1
|
||||
end
|
||||
rm $argv[1]
|
||||
nano $argv[1]
|
||||
end
|
||||
else
|
||||
@@ -274,9 +282,9 @@ end
|
||||
|
||||
if test -e /usr/bin/mpv
|
||||
alias uni_play='mpv --vo=tct'
|
||||
alias asci_play='mpv --vo=caca'
|
||||
alias ascii_play='mpv --vo=caca'
|
||||
else
|
||||
for cmd in uni_play asci_play
|
||||
for cmd in uni_play ascii_play
|
||||
function $cmd --inherit-variable cmd
|
||||
echo "The command 'mpv' is not installed. Please install mpv to use this: https://github.com/mpv-player/mpv"
|
||||
end
|
||||
@@ -285,7 +293,7 @@ end
|
||||
|
||||
################ GREP #########################################################
|
||||
|
||||
if test -e /usr/bin/ugrep
|
||||
if command -q ugrep
|
||||
alias grep='ugrep --color=auto'
|
||||
alias egrep='ugrep -E --color=auto'
|
||||
alias fgrep='ugrep -F --color=auto'
|
||||
@@ -294,6 +302,12 @@ else
|
||||
alias fgrep='grep -F'
|
||||
end
|
||||
|
||||
if command -q ugrep
|
||||
alias igrep='ugrep --color=auto --invert-match'
|
||||
else if command -q grep
|
||||
alias igrep='grep --color=auto --invert-match'
|
||||
end
|
||||
|
||||
################ WGET #########################################################
|
||||
|
||||
if test -e /usr/bin/wget
|
||||
|
||||
+583
-116
@@ -4,123 +4,20 @@
|
||||
|
||||
source $HOME/.config/fish/configs/uni.fish
|
||||
|
||||
function get_pkg_version
|
||||
set pkg $argv[1]
|
||||
|
||||
if pacman -Q $pkg >/dev/null 2>&1
|
||||
pacman -Q $pkg
|
||||
else
|
||||
echo ""
|
||||
end
|
||||
end
|
||||
|
||||
function kernel_to_pkg
|
||||
set kernel (uname -r)
|
||||
|
||||
if string match -q "*zen*" $kernel
|
||||
echo linux-zen
|
||||
else if string match -q "*lts*" $kernel
|
||||
echo linux-lts
|
||||
else if string match -q "*hardened*" $kernel
|
||||
echo linux-hardened
|
||||
else
|
||||
echo linux
|
||||
end
|
||||
end
|
||||
|
||||
function updateall
|
||||
######## Get current versions (if installed)
|
||||
if command -q discord
|
||||
set discord_version (get_pkg_version discord)
|
||||
end
|
||||
set kernel_version (get_pkg_version (kernel_to_pkg))
|
||||
|
||||
######## Run PACMAN updates
|
||||
set_color cyan
|
||||
echo "#### Updating pacman ####"
|
||||
set_color normal
|
||||
sudo pacman -Syu
|
||||
|
||||
######## Do additional Discord Updates
|
||||
if command -q discord; and test "$discord_version" != "$(get_pkg_version discord)"
|
||||
set_color cyan
|
||||
echo "Discord version changed: $discord_version -> $(get_pkg_version discord)"
|
||||
set_color normal
|
||||
if test -e /usr/bin/curl
|
||||
echo "Running Vencord installer..."
|
||||
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
|
||||
else
|
||||
echo "'curl' is not installed. Install it to update Discord plugins."
|
||||
end
|
||||
end
|
||||
|
||||
######## Run FLATPAK Updates
|
||||
|
||||
if test -e /usr/bin/flatpak
|
||||
set_color cyan
|
||||
echo "#### Updating flatpak ####"
|
||||
set_color normal
|
||||
flatpak update
|
||||
end
|
||||
|
||||
######## Run GIT Updates
|
||||
|
||||
set_color cyan
|
||||
echo "#### Updating quickshell ####"
|
||||
set_color normal
|
||||
if test -d ~/.config/quickshell && test -d ~/.config/quickshell/.git
|
||||
pushd ~/.config/quickshell/
|
||||
git pull
|
||||
popd
|
||||
end
|
||||
|
||||
set_color cyan
|
||||
echo "#### Updating fish ####"
|
||||
set_color normal
|
||||
if test -d ~/.config/fish && test -d ~/.config/fish/.git
|
||||
pushd ~/.config/fish/
|
||||
git pull
|
||||
popd
|
||||
end
|
||||
|
||||
set_color cyan
|
||||
echo "#### Updating hyprland ####"
|
||||
set_color normal
|
||||
if test -d ~/.config/hypr && test -d ~/.config/hypr/.git
|
||||
pushd ~/.config/hypr/
|
||||
git pull
|
||||
popd
|
||||
end
|
||||
|
||||
######## Run AUR Updates
|
||||
|
||||
set_color cyan
|
||||
echo "#### Updating AUR ####"
|
||||
set_color normal
|
||||
if test -e /usr/bin/paru
|
||||
paru -Sua --sudoloop
|
||||
else if test -e /usr/bin/yay
|
||||
yay -Sua --sudoloop
|
||||
end
|
||||
|
||||
######## Restart if Kernel Updated
|
||||
|
||||
if test "$kernel_version" != "$(get_pkg_version $(kernel_to_pkg))"
|
||||
set_color cyan
|
||||
echo "Kernel changed: $kernel_version -> $(get_pkg_version $(kernel_to_pkg))"
|
||||
read -P "Reboot now? [y/N]: " answer
|
||||
set_color normal
|
||||
|
||||
if test "$answer" = "y" -o "$answer" = "Y"
|
||||
reboot
|
||||
else
|
||||
echo "Skipping reboot."
|
||||
end
|
||||
end
|
||||
end
|
||||
# ------------------------------------------------------------------------------
|
||||
# Aliases & small utilities (kept after main for readability)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
alias fixpacman='sudo rm -f /var/lib/pacman/db.lck'
|
||||
|
||||
function pacman
|
||||
if test "$argv[1]" = "-S"
|
||||
command pacman -S --needed $argv[2..]
|
||||
else
|
||||
command pacman $argv
|
||||
end
|
||||
end
|
||||
|
||||
if test -e /usr/bin/expac
|
||||
alias rip='expac --timefmt="%Y-%m-%d %T" "%l\t%n %v" | sort | tail -200 | nl'
|
||||
alias big='expac -H M "%m\t%n" | sort -h | nl'
|
||||
@@ -146,17 +43,28 @@ end
|
||||
|
||||
if test -e /usr/bin/tmux
|
||||
function quickshell-reload
|
||||
if test -e /usr/bin/quickshell
|
||||
if command -q quickshell
|
||||
tmux kill-session -t qs 2>/dev/null
|
||||
tmux new-session -d -s qs 'quickshell'
|
||||
tmux new-session -d -s qs 'env QT_QPA_PLATFORMTHEME=qt6ct quickshell'
|
||||
else
|
||||
echo "'quickshell' is not installed. Install it via your package manager."
|
||||
end
|
||||
end
|
||||
function hypridle-reload
|
||||
if command -q hypridle
|
||||
tmux kill-session -t hypridle 2>/dev/null
|
||||
tmux new-session -d -s hypridle 'hypridle'
|
||||
else
|
||||
echo "'hypridle' is not installed. Install it via your package manager."
|
||||
end
|
||||
end
|
||||
else
|
||||
function quickshell-reload
|
||||
echo "'tmux' is not installed. Install it via your package manager."
|
||||
end
|
||||
function hypridle-reload
|
||||
echo "'tmux' is not installed. Install it via your package manager."
|
||||
end
|
||||
end
|
||||
|
||||
if test -e /usr/bin/reflector
|
||||
@@ -165,3 +73,562 @@ if test -e /usr/bin/reflector
|
||||
alias mirrord='sudo reflector --latest 50 --number 20 --sort delay --save /etc/pacman.d/mirrorlist'
|
||||
alias mirrors='sudo reflector --latest 50 --number 20 --sort score --save /etc/pacman.d/mirrorlist'
|
||||
end
|
||||
|
||||
function pacman-autoremove
|
||||
set -l orphans (pacman -Qtdq)
|
||||
if test (count $orphans) -gt 0
|
||||
sudo pacman -Rns $orphans
|
||||
else
|
||||
echo "No orphaned packages."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
function get_pkg_version
|
||||
set pkg $argv[1]
|
||||
|
||||
if pacman -Q $pkg >/dev/null 2>&1
|
||||
pacman -Q $pkg
|
||||
else
|
||||
echo ""
|
||||
end
|
||||
end
|
||||
|
||||
function kernel_to_pkg
|
||||
set kernel (uname -r)
|
||||
|
||||
if string match -q "*zen*" $kernel
|
||||
echo linux-zen
|
||||
else if string match -q "*lts*" $kernel
|
||||
echo linux-lts
|
||||
else if string match -q "*hardened*" $kernel
|
||||
echo linux-hardened
|
||||
else
|
||||
echo linux
|
||||
end
|
||||
end
|
||||
|
||||
# Print a colored section header (cyan)
|
||||
function _print_section
|
||||
set -l title $argv[1]
|
||||
set_color cyan
|
||||
echo "#### $title ####"
|
||||
set_color normal
|
||||
end
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Main: updateall
|
||||
# Orchestrates system + dotfiles updates with:
|
||||
# - suppression when up-to-date (short "up to date" line)
|
||||
# - full output when updates exist (do NOT suppress)
|
||||
# - per-component summary at the end (git ones are important)
|
||||
# - --vencord / -v flag gates all discord/vencord queries
|
||||
# - AUR diff is mandatory (cannot be skipped)
|
||||
#
|
||||
# Order (readability):
|
||||
# 1) Flags / summary init / version snapshot
|
||||
# 2) System packages: pacman -> AUR -> flatpak
|
||||
# 3) Dotfiles: git (quickshell/fish/hypr/matugen)
|
||||
# 4) Optional: discord/vencord (only if --vencord)
|
||||
# 5) Kernel reboot prompt
|
||||
# 6) Summary
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
function updateall
|
||||
# ---- 1) Flags ----
|
||||
set -l _do_vencord 0
|
||||
argparse --name=updateall 'v/vencord' 'h/help' -- $argv
|
||||
or return 1
|
||||
if set -q _flag_help
|
||||
echo "Usage: updateall [--vencord] [-h/--help]"
|
||||
echo " --vencord, -v also (re)install/update Vencord when Discord changes or force when up to date"
|
||||
echo " -h, --help show this help"
|
||||
return 0
|
||||
end
|
||||
if set -q _flag_vencord
|
||||
set _do_vencord 1
|
||||
end
|
||||
if test (count $argv) -gt 0
|
||||
echo "updateall: unknown argument: $argv" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
# Summary tracking - parallel arrays: labels / status / color
|
||||
set -l _labels
|
||||
set -l _status
|
||||
set -l _colors
|
||||
|
||||
# Version snapshot (discord only if --vencord, per request)
|
||||
set -l discord_version ""
|
||||
if test $_do_vencord -eq 1; and type -q discord
|
||||
set discord_version (get_pkg_version discord)
|
||||
end
|
||||
set -l kernel_version (get_pkg_version (kernel_to_pkg))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 2) System packages
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# ---- pacman (core) ----
|
||||
_print_section "Updating pacman"
|
||||
set -l pacman_status "skipped"
|
||||
set -l pacman_color yellow
|
||||
if type -q pacman
|
||||
set -l has_updates 1
|
||||
set -l qu_output ""
|
||||
if type -q checkupdates
|
||||
set qu_output (checkupdates 2>&1)
|
||||
if test $status -eq 0 -a -n "$qu_output"
|
||||
set has_updates 0
|
||||
else if string match -q "*ERROR*Failed to synchronize*" "$qu_output"
|
||||
set has_updates 0
|
||||
end
|
||||
else
|
||||
set qu_output (pacman -Qu 2>&1)
|
||||
if test $status -eq 0
|
||||
set has_updates 0
|
||||
else if string match -q "*database*" "$qu_output"
|
||||
set has_updates 0
|
||||
end
|
||||
end
|
||||
|
||||
if test $has_updates -eq 1
|
||||
echo "pacman: up to date"
|
||||
set pacman_status "up to date"
|
||||
set pacman_color green
|
||||
else
|
||||
if test -n "$qu_output"
|
||||
echo "Pending pacman updates:"
|
||||
printf "%s\n" $qu_output
|
||||
end
|
||||
sudo pacman -Syu
|
||||
set -l pacman_code $status
|
||||
if test $pacman_code -eq 0
|
||||
set pacman_status "updated"
|
||||
set pacman_color green
|
||||
else
|
||||
set pacman_status "failed ($pacman_code)"
|
||||
set pacman_color red
|
||||
end
|
||||
end
|
||||
else
|
||||
echo "pacman not found, skipping"
|
||||
set pacman_status "not installed"
|
||||
set pacman_color yellow
|
||||
end
|
||||
set -a _labels "pacman"
|
||||
set -a _status $pacman_status
|
||||
set -a _colors $pacman_color
|
||||
|
||||
# ---- AUR (paru/yay) - directly after pacman, mandatory diff ----
|
||||
_print_section "Updating AUR"
|
||||
set -l aur_status "skipped"
|
||||
set -l aur_color yellow
|
||||
set -l aur_helper ""
|
||||
if type -q paru
|
||||
set aur_helper paru
|
||||
else if type -q yay
|
||||
set aur_helper yay
|
||||
end
|
||||
|
||||
if test -n "$aur_helper"
|
||||
set -l aur_qu ($aur_helper -Qua 2>&1)
|
||||
set -l aur_qu_code $status
|
||||
|
||||
# Robust state detection: use (count) not quoted -z, and explicit patterns.
|
||||
# aur_qu is a list (one element per line) -> count is reliable.
|
||||
set -l aur_is_up_to_date 0
|
||||
set -l aur_has_check_error 0
|
||||
|
||||
if test $aur_qu_code -eq 0
|
||||
if test (count $aur_qu) -eq 0
|
||||
set aur_is_up_to_date 1
|
||||
else if string match -qr -- "there is nothing to do|No AUR|No packages to upgrade" $aur_qu
|
||||
set aur_is_up_to_date 1
|
||||
end
|
||||
else
|
||||
# Non-zero: only treat as up-to-date if helper explicitly says so
|
||||
if string match -qr -- "there is nothing to do|No AUR" $aur_qu
|
||||
set aur_is_up_to_date 1
|
||||
else
|
||||
set aur_has_check_error 1
|
||||
end
|
||||
end
|
||||
|
||||
if test $aur_is_up_to_date -eq 1
|
||||
echo "AUR: up to date"
|
||||
set aur_status "up to date"
|
||||
set aur_color green
|
||||
else if test $aur_has_check_error -eq 1
|
||||
# Real check failure: do NOT silently report up-to-date
|
||||
echo "Failed to check for AUR updates (code $aur_qu_code):"
|
||||
if test (count $aur_qu) -gt 0
|
||||
printf "%s\n" $aur_qu
|
||||
else
|
||||
echo "(no output)"
|
||||
end
|
||||
echo ""
|
||||
set_color yellow
|
||||
echo "==> AUR PKGBUILD review is MANDATORY - diff cannot be skipped."
|
||||
echo " Note: PKGBUILDs must NEVER contain 'sudo'. Please verify diffs contain no 'sudo'."
|
||||
set_color normal
|
||||
set -l answer ""
|
||||
read -l -P "Update now? [y/N]: " answer
|
||||
if string match -qr -- "^[Yy]\$" "$answer"
|
||||
if test "$aur_helper" = "paru"
|
||||
paru -Sua --sudoloop --review
|
||||
else
|
||||
yay -Sua --sudoloop --diffmenu --answerdiff All --answerclean All
|
||||
end
|
||||
set -l _aur_code $status
|
||||
if test $_aur_code -eq 0
|
||||
set aur_status "updated"
|
||||
set aur_color green
|
||||
else
|
||||
set aur_status "failed ($_aur_code)"
|
||||
set aur_color red
|
||||
end
|
||||
end
|
||||
else
|
||||
echo "Pending AUR updates:"
|
||||
printf "%s\n" $aur_qu
|
||||
set_color yellow
|
||||
echo "==> AUR PKGBUILD review is MANDATORY - diff cannot be skipped."
|
||||
echo " Note: PKGBUILDs must NEVER contain 'sudo'. Please verify diffs contain no 'sudo'."
|
||||
set_color normal
|
||||
set -l answer ""
|
||||
read -l -P "Update now? [y/N]: " answer
|
||||
if string match -qr -- "^[Yy]\$" "$answer"
|
||||
if test "$aur_helper" = "paru"
|
||||
paru -Sua --sudoloop --review
|
||||
else
|
||||
yay -Sua --sudoloop --diffmenu --answerdiff All --answerclean All
|
||||
end
|
||||
set -l _aur_code $status
|
||||
if test $_aur_code -eq 0
|
||||
set aur_status "updated"
|
||||
set aur_color green
|
||||
else
|
||||
set aur_status "failed ($_aur_code)"
|
||||
set aur_color red
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
echo "No AUR helper (paru/yay) found, skipping"
|
||||
set aur_status "no helper"
|
||||
set aur_color yellow
|
||||
end
|
||||
set -a _labels "AUR"
|
||||
set -a _status $aur_status
|
||||
set -a _colors $aur_color
|
||||
|
||||
# ---- flatpak ----
|
||||
_print_section "Updating flatpak"
|
||||
set -l flatpak_status "skipped"
|
||||
set -l flatpak_color yellow
|
||||
if not type -q flatpak
|
||||
set flatpak_status "not installed"
|
||||
set flatpak_color yellow
|
||||
else
|
||||
set -l flatpak_tmp (mktemp)
|
||||
if test $status -ne 0 -o -z "$flatpak_tmp"
|
||||
echo "flatpak: failed to create temp file"
|
||||
set flatpak_status "update check failed"
|
||||
set flatpak_color red
|
||||
else
|
||||
set -l flatpak_check_code
|
||||
set -l flatpak_check
|
||||
if type -q timeout
|
||||
timeout 5s flatpak remote-ls --updates >"$flatpak_tmp" 2>&1
|
||||
set flatpak_check_code $status
|
||||
else
|
||||
flatpak remote-ls --updates >"$flatpak_tmp" 2>&1
|
||||
set flatpak_check_code $status
|
||||
end
|
||||
set flatpak_check (cat "$flatpak_tmp")
|
||||
rm -f "$flatpak_tmp"
|
||||
|
||||
# flatpak_has_updates: 0 = pending updates, 1 = up to date, 2 = check failed/timeout
|
||||
set -l flatpak_has_updates 0
|
||||
if test $flatpak_check_code -eq 0
|
||||
if test -z "$flatpak_check"
|
||||
set flatpak_has_updates 1
|
||||
else
|
||||
set flatpak_has_updates 0
|
||||
end
|
||||
else if test $flatpak_check_code -eq 124
|
||||
set flatpak_has_updates 2
|
||||
else
|
||||
set flatpak_has_updates 2
|
||||
end
|
||||
|
||||
if test $flatpak_has_updates -eq 2
|
||||
if test $flatpak_check_code -eq 124
|
||||
echo "flatpak: update check timed out (5s)"
|
||||
else
|
||||
echo "flatpak: update check failed"
|
||||
end
|
||||
if test -n "$flatpak_check"
|
||||
printf "%s\n" $flatpak_check
|
||||
end
|
||||
set flatpak_status "update check failed"
|
||||
set flatpak_color red
|
||||
else if test $flatpak_has_updates -eq 1
|
||||
echo "flatpak: up to date"
|
||||
set flatpak_status "up to date"
|
||||
set flatpak_color green
|
||||
else
|
||||
if test -n "$flatpak_check"
|
||||
echo "Pending flatpak updates:"
|
||||
printf "%s\n" $flatpak_check
|
||||
end
|
||||
set -l flatpak_code
|
||||
if type -q timeout
|
||||
timeout 300s flatpak update
|
||||
set flatpak_code $status
|
||||
else
|
||||
flatpak update
|
||||
set flatpak_code $status
|
||||
end
|
||||
if test $flatpak_code -eq 124
|
||||
echo "flatpak: update timed out (300s)"
|
||||
set flatpak_status "update timed out"
|
||||
set flatpak_color red
|
||||
else if test $flatpak_code -eq 0
|
||||
set flatpak_status "updated"
|
||||
set flatpak_color green
|
||||
else
|
||||
set flatpak_status "failed ($flatpak_code)"
|
||||
set flatpak_color red
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
set -a _labels "flatpak"
|
||||
set -a _status $flatpak_status
|
||||
set -a _colors $flatpak_color
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 3) Dotfiles (git) - always show per-repo success/fail, suppress only when up to date
|
||||
# ----------------------------------------------------------------------
|
||||
set -l git_repos "quickshell:$HOME/.config/quickshell" "fish:$HOME/.config/fish" "hypr:$HOME/.config/hypr" "matugen:$HOME/.config/matugen"
|
||||
|
||||
if not type -q git
|
||||
echo "git not installed"
|
||||
set git_status "git not installed"
|
||||
set git_color yellow
|
||||
set -a _labels "git"
|
||||
set -a _status $git_status
|
||||
set -a _colors $git_color
|
||||
else
|
||||
for entry in $git_repos
|
||||
set -l parts (string split ":" -- $entry)
|
||||
set -l name $parts[1]
|
||||
set -l path $parts[2]
|
||||
_print_section "Updating $name"
|
||||
set -l git_status "skipped"
|
||||
set -l git_color yellow
|
||||
|
||||
if not test -d $path/.git
|
||||
echo "skipped: $path not a git repo"
|
||||
set git_status "not tracked"
|
||||
set git_color yellow
|
||||
else
|
||||
git -C $path fetch --quiet >/dev/null 2>&1
|
||||
set -l fetch_code $status
|
||||
set -l behind_str (git -C $path rev-list --count HEAD..@{u} 2>&1)
|
||||
set -l behind_code $status
|
||||
if test $fetch_code -ne 0 -o $behind_code -ne 0
|
||||
set -l git_output (git -C $path pull 2>&1)
|
||||
set -l git_code $status
|
||||
if test $git_code -ne 0
|
||||
printf "%s\n" $git_output
|
||||
set git_status "failed ($git_code)"
|
||||
set git_color red
|
||||
else if string match -q "*Already up to date*" "$git_output"
|
||||
echo "$name: up to date"
|
||||
set git_status "up to date"
|
||||
set git_color green
|
||||
else
|
||||
printf "%s\n" $git_output
|
||||
set git_status "updated"
|
||||
set git_color green
|
||||
end
|
||||
else if test "$behind_str" = "0"
|
||||
echo "$name: up to date"
|
||||
set git_status "up to date"
|
||||
set git_color green
|
||||
else
|
||||
git -C $path pull
|
||||
set -l pull_code $status
|
||||
if test $pull_code -eq 0
|
||||
set git_status "updated"
|
||||
set git_color green
|
||||
else
|
||||
set git_status "failed ($pull_code)"
|
||||
set git_color red
|
||||
end
|
||||
end
|
||||
end
|
||||
set -a _labels "git:$name"
|
||||
set -a _status $git_status
|
||||
set -a _colors $git_color
|
||||
end
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 4) Optional: Discord / Vencord (only when --vencord)
|
||||
# ----------------------------------------------------------------------
|
||||
set -l discord_status "skipped"
|
||||
set -l discord_color yellow
|
||||
set -l vencord_status "skipped"
|
||||
set -l vencord_color yellow
|
||||
set -l _need_vencord_label 0
|
||||
if test $_do_vencord -eq 0
|
||||
set discord_status "skipped (use --vencord)"
|
||||
set discord_color yellow
|
||||
set vencord_status "skipped (use --vencord)"
|
||||
set vencord_color yellow
|
||||
else if type -q discord
|
||||
set -l new_discord_version (get_pkg_version discord)
|
||||
if test "$discord_version" != "$new_discord_version"
|
||||
set_color cyan
|
||||
echo "Discord version changed: $discord_version -> $new_discord_version"
|
||||
set_color normal
|
||||
set discord_status "updated ($new_discord_version)"
|
||||
set discord_color green
|
||||
if test $_do_vencord -eq 1
|
||||
set _need_vencord_label 1
|
||||
if type -q curl
|
||||
echo "Running Vencord installer (--vencord)..."
|
||||
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
|
||||
if test $status -eq 0
|
||||
set vencord_status "updated ($new_discord_version)"
|
||||
set vencord_color green
|
||||
set discord_status "$discord_status + vencord ok"
|
||||
else
|
||||
set vencord_status "failed ($status)"
|
||||
set vencord_color red
|
||||
set discord_status "$discord_status + vencord failed"
|
||||
set discord_color red
|
||||
end
|
||||
else
|
||||
echo "'curl' is not installed. Install it to update Discord plugins."
|
||||
set vencord_status "curl missing"
|
||||
set vencord_color yellow
|
||||
set discord_status "$discord_status + vencord skipped (curl missing)"
|
||||
set discord_color yellow
|
||||
end
|
||||
else
|
||||
set vencord_status "skipped (discord updated, use --vencord)"
|
||||
set vencord_color yellow
|
||||
echo "Discord updated, skipping Vencord (use --vencord to update)"
|
||||
end
|
||||
else
|
||||
set discord_status "up to date ($new_discord_version)"
|
||||
set discord_color green
|
||||
if test $_do_vencord -eq 1
|
||||
set _need_vencord_label 1
|
||||
set_color cyan
|
||||
echo "Discord up to date ($new_discord_version), but --vencord given: running Vencord installer..."
|
||||
set_color normal
|
||||
if type -q curl
|
||||
sh -c "$(curl -sS https://raw.githubusercontent.com/Vendicated/VencordInstaller/main/install.sh)"
|
||||
if test $status -eq 0
|
||||
set vencord_status "refreshed/updated"
|
||||
set vencord_color green
|
||||
set discord_status "$discord_status + vencord ok"
|
||||
else
|
||||
set vencord_status "failed ($status)"
|
||||
set vencord_color red
|
||||
set discord_status "$discord_status + vencord failed"
|
||||
end
|
||||
else
|
||||
echo "'curl' is not installed. Install it to update Discord plugins."
|
||||
set vencord_status "curl missing"
|
||||
set vencord_color yellow
|
||||
end
|
||||
else
|
||||
set vencord_status "skipped (use --vencord)"
|
||||
set vencord_color yellow
|
||||
end
|
||||
end
|
||||
else
|
||||
set discord_status "not installed"
|
||||
set discord_color yellow
|
||||
if test $_do_vencord -eq 1
|
||||
set _need_vencord_label 1
|
||||
set vencord_status "skipped (discord not installed)"
|
||||
set vencord_color yellow
|
||||
echo "Discord not installed, skipping Vencord"
|
||||
end
|
||||
end
|
||||
set -a _labels "discord"
|
||||
set -a _status $discord_status
|
||||
set -a _colors $discord_color
|
||||
if test $_do_vencord -eq 1
|
||||
set -a _labels "vencord"
|
||||
set -a _status $vencord_status
|
||||
set -a _colors $vencord_color
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 5) Kernel (needs reboot if package changed)
|
||||
# ----------------------------------------------------------------------
|
||||
set -l kernel_status "up to date"
|
||||
set -l kernel_color green
|
||||
set -l new_kernel_version (get_pkg_version (kernel_to_pkg))
|
||||
if test "$kernel_version" != "$new_kernel_version"
|
||||
set_color cyan
|
||||
echo "Kernel changed: $kernel_version -> $new_kernel_version"
|
||||
set_color normal
|
||||
set kernel_status "updated ($kernel_version -> $new_kernel_version)"
|
||||
set kernel_color green
|
||||
set answer ""
|
||||
read -P "Reboot now? [y/N]: " answer
|
||||
if test "$answer" = "y" -o "$answer" = "Y"
|
||||
reboot
|
||||
else
|
||||
echo "Skipping reboot."
|
||||
set kernel_status "$kernel_status (reboot skipped)"
|
||||
end
|
||||
else
|
||||
set kernel_status "up to date ($new_kernel_version)"
|
||||
set kernel_color green
|
||||
end
|
||||
set -a _labels "kernel"
|
||||
set -a _status $kernel_status
|
||||
set -a _colors $kernel_color
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 6) Summary (always shown, per-component success/fail)
|
||||
# ----------------------------------------------------------------------
|
||||
echo ""
|
||||
set_color --bold cyan
|
||||
echo "########################"
|
||||
echo "#### Update Summary ####"
|
||||
echo "########################"
|
||||
set_color normal
|
||||
set -l max_len 0
|
||||
for l in $_labels
|
||||
if test (string length -- $l) -gt $max_len
|
||||
set max_len (string length -- $l)
|
||||
end
|
||||
end
|
||||
for i in (seq (count $_labels))
|
||||
set -l label $_labels[$i]
|
||||
set -l stat $_status[$i]
|
||||
set -l col $_colors[$i]
|
||||
set -l pad (string repeat -n (math $max_len - (string length -- $label)) " ")
|
||||
set_color normal
|
||||
printf "%s%s : " $label $pad
|
||||
set_color $col
|
||||
echo $stat
|
||||
set_color normal
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,267 @@
|
||||
function copytime -d 'Copy timestamps between files; for media files also copies the container creation date'
|
||||
argparse -n copytime 'h/help' 'd/date=' -- $argv
|
||||
or return 2
|
||||
|
||||
if set -q _flag_help
|
||||
__copytime_usage
|
||||
return 0
|
||||
end
|
||||
|
||||
if test (count $argv) -lt 1
|
||||
__copytime_usage
|
||||
return 2
|
||||
end
|
||||
|
||||
__copytime_colors
|
||||
|
||||
if set -q _flag_date
|
||||
set -l rc 0
|
||||
for f in $argv
|
||||
__copytime_setdate "$f" "$_flag_date"
|
||||
or set rc 1
|
||||
end
|
||||
return $rc
|
||||
end
|
||||
|
||||
if test (count $argv) -lt 2
|
||||
__copytime_usage
|
||||
return 2
|
||||
end
|
||||
|
||||
set -l src $argv[1]
|
||||
set -l dsts $argv[2..-1]
|
||||
|
||||
if not test -e "$src"
|
||||
__copytime_error "no such source: '$src'"
|
||||
return 1
|
||||
end
|
||||
|
||||
switch (uname -s)
|
||||
case Linux
|
||||
__copytime_linux "$src" $dsts
|
||||
case Darwin
|
||||
__copytime_darwin "$src" $dsts
|
||||
case '*'
|
||||
__copytime_error "unsupported platform '(uname -s)'"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function __copytime_linux
|
||||
set -l src $argv[1]
|
||||
set -l rc 0
|
||||
|
||||
set -l mtime (stat -c '%y' -- "$src" | string replace -r '\.[0-9]+' '')
|
||||
set -l atime (stat -c '%x' -- "$src" | string replace -r '\.[0-9]+' '')
|
||||
echo "$vrot_c_dim source: $src$vrot_c_reset"
|
||||
echo "$vrot_c_dim modified: $mtime$vrot_c_reset"
|
||||
echo "$vrot_c_dim accessed: $atime$vrot_c_reset"
|
||||
|
||||
set -l birth (stat -c '%w' -- "$src")
|
||||
if test -n "$birth"; and string match -q '*[-Unknown]*' "$birth"
|
||||
set birth ''
|
||||
end
|
||||
if test -n "$birth"
|
||||
set -l btime (string replace -r '\.[0-9]+' '' -- "$birth")
|
||||
echo "$vrot_c_dim created: $btime (filesystem creation time cannot be set on Linux)$vrot_c_reset"
|
||||
end
|
||||
|
||||
set -l created (__copytime_mediadate "$src")
|
||||
if test -n "$created"
|
||||
set -l ctime (string replace 'T' ' ' -- "$created" | string replace -r '\.\d+Z?$' '')
|
||||
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
|
||||
end
|
||||
|
||||
for dst in $argv[2..-1]
|
||||
if not test -e "$dst"
|
||||
__copytime_error "skipping missing destination: '$dst'"
|
||||
set rc 1
|
||||
continue
|
||||
end
|
||||
touch -a -m -r "$src" "$dst"
|
||||
if test $status -ne 0
|
||||
__copytime_error "failed to copy timestamps to '$dst'"
|
||||
set rc 1
|
||||
continue
|
||||
end
|
||||
set -l dm (stat -c '%y' -- "$dst" | string replace -r '\.[0-9]+' '')
|
||||
echo "$vrot_c_ok ✔ $dst$vrot_c_dim ← modified $dm$vrot_c_reset"
|
||||
if test -n "$created"
|
||||
__copytime_meta "$dst" "$created"
|
||||
or set rc 1
|
||||
end
|
||||
end
|
||||
return $rc
|
||||
end
|
||||
|
||||
function __copytime_darwin
|
||||
set -l src $argv[1]
|
||||
set -l rc 0
|
||||
|
||||
set -l mtime (stat -f '%Sm' -t '%Y-%m-%d %H:%M:%S' -- "$src")
|
||||
set -l btime (stat -f '%SB' -t '%Y-%m-%d %H:%M:%S' -- "$src")
|
||||
echo "$vrot_c_dim source: $src$vrot_c_reset"
|
||||
echo "$vrot_c_dim modified: $mtime$vrot_c_reset"
|
||||
echo "$vrot_c_dim created: $btime$vrot_c_reset"
|
||||
|
||||
set -l created (__copytime_mediadate "$src")
|
||||
if test -n "$created"
|
||||
set -l ctime (string replace 'T' ' ' -- "$created" | string replace -r '\.\d+Z?$' '')
|
||||
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
|
||||
end
|
||||
|
||||
set -l birth (stat -f '%SB' -t '%m/%d/%Y %H:%M:%S' -- "$src")
|
||||
|
||||
for dst in $argv[2..-1]
|
||||
if not test -e "$dst"
|
||||
__copytime_error "skipping missing destination: '$dst'"
|
||||
set rc 1
|
||||
continue
|
||||
end
|
||||
touch -a -m -r "$src" "$dst"
|
||||
if test $status -ne 0
|
||||
set rc 1
|
||||
continue
|
||||
end
|
||||
if command -q SetFile
|
||||
SetFile -d "$birth" "$dst"
|
||||
if test $status -ne 0
|
||||
__copytime_error "failed to set creation time on '$dst'"
|
||||
set rc 1
|
||||
end
|
||||
else
|
||||
echo "$vrot_c_warn ⚠ SetFile not found — creation time not copied to $dst$vrot_c_reset" >&2
|
||||
end
|
||||
set -l db (stat -f '%SB' -t '%Y-%m-%d %H:%M:%S' -- "$dst")
|
||||
echo "$vrot_c_ok ✔ $dst$vrot_c_dim ← created $db$vrot_c_reset"
|
||||
if test -n "$created"
|
||||
__copytime_meta "$dst" "$created"
|
||||
or set rc 1
|
||||
end
|
||||
end
|
||||
return $rc
|
||||
end
|
||||
|
||||
function __copytime_mediadate
|
||||
if not command -q ffprobe
|
||||
return 0
|
||||
end
|
||||
if not __copytime_media "$argv[1]"
|
||||
return 0
|
||||
end
|
||||
set -l d (ffprobe -v error -show_entries format_tags=creation_time \
|
||||
-of default=noprint_wrappers=1:nokey=1 "$argv[1]")[1]
|
||||
string match -rq '^[0-9]{4}-[0-9]{2}-[0-9]{2}' "$d"; and echo "$d"
|
||||
end
|
||||
|
||||
function __copytime_meta
|
||||
set -l dst $argv[1]
|
||||
set -l date $argv[2]
|
||||
|
||||
if not command -q ffmpeg
|
||||
return 0
|
||||
end
|
||||
if not __copytime_media "$dst"
|
||||
return 0
|
||||
end
|
||||
|
||||
set -l tmp (string join '' "$dst" .ct. (random) (path extension "$dst"))
|
||||
ffmpeg -hide_banner -loglevel error -y -i "$dst" -map 0 -map '-0:d' -map '-0:t' \
|
||||
-c copy -metadata creation_time="$date" "$tmp"
|
||||
if test $status -ne 0
|
||||
rm -f "$tmp"
|
||||
__copytime_error "failed to copy container creation date to '$dst'"
|
||||
return 1
|
||||
end
|
||||
mv -f -- "$tmp" "$dst"
|
||||
if test $status -ne 0
|
||||
rm -f "$tmp"
|
||||
__copytime_error "failed to replace '$dst'"
|
||||
return 1
|
||||
end
|
||||
set -l ctime (string replace 'T' ' ' -- "$date" | string replace -r '\.\d+Z?$' '')
|
||||
echo "$vrot_c_dim container created: $ctime$vrot_c_reset"
|
||||
end
|
||||
|
||||
function __copytime_setdate
|
||||
set -l file $argv[1]
|
||||
set -l date $argv[2]
|
||||
|
||||
if not test -e "$file"
|
||||
__copytime_error "no such file: '$file'"
|
||||
return 1
|
||||
end
|
||||
if not __copytime_media "$file"
|
||||
__copytime_error "'$file' is not a supported media file"
|
||||
return 1
|
||||
end
|
||||
if not command -q ffmpeg
|
||||
__copytime_error "ffmpeg is required to set container dates"
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l tmp (string join '' "$file" .ct. (random) (path extension "$file"))
|
||||
ffmpeg -hide_banner -loglevel error -y -i "$file" -map 0 -map '-0:d' -map '-0:t' \
|
||||
-c copy -metadata creation_time="$date" "$tmp"
|
||||
if test $status -ne 0
|
||||
rm -f "$tmp"
|
||||
__copytime_error "failed to write creation date to '$file'"
|
||||
return 1
|
||||
end
|
||||
mv -f -- "$tmp" "$file"
|
||||
if test $status -ne 0
|
||||
rm -f "$tmp"
|
||||
__copytime_error "failed to replace '$file'"
|
||||
return 1
|
||||
end
|
||||
set -l dsp (string replace 'T' ' ' -- "$date")
|
||||
echo "$vrot_c_ok ✔ $file$vrot_c_dim ← container creation date $dsp$vrot_c_reset"
|
||||
end
|
||||
|
||||
function __copytime_media
|
||||
set -l ext (string lower (path extension "$argv[1]"))
|
||||
switch "$ext"
|
||||
case '.mp4' '.mov' '.m4v' '.mkv' '.webm' '.avi' '.ts' '.mts' '.m2ts' '.flv' '.wmv' '.mpg' '.mpeg' '.3gp' '.vob' '.ogv'
|
||||
return 0
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function __copytime_colors
|
||||
set -q vrot_colors_set; and return 0
|
||||
set -g vrot_colors_set 1
|
||||
if isatty stdout
|
||||
set -g vrot_c_ok (set_color brgreen)
|
||||
set -g vrot_c_dim (set_color brblack)
|
||||
set -g vrot_c_warn (set_color bryellow)
|
||||
set -g vrot_c_err (set_color brred)
|
||||
set -g vrot_c_reset (set_color normal)
|
||||
else
|
||||
for c in ok dim warn err reset
|
||||
set -g vrot_c_$c ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __copytime_error
|
||||
echo "$vrot_c_err""copytime: "$argv"$vrot_c_reset" >&2
|
||||
end
|
||||
|
||||
function __copytime_usage
|
||||
echo 'usage: copytime <source> <destination> [<destination> ...]'
|
||||
echo ' copytime --date <DATE> <video> [<video> ...]'
|
||||
echo
|
||||
echo 'Copies the access and modified timestamps from <source> to each'
|
||||
echo '<destination> (same semantics as `touch -r`). On macOS the filesystem'
|
||||
echo 'creation time is copied too (requires SetFile).'
|
||||
echo
|
||||
echo 'For media files (mp4, mkv, mov, webm, ...), the creation date stored'
|
||||
echo 'inside the container - the one apps like Plex and photo managers show -'
|
||||
echo 'is copied from source to destination and printed. Data/timecode tracks'
|
||||
echo 'are dropped while remuxing (lossless, no re-encode).'
|
||||
echo
|
||||
echo 'options:'
|
||||
echo ' -d, --date <DATE> set the container creation date of the given video(s)'
|
||||
echo ' directly, e.g. "2020-01-02 03:04:05"'
|
||||
echo ' -h, --help show this help'
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
function fish_greeting
|
||||
if test -e /usr/bin/fastfetch
|
||||
fastfetch
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,313 @@
|
||||
function rscp --description "Copy SOURCE... to DESTINATION via rsync (local or NAS)"
|
||||
# rscp: rsync-based copy that understands the local NAS mounts.
|
||||
#
|
||||
# Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION
|
||||
#
|
||||
# Only the LAST argument is the destination; everything before it is a
|
||||
# source. That way wildcards just work: `rscp *.mkv /dest/` copies every
|
||||
# match instead of silently dropping all but the first one.
|
||||
#
|
||||
# Paths under /home/honney/mount/<dataset> are transferred directly as
|
||||
# NAS:/mnt/tank/<dataset>, so rsync talks to the NAS instead of going
|
||||
# through the local mount. Purely local (PC -> PC) copies use rsync with
|
||||
# the same flags as rcp (-avh --progress).
|
||||
# NAS -> NAS copies run on the NAS itself via `ssh <host> ... rsync`,
|
||||
# keeping the flags of the "to remote" direction (sudo + chown).
|
||||
|
||||
set -l force 0
|
||||
# Only leading flags are options; everything else (even a source starting
|
||||
# with "-") is a path. Use `--` to end option parsing explicitly.
|
||||
while test (count $argv) -gt 0
|
||||
switch $argv[1]
|
||||
case -y --yes
|
||||
set force 1
|
||||
set -e argv[1]
|
||||
case -h --help
|
||||
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION"
|
||||
echo ""
|
||||
echo "Copy one or more SOURCEs to DESTINATION with rsync."
|
||||
echo "Only the last argument is the destination; everything before it is a source,"
|
||||
echo "so wildcards at the source (e.g. rscp *.mkv /dest/) work as expected."
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -y, --yes skip the overwrite confirmation prompt"
|
||||
echo " -h, --help show this help"
|
||||
return 0
|
||||
case --
|
||||
set -e argv[1]
|
||||
break
|
||||
case '-*'
|
||||
echo "rscp: unknown option: $argv[1]" >&2
|
||||
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION" >&2
|
||||
return 1
|
||||
case '*'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if test (count $argv) -lt 2
|
||||
echo "Usage: rscp [-y|--yes] [--] SOURCE... DESTINATION" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
if not command -q rsync
|
||||
echo "rscp: 'rsync' is not installed. Install it via your package manager." >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
# Mount <-> NAS dataset mapping (keep both lists in the same order)
|
||||
set -l mounts /home/honney/mount/Media /home/honney/mount/Data /home/honney/mount/Ripping /home/honney/mount/Apps
|
||||
set -l remotes NAS:/mnt/tank/Media NAS:/mnt/tank/Data NAS:/mnt/tank/Ripping NAS:/mnt/tank/Apps
|
||||
|
||||
# Only the last argument is the destination; everything before it is a
|
||||
# source, so any number of (wildcard-expanded) sources is supported.
|
||||
set -l n (count $argv)
|
||||
set -l last_src (math $n - 1)
|
||||
set -l dst_raw $argv[$n]
|
||||
set -l srcs_raw $argv[1..$last_src]
|
||||
|
||||
# Translate sources: local mount path -> NAS:<path>. For each source keep
|
||||
# the translated path, a 1/0 remote flag, the remote host and the path
|
||||
# as seen on the remote side (without the "HOST:" prefix).
|
||||
set -l srcs
|
||||
set -l src_remote_flags
|
||||
set -l src_hosts
|
||||
set -l src_naslocals
|
||||
set -l hosts
|
||||
for raw in $srcs_raw
|
||||
set -l s $raw
|
||||
set -l is_remote 0
|
||||
for i in (seq (count $mounts))
|
||||
if string match -q -- $mounts[$i] $s; or string match -q -- "$mounts[$i]/*" $s
|
||||
set s (string replace -f -- $mounts[$i] $remotes[$i] $s)
|
||||
set is_remote 1
|
||||
break
|
||||
end
|
||||
end
|
||||
# Also accept an explicit HOST:/path given directly.
|
||||
if test $is_remote -eq 0
|
||||
if string match -qr '^[A-Za-z0-9_.@-]+:/' -- $s
|
||||
set is_remote 1
|
||||
end
|
||||
end
|
||||
set -l host ""
|
||||
set -l naslocal $s
|
||||
if test $is_remote -eq 1
|
||||
set -l parts (string split -m1 : -- $s)
|
||||
set host $parts[1]
|
||||
set naslocal (string join : -- $parts[2..-1])
|
||||
if not contains -- $host $hosts
|
||||
set -a hosts $host
|
||||
end
|
||||
end
|
||||
set -a srcs $s
|
||||
set -a src_remote_flags $is_remote
|
||||
set -a src_hosts $host
|
||||
set -a src_naslocals $naslocal
|
||||
end
|
||||
|
||||
# Translate the destination the same way (it is always $argv[-1]).
|
||||
set -l dst $dst_raw
|
||||
set -l dst_remote 0
|
||||
for i in (seq (count $mounts))
|
||||
if string match -q -- $mounts[$i] $dst; or string match -q -- "$mounts[$i]/*" $dst
|
||||
set dst (string replace -f -- $mounts[$i] $remotes[$i] $dst)
|
||||
set dst_remote 1
|
||||
break
|
||||
end
|
||||
end
|
||||
if test $dst_remote -eq 0
|
||||
if string match -qr '^[A-Za-z0-9_.@-]+:/' -- $dst
|
||||
set dst_remote 1
|
||||
end
|
||||
end
|
||||
set -l dst_host ""
|
||||
set -l dst_naslocal $dst
|
||||
if test $dst_remote -eq 1
|
||||
set -l dparts (string split -m1 : -- $dst)
|
||||
set dst_host $dparts[1]
|
||||
set dst_naslocal (string join : -- $dparts[2..-1])
|
||||
if not contains -- $dst_host $hosts
|
||||
set -a hosts $dst_host
|
||||
end
|
||||
end
|
||||
|
||||
set -l n_src_remote 0
|
||||
for f in $src_remote_flags
|
||||
if test $f -eq 1
|
||||
set n_src_remote (math $n_src_remote + 1)
|
||||
end
|
||||
end
|
||||
set -l any_remote 0
|
||||
if test $dst_remote -eq 1; or test $n_src_remote -gt 0
|
||||
set any_remote 1
|
||||
end
|
||||
|
||||
# Failsafe: when a remote side is involved, verify ssh actually knows the
|
||||
# host (e.g. via ~/.ssh/config) before copying anything. The probe is
|
||||
# non-interactive; the real transfer below still uses your normal ssh
|
||||
# config/auth (password prompt included).
|
||||
if test $any_remote -eq 1
|
||||
if not command -q ssh
|
||||
echo "rscp: 'ssh' is not installed, but a remote copy was requested." >&2
|
||||
return 1
|
||||
end
|
||||
if test (count $hosts) -gt 1
|
||||
echo "rscp: copies between different remote hosts are not supported: $hosts" >&2
|
||||
return 1
|
||||
end
|
||||
for h in $hosts
|
||||
set -l probe_err (ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null $h true 2>&1)
|
||||
set -l probe_st $status
|
||||
if test $probe_st -ne 0
|
||||
if string match -qi -- "*could not resolve*" $probe_err; or string match -qi -- "*name or service not known*" $probe_err; or string match -qi -- "*no address associated*" $probe_err; or string match -qi -- "*nodename nor servname*" $probe_err
|
||||
echo "rscp: ssh host '$h' is unknown (check the 'Host $h' entry in ~/.ssh/config)." >&2
|
||||
return 1
|
||||
else if string match -qi -- "*permission denied*" $probe_err; or string match -qi -- "*authentication fail*" $probe_err
|
||||
echo "rscp: note: key auth for '$h' failed; continuing, ssh may ask for a password." >&2
|
||||
else
|
||||
echo "rscp: cannot reach ssh host '$h': $probe_err" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Failsafe: if the destination already exists *and has content*, ask
|
||||
# before overwriting. An existing but empty directory is not worth
|
||||
# asking about - there is nothing that could be lost.
|
||||
set -l dst_disp $dst_raw
|
||||
if test "$dst" != "$dst_raw"
|
||||
set dst_disp "$dst_raw ($dst)"
|
||||
end
|
||||
set -l dst_exists 0
|
||||
set -l dst_is_dir 0
|
||||
set -l dst_nonempty 0
|
||||
if test $dst_remote -eq 1
|
||||
set -l qdst (__rscp_shquote $dst_naslocal)
|
||||
if ssh $dst_host test -e $qdst
|
||||
set dst_exists 1
|
||||
else if ssh $dst_host test -L $qdst
|
||||
set dst_exists 1
|
||||
end
|
||||
if test $dst_exists -eq 1
|
||||
if ssh $dst_host test -d $qdst
|
||||
set dst_is_dir 1
|
||||
set -l listing (ssh $dst_host ls -A $qdst 2>/dev/null)
|
||||
set -l ls_st $status
|
||||
if test $ls_st -ne 0; or test (count $listing) -gt 0
|
||||
# Unlistable -> stay safe and treat it as non-empty.
|
||||
set dst_nonempty 1
|
||||
end
|
||||
else
|
||||
# File (or symlink): overwriting would replace content.
|
||||
set dst_nonempty 1
|
||||
end
|
||||
end
|
||||
else
|
||||
if test -e "$dst"; or test -L "$dst"
|
||||
set dst_exists 1
|
||||
end
|
||||
if test $dst_exists -eq 1
|
||||
if test -d "$dst"
|
||||
set dst_is_dir 1
|
||||
set -l listing (command ls -A -- "$dst" 2>/dev/null)
|
||||
set -l ls_st $status
|
||||
if test $ls_st -ne 0; or test (count $listing) -gt 0
|
||||
set dst_nonempty 1
|
||||
end
|
||||
else
|
||||
set dst_nonempty 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if test $dst_nonempty -eq 1
|
||||
if test (count $srcs) -gt 1; and test $dst_is_dir -eq 0
|
||||
echo "rscp: destination '$dst_disp' exists and is not a directory, but multiple sources were given." >&2
|
||||
return 1
|
||||
end
|
||||
if test $force -eq 0
|
||||
if not isatty stdin
|
||||
echo "rscp: destination '$dst_disp' already exists and is not empty. Re-run interactively or pass -y/--yes to overwrite." >&2
|
||||
return 1
|
||||
end
|
||||
if not read -l -P "rscp: destination '$dst_disp' already exists and is not empty. Overwrite/merge? [y/N] " confirm_raw
|
||||
echo "rscp: aborted." >&2
|
||||
return 1
|
||||
end
|
||||
switch (string lower -- (string trim -- "$confirm_raw"))
|
||||
case y yes
|
||||
# proceed
|
||||
case '*'
|
||||
echo "rscp: aborted."
|
||||
return 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# --no-perms: required - TrueNAS ZFS datasets use SMB ACLs and reject unix perms preservation
|
||||
set -l base_opts -avh --no-perms --info=progress2 --partial
|
||||
# Flags of the "to remote" direction; remote-to-remote via ssh on the NAS
|
||||
# keeps these same flags (sudo for the chown, which needs root).
|
||||
set -l to_remote_opts --rsync-path="sudo -n rsync" --chown=1000:0
|
||||
|
||||
if test $any_remote -eq 0
|
||||
# PC -> PC goes through rsync with the same flags as rcp (no NAS-only
|
||||
# --no-perms/--chown permission workarounds needed locally).
|
||||
set -l local_opts -avh --progress
|
||||
echo rsync $local_opts -- $srcs $dst
|
||||
command rsync $local_opts -- $srcs $dst
|
||||
return $status
|
||||
end
|
||||
|
||||
if test $n_src_remote -eq (count $srcs); and test $dst_remote -eq 1
|
||||
# NAS -> NAS: run rsync directly on the NAS itself. Only one remote
|
||||
# host is possible here (checked above), so $hosts[1] is that host.
|
||||
set -l rsrcs
|
||||
for nl in $src_naslocals
|
||||
set -a rsrcs (__rscp_shquote $nl)
|
||||
end
|
||||
set -l rdst (__rscp_shquote $dst_naslocal)
|
||||
set -l ssh_tty
|
||||
if isatty stdin
|
||||
set ssh_tty -t
|
||||
end
|
||||
echo ssh $ssh_tty $hosts[1] sudo -n rsync $base_opts --chown=1000:0 -- $rsrcs $rdst
|
||||
command ssh $ssh_tty $hosts[1] sudo -n rsync $base_opts --chown=1000:0 -- $rsrcs $rdst
|
||||
return $status
|
||||
end
|
||||
|
||||
if test $n_src_remote -gt 0; and test $n_src_remote -lt (count $srcs)
|
||||
# Mixed local and remote sources cannot go into a single rsync call,
|
||||
# so copy source by source. The overwrite question above was already
|
||||
# asked once, hence -y here (each call still re-checks everything else).
|
||||
for k in (seq (count $srcs))
|
||||
rscp -y -- $srcs_raw[$k] $dst_raw
|
||||
set -l st $status
|
||||
if test $st -ne 0
|
||||
return $st
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
# Single-sided copy: local -> NAS, NAS -> local, or one source of any kind.
|
||||
set -l call_opts $base_opts
|
||||
if test $dst_remote -eq 1
|
||||
set -a call_opts $to_remote_opts
|
||||
else if test $n_src_remote -gt 0
|
||||
set -a call_opts --rsync-path="sudo -n rsync"
|
||||
end
|
||||
|
||||
echo rsync $call_opts -- $srcs $dst
|
||||
command rsync $call_opts -- $srcs $dst
|
||||
return $status
|
||||
end
|
||||
|
||||
function __rscp_shquote --description "Single-quote strings for a POSIX remote shell"
|
||||
# Usage: __rscp_shquote STRING... ; prints each string single-quoted.
|
||||
for s in $argv
|
||||
set -l e (string replace -a -- "'" "'\"'\"'" $s)
|
||||
echo "'$e'"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
function sshkey --description "generate a SSH key"
|
||||
if test (count $argv) -ne 1
|
||||
echo "Usage: sshkey <file>"
|
||||
echo "example: sshkey ~/.ssh/your_key_name"
|
||||
return 1
|
||||
end
|
||||
|
||||
set file $argv[1]
|
||||
|
||||
if test -e "$file"
|
||||
echo "Error: $file already exists."
|
||||
return 1
|
||||
end
|
||||
|
||||
ssh-keygen -t ed25519 -f "$file" -C "$(hostname)" -N ""
|
||||
end
|
||||
@@ -0,0 +1,319 @@
|
||||
function vrot -d 'Rotate a video with ffmpeg: metadata-only by default, re-encode with -r'
|
||||
argparse -n vrot 'h/help' 'r/reencode' 'a/angle=' 'p/preset=' -- $argv
|
||||
or return 2
|
||||
|
||||
if set -q _flag_help
|
||||
__vrot_usage
|
||||
return 0
|
||||
end
|
||||
|
||||
if test (count $argv) -lt 1
|
||||
__vrot_usage
|
||||
return 2
|
||||
end
|
||||
|
||||
set -q _flag_angle; or set _flag_angle 90
|
||||
set -q _flag_preset; or set _flag_preset medium
|
||||
|
||||
switch $_flag_angle
|
||||
case 90 180 270
|
||||
case '*'
|
||||
__vrot_error "angle must be 90, 180 or 270 (got '$_flag_angle')"
|
||||
return 2
|
||||
end
|
||||
|
||||
__vrot_colors
|
||||
|
||||
set -l want_reencode 0
|
||||
set -q _flag_reencode; and set want_reencode 1
|
||||
|
||||
set -l rc 0
|
||||
for file in $argv
|
||||
if not test -f "$file"
|
||||
__vrot_error "no such file: '$file'"
|
||||
set rc 1
|
||||
continue
|
||||
end
|
||||
__vrot_one "$file" "$_flag_angle" "$_flag_preset" "$want_reencode"
|
||||
or set rc 1
|
||||
end
|
||||
return $rc
|
||||
end
|
||||
|
||||
function __vrot_one
|
||||
set -l file $argv[1]
|
||||
set -l angle $argv[2]
|
||||
set -l preset $argv[3]
|
||||
set -l want_reencode $argv[4]
|
||||
|
||||
set -l name (path basename "$file")
|
||||
set -l ext (path extension "$file")
|
||||
set -l out (path change-extension '' "$file")_rot$ext
|
||||
set -l outname (path basename "$out")
|
||||
|
||||
__vrot_banner "$name → $outname"
|
||||
|
||||
set -l lines (ffprobe -v error -select_streams v:0 \
|
||||
-show_entries stream=codec_name,width,height,r_frame_rate,nb_frames:format=duration,bit_rate \
|
||||
-of default=noprint_wrappers=1 "$file")
|
||||
|
||||
set -l codec (string match 'codec_name=*' -- $lines | string replace 'codec_name=' '')[1]
|
||||
set -l width (string match 'width=*' -- $lines | string replace 'width=' '')[1]
|
||||
set -l height (string match 'height=*' -- $lines | string replace 'height=' '')[1]
|
||||
set -l fpsraw (string match 'r_frame_rate=*' -- $lines | string replace 'r_frame_rate=' '')[1]
|
||||
set -l frames (string match 'nb_frames=*' -- $lines | string replace 'nb_frames=' '')[1]
|
||||
set -l duration (string match 'duration=*' -- $lines | string replace 'duration=' '')[1]
|
||||
set -l bitrate (string match 'bit_rate=*' -- $lines | string replace 'bit_rate=' '')[1]
|
||||
|
||||
set -l info "$width"x"$height"
|
||||
if test -n "$codec"
|
||||
set info "$info "(string upper "$codec")
|
||||
end
|
||||
if test -n "$fpsraw"; and string match -rq '^[0-9]+/[0-9]+$' "$fpsraw"; and not string match -q '*/0' "$fpsraw"
|
||||
set info "$info "(math -s 2 "$fpsraw")" fps"
|
||||
end
|
||||
if test -n "$duration"; and string match -rq '^[0-9.]+$' "$duration"
|
||||
set info "$info "(__vrot_fmtsecs "$duration")
|
||||
end
|
||||
if test -n "$bitrate"; and string match -rq '^[0-9.]+$' "$bitrate"
|
||||
set info "$info "(math -s 1 "$bitrate/1000000")" Mbit/s"
|
||||
end
|
||||
echo "$vrot_c_dim $info$vrot_c_reset"
|
||||
|
||||
if test "$file" = "$out"
|
||||
__vrot_error "output would overwrite input: '$out'"
|
||||
return 1
|
||||
end
|
||||
|
||||
if test -e "$out"
|
||||
read -l -P "vrot: '$out' exists. Overwrite? [y/N] " ans
|
||||
if not string match -qi 'y' "$ans"
|
||||
echo "$vrot_c_dim skipped: $out$vrot_c_reset"
|
||||
return 1
|
||||
end
|
||||
rm -f "$out"
|
||||
end
|
||||
|
||||
if test "$want_reencode" -eq 1
|
||||
__vrot_reencode "$file" "$out" "$angle" "$preset" "$height" "$codec" "$duration" "$frames"
|
||||
return $status
|
||||
end
|
||||
|
||||
echo "$vrot_c_dim mode: metadata-only rotation (lossless, instant)$vrot_c_reset"
|
||||
ffmpeg -hide_banner -loglevel error -nostdin -i "$file" -map 0 -c copy -ignore_unknown \
|
||||
-movflags +faststart -metadata:s:v:0 rotate=$angle "$out"
|
||||
if test $status -eq 0
|
||||
__vrot_summary "$out"
|
||||
return 0
|
||||
end
|
||||
|
||||
echo "$vrot_c_warn ↷ dropping unsupported data/attachment tracks, retrying…$vrot_c_reset"
|
||||
rm -f "$out"
|
||||
ffmpeg -hide_banner -loglevel error -nostdin -i "$file" -map 0 -map '-0:d' -map '-0:t' \
|
||||
-c copy -movflags +faststart -metadata:s:v:0 rotate=$angle "$out"
|
||||
if test $status -eq 0
|
||||
__vrot_summary "$out"
|
||||
return 0
|
||||
end
|
||||
|
||||
echo "$vrot_c_warn ↷ metadata rotation unsupported here, re-encoding instead…$vrot_c_reset"
|
||||
rm -f "$out"
|
||||
__vrot_reencode "$file" "$out" "$angle" "$preset" "$height" "$codec" "$duration" "$frames"
|
||||
end
|
||||
|
||||
function __vrot_reencode
|
||||
set -l file $argv[1]
|
||||
set -l out $argv[2]
|
||||
set -l angle $argv[3]
|
||||
set -l preset $argv[4]
|
||||
set -l height $argv[5]
|
||||
set -l codec $argv[6]
|
||||
set -l duration $argv[7]
|
||||
set -l frames $argv[8]
|
||||
|
||||
test -n "$height"; or set height 1080
|
||||
|
||||
set -l enc libx264
|
||||
switch "$codec"
|
||||
case 'hevc*' 'h265*' 'h266*'
|
||||
set enc libx265
|
||||
end
|
||||
|
||||
set -l crf 20
|
||||
set -l maxrate 20M
|
||||
set -l bufsize 40M
|
||||
if test $height -ge 2160
|
||||
set crf 22; set maxrate 40M; set bufsize 80M
|
||||
else if test $height -ge 1440
|
||||
set crf 21; set maxrate 30M; set bufsize 60M
|
||||
else if test $height -ge 1080
|
||||
set crf 20; set maxrate 20M; set bufsize 40M
|
||||
else if test $height -ge 720
|
||||
set crf 19; set maxrate 10M; set bufsize 20M
|
||||
else
|
||||
set crf 18; set maxrate 6M; set bufsize 12M
|
||||
end
|
||||
|
||||
set -l vf 'transpose=1'
|
||||
switch $angle
|
||||
case 180
|
||||
set vf 'transpose=1,transpose=1'
|
||||
case 270
|
||||
set vf 'transpose=2'
|
||||
end
|
||||
|
||||
set -l faststart
|
||||
switch (string lower (path extension "$out"))
|
||||
case '.mp4' '.mov' '.m4v'
|
||||
set faststart '-movflags' '+faststart'
|
||||
end
|
||||
|
||||
echo "$vrot_c_dim mode: re-encode ($enc · crf $crf · cap $maxrate)$vrot_c_reset"
|
||||
|
||||
set -l total_frames ''
|
||||
string match -rq '^\d+$' "$frames"; and test "$frames" -gt 0; and set total_frames $frames
|
||||
|
||||
set -l out_t ''
|
||||
set -l frame 0
|
||||
set -l fps_txt ''
|
||||
set -l bitrate_txt ''
|
||||
set -l speed_txt ''
|
||||
|
||||
ffmpeg -hide_banner -loglevel error -nostdin -progress pipe:1 -i "$file" \
|
||||
-map 0:v -map '0:a?' -map '0:s?' -ignore_unknown -vf "$vf" -c:v $enc -crf $crf \
|
||||
-maxrate $maxrate -bufsize $bufsize -preset $preset -c:a copy -c:s copy \
|
||||
$faststart "$out" | while read -l line
|
||||
switch "$line"
|
||||
case 'frame=*'
|
||||
set frame (string replace 'frame=' '' -- "$line")
|
||||
case 'fps=*'
|
||||
set fps_txt (string replace 'fps=' '' -- "$line")"fps"
|
||||
case 'bitrate=*'
|
||||
set bitrate_txt (string replace 'bitrate=' '' -- "$line")
|
||||
if string match -q '*kbits/s' "$bitrate_txt"
|
||||
set bitrate_txt (math -s 1 (string replace 'kbits/s' '' -- "$bitrate_txt") / 1000)"Mbit/s"
|
||||
else if string match -q '*Mbits/s' "$bitrate_txt"
|
||||
set bitrate_txt (string replace 'Mbits/s' 'Mbit/s' -- "$bitrate_txt")
|
||||
end
|
||||
case 'out_time=*'
|
||||
set -l t (string replace 'out_time=' '' -- "$line")
|
||||
set -l parts (string split ':' -- "$t")
|
||||
if test (count $parts) -eq 3; and string match -rq '^\d+$' "$parts[1]"; and string match -rq '^\d+$' "$parts[2]"; and string match -rq '^[\d.]+$' "$parts[3]"
|
||||
set out_t (math "$parts[1]*3600+$parts[2]*60+$parts[3]")
|
||||
end
|
||||
case 'speed=*'
|
||||
set speed_txt (string replace 'speed=' '' -- "$line")
|
||||
end
|
||||
if isatty stdout
|
||||
printf '\r\033[K'
|
||||
set -l pct '--.-%'
|
||||
set -l eta_txt ''
|
||||
set -l bar (string repeat -n 24 '░')
|
||||
set -l frac ''
|
||||
if test -n "$total_frames"; and string match -rq '^\d+$' "$frame"; and test "$total_frames" -gt 0
|
||||
set frac (math "min(1, $frame/$total_frames)")
|
||||
else if test -n "$out_t"; and string match -rq '^[0-9.]+$' "$duration"; and not string match -rq '^0+(\.0*)?$' "$duration"
|
||||
set frac (math "min(1, $out_t/$duration)")
|
||||
end
|
||||
if test -n "$frac"
|
||||
set -l filled (math "floor($frac*24)")
|
||||
set -l bar (string repeat -n $filled '█')
|
||||
set bar "$bar"(string repeat -n (math "24-$filled") '░')
|
||||
set pct (math -s 1 "$frac*100")%
|
||||
set -l sp (string replace -r '[xX]$' '' -- "$speed_txt")
|
||||
if test -n "$sp"; and string match -rq '^[0-9.]+$' "$sp"; and not string match -rq '^0+(\.0*)?$' "$sp"; and test -n "$out_t"; and string match -rq '^[0-9.]+$'
|
||||
"$duration"
|
||||
set eta_txt " ETA "(__vrot_fmtsecs (math "($duration - $out_t)/$sp"))
|
||||
end
|
||||
end
|
||||
set -l frame_txt $frame
|
||||
if test -n "$total_frames"
|
||||
set frame_txt "$frame/$total_frames"
|
||||
end
|
||||
echo -n " $vrot_c_ok$bar$vrot_c_reset $pct frame=$frame_txt $fps_txt $bitrate_txt $speed_txt$eta_txt"
|
||||
end
|
||||
end
|
||||
set -l ff_status $pipestatus[1]
|
||||
printf '\n'
|
||||
|
||||
if test $ff_status -ne 0
|
||||
__vrot_error "encoding failed (ffmpeg exited $ff_status)"
|
||||
return 1
|
||||
end
|
||||
__vrot_summary "$out"
|
||||
end
|
||||
|
||||
function __vrot_summary
|
||||
set -l out $argv[1]
|
||||
set -l size ''
|
||||
if command -q numfmt
|
||||
set size (numfmt --to=iec --suffix=B -- (stat -c %s -- "$out") 2>/dev/null)
|
||||
else
|
||||
set size (du -h -- "$out" | string replace -r '\t.*' '')
|
||||
end
|
||||
set -l dims (ffprobe -v error -select_streams v:0 \
|
||||
-show_entries stream=width,height -of default=noprint_wrappers=1:nokey=1 "$out" \
|
||||
| string match -r '^\d+$' | string join '×')
|
||||
set -l extra ''
|
||||
if test -n "$dims"
|
||||
set extra " · $dims"
|
||||
end
|
||||
echo "$vrot_c_ok ✔ $out$vrot_c_dim ($size$extra)$vrot_c_reset"
|
||||
end
|
||||
|
||||
function __vrot_banner
|
||||
set -l title $argv[1]
|
||||
echo "$vrot_c_dim"(string repeat -n 58 '─')"$vrot_c_reset"
|
||||
echo "$vrot_c_hi $title$vrot_c_reset"
|
||||
end
|
||||
|
||||
function __vrot_colors
|
||||
set -q vrot_colors_set; and return 0
|
||||
set -g vrot_colors_set 1
|
||||
if isatty stdout
|
||||
set -g vrot_c_hi (set_color brwhite --bold)
|
||||
set -g vrot_c_dim (set_color brblack)
|
||||
set -g vrot_c_ok (set_color brgreen)
|
||||
set -g vrot_c_warn (set_color bryellow)
|
||||
set -g vrot_c_err (set_color brred)
|
||||
set -g vrot_c_reset (set_color normal)
|
||||
else
|
||||
for c in hi dim ok warn err reset
|
||||
set -g vrot_c_$c ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function __vrot_fmtsecs
|
||||
set -l s (math "max(0, round($argv[1]))")
|
||||
set -l h (math "floor($s/3600)")
|
||||
set -l m (math "floor($s%3600/60)")
|
||||
set -l sec (math "$s%60")
|
||||
if test $h -gt 0
|
||||
printf '%02d:%02d:%02d' $h $m $sec
|
||||
else
|
||||
printf '%02d:%02d' $m $sec
|
||||
end
|
||||
end
|
||||
|
||||
function __vrot_error
|
||||
echo "$vrot_c_err""vrot: "$argv"$vrot_c_reset" >&2
|
||||
end
|
||||
|
||||
function __vrot_usage
|
||||
echo 'usage: vrot [options] <video> [<video> ...]'
|
||||
echo
|
||||
echo 'Rotates one or more videos and writes <name>_rot.<ext> next to each.'
|
||||
echo
|
||||
echo 'Default mode is metadata-only rotation: lossless and instant. Works for'
|
||||
echo 'MP4/MOV/M4V (including GoPro files; unsupported data/timecode tracks are'
|
||||
echo 'dropped automatically). If the container cannot carry the flag, vrot'
|
||||
echo 'falls back to re-encoding, with a live progress bar. Players that'
|
||||
echo 'ignore rotation flags need -r.'
|
||||
echo
|
||||
echo 'options:'
|
||||
echo ' -a, --angle <90|180|270> clockwise angle (default 90)'
|
||||
echo ' -r, --reencode rotate pixels by re-encoding'
|
||||
echo ' -p, --preset <name> x264/x265 preset (default medium)'
|
||||
echo ' -h, --help show this help'
|
||||
end
|
||||
+44
-17
@@ -20,31 +20,58 @@ mount_cifs() {
|
||||
echo "Successfully mounted: $mount_point"
|
||||
}
|
||||
|
||||
function is_mounted() {
|
||||
mountpoint -q "$1"
|
||||
}
|
||||
|
||||
# Mount FRITZ.NAS (from fstab line 1)
|
||||
if ping -c 1 -W 1 "$HOST" >/dev/null 2>&1; then
|
||||
if ! is_mounted "/home/honney/mount/fritzNAS"; then
|
||||
if ping -c 1 -W 1 "192.168.1.1" >/dev/null 2>&1; then
|
||||
mount_cifs "//192.168.1.1/FRITZ.NAS" \
|
||||
"/home/honney/mount/fritzNAS" \
|
||||
"credentials=/home/honney/.cred/samba_credentials,uid=1000,gid=1000,vers=3.0,cache=none,nounix,noserverino,file_mode=0755,dir_mode=0755"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ping -c 1 -W 1 "100.64.0.3" >/dev/null 2>&1; then
|
||||
# Mount Data (from fstab line 2)
|
||||
mount_cifs "//100.64.0.3/Data" \
|
||||
"/home/honney/mount/Data" \
|
||||
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
|
||||
|
||||
# Mount Media (from fstab line 3)
|
||||
mount_cifs "//100.64.0.3/Media" \
|
||||
"/home/honney/mount/Media" \
|
||||
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
|
||||
echo ""
|
||||
mount_points=("/home/honney/mount/Data" "/home/honney/mount/Media" "/home/honney/mount/Ripping" "/home/honney/mount/Apps")
|
||||
|
||||
# Mount Ripping (from fstab line 4)
|
||||
mount_cifs "//100.64.0.3/Ripping" \
|
||||
"/home/honney/mount/Ripping" \
|
||||
if ping -c 1 -W 1 "192.168.188.122" >/dev/null 2>&1; then
|
||||
echo "192.168.188.122, mounting shares..."
|
||||
echo ""
|
||||
mounts=("//192.168.188.122/Data" "//192.168.188.122/Media" "//192.168.188.122/Ripping" "//192.168.188.122/Apps")
|
||||
for i in "${!mounts[@]}"; do
|
||||
mount="${mounts[$i]}"
|
||||
mount_point="${mount_points[$i]}"
|
||||
echo "Checking $mount_point"
|
||||
if ! is_mounted "$mount_point"; then
|
||||
echo "$mount_point unmounted"
|
||||
mount_cifs "$mount" \
|
||||
"$mount_point" \
|
||||
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
|
||||
else
|
||||
echo "$mount_point already mounted"
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
|
||||
# Mount Apps (from fstab line 5)
|
||||
mount_cifs "//100.64.0.3/Apps" \
|
||||
"/home/honney/mount/Apps" \
|
||||
elif ping -c 1 -W 1 "100.64.0.3" >/dev/null 2>&1; then
|
||||
echo "192.168.188.122 unreachable"
|
||||
echo "100.64.0.3 reachable, mounting shares..."
|
||||
echo ""
|
||||
mounts=("//100.64.0.3/Data" "//100.64.0.3/Media" "//100.64.0.3/Ripping" "//100.64.0.3/Apps")
|
||||
for i in "${!mounts[@]}"; do
|
||||
mount="${mounts[$i]}"
|
||||
mount_point="${mount_points[$i]}"
|
||||
echo "Checking $mount_point"
|
||||
if ! is_mounted "$mount_point"; then
|
||||
echo "$mount_point unmounted"
|
||||
mount_cifs "$mount" \
|
||||
"$mount_point" \
|
||||
"credentials=/home/honney/.cred/trueNAS_credentials,vers=3.1.1,iocharset=utf8,rw,uid=1000,gid=1000,nounix,noperm,file_mode=0660,dir_mode=0770,hard,intr,cache=loose"
|
||||
else
|
||||
echo "$mount_point already mounted"
|
||||
fi
|
||||
echo ""
|
||||
done
|
||||
fi
|
||||
|
||||
+49
-25
@@ -1,35 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Source the functions file
|
||||
source "$HOME/.config/function_helper.sh"
|
||||
function is_mounted() {
|
||||
mountpoint -q "$1"
|
||||
}
|
||||
|
||||
# Define mount points
|
||||
MOUNT_POINT_RAID="$HOME/Raid/"
|
||||
MOUNT_POINT_SSD="$HOME/Server-SSD/"
|
||||
|
||||
PASSWORD_FILE="$HOME/.cred/credentials.txt"
|
||||
PASSWORD=$(<"$PASSWORD_FILE")
|
||||
|
||||
# Unmount RAID
|
||||
if is_mounted "$MOUNT_POINT_RAID"; then
|
||||
if echo "$PASSWORD" | sudo -S umount "$MOUNT_POINT_RAID"; then
|
||||
send_notification "low" "Unmount Successful" "Unmounted $MOUNT_POINT_RAID successfully." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-encrypted-symbolic.svg"
|
||||
function unmount() {
|
||||
if is_mounted "$1"; then
|
||||
if ! sudo umount -l "$1"; then
|
||||
echo "Unmount failed: $1"
|
||||
return 1
|
||||
else
|
||||
send_notification "high" "Unmount Failed" "Failed to unmount $MOUNT_POINT_RAID." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-symbolic.svg"
|
||||
exit 1
|
||||
echo "Unmount completed: $1"
|
||||
fi
|
||||
else
|
||||
send_notification "low" "Not Mounted" "$MOUNT_POINT_RAID is not mounted." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk.svg"
|
||||
echo "$1 is not mounted"
|
||||
fi
|
||||
}
|
||||
|
||||
function force_unmount() {
|
||||
if is_mounted "$1"; then
|
||||
if ! sudo umount -fl "$1"; then
|
||||
echo "Unmount failed: $1"
|
||||
return 1
|
||||
else
|
||||
echo "Unmount completed: $1"
|
||||
fi
|
||||
else
|
||||
echo "$1 is not mounted"
|
||||
fi
|
||||
}
|
||||
|
||||
function has_connection() {
|
||||
if ping -c 1 -W 1 "$1" &>/dev/null; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
mounts=("/home/honney/mount/Data" "/home/honney/mount/Media" "/home/honney/mount/Ripping" "/home/honney/mount/Apps")
|
||||
|
||||
if has_connection "100.64.0.3" || has_connection "192.168.188.122"; then
|
||||
for mount in "${mounts[@]}"; do
|
||||
unmount "$mount"
|
||||
done
|
||||
else
|
||||
for mount in "${mounts[@]}"; do
|
||||
force_unmount "$mount"
|
||||
done
|
||||
fi
|
||||
|
||||
# Unmount SSD
|
||||
if is_mounted "$MOUNT_POINT_SSD"; then
|
||||
if echo "$PASSWORD" | sudo -S umount "$MOUNT_POINT_SSD"; then
|
||||
send_notification "low" "Unmount Successful" "Unmounted $MOUNT_POINT_SSD successfully." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-encrypted-symbolic.svg"
|
||||
if has_connection "192.168.1.1"; then
|
||||
unmount "/home/honney/mount/fritzNAS"
|
||||
else
|
||||
send_notification "high" "Unmount Failed" "Failed to unmount $MOUNT_POINT_SSD." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk-symbolic.svg"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
send_notification "low" "Not Mounted" "$MOUNT_POINT_SSD is not mounted." "$HOME/.icons/BeautyLine-Garuda/devices/scalable/drive-harddisk.svg"
|
||||
force_unmount "/home/honney/mount/fritzNAS"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user