Merge branch 'etkeys/feature/glob-with-exclude'
This commit is contained in:
commit
22ed23c7d9
3 changed files with 150 additions and 2 deletions
13
README.md
13
README.md
|
@ -181,6 +181,7 @@ mapped to extended configuration dictionaries.
|
|||
| `glob` | Treat a `*` character as a wildcard, and perform link operations on all of those matches (default: false) |
|
||||
| `if` | Execute this in your `$SHELL` and only link if it is successful. |
|
||||
| `ignore-missing` | Do not fail if the source is missing and create the link anyway (default: false) |
|
||||
| `exclude` | Array of paths to remove from glob matches. Uses same syntax as `path`. Ignored if `glob` is `false`. (default: empty, keep all matches) |
|
||||
|
||||
Dotbot uses [glob.glob](https://docs.python.org/3/library/glob.html#glob.glob)
|
||||
to resolve glob paths. However, due to its design, using a glob path such as
|
||||
|
@ -227,6 +228,12 @@ Explicit sources:
|
|||
glob: true
|
||||
path: config/*
|
||||
relink: true
|
||||
exclude: [ config/Code ]
|
||||
~/.config/Code/User/:
|
||||
create: true
|
||||
glob: true
|
||||
path: config/Code/User/*
|
||||
relink: true
|
||||
```
|
||||
|
||||
Implicit sources:
|
||||
|
@ -243,6 +250,12 @@ Implicit sources:
|
|||
glob: true
|
||||
path: config/*
|
||||
relink: true
|
||||
exclude: [ config/Code ]
|
||||
~/.config/Code/User/:
|
||||
create: true
|
||||
glob: true
|
||||
path: config/Code/User/*
|
||||
relink: true
|
||||
```
|
||||
|
||||
### Create
|
||||
|
|
|
@ -34,6 +34,7 @@ class Link(dotbot.Plugin):
|
|||
use_glob = defaults.get('glob', False)
|
||||
test = defaults.get('if', None)
|
||||
ignore_missing = defaults.get('ignore-missing', False)
|
||||
exclude_paths = defaults.get('exclude', [])
|
||||
if isinstance(source, dict):
|
||||
# extended config
|
||||
test = source.get('if', test)
|
||||
|
@ -44,6 +45,7 @@ class Link(dotbot.Plugin):
|
|||
create = source.get('create', create)
|
||||
use_glob = source.get('glob', use_glob)
|
||||
ignore_missing = source.get('ignore-missing', ignore_missing)
|
||||
exclude_paths = source.get('exclude', exclude_paths)
|
||||
path = self._default_source(destination, source.get('path'))
|
||||
else:
|
||||
path = self._default_source(destination, source)
|
||||
|
@ -52,8 +54,7 @@ class Link(dotbot.Plugin):
|
|||
continue
|
||||
path = os.path.expandvars(os.path.expanduser(path))
|
||||
if use_glob:
|
||||
self._log.debug("Globbing with path: " + str(path))
|
||||
glob_results = glob.glob(path)
|
||||
glob_results = self._create_glob_results(path, exclude_paths)
|
||||
if len(glob_results) == 0:
|
||||
self._log.warning("Globbing couldn't find anything matching " + str(path))
|
||||
success = False
|
||||
|
@ -123,6 +124,17 @@ class Link(dotbot.Plugin):
|
|||
else:
|
||||
return source
|
||||
|
||||
def _create_glob_results(self, path, exclude_paths):
|
||||
self._log.debug("Globbing with path: " + str(path))
|
||||
base_include = glob.glob(path)
|
||||
to_exclude = []
|
||||
for expath in exclude_paths:
|
||||
self._log.debug("Excluding globs with path: " + str(expath))
|
||||
to_exclude.extend(glob.glob(expath))
|
||||
self._log.debug("Excluded globs from '" + path + "': " + str(to_exclude))
|
||||
ret = set(base_include) - set(to_exclude)
|
||||
return list(ret)
|
||||
|
||||
def _is_link(self, path):
|
||||
'''
|
||||
Returns true if the path is a symbolic link.
|
||||
|
|
123
test/tests/link-glob-exclude.bash
Normal file
123
test/tests/link-glob-exclude.bash
Normal file
|
@ -0,0 +1,123 @@
|
|||
test_description='link glob exclude'
|
||||
. '../test-lib.bash'
|
||||
|
||||
test_expect_success 'setup 1' '
|
||||
mkdir -p ${DOTFILES}/config/{foo,bar,baz} &&
|
||||
echo "apple" > ${DOTFILES}/config/foo/a &&
|
||||
echo "banana" > ${DOTFILES}/config/bar/b &&
|
||||
echo "cherry" > ${DOTFILES}/config/bar/c &&
|
||||
echo "donut" > ${DOTFILES}/config/baz/d
|
||||
'
|
||||
|
||||
test_expect_success 'run 1' '
|
||||
run_dotbot -v <<EOF
|
||||
- defaults:
|
||||
link:
|
||||
glob: true
|
||||
create: true
|
||||
- link:
|
||||
~/.config/:
|
||||
path: config/*
|
||||
exclude: [config/baz]
|
||||
EOF
|
||||
'
|
||||
|
||||
test_expect_success 'test 1' '
|
||||
! readlink ~/.config/ &&
|
||||
readlink ~/.config/foo &&
|
||||
! readlink ~/.config/baz &&
|
||||
grep "apple" ~/.config/foo/a &&
|
||||
grep "banana" ~/.config/bar/b &&
|
||||
grep "cherry" ~/.config/bar/c
|
||||
'
|
||||
|
||||
test_expect_success 'setup 2' '
|
||||
rm -rf ~/.config &&
|
||||
mkdir ${DOTFILES}/config/baz/buzz &&
|
||||
echo "egg" > ${DOTFILES}/config/baz/buzz/e
|
||||
'
|
||||
|
||||
test_expect_success 'run 2' '
|
||||
run_dotbot -v <<EOF
|
||||
- defaults:
|
||||
link:
|
||||
glob: true
|
||||
create: true
|
||||
- link:
|
||||
~/.config/:
|
||||
path: config/*/*
|
||||
exclude: [config/baz/*]
|
||||
EOF
|
||||
'
|
||||
|
||||
test_expect_success 'test 2' '
|
||||
! readlink ~/.config/ &&
|
||||
! readlink ~/.config/foo &&
|
||||
[ ! -d ~/.config/baz ] &&
|
||||
readlink ~/.config/foo/a &&
|
||||
grep "apple" ~/.config/foo/a &&
|
||||
grep "banana" ~/.config/bar/b &&
|
||||
grep "cherry" ~/.config/bar/c
|
||||
'
|
||||
|
||||
test_expect_success 'setup 3' '
|
||||
rm -rf ~/.config &&
|
||||
mkdir ${DOTFILES}/config/baz/bizz &&
|
||||
echo "grape" > ${DOTFILES}/config/baz/bizz/g
|
||||
'
|
||||
|
||||
test_expect_success 'run 3' '
|
||||
run_dotbot -v <<EOF
|
||||
- defaults:
|
||||
link:
|
||||
glob: true
|
||||
create: true
|
||||
- link:
|
||||
~/.config/:
|
||||
path: config/*/*
|
||||
exclude: [config/baz/buzz]
|
||||
EOF
|
||||
'
|
||||
|
||||
test_expect_success 'test 3' '
|
||||
! readlink ~/.config/ &&
|
||||
! readlink ~/.config/foo &&
|
||||
readlink ~/.config/foo/a &&
|
||||
! readlink ~/.config/baz/buzz &&
|
||||
readlink ~/.config/baz/bizz &&
|
||||
grep "apple" ~/.config/foo/a &&
|
||||
grep "banana" ~/.config/bar/b &&
|
||||
grep "cherry" ~/.config/bar/c &&
|
||||
grep "donut" ~/.config/baz/d &&
|
||||
grep "grape" ~/.config/baz/bizz/g
|
||||
'
|
||||
|
||||
test_expect_success 'setup 4' '
|
||||
rm -rf ~/.config &&
|
||||
mkdir ${DOTFILES}/config/fiz &&
|
||||
echo "fig" > ${DOTFILES}/config/fiz/f
|
||||
'
|
||||
|
||||
test_expect_success 'run 4' '
|
||||
run_dotbot -v <<EOF
|
||||
- defaults:
|
||||
link:
|
||||
glob: true
|
||||
create: true
|
||||
- link:
|
||||
~/.config/:
|
||||
path: config/*/*
|
||||
exclude: [config/baz/*, config/fiz/*]
|
||||
EOF
|
||||
'
|
||||
|
||||
test_expect_success 'test 4' '
|
||||
! readlink ~/.config/ &&
|
||||
! readlink ~/.config/foo &&
|
||||
[ ! -d ~/.config/baz ] &&
|
||||
[ ! -d ~/.config/fiz ] &&
|
||||
readlink ~/.config/foo/a &&
|
||||
grep "apple" ~/.config/foo/a &&
|
||||
grep "banana" ~/.config/bar/b &&
|
||||
grep "cherry" ~/.config/bar/c
|
||||
'
|
Loading…
Reference in a new issue