Add the possibility of specifying more than one source path, in which case the destination is assumed to be a folder in which source paths are linked
This commit is contained in:
parent
769767c129
commit
d152fd6cd3
1 changed files with 92 additions and 74 deletions
|
@ -52,87 +52,103 @@ class Link(dotbot.Plugin):
|
||||||
base_prefix = source.get("prefix", base_prefix)
|
base_prefix = source.get("prefix", base_prefix)
|
||||||
ignore_missing = source.get("ignore-missing", ignore_missing)
|
ignore_missing = source.get("ignore-missing", ignore_missing)
|
||||||
exclude_paths = source.get("exclude", exclude_paths)
|
exclude_paths = source.get("exclude", exclude_paths)
|
||||||
path = self._default_source(destination, source.get("path"))
|
paths = self._default_sources(destination, source.get("path"))
|
||||||
else:
|
else:
|
||||||
path = self._default_source(destination, source)
|
paths = self._default_sources(destination, source)
|
||||||
if test is not None and not self._test_success(test):
|
if test is not None and not self._test_success(test):
|
||||||
self._log.lowinfo("Skipping %s" % destination)
|
self._log.lowinfo("Skipping %s" % destination)
|
||||||
continue
|
continue
|
||||||
path = os.path.expandvars(os.path.expanduser(path))
|
for path in paths:
|
||||||
if use_glob:
|
if len(paths) > 1:
|
||||||
glob_results = self._create_glob_results(path, exclude_paths)
|
self._log.lowinfo("Multiple paths given, processing path " + path)
|
||||||
if len(glob_results) == 0:
|
path = os.path.expandvars(os.path.expanduser(path))
|
||||||
self._log.warning("Globbing couldn't find anything matching " + str(path))
|
if use_glob:
|
||||||
success = False
|
glob_results = self._create_glob_results(path, exclude_paths)
|
||||||
continue
|
if len(glob_results) == 0:
|
||||||
if len(glob_results) == 1 and destination[-1] == "/":
|
self._log.warning("Globbing couldn't find anything matching " + str(path))
|
||||||
self._log.error("Ambiguous action requested.")
|
success = False
|
||||||
self._log.error(
|
continue
|
||||||
"No wildcard in glob, directory use undefined: "
|
if len(glob_results) == 1 and destination[-1] == "/" and len(paths) == 1:
|
||||||
+ destination
|
# Note: if there is more than one path, we can assume that the user meant to link *into* the directory - the opposite wouldn't make sense
|
||||||
+ " -> "
|
self._log.error("Ambiguous action requested.")
|
||||||
+ str(glob_results)
|
self._log.error(
|
||||||
)
|
"No wildcard in glob, directory use undefined: "
|
||||||
self._log.warning("Did you want to link the directory or into it?")
|
+ destination
|
||||||
success = False
|
+ " -> "
|
||||||
continue
|
+ str(glob_results)
|
||||||
elif len(glob_results) == 1 and destination[-1] != "/":
|
)
|
||||||
# perform a normal link operation
|
self._log.warning("Did you want to link the directory or into it?")
|
||||||
|
success = False
|
||||||
|
break
|
||||||
|
elif len(glob_results) == 1 and destination[-1] != "/" and len(paths) == 1:
|
||||||
|
# perform a normal link operation.
|
||||||
|
# again, if more than one path is given, want to link into the directory
|
||||||
|
if create:
|
||||||
|
success &= self._create(destination)
|
||||||
|
if force or relink:
|
||||||
|
success &= self._delete(
|
||||||
|
path, destination, relative, canonical_path, force
|
||||||
|
)
|
||||||
|
success &= self._link(
|
||||||
|
path, destination, relative, canonical_path, ignore_missing
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._log.lowinfo("Globs from '" + path + "': " + str(glob_results))
|
||||||
|
for glob_full_item in glob_results:
|
||||||
|
# Find common dirname between pattern and the item:
|
||||||
|
glob_dirname = os.path.dirname(
|
||||||
|
os.path.commonprefix([path, glob_full_item])
|
||||||
|
)
|
||||||
|
glob_item = (
|
||||||
|
glob_full_item
|
||||||
|
if len(glob_dirname) == 0
|
||||||
|
else glob_full_item[len(glob_dirname) + 1 :]
|
||||||
|
)
|
||||||
|
# Add prefix to basepath, if provided
|
||||||
|
if base_prefix:
|
||||||
|
glob_item = base_prefix + glob_item
|
||||||
|
# Where is it going
|
||||||
|
glob_link_destination = os.path.join(destination, glob_item)
|
||||||
|
if create:
|
||||||
|
success &= self._create(glob_link_destination)
|
||||||
|
if force or relink:
|
||||||
|
success &= self._delete(
|
||||||
|
glob_full_item,
|
||||||
|
glob_link_destination,
|
||||||
|
relative,
|
||||||
|
canonical_path,
|
||||||
|
force,
|
||||||
|
)
|
||||||
|
success &= self._link(
|
||||||
|
glob_full_item,
|
||||||
|
glob_link_destination,
|
||||||
|
relative,
|
||||||
|
canonical_path,
|
||||||
|
ignore_missing,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if len(paths) > 1:
|
||||||
|
# Multiple paths were given, so the destination is a directory into which the files need to be linked.
|
||||||
|
destination = os.path.join(destination, os.path.basename(path))
|
||||||
|
# Only one path was given, so the destination is a file
|
||||||
if create:
|
if create:
|
||||||
success &= self._create(destination)
|
success &= self._create(destination)
|
||||||
|
if not ignore_missing and not self._exists(
|
||||||
|
os.path.join(self._context.base_directory(), path)
|
||||||
|
):
|
||||||
|
# we seemingly check this twice (here and in _link) because
|
||||||
|
# if the file doesn't exist and force is True, we don't
|
||||||
|
# want to remove the original (this is tested by
|
||||||
|
# link-force-leaves-when-nonexistent.bash)
|
||||||
|
success = False
|
||||||
|
self._log.warning("Nonexistent source %s -> %s" % (destination, path))
|
||||||
|
break
|
||||||
if force or relink:
|
if force or relink:
|
||||||
success &= self._delete(path, destination, relative, canonical_path, force)
|
success &= self._delete(path, destination, relative, canonical_path, force)
|
||||||
success &= self._link(
|
success &= self._link(
|
||||||
path, destination, relative, canonical_path, ignore_missing
|
path, destination, relative, canonical_path, ignore_missing
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
self._log.lowinfo("Globs from '" + path + "': " + str(glob_results))
|
|
||||||
for glob_full_item in glob_results:
|
|
||||||
# Find common dirname between pattern and the item:
|
|
||||||
glob_dirname = os.path.dirname(os.path.commonprefix([path, glob_full_item]))
|
|
||||||
glob_item = (
|
|
||||||
glob_full_item
|
|
||||||
if len(glob_dirname) == 0
|
|
||||||
else glob_full_item[len(glob_dirname) + 1 :]
|
|
||||||
)
|
|
||||||
# Add prefix to basepath, if provided
|
|
||||||
if base_prefix:
|
|
||||||
glob_item = base_prefix + glob_item
|
|
||||||
# where is it going
|
|
||||||
glob_link_destination = os.path.join(destination, glob_item)
|
|
||||||
if create:
|
|
||||||
success &= self._create(glob_link_destination)
|
|
||||||
if force or relink:
|
|
||||||
success &= self._delete(
|
|
||||||
glob_full_item,
|
|
||||||
glob_link_destination,
|
|
||||||
relative,
|
|
||||||
canonical_path,
|
|
||||||
force,
|
|
||||||
)
|
|
||||||
success &= self._link(
|
|
||||||
glob_full_item,
|
|
||||||
glob_link_destination,
|
|
||||||
relative,
|
|
||||||
canonical_path,
|
|
||||||
ignore_missing,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if create:
|
|
||||||
success &= self._create(destination)
|
|
||||||
if not ignore_missing and not self._exists(
|
|
||||||
os.path.join(self._context.base_directory(), path)
|
|
||||||
):
|
|
||||||
# we seemingly check this twice (here and in _link) because
|
|
||||||
# if the file doesn't exist and force is True, we don't
|
|
||||||
# want to remove the original (this is tested by
|
|
||||||
# link-force-leaves-when-nonexistent.bash)
|
|
||||||
success = False
|
|
||||||
self._log.warning("Nonexistent source %s -> %s" % (destination, path))
|
|
||||||
continue
|
|
||||||
if force or relink:
|
|
||||||
success &= self._delete(path, destination, relative, canonical_path, force)
|
|
||||||
success &= self._link(path, destination, relative, canonical_path, ignore_missing)
|
|
||||||
if success:
|
if success:
|
||||||
self._log.info("All links have been set up")
|
self._log.info("All links have been set up")
|
||||||
else:
|
else:
|
||||||
|
@ -145,15 +161,17 @@ class Link(dotbot.Plugin):
|
||||||
self._log.debug("Test '%s' returned false" % command)
|
self._log.debug("Test '%s' returned false" % command)
|
||||||
return ret == 0
|
return ret == 0
|
||||||
|
|
||||||
def _default_source(self, destination, source):
|
def _default_sources(self, destination, source):
|
||||||
if source is None:
|
if source is None:
|
||||||
basename = os.path.basename(destination)
|
basename = os.path.basename(destination)
|
||||||
if basename.startswith("."):
|
if basename.startswith("."):
|
||||||
return basename[1:]
|
return [basename[1:]]
|
||||||
else:
|
else:
|
||||||
return basename
|
return [basename]
|
||||||
else:
|
elif isinstance(source, list):
|
||||||
return source
|
return source
|
||||||
|
else:
|
||||||
|
return [source]
|
||||||
|
|
||||||
def _glob(self, path):
|
def _glob(self, path):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue