Add exclude parameter for link globbing
- Added `exclude` parameter to _link_. Now, an array of glob patterns can be given that will be used to remove items from a glob match. This parameter will only have an effect when `glob` is `true`. - Updated README to add description for `exclude` and add in examples. Resolves #247
This commit is contained in:
parent
5294594f5a
commit
2ec7a24129
3 changed files with 150 additions and 2 deletions
13
README.md
13
README.md
|
@ -178,6 +178,7 @@ mapped to extended configuration dictionaries.
|
||||||
| `glob` | Treat a `*` character as a wildcard, and perform link operations on all of those matches (default: false) |
|
| `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. |
|
| `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) |
|
| `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) |
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
|
@ -218,6 +219,12 @@ Explicit sources:
|
||||||
glob: true
|
glob: true
|
||||||
path: config/*
|
path: config/*
|
||||||
relink: true
|
relink: true
|
||||||
|
exclude: [ config/Code ]
|
||||||
|
~/.config/Code/User/:
|
||||||
|
create: true
|
||||||
|
glob: true
|
||||||
|
path: config/Code/User/*
|
||||||
|
relink: true
|
||||||
```
|
```
|
||||||
|
|
||||||
Implicit sources:
|
Implicit sources:
|
||||||
|
@ -234,6 +241,12 @@ Implicit sources:
|
||||||
glob: true
|
glob: true
|
||||||
path: config/*
|
path: config/*
|
||||||
relink: true
|
relink: true
|
||||||
|
exclude: [ config/Code ]
|
||||||
|
~/.config/Code/User/:
|
||||||
|
create: true
|
||||||
|
glob: true
|
||||||
|
path: config/Code/User/*
|
||||||
|
relink: true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create
|
### Create
|
||||||
|
|
|
@ -34,6 +34,7 @@ class Link(dotbot.Plugin):
|
||||||
use_glob = defaults.get('glob', False)
|
use_glob = defaults.get('glob', False)
|
||||||
test = defaults.get('if', None)
|
test = defaults.get('if', None)
|
||||||
ignore_missing = defaults.get('ignore-missing', False)
|
ignore_missing = defaults.get('ignore-missing', False)
|
||||||
|
exclude_paths = defaults.get('exclude', [])
|
||||||
if isinstance(source, dict):
|
if isinstance(source, dict):
|
||||||
# extended config
|
# extended config
|
||||||
test = source.get('if', test)
|
test = source.get('if', test)
|
||||||
|
@ -44,6 +45,7 @@ class Link(dotbot.Plugin):
|
||||||
create = source.get('create', create)
|
create = source.get('create', create)
|
||||||
use_glob = source.get('glob', use_glob)
|
use_glob = source.get('glob', use_glob)
|
||||||
ignore_missing = source.get('ignore-missing', ignore_missing)
|
ignore_missing = source.get('ignore-missing', ignore_missing)
|
||||||
|
exclude_paths = source.get('exclude', exclude_paths)
|
||||||
path = self._default_source(destination, source.get('path'))
|
path = self._default_source(destination, source.get('path'))
|
||||||
else:
|
else:
|
||||||
path = self._default_source(destination, source)
|
path = self._default_source(destination, source)
|
||||||
|
@ -52,8 +54,7 @@ class Link(dotbot.Plugin):
|
||||||
continue
|
continue
|
||||||
path = os.path.expandvars(os.path.expanduser(path))
|
path = os.path.expandvars(os.path.expanduser(path))
|
||||||
if use_glob:
|
if use_glob:
|
||||||
self._log.debug("Globbing with path: " + str(path))
|
glob_results = self._create_glob_results(path, exclude_paths)
|
||||||
glob_results = glob.glob(path)
|
|
||||||
if len(glob_results) == 0:
|
if len(glob_results) == 0:
|
||||||
self._log.warning("Globbing couldn't find anything matching " + str(path))
|
self._log.warning("Globbing couldn't find anything matching " + str(path))
|
||||||
success = False
|
success = False
|
||||||
|
@ -121,6 +122,17 @@ class Link(dotbot.Plugin):
|
||||||
else:
|
else:
|
||||||
return source
|
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):
|
def _is_link(self, path):
|
||||||
'''
|
'''
|
||||||
Returns true if the path is a symbolic link.
|
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