dotcli: Initial config
dotcli is my utility script for everything dotfiles. A bootstrap command is included in the README. A test suite and the necessary scaffolding for extending dotcli is also included.
This commit is contained in:
@@ -1,4 +1,89 @@
|
||||
function dot --wraps=git --description 'Manage dotfiles via a bare repo checked out over $HOME'
|
||||
git --git-dir=$HOME/.dotfiles --work-tree=$HOME $argv
|
||||
set -l dotfiles_dir $HOME/.dotfiles
|
||||
|
||||
if test "$argv[1]" = init
|
||||
set -e argv[1]
|
||||
__dot_init $dotfiles_dir $argv
|
||||
return $status
|
||||
end
|
||||
|
||||
set -l commands_dir $HOME/.config/dot/commands
|
||||
set -l command_file $commands_dir/$argv[1].fish
|
||||
|
||||
if test -n "$argv[1]" -a -f "$command_file"
|
||||
source $command_file
|
||||
_dot_$argv[1] $argv[2..-1]
|
||||
return $status
|
||||
end
|
||||
|
||||
git --git-dir=$dotfiles_dir --work-tree=$HOME $argv
|
||||
end
|
||||
|
||||
# Kept inline (not a separate autoloaded function file) because this is the
|
||||
# only subcommand that must work before the dotfiles repo has been cloned.
|
||||
function __dot_init
|
||||
set -l dotfiles_dir $argv[1]
|
||||
set -e argv[1]
|
||||
|
||||
argparse 'url=' -- $argv
|
||||
or return 1
|
||||
|
||||
set -l url $_flag_url
|
||||
test -n "$url"; or set url ssh://gitea@git.alexion.dev:2022/alexion/dotfiles.git
|
||||
|
||||
if test -e $dotfiles_dir
|
||||
echo "dot init: $dotfiles_dir already exists, refusing to re-initialize" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
git clone --bare $url $dotfiles_dir
|
||||
or begin
|
||||
echo "dot init: failed to clone $url" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
git --git-dir=$dotfiles_dir config status.showUntrackedFiles no
|
||||
|
||||
set -l checkout_output (git --git-dir=$dotfiles_dir --work-tree=$HOME checkout 2>&1)
|
||||
set -l checkout_status $status
|
||||
|
||||
if test $checkout_status -ne 0
|
||||
set -l conflicts
|
||||
set -l in_block 0
|
||||
|
||||
for line in $checkout_output
|
||||
if test $in_block -eq 1
|
||||
if string match -rq '^\s' -- $line
|
||||
set -a conflicts (string trim -- $line)
|
||||
continue
|
||||
else
|
||||
set in_block 0
|
||||
end
|
||||
end
|
||||
|
||||
string match -q '*would be overwritten by checkout:*' -- $line
|
||||
and set in_block 1
|
||||
end
|
||||
|
||||
if test (count $conflicts) -eq 0
|
||||
echo "dot init: checkout failed and no recoverable conflicts were found:" >&2
|
||||
printf '%s\n' $checkout_output >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l backup_dir $HOME/.dotfiles-backup/(date +%Y%m%dT%H%M%S)
|
||||
for f in $conflicts
|
||||
mkdir -p (path dirname $backup_dir/$f)
|
||||
mv $HOME/$f $backup_dir/$f
|
||||
echo "dot init: backed up ~/$f to $backup_dir/$f"
|
||||
end
|
||||
|
||||
git --git-dir=$dotfiles_dir --work-tree=$HOME checkout
|
||||
or begin
|
||||
echo "dot init: checkout still failing after backing up conflicts, aborting" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
echo "dot init: bootstrapped $dotfiles_dir from $url"
|
||||
end
|
||||
complete -c dot -w git
|
||||
|
||||
116
.config/fish/functions/fishtape.fish
Normal file
116
.config/fish/functions/fishtape.fish
Normal file
@@ -0,0 +1,116 @@
|
||||
function fishtape --description "Test scripts, functions, and plugins in Fish"
|
||||
switch "$argv"
|
||||
case -v --version
|
||||
echo "fishtape, version 3.0.1"
|
||||
case "" -h --help
|
||||
echo "Usage: fishtape <files ...> Run test files"
|
||||
echo "Options:"
|
||||
echo " -v or --version Print version"
|
||||
echo " -h or --help Print this help message"
|
||||
case \*
|
||||
set --local files (realpath $argv)
|
||||
|
||||
for file in $files
|
||||
if test ! -f $file
|
||||
echo "fishtape: Invalid file or file not found: \"$file\"" >&2
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
set --local operators -{n,z,b,c,d,e,f,g,G,k,L,O,p,r,s,S,t,u,w,x}
|
||||
set --local expectations \
|
||||
"a non-zero length string" \
|
||||
"a zero length string" \
|
||||
"a block device" \
|
||||
"a character device" \
|
||||
"a directory" \
|
||||
"an existing file" \
|
||||
"a regular file" \
|
||||
"a file with the set-group-ID bit set" \
|
||||
"a file with same group ID as the current user" \
|
||||
"a file with the sticky bit set" \
|
||||
"a symbolic link" \
|
||||
"a file owned by the current user" \
|
||||
"a named pipe" \
|
||||
"a file marked as readable" \
|
||||
"a file of size greater than zero" \
|
||||
"a socket" \
|
||||
"a terminal tty file descriptor" \
|
||||
"a file with the set-user-ID bit set" \
|
||||
"a file marked as writable" \
|
||||
"a file marked as executable"
|
||||
|
||||
set --universal _fishtape_test_number 0
|
||||
set --universal _fishtape_test_passed 0
|
||||
set --universal _fishtape_test_failed 0
|
||||
|
||||
function @echo
|
||||
echo "# $argv"
|
||||
end
|
||||
|
||||
function @test --argument-names name --inherit-variable operators --inherit-variable expectations
|
||||
set --erase argv[1]
|
||||
set --query argv[2] || set --append argv ""
|
||||
|
||||
set _fishtape_test_number (math $_fishtape_test_number + 1)
|
||||
|
||||
if test $argv
|
||||
set _fishtape_test_passed (math $_fishtape_test_passed + 1)
|
||||
|
||||
echo "ok $_fishtape_test_number $name"
|
||||
else
|
||||
if test $argv[1] = "!"
|
||||
set operator "! "
|
||||
set expected "not "
|
||||
set --erase argv[1]
|
||||
end
|
||||
|
||||
if set --query argv[3]
|
||||
set operator "$operator"$argv[2]
|
||||
set expected (string escape -- $argv[3])
|
||||
set actual (string escape -- $argv[1])
|
||||
else
|
||||
set operator "$operator"$argv[1]
|
||||
set expected "$expected"$expectations[(contains --index -- $argv[1] $operators)]
|
||||
set actual (string escape -- $argv[2])
|
||||
end
|
||||
|
||||
set _fishtape_test_failed (math $_fishtape_test_failed + 1)
|
||||
|
||||
status print-stack-trace |
|
||||
string replace --filter --regex -- "\s+called on line (\d+) of file (.+)" '$2:$1' |
|
||||
read --local at
|
||||
|
||||
echo "not ok $_fishtape_test_number $name"
|
||||
echo " ---"
|
||||
echo " operator: $operator"
|
||||
echo " expected: $expected"
|
||||
echo " actual: $actual"
|
||||
echo " at: $at"
|
||||
echo " ..."
|
||||
end
|
||||
end
|
||||
|
||||
echo TAP version 13
|
||||
|
||||
for file in $files
|
||||
fish --init-command=(functions @echo | string collect) --init-command=(functions @test | string collect) $file
|
||||
end
|
||||
|
||||
echo
|
||||
echo "1..$_fishtape_test_number"
|
||||
echo "# pass $_fishtape_test_passed"
|
||||
test $_fishtape_test_failed -eq 0 &&
|
||||
echo "# ok" ||
|
||||
echo "# fail $_fishtape_test_failed"
|
||||
|
||||
functions --erase @echo @test
|
||||
|
||||
set --local failed $_fishtape_test_failed
|
||||
set --erase _fishtape_test_number
|
||||
set --erase _fishtape_test_passed
|
||||
set --erase _fishtape_test_failed
|
||||
|
||||
test $failed -eq 0
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user