Coverage for gsb/rewind.py: 100%

20 statements  

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

1"""Functionality for restoring to an old backup""" 

2 

3import logging 

4from pathlib import Path 

5 

6from . import _git, backup 

7from .logging import IMPORTANT 

8 

9LOGGER = logging.getLogger(__name__) 

10 

11 

12def generate_restore_tag_name(revision: str) -> str: 

13 """Generate a new calver-ish tag name 

14 

15 Parameters 

16 ---------- 

17 revision : str 

18 The commit hash or tag name of the backup to restore 

19 

20 Returns 

21 ------- 

22 str 

23 A tag name that indicates both the time a backup was restored and the 

24 identifier of the original revision 

25 """ 

26 return f"{backup.generate_tag_name()}.restore_of_{revision}" 

27 

28 

29def restore_backup(repo_root: Path, revision: str, keep_gsb_files: bool = True) -> str: 

30 """Rewind to a previous backup state and create a new backup 

31 

32 Parameters 

33 ---------- 

34 repo_root : Path 

35 The directory containing the GSB-managed repo 

36 revision : str 

37 The commit hash or tag name of the backup to restore 

38 keep_gsb_files : bool, optional 

39 By default, `.gsb_manifest` and `.gitignore` *will not* be restored 

40 (that is, the latest versions will be kept). To override this behavior, 

41 pass in `keep_gsb_files = False`. 

42 

43 Returns 

44 ------- 

45 str 

46 The tag name of the new restored backup 

47 

48 Notes 

49 ----- 

50 Before creating the backup, any un-backed up changes will first be backed up 

51 

52 Raises 

53 ------ 

54 OSError 

55 If the specified repo does not exist or is not a GSB-managed repo 

56 ValueError 

57 If the specified revision does not exist 

58 """ 

59 _git.show(repo_root, revision) 

60 

61 LOGGER.log( 

62 IMPORTANT, "Backing up any unsaved changes before rewinding to %s", revision 

63 ) 

64 try: 

65 orig_head = backup.create_backup( 

66 repo_root, f"Backing up state before rewinding to {revision}" 

67 ) 

68 except ValueError as already_backed_up: 

69 LOGGER.warning("Nothing to back up: %s", already_backed_up) 

70 orig_head = _git.show(repo_root, "HEAD").hash # type: ignore[union-attr] 

71 

72 _git.reset(repo_root, revision, hard=True) 

73 _git.reset(repo_root, orig_head, hard=False) 

74 if keep_gsb_files: 

75 _git.checkout_files(repo_root, orig_head, backup.REQUIRED_FILES) 

76 return backup.create_backup( 

77 repo_root, 

78 f"Restored to {revision}", 

79 tag_name=generate_restore_tag_name(revision), 

80 )