mirror of
https://github.com/TheLocehiliosan/yadm
synced 2025-06-13 13:03:58 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
130965e34d
10
CHANGES
10
CHANGES
@ -1,3 +1,13 @@
|
|||||||
|
1.12.0
|
||||||
|
* Add basic Zsh completion (#71, #79)
|
||||||
|
* Support directories in `.yadm/encrypt` (#81, #82)
|
||||||
|
* Support exclusions in `.yadm/encrypt` (#86)
|
||||||
|
* Improve portability with printf (#87)
|
||||||
|
* Eliminate usage of `eval` and `ls`
|
||||||
|
|
||||||
|
1.11.1
|
||||||
|
* Create private dirs prior to merge (#74)
|
||||||
|
|
||||||
1.11.0
|
1.11.0
|
||||||
* Option for Cygwin to copy files instead of symlink (#62)
|
* Option for Cygwin to copy files instead of symlink (#62)
|
||||||
* Support `YADM_DISTRO` in Jinja templates (#68)
|
* Support `YADM_DISTRO` in Jinja templates (#68)
|
||||||
|
@ -3,13 +3,15 @@ CONTRIBUTORS
|
|||||||
Tim Byrne
|
Tim Byrne
|
||||||
Espen Henriksen
|
Espen Henriksen
|
||||||
Cameron Eagans
|
Cameron Eagans
|
||||||
|
Klas Mellbourn
|
||||||
Jan Schulz
|
Jan Schulz
|
||||||
Patrick Hof
|
|
||||||
Satoshi Ohki
|
|
||||||
Siôn Le Roux
|
Siôn Le Roux
|
||||||
Sébastien Gross
|
Sébastien Gross
|
||||||
|
Thomas Luzat
|
||||||
Tomas Cernaj
|
Tomas Cernaj
|
||||||
Uroš Golja
|
Uroš Golja
|
||||||
|
japm48
|
||||||
Franciszek Madej
|
Franciszek Madej
|
||||||
Klas Mellbourn
|
|
||||||
Paraplegic Racehorse
|
Paraplegic Racehorse
|
||||||
|
Patrick Hof
|
||||||
|
Satoshi Ohki
|
||||||
|
14
Makefile
14
Makefile
@ -1,12 +1,15 @@
|
|||||||
|
.PHONY: all
|
||||||
all: yadm.md contrib
|
all: yadm.md contrib
|
||||||
|
|
||||||
yadm.md: yadm.1
|
yadm.md: yadm.1
|
||||||
@groff -man -Tascii ./yadm.1 | col -bx | sed 's/^[A-Z]/## &/g' | sed '/yadm(1)/d' > yadm.md
|
@groff -man -Tascii ./yadm.1 | col -bx | sed 's/^[A-Z]/## &/g' | sed '/yadm(1)/d' > yadm.md
|
||||||
|
|
||||||
|
.PHONY: contrib
|
||||||
contrib:
|
contrib:
|
||||||
@echo "CONTRIBUTORS\n" > CONTRIBUTORS
|
@echo "CONTRIBUTORS\n" > CONTRIBUTORS
|
||||||
@git shortlog -ns master gh-pages dev dev-pages | cut -f2 >> CONTRIBUTORS
|
@git shortlog -ns master gh-pages dev dev-pages | cut -f2 >> CONTRIBUTORS
|
||||||
|
|
||||||
|
.PHONY: pdf
|
||||||
pdf:
|
pdf:
|
||||||
@groff -man -Tps ./yadm.1 > yadm.ps
|
@groff -man -Tps ./yadm.1 > yadm.ps
|
||||||
@open yadm.ps
|
@open yadm.ps
|
||||||
@ -39,8 +42,19 @@ shellcheck:
|
|||||||
[ "$$test_result" -ne 0 ] && exit 1; \
|
[ "$$test_result" -ne 0 ] && exit 1; \
|
||||||
done; true
|
done; true
|
||||||
|
|
||||||
|
.PHONY: testhost
|
||||||
|
testhost:
|
||||||
|
@target=HEAD
|
||||||
|
@rm -rf /tmp/testhost
|
||||||
|
@git show $(target):yadm > /tmp/testhost
|
||||||
|
@chmod a+x /tmp/testhost
|
||||||
|
@echo Starting testhost target=\"$$target\"
|
||||||
|
@docker run -w /root --hostname testhost --rm -it -v "/tmp/testhost:/bin/yadm:ro" yadm/testbed:latest bash
|
||||||
|
|
||||||
|
.PHONY: man
|
||||||
man:
|
man:
|
||||||
groff -man -Tascii ./yadm.1 | less
|
groff -man -Tascii ./yadm.1 | less
|
||||||
|
|
||||||
|
.PHONY: wide
|
||||||
wide:
|
wide:
|
||||||
man ./yadm.1
|
man ./yadm.1
|
||||||
|
@ -1,19 +1,36 @@
|
|||||||
# Prerequisites
|
|
||||||
|
|
||||||
**yadm** completion only works if Git completions are also enabled.
|
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
## Homebrew
|
## Bash completions
|
||||||
|
### Prerequisites
|
||||||
|
**yadm** completion only works if Git completions are also enabled.
|
||||||
|
|
||||||
|
### Homebrew
|
||||||
If using `homebrew` to install **yadm**, completions should automatically be handled if you also install `brew install bash-completion`. This might require you to include the main completion script in your own bashrc file like this:
|
If using `homebrew` to install **yadm**, completions should automatically be handled if you also install `brew install bash-completion`. This might require you to include the main completion script in your own bashrc file like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
[ -f /usr/local/etc/bash_completion ] && source /usr/local/etc/bash_completion
|
[ -f /usr/local/etc/bash_completion ] && source /usr/local/etc/bash_completion
|
||||||
```
|
```
|
||||||
|
|
||||||
## Manual installation
|
### Manual installation
|
||||||
Copy the completion script locally, and add this to you bashrc:
|
Copy the completion script locally, and add this to you bashrc:
|
||||||
```
|
```
|
||||||
[ -f /full/path/to/yadm.bash_completion ] && source /full/path/to/yadm.bash_completion
|
[ -f /full/path/to/yadm.bash_completion ] && source /full/path/to/yadm.bash_completion
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Zsh completions
|
||||||
|
### Homebrew
|
||||||
|
If using `homebrew` to install **yadm**, completions should handled automatically.
|
||||||
|
|
||||||
|
### Manual installation
|
||||||
|
Copy the completion script `yadm.zsh_completion` locally, rename it to `_yadm`, and add the containing folder to `$fpath` in `.zshrc`:
|
||||||
|
```
|
||||||
|
fpath=(/path/to/folder/containing_yadm $fpath)
|
||||||
|
autoload -U compinit
|
||||||
|
compinit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installation using [zplug](https://github.com/b4b4r07/zplug)
|
||||||
|
Load `_yadm` as a plugin in your `.zshrc`:
|
||||||
|
```
|
||||||
|
fpath=("$ZPLUG_HOME/bin" $fpath)
|
||||||
|
zplug "TheLocehiliosan/yadm", rename-to:_yadm, use:"completion/yadm.zsh_completion", as:command, defer:2
|
||||||
|
```
|
||||||
|
46
completion/yadm.zsh_completion
Normal file
46
completion/yadm.zsh_completion
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#compdef yadm
|
||||||
|
_yadm(){
|
||||||
|
local -a _1st_arguments
|
||||||
|
_1st_arguments=(
|
||||||
|
'help:Display yadm command help'
|
||||||
|
'init:Initialize an empty repository'
|
||||||
|
'config:Configure a setting'
|
||||||
|
'list:List tracked files'
|
||||||
|
'alt:Create links for alternates'
|
||||||
|
'bootstrap:Execute $HOME/.yadm/bootstrap'
|
||||||
|
'encrypt:Encrypt files'
|
||||||
|
'decrypt:Decrypt files'
|
||||||
|
'perms:Fix perms for private files'
|
||||||
|
'add:git add'
|
||||||
|
'push:git push'
|
||||||
|
'pull:git pull'
|
||||||
|
'diff:git diff'
|
||||||
|
'checkout:git checkout'
|
||||||
|
'co:git co'
|
||||||
|
'commit:git commit'
|
||||||
|
'ci:git ci'
|
||||||
|
'status:git status'
|
||||||
|
'st:git st'
|
||||||
|
'reset:git reset'
|
||||||
|
'log:git log'
|
||||||
|
)
|
||||||
|
|
||||||
|
local context state line expl
|
||||||
|
local -A opt_args
|
||||||
|
|
||||||
|
_arguments '*:: :->subcmds' && return 0
|
||||||
|
|
||||||
|
if (( CURRENT == 1 )); then
|
||||||
|
_describe -t commands "yadm commands" _1st_arguments -V1
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$words[1]" in
|
||||||
|
*)
|
||||||
|
_arguments ':filenames:_files'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_yadm "$@"
|
@ -1,66 +0,0 @@
|
|||||||
load common
|
|
||||||
load_fixtures
|
|
||||||
|
|
||||||
@test "Default /bin/ls" {
|
|
||||||
echo "
|
|
||||||
By default, the value of LS_PROGRAM should be /bin/ls
|
|
||||||
"
|
|
||||||
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
YADM_TEST=1 source "$T_YADM"
|
|
||||||
status=0
|
|
||||||
output=$( require_ls; echo "$LS_PROGRAM" ) || {
|
|
||||||
status=$?
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "output=$output"
|
|
||||||
|
|
||||||
[ "$status" == 0 ]
|
|
||||||
[ "$output" = "/bin/ls" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Fallback on 'ls'" {
|
|
||||||
echo "
|
|
||||||
When LS_PROGRAM doesn't exist, use 'ls'
|
|
||||||
"
|
|
||||||
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
YADM_TEST=1 source "$T_YADM"
|
|
||||||
status=0
|
|
||||||
LS_PROGRAM="/ls/missing"
|
|
||||||
output=$( require_ls; echo "$LS_PROGRAM" ) || {
|
|
||||||
status=$?
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "output=$output"
|
|
||||||
|
|
||||||
[ "$status" == 0 ]
|
|
||||||
[ "$output" = "ls" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Fail if ls isn't in PATH" {
|
|
||||||
echo "
|
|
||||||
When LS_PROGRAM doesn't exist, use 'ls'
|
|
||||||
"
|
|
||||||
|
|
||||||
# shellcheck source=/dev/null
|
|
||||||
YADM_TEST=1 source "$T_YADM"
|
|
||||||
status=0
|
|
||||||
LS_PROGRAM="/ls/missing"
|
|
||||||
savepath="$PATH"
|
|
||||||
# shellcheck disable=SC2123
|
|
||||||
PATH=
|
|
||||||
output=$( require_ls 2>&1; echo "$LS_PROGRAM" ) || {
|
|
||||||
status=$?
|
|
||||||
true
|
|
||||||
}
|
|
||||||
PATH="$savepath"
|
|
||||||
|
|
||||||
echo "output=$output"
|
|
||||||
|
|
||||||
[ "$status" != 0 ]
|
|
||||||
[[ "$output" =~ functionality\ requires\ .ls.\ to\ be\ installed ]]
|
|
||||||
}
|
|
||||||
|
|
318
test/007_unit_parse_encrypt.bats
Normal file
318
test/007_unit_parse_encrypt.bats
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
load common
|
||||||
|
load_fixtures
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
# SC2153 is intentional
|
||||||
|
# shellcheck disable=SC2153
|
||||||
|
make_parents "$T_YADM_ENCRYPT"
|
||||||
|
make_parents "$T_DIR_WORK"
|
||||||
|
make_parents "$T_DIR_REPO"
|
||||||
|
mkdir "$T_DIR_WORK"
|
||||||
|
git init --shared=0600 --bare "$T_DIR_REPO" >/dev/null 2>&1
|
||||||
|
GIT_DIR="$T_DIR_REPO" git config core.bare 'false'
|
||||||
|
GIT_DIR="$T_DIR_REPO" git config core.worktree "$T_DIR_WORK"
|
||||||
|
GIT_DIR="$T_DIR_REPO" git config yadm.managed 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
destroy_tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_parse() {
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
YADM_TEST=1 source "$T_YADM"
|
||||||
|
YADM_ENCRYPT="$T_YADM_ENCRYPT"
|
||||||
|
export YADM_ENCRYPT
|
||||||
|
GIT_DIR="$T_DIR_REPO"
|
||||||
|
export GIT_DIR
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
|
||||||
|
status=0
|
||||||
|
{ output=$( parse_encrypt) && parse_encrypt; } || {
|
||||||
|
status=$?
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$1" == "twice" ]; then
|
||||||
|
GIT_DIR="$T_DIR_REPO" parse_encrypt
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "OUTPUT:$output\n"
|
||||||
|
echo "ENCRYPT_INCLUDE_FILES:"
|
||||||
|
echo " Size: ${#ENCRYPT_INCLUDE_FILES[@]}"
|
||||||
|
echo " Items: ${ENCRYPT_INCLUDE_FILES[*]}"
|
||||||
|
echo "EXPECT_INCLUDE:"
|
||||||
|
echo " Size: ${#EXPECT_INCLUDE[@]}"
|
||||||
|
echo " Items: ${EXPECT_INCLUDE[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (not called)" {
|
||||||
|
echo "
|
||||||
|
parse_encrypt() is not called
|
||||||
|
Array should be 'unparsed'
|
||||||
|
"
|
||||||
|
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
YADM_TEST=1 source "$T_YADM"
|
||||||
|
|
||||||
|
echo "ENCRYPT_INCLUDE_FILES=$ENCRYPT_INCLUDE_FILES"
|
||||||
|
|
||||||
|
[ "$ENCRYPT_INCLUDE_FILES" == "unparsed" ]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (short-circuit)" {
|
||||||
|
echo "
|
||||||
|
Parsing should not happen more than once
|
||||||
|
"
|
||||||
|
|
||||||
|
run_parse "twice"
|
||||||
|
echo "PARSE_ENCRYPT_SHORT: $PARSE_ENCRYPT_SHORT"
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[[ "$PARSE_ENCRYPT_SHORT" =~ not\ reprocessed ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (file missing)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is empty
|
||||||
|
Array should be empty
|
||||||
|
"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=()
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (empty file)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is empty
|
||||||
|
Array should be empty
|
||||||
|
"
|
||||||
|
|
||||||
|
touch "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=()
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (files)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is references present and missing files
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "file3" > "$T_DIR_WORK/file3"
|
||||||
|
echo "file5" > "$T_DIR_WORK/file5"
|
||||||
|
|
||||||
|
{ echo "file1"
|
||||||
|
echo "file2"
|
||||||
|
echo "file3"
|
||||||
|
echo "file4"
|
||||||
|
echo "file5"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("file1" "file3" "file5")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (files and dirs)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is references present and missing files
|
||||||
|
.yadm/encrypt is references present and missing dirs
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
mkdir -p "$T_DIR_WORK/dir1"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir2"
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "file2" > "$T_DIR_WORK/file2"
|
||||||
|
echo "a" > "$T_DIR_WORK/dir1/a"
|
||||||
|
echo "b" > "$T_DIR_WORK/dir1/b"
|
||||||
|
|
||||||
|
{ echo "file1"
|
||||||
|
echo "file2"
|
||||||
|
echo "file3"
|
||||||
|
echo "dir1"
|
||||||
|
echo "dir2"
|
||||||
|
echo "dir3"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("file1" "file2" "dir1" "dir2")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (comments/empty lines)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is references present and missing files
|
||||||
|
.yadm/encrypt is references present and missing dirs
|
||||||
|
.yadm/encrypt contains comments / blank lines
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
mkdir -p "$T_DIR_WORK/dir1"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir2"
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "file2" > "$T_DIR_WORK/file2"
|
||||||
|
echo "file3" > "$T_DIR_WORK/file3"
|
||||||
|
echo "a" > "$T_DIR_WORK/dir1/a"
|
||||||
|
echo "b" > "$T_DIR_WORK/dir1/b"
|
||||||
|
|
||||||
|
{ echo "file1"
|
||||||
|
echo "file2"
|
||||||
|
echo "#file3"
|
||||||
|
echo " #file3"
|
||||||
|
echo ""
|
||||||
|
echo "dir1"
|
||||||
|
echo "dir2"
|
||||||
|
echo "dir3"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("file1" "file2" "dir1" "dir2")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (w/spaces)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt is references present and missing files
|
||||||
|
.yadm/encrypt is references present and missing dirs
|
||||||
|
.yadm/encrypt references contain spaces
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
mkdir -p "$T_DIR_WORK/di r1"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir2"
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "fi le2" > "$T_DIR_WORK/fi le2"
|
||||||
|
echo "file3" > "$T_DIR_WORK/file3"
|
||||||
|
echo "a" > "$T_DIR_WORK/di r1/a"
|
||||||
|
echo "b" > "$T_DIR_WORK/di r1/b"
|
||||||
|
|
||||||
|
{ echo "file1"
|
||||||
|
echo "fi le2"
|
||||||
|
echo "#file3"
|
||||||
|
echo " #file3"
|
||||||
|
echo ""
|
||||||
|
echo "di r1"
|
||||||
|
echo "dir2"
|
||||||
|
echo "dir3"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("file1" "fi le2" "di r1" "dir2")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (wildcards)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt contains wildcards
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
mkdir -p "$T_DIR_WORK/di r1"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir2"
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "fi le2" > "$T_DIR_WORK/fi le2"
|
||||||
|
echo "file2" > "$T_DIR_WORK/file2"
|
||||||
|
echo "file3" > "$T_DIR_WORK/file3"
|
||||||
|
echo "a" > "$T_DIR_WORK/di r1/a"
|
||||||
|
echo "b" > "$T_DIR_WORK/di r1/b"
|
||||||
|
|
||||||
|
{ echo "fi*"
|
||||||
|
echo "#file3"
|
||||||
|
echo " #file3"
|
||||||
|
echo ""
|
||||||
|
echo "#dir2"
|
||||||
|
echo "di r1"
|
||||||
|
echo "dir2"
|
||||||
|
echo "dir3"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("fi le2" "file1" "file2" "file3" "di r1" "dir2")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "parse_encrypt (excludes)" {
|
||||||
|
echo "
|
||||||
|
.yadm/encrypt contains exclusions
|
||||||
|
Array should be as expected
|
||||||
|
"
|
||||||
|
|
||||||
|
mkdir -p "$T_DIR_WORK/di r1"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir2"
|
||||||
|
mkdir -p "$T_DIR_WORK/dir3"
|
||||||
|
echo "file1" > "$T_DIR_WORK/file1"
|
||||||
|
echo "file1.ex" > "$T_DIR_WORK/file1.ex"
|
||||||
|
echo "fi le2" > "$T_DIR_WORK/fi le2"
|
||||||
|
echo "file3" > "$T_DIR_WORK/file3"
|
||||||
|
echo "test" > "$T_DIR_WORK/test"
|
||||||
|
echo "a.txt" > "$T_DIR_WORK/di r1/a.txt"
|
||||||
|
echo "b.txt" > "$T_DIR_WORK/di r1/b.txt"
|
||||||
|
echo "c.inc" > "$T_DIR_WORK/di r1/c.inc"
|
||||||
|
|
||||||
|
{ echo "fi*"
|
||||||
|
echo "#file3"
|
||||||
|
echo " #file3"
|
||||||
|
echo ""
|
||||||
|
echo " #test"
|
||||||
|
echo "#dir2"
|
||||||
|
echo "di r1/*"
|
||||||
|
echo "dir2"
|
||||||
|
echo "dir3"
|
||||||
|
echo "dir4"
|
||||||
|
echo "!*.ex"
|
||||||
|
echo "!di r1/*.txt"
|
||||||
|
} > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
EXPECT_INCLUDE=("fi le2" "file1" "file3" "di r1/c.inc" "dir2" "dir3")
|
||||||
|
|
||||||
|
run_parse
|
||||||
|
|
||||||
|
[ "$status" == 0 ]
|
||||||
|
[ "$output" == "" ]
|
||||||
|
[ "${#ENCRYPT_INCLUDE_FILES[@]}" -eq "${#EXPECT_INCLUDE[@]}" ]
|
||||||
|
[ "${ENCRYPT_INCLUDE_FILES[*]}" == "${EXPECT_INCLUDE[*]}" ]
|
||||||
|
}
|
@ -440,3 +440,140 @@ EOF
|
|||||||
remote_output=$(GIT_DIR="$T_DIR_REPO" git remote show)
|
remote_output=$(GIT_DIR="$T_DIR_REPO" git remote show)
|
||||||
[ "$remote_output" = "origin" ]
|
[ "$remote_output" = "origin" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "Command 'clone' (local insecure .ssh and .gnupg data, no related data in repo)" {
|
||||||
|
echo "
|
||||||
|
Local .ssh/.gnupg data exists and is insecure
|
||||||
|
but yadm repo contains no .ssh/.gnupg data
|
||||||
|
local insecure data should remain accessible
|
||||||
|
(yadm is hands-off)
|
||||||
|
"
|
||||||
|
#; setup scenario
|
||||||
|
rm -rf "$T_DIR_WORK" "$T_DIR_REPO"
|
||||||
|
mkdir -p "$T_DIR_WORK/.ssh"
|
||||||
|
mkdir -p "$T_DIR_WORK/.gnupg"
|
||||||
|
touch "$T_DIR_WORK/.ssh/testfile"
|
||||||
|
touch "$T_DIR_WORK/.gnupg/testfile"
|
||||||
|
find "$T_DIR_WORK" -exec chmod a+rw '{}' ';'
|
||||||
|
|
||||||
|
#; run clone (with debug on)
|
||||||
|
run "${T_YADM_Y[@]}" clone -d -w "$T_DIR_WORK" "$REMOTE_URL"
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Initialized ]]
|
||||||
|
[[ "$output" =~ initial\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
[[ "$output" =~ initial\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
# standard perms still apply afterwards unless disabled with auto.perms
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwx------"
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwx------"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'clone' (local insecure .gnupg data, related data in repo)" {
|
||||||
|
echo "
|
||||||
|
Local .gnupg data exists and is insecure
|
||||||
|
and yadm repo contains .gnupg data
|
||||||
|
.gnupg dir should be secured post merge
|
||||||
|
"
|
||||||
|
#; setup scenario
|
||||||
|
IN_REPO=(.bash_profile .vimrc .gnupg/gpg.conf)
|
||||||
|
setup
|
||||||
|
rm -rf "$T_DIR_WORK" "$T_DIR_REPO"
|
||||||
|
mkdir -p "$T_DIR_WORK/.gnupg"
|
||||||
|
touch "$T_DIR_WORK/.gnupg/testfile"
|
||||||
|
find "$T_DIR_WORK" -exec chmod a+rw '{}' ';'
|
||||||
|
|
||||||
|
#; run clone (with debug on)
|
||||||
|
run "${T_YADM_Y[@]}" clone -d -w "$T_DIR_WORK" "$REMOTE_URL"
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Initialized ]]
|
||||||
|
[[ "$output" =~ initial\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwxrwxrwx.+\.gnupg ]]
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwx------"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'clone' (local insecure .ssh data, related data in repo)" {
|
||||||
|
echo "
|
||||||
|
Local .ssh data exists and is insecure
|
||||||
|
and yadm repo contains .ssh data
|
||||||
|
.ssh dir should be secured post merge
|
||||||
|
"
|
||||||
|
#; setup scenario
|
||||||
|
IN_REPO=(.bash_profile .vimrc .ssh/config)
|
||||||
|
setup
|
||||||
|
rm -rf "$T_DIR_WORK" "$T_DIR_REPO"
|
||||||
|
mkdir -p "$T_DIR_WORK/.ssh"
|
||||||
|
touch "$T_DIR_WORK/.ssh/testfile"
|
||||||
|
find "$T_DIR_WORK" -exec chmod a+rw '{}' ';'
|
||||||
|
|
||||||
|
#; run clone (with debug on)
|
||||||
|
run "${T_YADM_Y[@]}" clone -d -w "$T_DIR_WORK" "$REMOTE_URL"
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Initialized ]]
|
||||||
|
[[ "$output" =~ initial\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwxrwxrwx.+\.ssh ]]
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwx------"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'clone' (no existing .gnupg, .gnupg data tracked in repo)" {
|
||||||
|
echo "
|
||||||
|
Local .gnupg does not exist
|
||||||
|
and yadm repo contains .gnupg data
|
||||||
|
.gnupg dir should be created and secured prior to merge
|
||||||
|
tracked .gnupg data should be user accessible only
|
||||||
|
"
|
||||||
|
#; setup scenario
|
||||||
|
IN_REPO=(.bash_profile .vimrc .gnupg/gpg.conf)
|
||||||
|
setup
|
||||||
|
rm -rf "$T_DIR_WORK"
|
||||||
|
mkdir -p "$T_DIR_WORK"
|
||||||
|
rm -rf "$T_DIR_REPO"
|
||||||
|
|
||||||
|
#; run clone (with debug on)
|
||||||
|
run "${T_YADM_Y[@]}" clone -d -w "$T_DIR_WORK" "$REMOTE_URL"
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Initialized ]]
|
||||||
|
[[ ! "$output" =~ initial\ private\ dir\ perms ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwx------.+\.gnupg ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwx------.+\.gnupg ]]
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwx------"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'clone' (no existing .ssh, .ssh data tracked in repo)" {
|
||||||
|
echo "
|
||||||
|
Local .ssh does not exist
|
||||||
|
and yadm repo contains .ssh data
|
||||||
|
.ssh dir should be created and secured prior to merge
|
||||||
|
tracked .ssh data should be user accessible only
|
||||||
|
"
|
||||||
|
#; setup scenario
|
||||||
|
IN_REPO=(.bash_profile .vimrc .ssh/config)
|
||||||
|
setup
|
||||||
|
rm -rf "$T_DIR_WORK"
|
||||||
|
mkdir -p "$T_DIR_WORK"
|
||||||
|
rm -rf "$T_DIR_REPO"
|
||||||
|
|
||||||
|
#; run clone (with debug on)
|
||||||
|
run "${T_YADM_Y[@]}" clone -d -w "$T_DIR_WORK" "$REMOTE_URL"
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Initialized ]]
|
||||||
|
[[ ! "$output" =~ initial\ private\ dir\ perms ]]
|
||||||
|
[[ "$output" =~ pre-merge\ private\ dir\ perms\ drwx------.+\.ssh ]]
|
||||||
|
[[ "$output" =~ post-merge\ private\ dir\ perms\ drwx------.+\.ssh ]]
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwx------"
|
||||||
|
}
|
||||||
|
@ -4,15 +4,20 @@ status=;output=; #; populated by bats run()
|
|||||||
|
|
||||||
IN_REPO=(alt* "dir one")
|
IN_REPO=(alt* "dir one")
|
||||||
export TEST_TREE_WITH_ALT=1
|
export TEST_TREE_WITH_ALT=1
|
||||||
|
EXCLUDED_NAME="excluded-base"
|
||||||
|
|
||||||
function create_encrypt() {
|
function create_encrypt() {
|
||||||
for efile in "encrypted-base##" "encrypted-system##$T_SYS" "encrypted-host##$T_SYS.$T_HOST" "encrypted-user##$T_SYS.$T_HOST.$T_USER"; do
|
for efile in "encrypted-base##" "encrypted-system##$T_SYS" "encrypted-host##$T_SYS.$T_HOST" "encrypted-user##$T_SYS.$T_HOST.$T_USER"; do
|
||||||
echo "$efile" >> "$T_YADM_ENCRYPT"
|
echo "$efile" >> "$T_YADM_ENCRYPT"
|
||||||
echo "$efile" >> "$T_DIR_WORK/$efile"
|
echo "$efile" >> "$T_DIR_WORK/$efile"
|
||||||
mkdir -p "$T_DIR_WORK/dir one/$efile"
|
mkdir -p "$T_DIR_WORK/dir one/$efile"
|
||||||
echo "'dir one'/$efile/file1" >> "$T_YADM_ENCRYPT"
|
echo "dir one/$efile/file1" >> "$T_YADM_ENCRYPT"
|
||||||
echo "dir one/$efile/file1" >> "$T_DIR_WORK/dir one/$efile/file1"
|
echo "dir one/$efile/file1" >> "$T_DIR_WORK/dir one/$efile/file1"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "$EXCLUDED_NAME##" >> "$T_YADM_ENCRYPT"
|
||||||
|
echo "!$EXCLUDED_NAME##" >> "$T_YADM_ENCRYPT"
|
||||||
|
echo "$EXCLUDED_NAME##" >> "$T_DIR_WORK/$EXCLUDED_NAME##"
|
||||||
}
|
}
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
@ -130,6 +135,12 @@ function test_alt() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -L "$T_DIR_WORK/$EXCLUDED_NAME" ] ; then
|
||||||
|
echo "ERROR: Found link: $T_DIR_WORK/$EXCLUDED_NAME"
|
||||||
|
echo "ERROR: Excluded files should not be linked"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
#; validate link content
|
#; validate link content
|
||||||
if [[ "$alt_type" =~ none ]] || [ "$auto_alt" = "false" ]; then
|
if [[ "$alt_type" =~ none ]] || [ "$auto_alt" = "false" ]; then
|
||||||
#; no link should be present
|
#; no link should be present
|
||||||
|
@ -88,6 +88,8 @@ EOF
|
|||||||
"$T_GPG_PROGRAM" -q -d "$T_YADM_ARCHIVE" | tar t | sort > "$T_TMP/archive_list"
|
"$T_GPG_PROGRAM" -q -d "$T_YADM_ARCHIVE" | tar t | sort > "$T_TMP/archive_list"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
excluded="$2"
|
||||||
|
|
||||||
#; inventory what is expected in the archive
|
#; inventory what is expected in the archive
|
||||||
(
|
(
|
||||||
if cd "$T_DIR_WORK"; then
|
if cd "$T_DIR_WORK"; then
|
||||||
@ -95,10 +97,23 @@ EOF
|
|||||||
# (globbing is desired)
|
# (globbing is desired)
|
||||||
while IFS='' read -r glob || [ -n "$glob" ]; do
|
while IFS='' read -r glob || [ -n "$glob" ]; do
|
||||||
if [[ ! $glob =~ ^# && ! $glob =~ ^[[:space:]]*$ ]] ; then
|
if [[ ! $glob =~ ^# && ! $glob =~ ^[[:space:]]*$ ]] ; then
|
||||||
|
if [[ ! $glob =~ ^!(.+) ]] ; then
|
||||||
local IFS=$'\n'
|
local IFS=$'\n'
|
||||||
for matching_file in $(eval ls "$glob" 2>/dev/null); do
|
for matching_file in $glob; do
|
||||||
echo "$matching_file"
|
if [ -e "$matching_file" ]; then
|
||||||
|
if [ "$matching_file" != "$excluded" ]; then
|
||||||
|
if [ -d "$matching_file" ]; then
|
||||||
|
echo "$matching_file/"
|
||||||
|
for subfile in "$matching_file"/*; do
|
||||||
|
echo "$subfile"
|
||||||
done
|
done
|
||||||
|
else
|
||||||
|
echo "$matching_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done < "$T_YADM_ENCRYPT" | sort > "$T_TMP/expected_list"
|
done < "$T_YADM_ENCRYPT" | sort > "$T_TMP/expected_list"
|
||||||
fi
|
fi
|
||||||
@ -290,7 +305,77 @@ EOF
|
|||||||
#; add paths with spaces to YADM_ARCHIVE
|
#; add paths with spaces to YADM_ARCHIVE
|
||||||
local original_encrypt
|
local original_encrypt
|
||||||
original_encrypt=$(cat "$T_YADM_ENCRYPT")
|
original_encrypt=$(cat "$T_YADM_ENCRYPT")
|
||||||
echo -e "'space test'/file*" >> "$T_YADM_ENCRYPT"
|
echo -e "space test/file*" >> "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
#; run encrypt
|
||||||
|
run expect <<EOF
|
||||||
|
set timeout 2;
|
||||||
|
spawn ${T_YADM_Y[*]} encrypt;
|
||||||
|
expect "passphrase:" {send "$T_PASSWD\n"}
|
||||||
|
expect "passphrase:" {send "$T_PASSWD\n"}
|
||||||
|
expect "$"
|
||||||
|
foreach {pid spawnid os_error_flag value} [wait] break
|
||||||
|
exit \$value
|
||||||
|
EOF
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Wrote\ new\ file:.+$T_YADM_ARCHIVE ]]
|
||||||
|
|
||||||
|
#; validate the archive
|
||||||
|
validate_archive symmetric
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'encrypt' (exclusions in YADM_ENCRYPT)" {
|
||||||
|
echo "
|
||||||
|
When 'encrypt' command is provided,
|
||||||
|
and YADM_ENCRYPT is present
|
||||||
|
Create YADM_ARCHIVE
|
||||||
|
Report the archive created
|
||||||
|
Archive should be valid
|
||||||
|
Exit with 0
|
||||||
|
"
|
||||||
|
|
||||||
|
#; add paths with spaces to YADM_ARCHIVE
|
||||||
|
local original_encrypt
|
||||||
|
original_encrypt=$(cat "$T_YADM_ENCRYPT")
|
||||||
|
echo -e ".ssh/*" >> "$T_YADM_ENCRYPT"
|
||||||
|
echo -e "!.ssh/sec*.pub" >> "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
|
#; run encrypt
|
||||||
|
run expect <<EOF
|
||||||
|
set timeout 2;
|
||||||
|
spawn ${T_YADM_Y[*]} encrypt;
|
||||||
|
expect "passphrase:" {send "$T_PASSWD\n"}
|
||||||
|
expect "passphrase:" {send "$T_PASSWD\n"}
|
||||||
|
expect "$"
|
||||||
|
foreach {pid spawnid os_error_flag value} [wait] break
|
||||||
|
exit \$value
|
||||||
|
EOF
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ Wrote\ new\ file:.+$T_YADM_ARCHIVE ]]
|
||||||
|
[[ ! "$output" =~ \.ssh/secret.pub ]]
|
||||||
|
|
||||||
|
#; validate the archive
|
||||||
|
validate_archive symmetric ".ssh/secret.pub"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Command 'encrypt' (directories in YADM_ENCRYPT)" {
|
||||||
|
echo "
|
||||||
|
When 'encrypt' command is provided,
|
||||||
|
and YADM_ENCRYPT is present
|
||||||
|
Create YADM_ARCHIVE
|
||||||
|
Report the archive created
|
||||||
|
Archive should be valid
|
||||||
|
Exit with 0
|
||||||
|
"
|
||||||
|
|
||||||
|
#; add directory paths to YADM_ARCHIVE
|
||||||
|
local original_encrypt
|
||||||
|
original_encrypt=$(cat "$T_YADM_ENCRYPT")
|
||||||
|
echo -e "space test" >> "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
#; run encrypt
|
#; run encrypt
|
||||||
run expect <<EOF
|
run expect <<EOF
|
||||||
|
@ -27,13 +27,8 @@ function validate_perms() {
|
|||||||
gpg)
|
gpg)
|
||||||
restricted=("${restricted[@]}" $T_DIR_WORK/.gnupg $T_DIR_WORK/.gnupg/*)
|
restricted=("${restricted[@]}" $T_DIR_WORK/.gnupg $T_DIR_WORK/.gnupg/*)
|
||||||
;;
|
;;
|
||||||
encrypt)
|
*)
|
||||||
local glob
|
restricted=("${restricted[@]}" $T_DIR_WORK/$p)
|
||||||
while IFS='' read -r glob || [ -n "$glob" ]; do
|
|
||||||
if [[ ! $glob =~ ^# ]] ; then
|
|
||||||
restricted=("${restricted[@]}" $T_DIR_WORK/$glob)
|
|
||||||
fi
|
|
||||||
done < "$T_YADM_ENCRYPT"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@ -80,7 +75,7 @@ function validate_perms() {
|
|||||||
"
|
"
|
||||||
|
|
||||||
#; this version has a comment in it
|
#; this version has a comment in it
|
||||||
echo -e "#.vimrc\n.hammerspoon/*" > "$T_YADM_ENCRYPT"
|
echo -e "#.vimrc\n.tmux.conf\n.hammerspoon/*\n!.tmux.conf" > "$T_YADM_ENCRYPT"
|
||||||
|
|
||||||
#; run perms
|
#; run perms
|
||||||
run "${T_YADM_Y[@]}" perms
|
run "${T_YADM_Y[@]}" perms
|
||||||
@ -89,11 +84,8 @@ function validate_perms() {
|
|||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "" ]
|
[ "$output" = "" ]
|
||||||
|
|
||||||
#; this version has no comments in it
|
|
||||||
echo -e ".hammerspoon/*" > "$T_YADM_ENCRYPT"
|
|
||||||
|
|
||||||
#; validate permissions
|
#; validate permissions
|
||||||
validate_perms ssh gpg encrypt
|
validate_perms ssh gpg ".hammerspoon/*"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Command 'perms' (ssh-perms=false)" {
|
@test "Command 'perms' (ssh-perms=false)" {
|
||||||
|
@ -9,6 +9,11 @@ export TEST_TREE_WITH_ALT=1
|
|||||||
setup() {
|
setup() {
|
||||||
destroy_tmp
|
destroy_tmp
|
||||||
build_repo "${IN_REPO[@]}"
|
build_repo "${IN_REPO[@]}"
|
||||||
|
echo "excluded-encrypt##yadm.j2" > "$T_YADM_ENCRYPT"
|
||||||
|
echo "included-encrypt##yadm.j2" >> "$T_YADM_ENCRYPT"
|
||||||
|
echo "!excluded-encrypt*" >> "$T_YADM_ENCRYPT"
|
||||||
|
echo "included-encrypt" > "$T_DIR_WORK/included-encrypt##yadm.j2"
|
||||||
|
echo "excluded-encrypt" > "$T_DIR_WORK/excluded-encrypt##yadm.j2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -27,6 +32,11 @@ function test_alt() {
|
|||||||
real_name="alt-jinja"
|
real_name="alt-jinja"
|
||||||
file_content_match="custom_class-custom_system-custom_host-custom_user-${T_DISTRO}"
|
file_content_match="custom_class-custom_system-custom_host-custom_user-${T_DISTRO}"
|
||||||
;;
|
;;
|
||||||
|
encrypt)
|
||||||
|
real_name="included-encrypt"
|
||||||
|
file_content_match="included-encrypt"
|
||||||
|
missing_name="excluded-encrypt"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$test_overwrite" = "true" ] ; then
|
if [ "$test_overwrite" = "true" ] ; then
|
||||||
@ -63,6 +73,11 @@ function test_alt() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$missing_name" ] && [ -f "$T_DIR_WORK/$missing_name" ]; then
|
||||||
|
echo "ERROR: File should not have been created '$missing_name'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
#; validate link content
|
#; validate link content
|
||||||
if [[ "$alt_type" =~ none ]] || [ "$auto_alt" = "false" ]; then
|
if [[ "$alt_type" =~ none ]] || [ "$auto_alt" = "false" ]; then
|
||||||
#; no real file should be present
|
#; no real file should be present
|
||||||
@ -173,3 +188,16 @@ function test_alt() {
|
|||||||
GIT_DIR="$T_DIR_REPO" git config local.class custom_class
|
GIT_DIR="$T_DIR_REPO" git config local.class custom_class
|
||||||
test_alt 'override_all' 'false' ''
|
test_alt 'override_all' 'false' ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "Command 'alt' (select jinja within .yadm/encrypt)" {
|
||||||
|
echo "
|
||||||
|
When the command 'alt' is provided
|
||||||
|
and file matches ##yadm.j2 within .yadm/encrypt
|
||||||
|
and file excluded within .yadm/encrypt
|
||||||
|
Report jinja template processing
|
||||||
|
Verify that the correct content is written
|
||||||
|
Exit with 0
|
||||||
|
"
|
||||||
|
|
||||||
|
test_alt 'encrypt' 'false' ''
|
||||||
|
}
|
||||||
|
@ -73,7 +73,7 @@ function count_introspect() {
|
|||||||
Exit with 0
|
Exit with 0
|
||||||
"
|
"
|
||||||
|
|
||||||
count_introspect "configs" 0 12 'yadm\.auto-alt'
|
count_introspect "configs" 0 13 'yadm\.auto-alt'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Command 'introspect' (repo)" {
|
@test "Command 'introspect' (repo)" {
|
||||||
|
102
test/118_accept_assert_private_dirs.bats
Normal file
102
test/118_accept_assert_private_dirs.bats
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
load common
|
||||||
|
load_fixtures
|
||||||
|
status=;output=; #; populated by bats run()
|
||||||
|
|
||||||
|
IN_REPO=(.bash_profile .vimrc)
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
destroy_tmp
|
||||||
|
build_repo "${IN_REPO[@]}"
|
||||||
|
rm -rf "$T_DIR_WORK"
|
||||||
|
mkdir -p "$T_DIR_WORK"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Private dirs (private dirs missing)" {
|
||||||
|
echo "
|
||||||
|
When a git command is run
|
||||||
|
And private directories are missing
|
||||||
|
Create private directories prior to command
|
||||||
|
"
|
||||||
|
|
||||||
|
#; confirm directories are missing at start
|
||||||
|
[ ! -e "$T_DIR_WORK/.gnupg" ]
|
||||||
|
[ ! -e "$T_DIR_WORK/.ssh" ]
|
||||||
|
|
||||||
|
#; run status
|
||||||
|
export DEBUG=yes
|
||||||
|
run "${T_YADM_Y[@]}" status
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ On\ branch\ master ]]
|
||||||
|
|
||||||
|
#; confirm private directories are created
|
||||||
|
[ -d "$T_DIR_WORK/.gnupg" ]
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwx------"
|
||||||
|
[ -d "$T_DIR_WORK/.ssh" ]
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwx------"
|
||||||
|
|
||||||
|
#; confirm directories are created before command is run
|
||||||
|
[[ "$output" =~ Creating.+/.gnupg/.+Creating.+/.ssh/.+Running\ git\ command\ git\ status ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Private dirs (private dirs missing / yadm.auto-private-dirs=false)" {
|
||||||
|
echo "
|
||||||
|
When a git command is run
|
||||||
|
And private directories are missing
|
||||||
|
But auto-private-dirs is false
|
||||||
|
Do not create private dirs
|
||||||
|
"
|
||||||
|
|
||||||
|
#; confirm directories are missing at start
|
||||||
|
[ ! -e "$T_DIR_WORK/.gnupg" ]
|
||||||
|
[ ! -e "$T_DIR_WORK/.ssh" ]
|
||||||
|
|
||||||
|
#; set configuration
|
||||||
|
run "${T_YADM_Y[@]}" config --bool "yadm.auto-private-dirs" "false"
|
||||||
|
|
||||||
|
#; run status
|
||||||
|
run "${T_YADM_Y[@]}" status
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ On\ branch\ master ]]
|
||||||
|
|
||||||
|
#; confirm private directories are not created
|
||||||
|
[ ! -e "$T_DIR_WORK/.gnupg" ]
|
||||||
|
[ ! -e "$T_DIR_WORK/.ssh" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "Private dirs (private dirs exist / yadm.auto-perms=false)" {
|
||||||
|
echo "
|
||||||
|
When a git command is run
|
||||||
|
And private directories exist
|
||||||
|
And yadm is configured not to auto update perms
|
||||||
|
Do not alter directories
|
||||||
|
"
|
||||||
|
|
||||||
|
#shellcheck disable=SC2174
|
||||||
|
mkdir -m 0777 -p "$T_DIR_WORK/.gnupg" "$T_DIR_WORK/.ssh"
|
||||||
|
|
||||||
|
#; confirm directories are preset and open
|
||||||
|
[ -d "$T_DIR_WORK/.gnupg" ]
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwxrwxrwx"
|
||||||
|
[ -d "$T_DIR_WORK/.ssh" ]
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwxrwxrwx"
|
||||||
|
|
||||||
|
#; set configuration
|
||||||
|
run "${T_YADM_Y[@]}" config --bool "yadm.auto-perms" "false"
|
||||||
|
|
||||||
|
#; run status
|
||||||
|
run "${T_YADM_Y[@]}" status
|
||||||
|
|
||||||
|
#; validate status and output
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[[ "$output" =~ On\ branch\ master ]]
|
||||||
|
|
||||||
|
#; confirm directories are still preset and open
|
||||||
|
[ -d "$T_DIR_WORK/.gnupg" ]
|
||||||
|
test_perms "$T_DIR_WORK/.gnupg" "drwxrwxrwx"
|
||||||
|
[ -d "$T_DIR_WORK/.ssh" ]
|
||||||
|
test_perms "$T_DIR_WORK/.ssh" "drwxrwxrwx"
|
||||||
|
}
|
221
yadm
221
yadm
@ -19,7 +19,7 @@ if [ -z "$BASH_VERSION" ]; then
|
|||||||
[ "$YADM_TEST" != 1 ] && exec bash "$0" "$@"
|
[ "$YADM_TEST" != 1 ] && exec bash "$0" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION=1.11.0
|
VERSION=1.12.0
|
||||||
|
|
||||||
YADM_WORK="$HOME"
|
YADM_WORK="$HOME"
|
||||||
YADM_DIR="$HOME/.yadm"
|
YADM_DIR="$HOME/.yadm"
|
||||||
@ -35,13 +35,14 @@ FULL_COMMAND=""
|
|||||||
|
|
||||||
GPG_PROGRAM="gpg"
|
GPG_PROGRAM="gpg"
|
||||||
GIT_PROGRAM="git"
|
GIT_PROGRAM="git"
|
||||||
LS_PROGRAM="/bin/ls"
|
|
||||||
ENVTPL_PROGRAM="envtpl"
|
ENVTPL_PROGRAM="envtpl"
|
||||||
LSB_RELEASE_PROGRAM="lsb_release"
|
LSB_RELEASE_PROGRAM="lsb_release"
|
||||||
|
|
||||||
PROC_VERSION="/proc/version"
|
PROC_VERSION="/proc/version"
|
||||||
OPERATING_SYSTEM="Unknown"
|
OPERATING_SYSTEM="Unknown"
|
||||||
|
|
||||||
|
ENCRYPT_INCLUDE_FILES="unparsed"
|
||||||
|
|
||||||
#; flag causing path translations with cygpath
|
#; flag causing path translations with cygpath
|
||||||
USE_CYGPATH=0
|
USE_CYGPATH=0
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ function main() {
|
|||||||
function alt() {
|
function alt() {
|
||||||
|
|
||||||
require_repo
|
require_repo
|
||||||
|
parse_encrypt
|
||||||
|
|
||||||
local_class="$(config local.class)"
|
local_class="$(config local.class)"
|
||||||
if [ -z "$local_class" ] ; then
|
if [ -z "$local_class" ] ; then
|
||||||
@ -160,32 +162,11 @@ function alt() {
|
|||||||
match1="^(.+)##(()|$match_system|$match_system\.$match_host|$match_system\.$match_host\.$match_user)$"
|
match1="^(.+)##(()|$match_system|$match_system\.$match_host|$match_system\.$match_host\.$match_user)$"
|
||||||
match2="^(.+)##($match_class|$match_class\.$match_system|$match_class\.$match_system\.$match_host|$match_class\.$match_system\.$match_host\.$match_user)$"
|
match2="^(.+)##($match_class|$match_class\.$match_system|$match_class\.$match_system\.$match_host|$match_class\.$match_system\.$match_host\.$match_user)$"
|
||||||
|
|
||||||
#; process relative to YADM_WORK
|
cd_work "Alternates" || return
|
||||||
YADM_WORK=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
|
||||||
cd "$YADM_WORK" || {
|
|
||||||
debug "Alternates not processed, unable to cd to $YADM_WORK"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
#; only be noisy if the "alt" command was run directly
|
#; only be noisy if the "alt" command was run directly
|
||||||
[ "$YADM_COMMAND" = "alt" ] && loud="YES"
|
[ "$YADM_COMMAND" = "alt" ] && loud="YES"
|
||||||
|
|
||||||
#; build a list of files from YADM_ENCRYPT
|
|
||||||
ENC_FILES=()
|
|
||||||
index=0
|
|
||||||
if [ -f "$YADM_ENCRYPT" ] ; then
|
|
||||||
while IFS='' read -r glob || [ -n "$glob" ]; do
|
|
||||||
if [[ ! $glob =~ ^# && ! $glob =~ ^[[:space:]]*$ ]] ; then
|
|
||||||
# echo "working on ->$glob<-"
|
|
||||||
local IFS=$'\n'
|
|
||||||
for matching_file in $(eval "$LS_PROGRAM" "$glob" 2>/dev/null); do
|
|
||||||
ENC_FILES[$index]="$matching_file"
|
|
||||||
((index++))
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
done < "$YADM_ENCRYPT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
#; decide if a copy should be done instead of a symbolic link
|
#; decide if a copy should be done instead of a symbolic link
|
||||||
local do_copy=0
|
local do_copy=0
|
||||||
if [[ $OPERATING_SYSTEM == CYGWIN* ]] ; then
|
if [[ $OPERATING_SYSTEM == CYGWIN* ]] ; then
|
||||||
@ -199,7 +180,7 @@ function alt() {
|
|||||||
for match in $match1 $match2; do
|
for match in $match1 $match2; do
|
||||||
last_linked=''
|
last_linked=''
|
||||||
local IFS=$'\n'
|
local IFS=$'\n'
|
||||||
for tracked_file in $("$GIT_PROGRAM" ls-files | sort) "${ENC_FILES[@]}"; do
|
for tracked_file in $("$GIT_PROGRAM" ls-files | sort) "${ENCRYPT_INCLUDE_FILES[@]}"; do
|
||||||
tracked_file="$YADM_WORK/$tracked_file"
|
tracked_file="$YADM_WORK/$tracked_file"
|
||||||
#; process both the path, and it's parent directory
|
#; process both the path, and it's parent directory
|
||||||
for alt_path in "$tracked_file" "${tracked_file%/*}"; do
|
for alt_path in "$tracked_file" "${tracked_file%/*}"; do
|
||||||
@ -229,7 +210,7 @@ function alt() {
|
|||||||
#; for every file which is a *##yadm.j2 create a real file
|
#; for every file which is a *##yadm.j2 create a real file
|
||||||
local IFS=$'\n'
|
local IFS=$'\n'
|
||||||
local match="^(.+)##yadm\\.j2$"
|
local match="^(.+)##yadm\\.j2$"
|
||||||
for tracked_file in $("$GIT_PROGRAM" ls-files | sort) $(cat "$YADM_ENCRYPT" 2>/dev/null); do
|
for tracked_file in $("$GIT_PROGRAM" ls-files | sort) "${ENCRYPT_INCLUDE_FILES[@]}"; do
|
||||||
tracked_file="$YADM_WORK/$tracked_file"
|
tracked_file="$YADM_WORK/$tracked_file"
|
||||||
if [ -e "$tracked_file" ] ; then
|
if [ -e "$tracked_file" ] ; then
|
||||||
if [[ $tracked_file =~ $match ]] ; then
|
if [[ $tracked_file =~ $match ]] ; then
|
||||||
@ -292,6 +273,8 @@ function clone() {
|
|||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
|
[ -n "$DEBUG" ] && display_private_perms "initial"
|
||||||
|
|
||||||
#; clone will begin with a bare repo
|
#; clone will begin with a bare repo
|
||||||
local empty=
|
local empty=
|
||||||
init $empty
|
init $empty
|
||||||
@ -310,6 +293,15 @@ function clone() {
|
|||||||
rm -rf "$YADM_REPO"
|
rm -rf "$YADM_REPO"
|
||||||
error_out "Unable to fetch origin ${clone_args[0]}"
|
error_out "Unable to fetch origin ${clone_args[0]}"
|
||||||
}
|
}
|
||||||
|
debug "Determining if repo tracks private directories"
|
||||||
|
for private_dir in .ssh/ .gnupg/; do
|
||||||
|
found_log=$("$GIT_PROGRAM" log -n 1 origin/master -- "$private_dir" 2>/dev/null)
|
||||||
|
if [ -n "$found_log" ]; then
|
||||||
|
debug "Private directory $private_dir is tracked by repo"
|
||||||
|
assert_private_dirs "$private_dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ -n "$DEBUG" ] && display_private_perms "pre-merge"
|
||||||
debug "Doing an initial merge of origin/master"
|
debug "Doing an initial merge of origin/master"
|
||||||
"$GIT_PROGRAM" merge origin/master || {
|
"$GIT_PROGRAM" merge origin/master || {
|
||||||
debug "Merge failed, doing a reset and stashing conflicts."
|
debug "Merge failed, doing a reset and stashing conflicts."
|
||||||
@ -351,6 +343,8 @@ EOF
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ -n "$DEBUG" ] && display_private_perms "post-merge"
|
||||||
|
|
||||||
CHANGES_POSSIBLE=1
|
CHANGES_POSSIBLE=1
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -422,14 +416,9 @@ function encrypt() {
|
|||||||
|
|
||||||
require_gpg
|
require_gpg
|
||||||
require_encrypt
|
require_encrypt
|
||||||
require_ls
|
parse_encrypt
|
||||||
|
|
||||||
#; process relative to YADM_WORK
|
cd_work "Encryption" || return
|
||||||
YADM_WORK=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
|
||||||
cd "$YADM_WORK" || {
|
|
||||||
debug "Encryption not processed, unable to cd to $YADM_WORK"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
#; Build gpg options for gpg
|
#; Build gpg options for gpg
|
||||||
GPG_KEY="$(config yadm.gpg-recipient)"
|
GPG_KEY="$(config yadm.gpg-recipient)"
|
||||||
@ -441,26 +430,13 @@ function encrypt() {
|
|||||||
GPG_OPTS=("-c")
|
GPG_OPTS=("-c")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#; build a list of files from YADM_ENCRYPT
|
|
||||||
ENC_FILES=()
|
|
||||||
index=0
|
|
||||||
while IFS='' read -r glob || [ -n "$glob" ]; do
|
|
||||||
if [[ ! $glob =~ ^# && ! $glob =~ ^[[:space:]]*$ ]] ; then
|
|
||||||
local IFS=$'\n'
|
|
||||||
for matching_file in $(eval "$LS_PROGRAM" "$glob" 2>/dev/null); do
|
|
||||||
ENC_FILES[$index]="$matching_file"
|
|
||||||
((index++))
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
done < "$YADM_ENCRYPT"
|
|
||||||
|
|
||||||
#; report which files will be encrypted
|
#; report which files will be encrypted
|
||||||
echo "Encrypting the following files:"
|
echo "Encrypting the following files:"
|
||||||
"$LS_PROGRAM" -1 "${ENC_FILES[@]}"
|
printf '%s\n' "${ENCRYPT_INCLUDE_FILES[@]}"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
#; encrypt all files which match the globs
|
#; encrypt all files which match the globs
|
||||||
if tar -f - -c "${ENC_FILES[@]}" | $GPG_PROGRAM --yes "${GPG_OPTS[@]}" --output "$YADM_ARCHIVE"; then
|
if tar -f - -c "${ENCRYPT_INCLUDE_FILES[@]}" | $GPG_PROGRAM --yes "${GPG_OPTS[@]}" --output "$YADM_ARCHIVE"; then
|
||||||
echo "Wrote new file: $YADM_ARCHIVE"
|
echo "Wrote new file: $YADM_ARCHIVE"
|
||||||
else
|
else
|
||||||
error_out "Unable to write $YADM_ARCHIVE"
|
error_out "Unable to write $YADM_ARCHIVE"
|
||||||
@ -513,9 +489,18 @@ function git_command() {
|
|||||||
set -- "config" "${@:2}"
|
set -- "config" "${@:2}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#; ensure private .ssh and .gnupg directories exist first
|
||||||
|
#; TODO: consider restricting this to only commands which modify the work-tree
|
||||||
|
|
||||||
|
auto_private_dirs=$(config --bool yadm.auto-private-dirs)
|
||||||
|
if [ "$auto_private_dirs" != "false" ] ; then
|
||||||
|
assert_private_dirs .gnupg/ .ssh/
|
||||||
|
fi
|
||||||
|
|
||||||
CHANGES_POSSIBLE=1
|
CHANGES_POSSIBLE=1
|
||||||
|
|
||||||
#; pass commands through to git
|
#; pass commands through to git
|
||||||
|
debug "Running git command $GIT_PROGRAM $*"
|
||||||
"$GIT_PROGRAM" "$@"
|
"$GIT_PROGRAM" "$@"
|
||||||
return "$?"
|
return "$?"
|
||||||
}
|
}
|
||||||
@ -613,6 +598,7 @@ local.os
|
|||||||
local.user
|
local.user
|
||||||
yadm.auto-alt
|
yadm.auto-alt
|
||||||
yadm.auto-perms
|
yadm.auto-perms
|
||||||
|
yadm.auto-private-dirs
|
||||||
yadm.cygwin-copy
|
yadm.cygwin-copy
|
||||||
yadm.git-program
|
yadm.git-program
|
||||||
yadm.gpg-perms
|
yadm.gpg-perms
|
||||||
@ -644,11 +630,7 @@ function list() {
|
|||||||
|
|
||||||
#; process relative to YADM_WORK when --all is specified
|
#; process relative to YADM_WORK when --all is specified
|
||||||
if [ -n "$LIST_ALL" ] ; then
|
if [ -n "$LIST_ALL" ] ; then
|
||||||
YADM_WORK=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
cd_work "List" || return
|
||||||
cd "$YADM_WORK" || {
|
|
||||||
debug "List not processed, unable to cd to $YADM_WORK"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#; list tracked files
|
#; list tracked files
|
||||||
@ -658,40 +640,29 @@ function list() {
|
|||||||
|
|
||||||
function perms() {
|
function perms() {
|
||||||
|
|
||||||
require_ls
|
parse_encrypt
|
||||||
|
|
||||||
#; TODO: prevent repeats in the files changed
|
#; TODO: prevent repeats in the files changed
|
||||||
|
|
||||||
#; process relative to YADM_WORK
|
cd_work "Perms" || return
|
||||||
YADM_WORK=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
|
||||||
cd "$YADM_WORK" || {
|
|
||||||
debug "Perms not processed, unable to cd to $YADM_WORK"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
GLOBS=()
|
GLOBS=()
|
||||||
|
|
||||||
#; include the archive created by "encrypt"
|
#; include the archive created by "encrypt"
|
||||||
[ -f "$YADM_ARCHIVE" ] && GLOBS=("${GLOBS[@]}" "$YADM_ARCHIVE")
|
[ -f "$YADM_ARCHIVE" ] && GLOBS+=("$YADM_ARCHIVE")
|
||||||
|
|
||||||
#; include all .ssh files (unless disabled)
|
#; include all .ssh files (unless disabled)
|
||||||
if [[ $(config --bool yadm.ssh-perms) != "false" ]] ; then
|
if [[ $(config --bool yadm.ssh-perms) != "false" ]] ; then
|
||||||
GLOBS=("${GLOBS[@]}" ".ssh" ".ssh/*")
|
GLOBS+=(".ssh" ".ssh/*")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#; include all gpg files (unless disabled)
|
#; include all gpg files (unless disabled)
|
||||||
if [[ $(config --bool yadm.gpg-perms) != "false" ]] ; then
|
if [[ $(config --bool yadm.gpg-perms) != "false" ]] ; then
|
||||||
GLOBS=("${GLOBS[@]}" ".gnupg" ".gnupg/*")
|
GLOBS+=(".gnupg" ".gnupg/*")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#; include globs found in YADM_ENCRYPT (if present)
|
#; include any files we encrypt
|
||||||
if [ -f "$YADM_ENCRYPT" ] ; then
|
GLOBS+=("${ENCRYPT_INCLUDE_FILES[@]}")
|
||||||
while IFS='' read -r glob || [ -n "$glob" ]; do
|
|
||||||
if [[ ! $glob =~ ^# ]] ; then
|
|
||||||
GLOBS=("${GLOBS[@]}" $(eval "$LS_PROGRAM" "$glob" 2>/dev/null))
|
|
||||||
fi
|
|
||||||
done < "$YADM_ENCRYPT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
#; remove group/other permissions from collected globs
|
#; remove group/other permissions from collected globs
|
||||||
#shellcheck disable=SC2068
|
#shellcheck disable=SC2068
|
||||||
@ -852,13 +823,13 @@ function set_operating_system() {
|
|||||||
|
|
||||||
function debug() {
|
function debug() {
|
||||||
|
|
||||||
[ -n "$DEBUG" ] && echo -e "DEBUG: $*"
|
[ -n "$DEBUG" ] && echo_e "DEBUG: $*"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function error_out() {
|
function error_out() {
|
||||||
|
|
||||||
echo -e "ERROR: $*"
|
echo_e "ERROR: $*"
|
||||||
exit_with_hook 1
|
exit_with_hook 1
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -906,6 +877,89 @@ function invoke_hook() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assert_private_dirs() {
|
||||||
|
work=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
||||||
|
for private_dir in "$@"; do
|
||||||
|
if [ ! -d "$work/$private_dir" ]; then
|
||||||
|
debug "Creating $work/$private_dir"
|
||||||
|
#shellcheck disable=SC2174
|
||||||
|
mkdir -m 0700 -p "$work/$private_dir" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function display_private_perms() {
|
||||||
|
when="$1"
|
||||||
|
for private_dir in .ssh .gnupg; do
|
||||||
|
if [ -d "$YADM_WORK/$private_dir" ]; then
|
||||||
|
private_perms=$(ls -ld "$YADM_WORK/$private_dir")
|
||||||
|
debug "$when" private dir perms "$private_perms"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function cd_work() {
|
||||||
|
YADM_WORK=$(unix_path "$("$GIT_PROGRAM" config core.worktree)")
|
||||||
|
cd "$YADM_WORK" || {
|
||||||
|
debug "$1 not processed, unable to cd to $YADM_WORK"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_encrypt() {
|
||||||
|
if [ "$ENCRYPT_INCLUDE_FILES" != "unparsed" ]; then
|
||||||
|
#shellcheck disable=SC2034
|
||||||
|
PARSE_ENCRYPT_SHORT="parse_encrypt() not reprocessed"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
ENCRYPT_INCLUDE_FILES=()
|
||||||
|
ENCRYPT_EXCLUDE_FILES=()
|
||||||
|
|
||||||
|
cd_work "Parsing encrypt" || return
|
||||||
|
|
||||||
|
exclude_pattern="^!(.+)"
|
||||||
|
if [ -f "$YADM_ENCRYPT" ] ; then
|
||||||
|
#; parse both included/excluded
|
||||||
|
while IFS='' read -r line || [ -n "$line" ]; do
|
||||||
|
if [[ ! $line =~ ^# && ! $line =~ ^[[:space:]]*$ ]] ; then
|
||||||
|
local IFS=$'\n'
|
||||||
|
for pattern in $line; do
|
||||||
|
if [[ "$pattern" =~ $exclude_pattern ]]; then
|
||||||
|
for ex_file in ${BASH_REMATCH[1]}; do
|
||||||
|
if [ -e "$ex_file" ]; then
|
||||||
|
ENCRYPT_EXCLUDE_FILES+=("$ex_file")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
for in_file in $pattern; do
|
||||||
|
if [ -e "$in_file" ]; then
|
||||||
|
ENCRYPT_INCLUDE_FILES+=("$in_file")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done < "$YADM_ENCRYPT"
|
||||||
|
|
||||||
|
#; remove excludes from the includes
|
||||||
|
#(SC2068 is disabled because in this case, we desire globbing)
|
||||||
|
FINAL_INCLUDE=()
|
||||||
|
#shellcheck disable=SC2068
|
||||||
|
for included in "${ENCRYPT_INCLUDE_FILES[@]}"; do
|
||||||
|
skip=
|
||||||
|
#shellcheck disable=SC2068
|
||||||
|
for ex_file in ${ENCRYPT_EXCLUDE_FILES[@]}; do
|
||||||
|
[ "$included" == "$ex_file" ] && { skip=1; break; }
|
||||||
|
done
|
||||||
|
[ -n "$skip" ] || FINAL_INCLUDE+=("$included")
|
||||||
|
done
|
||||||
|
ENCRYPT_INCLUDE_FILES=("${FINAL_INCLUDE[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#; ****** Auto Functions ******
|
#; ****** Auto Functions ******
|
||||||
|
|
||||||
function auto_alt() {
|
function auto_alt() {
|
||||||
@ -990,13 +1044,6 @@ function require_gpg() {
|
|||||||
function require_repo() {
|
function require_repo() {
|
||||||
[ -d "$YADM_REPO" ] || error_out "Git repo does not exist. did you forget to run 'init' or 'clone'?"
|
[ -d "$YADM_REPO" ] || error_out "Git repo does not exist. did you forget to run 'init' or 'clone'?"
|
||||||
}
|
}
|
||||||
function require_ls() {
|
|
||||||
if [ ! -f "$LS_PROGRAM" ] ; then
|
|
||||||
command -v ls >/dev/null 2>&1 || \
|
|
||||||
error_out "This functionality requires 'ls' to be installed at '$LS_PROGRAM' or listed in your \$PATH"
|
|
||||||
LS_PROGRAM=ls
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
function require_shell() {
|
function require_shell() {
|
||||||
[ -x "$SHELL" ] || error_out "\$SHELL does not refer to an executable."
|
[ -x "$SHELL" ] || error_out "\$SHELL does not refer to an executable."
|
||||||
}
|
}
|
||||||
@ -1028,6 +1075,20 @@ function mixed_path() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#; ****** echo replacements ******
|
||||||
|
function echo() {
|
||||||
|
IFS=' '
|
||||||
|
printf '%s\n' "$*"
|
||||||
|
}
|
||||||
|
function echo_n() {
|
||||||
|
IFS=' '
|
||||||
|
printf '%s' "$*"
|
||||||
|
}
|
||||||
|
function echo_e() {
|
||||||
|
IFS=' '
|
||||||
|
printf '%b\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
#; ****** Main processing (when not unit testing) ******
|
#; ****** Main processing (when not unit testing) ******
|
||||||
|
|
||||||
if [ "$YADM_TEST" != 1 ] ; then
|
if [ "$YADM_TEST" != 1 ] ; then
|
||||||
|
45
yadm.1
45
yadm.1
@ -1,5 +1,5 @@
|
|||||||
." vim: set spell so=8:
|
." vim: set spell so=8:
|
||||||
.TH yadm 1 "10 July 2017" "1.11.0"
|
.TH yadm 1 "25 October 2017" "1.12.0"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
yadm \- Yet Another Dotfiles Manager
|
yadm \- Yet Another Dotfiles Manager
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -350,6 +350,9 @@ If disabled, you may still run
|
|||||||
manually to update permissions.
|
manually to update permissions.
|
||||||
This feature is enabled by default.
|
This feature is enabled by default.
|
||||||
.TP
|
.TP
|
||||||
|
.B yadm.auto-private-dirs
|
||||||
|
Disable the automatic creating of private directories described in the section PERMISSIONS.
|
||||||
|
.TP
|
||||||
.B yadm.ssh-perms
|
.B yadm.ssh-perms
|
||||||
Disable the permission changes to
|
Disable the permission changes to
|
||||||
.IR $HOME/.ssh/* .
|
.IR $HOME/.ssh/* .
|
||||||
@ -583,6 +586,11 @@ For example:
|
|||||||
.gnupg/*.gpg
|
.gnupg/*.gpg
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
|
Standard filename expansions (*, ?, [) are supported. Other shell expansions
|
||||||
|
like brace and tilde are not supported. Spaces in paths are supported, and
|
||||||
|
should not be quoted. If a directory is specified, its contents will be
|
||||||
|
included, but not recursively. Paths beginning with a "!" will be excluded.
|
||||||
|
|
||||||
The
|
The
|
||||||
.B yadm encrypt
|
.B yadm encrypt
|
||||||
command will find all files matching the patterns, and prompt for a password. Once a
|
command will find all files matching the patterns, and prompt for a password. Once a
|
||||||
@ -608,12 +616,10 @@ It is recommended that you use a private repository when keeping confidential
|
|||||||
files, even though they are encrypted.
|
files, even though they are encrypted.
|
||||||
.SH PERMISSIONS
|
.SH PERMISSIONS
|
||||||
When files are checked out of a Git repository, their initial permissions are
|
When files are checked out of a Git repository, their initial permissions are
|
||||||
dependent upon the user's umask. This can result in confidential files with lax permissions.
|
dependent upon the user's umask. Because of this,
|
||||||
|
|
||||||
To prevent this,
|
|
||||||
.B yadm
|
.B yadm
|
||||||
will automatically update the permissions of confidential files.
|
will automatically update the permissions of some file paths. The "group" and
|
||||||
The "group" and "others" permissions will be removed from the following files:
|
"others" permissions will be removed from the following files:
|
||||||
|
|
||||||
.RI - " $HOME/.yadm/files.gpg
|
.RI - " $HOME/.yadm/files.gpg
|
||||||
|
|
||||||
@ -629,11 +635,32 @@ The "group" and "others" permissions will be removed from the following files:
|
|||||||
.B yadm
|
.B yadm
|
||||||
will automatically update permissions by default. This can be disabled using the
|
will automatically update permissions by default. This can be disabled using the
|
||||||
.I yadm.auto-perms
|
.I yadm.auto-perms
|
||||||
configuration.
|
configuration. Even if disabled, permissions can be manually updated by running
|
||||||
Even if disabled, permissions can be manually updated by running
|
|
||||||
.BR yadm\ perms .
|
.BR yadm\ perms .
|
||||||
The SSH directory processing can be disabled using the
|
The
|
||||||
|
.I .ssh
|
||||||
|
directory processing can be disabled using the
|
||||||
.I yadm.ssh-perms
|
.I yadm.ssh-perms
|
||||||
|
configuration. The
|
||||||
|
.I .gnupg
|
||||||
|
directory processing can be disabled using the
|
||||||
|
.I yadm.gpg-perms
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
When cloning a repo which includes data in a
|
||||||
|
.IR .ssh " or " .gnupg
|
||||||
|
directory, if those directories do not exist at the time of cloning,
|
||||||
|
.B yadm
|
||||||
|
will create the directories with mask 0700 prior to merging the fetched data
|
||||||
|
into the work-tree.
|
||||||
|
|
||||||
|
When running a Git command and
|
||||||
|
.IR .ssh " or " .gnupg
|
||||||
|
directories do not exist,
|
||||||
|
.B yadm
|
||||||
|
will create those directories with mask 0700 prior to running the Git command.
|
||||||
|
This can be disabled using the
|
||||||
|
.I yadm.auto-private-dirs
|
||||||
configuration.
|
configuration.
|
||||||
.SH HOOKS
|
.SH HOOKS
|
||||||
For every command
|
For every command
|
||||||
|
35
yadm.md
35
yadm.md
@ -214,6 +214,10 @@
|
|||||||
manually to update permissions. This feature is enabled by
|
manually to update permissions. This feature is enabled by
|
||||||
default.
|
default.
|
||||||
|
|
||||||
|
yadm.auto-private-dirs
|
||||||
|
Disable the automatic creating of private directories described
|
||||||
|
in the section PERMISSIONS.
|
||||||
|
|
||||||
yadm.ssh-perms
|
yadm.ssh-perms
|
||||||
Disable the permission changes to $HOME/.ssh/*. This feature is
|
Disable the permission changes to $HOME/.ssh/*. This feature is
|
||||||
enabled by default.
|
enabled by default.
|
||||||
@ -405,6 +409,12 @@
|
|||||||
.ssh/*.key
|
.ssh/*.key
|
||||||
.gnupg/*.gpg
|
.gnupg/*.gpg
|
||||||
|
|
||||||
|
Standard filename expansions (*, ?, [) are supported. Other shell
|
||||||
|
expansions like brace and tilde are not supported. Spaces in paths are
|
||||||
|
supported, and should not be quoted. If a directory is specified, its
|
||||||
|
contents will be included, but not recursively. Paths beginning with a
|
||||||
|
"!" will be excluded.
|
||||||
|
|
||||||
The yadm encrypt command will find all files matching the patterns, and
|
The yadm encrypt command will find all files matching the patterns, and
|
||||||
prompt for a password. Once a password has confirmed, the matching
|
prompt for a password. Once a password has confirmed, the matching
|
||||||
files will be encrypted and saved as $HOME/.yadm/files.gpg. The pat-
|
files will be encrypted and saved as $HOME/.yadm/files.gpg. The pat-
|
||||||
@ -423,12 +433,9 @@
|
|||||||
|
|
||||||
## PERMISSIONS
|
## PERMISSIONS
|
||||||
When files are checked out of a Git repository, their initial permis-
|
When files are checked out of a Git repository, their initial permis-
|
||||||
sions are dependent upon the user's umask. This can result in confiden-
|
sions are dependent upon the user's umask. Because of this, yadm will
|
||||||
tial files with lax permissions.
|
automatically update the permissions of some file paths. The "group"
|
||||||
|
and "others" permissions will be removed from the following files:
|
||||||
To prevent this, yadm will automatically update the permissions of con-
|
|
||||||
fidential files. The "group" and "others" permissions will be removed
|
|
||||||
from the following files:
|
|
||||||
|
|
||||||
- $HOME/.yadm/files.gpg
|
- $HOME/.yadm/files.gpg
|
||||||
|
|
||||||
@ -440,8 +447,20 @@
|
|||||||
|
|
||||||
yadm will automatically update permissions by default. This can be dis-
|
yadm will automatically update permissions by default. This can be dis-
|
||||||
abled using the yadm.auto-perms configuration. Even if disabled, per-
|
abled using the yadm.auto-perms configuration. Even if disabled, per-
|
||||||
missions can be manually updated by running yadm perms. The SSH direc-
|
missions can be manually updated by running yadm perms. The .ssh
|
||||||
tory processing can be disabled using the yadm.ssh-perms configuration.
|
directory processing can be disabled using the yadm.ssh-perms configu-
|
||||||
|
ration. The .gnupg directory processing can be disabled using the
|
||||||
|
yadm.gpg-perms configuration.
|
||||||
|
|
||||||
|
When cloning a repo which includes data in a .ssh or .gnupg directory,
|
||||||
|
if those directories do not exist at the time of cloning, yadm will
|
||||||
|
create the directories with mask 0700 prior to merging the fetched data
|
||||||
|
into the work-tree.
|
||||||
|
|
||||||
|
When running a Git command and .ssh or .gnupg directories do not exist,
|
||||||
|
yadm will create those directories with mask 0700 prior to running the
|
||||||
|
Git command. This can be disabled using the yadm.auto-private-dirs
|
||||||
|
configuration.
|
||||||
|
|
||||||
## HOOKS
|
## HOOKS
|
||||||
For every command yadm supports, a program can be provided to run
|
For every command yadm supports, a program can be provided to run
|
||||||
|
13
yadm.spec
13
yadm.spec
@ -1,6 +1,6 @@
|
|||||||
Summary: Yet Another Dotfiles Manager
|
Summary: Yet Another Dotfiles Manager
|
||||||
Name: yadm
|
Name: yadm
|
||||||
Version: 1.11.0
|
Version: 1.12.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
URL: https://github.com/TheLocehiliosan/yadm
|
URL: https://github.com/TheLocehiliosan/yadm
|
||||||
License: GPLv3
|
License: GPLv3
|
||||||
@ -34,10 +34,17 @@ install -m 644 yadm.1 ${RPM_BUILD_ROOT}%{_mandir}/man1
|
|||||||
%attr(755,root,root) %{_bindir}/yadm
|
%attr(755,root,root) %{_bindir}/yadm
|
||||||
%attr(644,root,root) %{_mandir}/man1/*
|
%attr(644,root,root) %{_mandir}/man1/*
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
%doc CHANGES CONTRIBUTORS README.md completion/yadm.bash_completion
|
%doc CHANGES CONTRIBUTORS README.md completion/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon July 10 2017 Tim Byrne <sultan@locehilios.com> - 1.11.0-1
|
* Wed Oct 25 2017 Tim Byrne <sultan@locehilios.com> - 1.12.0-1
|
||||||
|
- Bump version to 1.12.0
|
||||||
|
- Include zsh completion
|
||||||
|
|
||||||
|
* Wed Aug 23 2017 Tim Byrne <sultan@locehilios.com> - 1.11.1-1
|
||||||
|
- Bump version to 1.11.1
|
||||||
|
|
||||||
|
* Mon Jul 10 2017 Tim Byrne <sultan@locehilios.com> - 1.11.0-1
|
||||||
- Bump version to 1.11.0
|
- Bump version to 1.11.0
|
||||||
|
|
||||||
* Wed May 10 2017 Tim Byrne <sultan@locehilios.com> - 1.10.0-1
|
* Wed May 10 2017 Tim Byrne <sultan@locehilios.com> - 1.10.0-1
|
||||||
|
Loading…
Reference in New Issue
Block a user