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

1import os 

2from typing import Any 

3 

4from dotbot.plugin import Plugin 

5from dotbot.util.common import normslash 

6 

7 

8class Create(Plugin): 

9 """ 

10 Create empty paths. 

11 """ 

12 

13 supports_dry_run = True 

14 

15 _directive = "create" 

16 

17 def can_handle(self, directive: str) -> bool: 

18 return directive == self._directive 

19 

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) 

25 

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 

42 

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) 

49 

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