Coverage for gsb/onboard.py: 100%
26 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-08 20:16 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-08 20:16 +0000
1"""Functionality for onboarding a new save state"""
3from pathlib import Path
4from typing import Iterable
6from . import _git, backup
7from .manifest import MANIFEST_NAME, Manifest
9DEFAULT_IGNORE_LIST: tuple[str, ...] = ()
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
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.
35 Returns
36 -------
37 Manifest
38 The static configuration for that repo
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))
54 _git.init(repo_root)
56 _update_gitignore(repo_root, ignore or ())
58 # enforce round-trip
59 Manifest(repo_root, name or repo_root.resolve().name, tuple(patterns)).write()
60 manifest = Manifest.of(repo_root)
62 backup.create_backup(repo_root, "Start of gsb tracking")
64 return manifest
67def _update_gitignore(repo_root: Path, patterns: Iterable[str]) -> None:
68 """Create or append to the ".gitignore" file in the specified repo
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")