Coverage for src / dotbot / plugins / create.py: 88%
48 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-29 10:55 -0800
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-29 10:55 -0800
1import os
2from typing import Any
4from dotbot.plugin import Plugin
5from dotbot.util.common import normslash
8class Create(Plugin):
9 """
10 Create empty paths.
11 """
13 supports_dry_run = True
15 _directive = "create"
17 def can_handle(self, directive: str) -> bool:
18 return directive == self._directive
20 def handle(self, directive: str, data: Any) -> bool:
21 if directive != self._directive:
22 msg = f"Create cannot handle directive {directive}"
23 raise ValueError(msg)
24 return self._process_paths(data)
26 def _process_paths(self, paths: Any) -> bool:
27 success = True
28 defaults = self._context.defaults().get("create", {})
29 for key in paths:
30 path = os.path.abspath(os.path.expandvars(os.path.expanduser(normslash(key))))
31 mode = defaults.get("mode", 0o777) # same as the default for os.makedirs
32 if isinstance(paths, dict):
33 options = paths[key]
34 if options:
35 mode = options.get("mode", mode)
36 success &= self._create(path, mode)
37 if success:
38 self._log.info("All paths have been set up")
39 else:
40 self._log.error("Some paths were not successfully set up")
41 return success
43 def _exists(self, path: str) -> bool:
44 """
45 Returns true if the path exists.
46 """
47 path = os.path.expanduser(path)
48 return os.path.exists(path)
50 def _create(self, path: str, mode: int) -> bool:
51 success = True
52 if not self._exists(path):
53 self._log.debug(f"Trying to create path {path} with mode {mode}")
54 try:
55 if self._context.dry_run():
56 self._log.action(f"Would create path {path}")
57 return True
58 self._log.action(f"Creating path {path}")
59 os.makedirs(path, mode)
60 # On Windows, the *mode* argument to `os.makedirs()` is ignored.
61 # The mode must be set explicitly in a follow-up call.
62 os.chmod(path, mode)
63 except OSError:
64 self._log.warning(f"Failed to create path {path}")
65 success = False
66 else:
67 self._log.info(f"Path exists {path}")
68 return success