Coverage for gsb/onboard.py: 100%
26 statements
« prev ^ index » next coverage.py v7.2.6, created at 2024-09-08 16:23 -0400
« 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
5from . import _git, backup
6from .manifest import MANIFEST_NAME, Manifest
8DEFAULT_IGNORE_LIST: tuple[str, ...] = ()
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
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.
34 Returns
35 -------
36 Manifest
37 The static configuration for that repo
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))
53 _git.init(repo_root)
55 _update_gitignore(repo_root, ignore or ())
57 # enforce round-trip
58 Manifest(repo_root, name or repo_root.resolve().name, tuple(patterns)).write()
59 manifest = Manifest.of(repo_root)
61 backup.create_backup(repo_root, "Start of gsb tracking")
63 return manifest
66def _update_gitignore(repo_root: Path, patterns: Iterable[str]) -> None:
67 """Create or append to the ".gitignore" file in the specified repo
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")