Coverage for gsb/onboard.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v7.2.6, created at 2024-09-08 16:23 -0400

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

2from pathlib import Path 

3from typing import Iterable 

4 

5from . import _git, backup 

6from .manifest import MANIFEST_NAME, Manifest 

7 

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

9 

10 

11def create_repo( 

12 repo_root: Path, 

13 *patterns: str, 

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

15 name: str | None = None, 

16) -> Manifest: 

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

18 

19 Parameters 

20 ---------- 

21 repo_root : Path 

22 The directory where the repo should be created 

23 patterns : str 

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

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

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

27 ignore : list of str, optional 

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

29 will be ignored. 

30 name : str, optional 

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

32 folder's name will be used. 

33 

34 Returns 

35 ------- 

36 Manifest 

37 The static configuration for that repo 

38 

39 Raises 

40 ------ 

41 FileExistsError 

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

43 OSError 

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

45 """ 

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

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

48 if not patterns: 

49 patterns = (".",) 

50 if "." not in patterns: 

51 patterns = tuple(set(patterns)) 

52 

53 _git.init(repo_root) 

54 

55 _update_gitignore(repo_root, ignore or ()) 

56 

57 # enforce round-trip 

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

59 manifest = Manifest.of(repo_root) 

60 

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

62 

63 return manifest 

64 

65 

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

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

68 

69 Parameters 

70 ---------- 

71 repo_root : Path 

72 The directory where the repo should be created 

73 patterns 

74 List of glob-patterns to ignore 

75 """ 

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

77 gitignore.seek(0) 

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

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

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

81 new_lines: list[str] = sorted( 

82 [ 

83 pattern 

84 for pattern in {*DEFAULT_IGNORE_LIST, *patterns} 

85 if pattern not in existing_lines 

86 ] 

87 ) 

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