Coverage for gsb/onboard.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-08 20:16 +0000

1"""Functionality for onboarding a new save state""" 

2 

3from pathlib import Path 

4from typing import Iterable 

5 

6from . import _git, backup 

7from .manifest import MANIFEST_NAME, Manifest 

8 

9DEFAULT_IGNORE_LIST: tuple[str, ...] = () 

10 

11 

12def create_repo( 

13 repo_root: Path, 

14 *patterns: str, 

15 ignore: Iterable[str] | None = None, 

16 name: str | None = None, 

17) -> Manifest: 

18 """Create a new `gsb`-managed git repo in the specified location 

19 

20 Parameters 

21 ---------- 

22 repo_root : Path 

23 The directory where the repo should be created 

24 patterns : str 

25 List of glob-patterns to match, specifying what in the working directory 

26 should be archived. If none are provided, then it will be assumed that 

27 the intent is to back up the *entire* folder and all its contents. 

28 ignore : list of str, optional 

29 List of glob-patterns to *ignore*. If None are specified, then nothing 

30 will be ignored. 

31 name : str, optional 

32 An alias to assign to the repo. If None is provided, the `repo_root` 

33 folder's name will be used. 

34 

35 Returns 

36 ------- 

37 Manifest 

38 The static configuration for that repo 

39 

40 Raises 

41 ------ 

42 FileExistsError 

43 If there is already a `gsb` repo in that location 

44 OSError 

45 If `repo_root` does not exist, is not a directory or cannot be accessed 

46 """ 

47 if (repo_root / MANIFEST_NAME).exists(): 

48 raise FileExistsError(f"{repo_root} already contains a GSB-managed repo") 

49 if not patterns: 

50 patterns = (".",) 

51 if "." not in patterns: 

52 patterns = tuple(set(patterns)) 

53 

54 _git.init(repo_root) 

55 

56 _update_gitignore(repo_root, ignore or ()) 

57 

58 # enforce round-trip 

59 Manifest(repo_root, name or repo_root.resolve().name, tuple(patterns)).write() 

60 manifest = Manifest.of(repo_root) 

61 

62 backup.create_backup(repo_root, "Start of gsb tracking") 

63 

64 return manifest 

65 

66 

67def _update_gitignore(repo_root: Path, patterns: Iterable[str]) -> None: 

68 """Create or append to the ".gitignore" file in the specified repo 

69 

70 Parameters 

71 ---------- 

72 repo_root : Path 

73 The directory where the repo should be created 

74 patterns 

75 List of glob-patterns to ignore 

76 """ 

77 with open(repo_root / ".gitignore", "a+", encoding="UTF-8") as gitignore: 

78 gitignore.seek(0) 

79 existing_lines: list[str] = [line.strip() for line in gitignore.readlines()] 

80 if existing_lines and "# gsb" not in existing_lines: 

81 gitignore.write("\n# gsb\n") 

82 new_lines: list[str] = sorted( 

83 [ 

84 pattern 

85 for pattern in {*DEFAULT_IGNORE_LIST, *patterns} 

86 if pattern not in existing_lines 

87 ] 

88 ) 

89 gitignore.write("\n".join(new_lines) + "\n")