1
0
Fork 0
mirror of synced 2024-11-22 08:15:34 -05:00

Merge branch 'etkeys/feature/glob-with-exclude'

This commit is contained in:
Anish Athalye 2021-02-25 06:59:22 -05:00
commit 22ed23c7d9
3 changed files with 150 additions and 2 deletions

View file

@ -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) | | `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) |
Dotbot uses [glob.glob](https://docs.python.org/3/library/glob.html#glob.glob) 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 to resolve glob paths. However, due to its design, using a glob path such as
@ -227,6 +228,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:
@ -243,6 +250,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

View file

@ -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
@ -123,6 +124,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.

View 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
'