Coverage for gsb/rewind.py: 100%

20 statements  

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

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

2import logging 

3from pathlib import Path 

4 

5from . import _git, backup 

6from .logging import IMPORTANT 

7 

8LOGGER = logging.getLogger(__name__) 

9 

10 

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

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

13 

14 Parameters 

15 ---------- 

16 revision : str 

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

18 

19 Returns 

20 ------- 

21 str 

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

23 identifier of the original revision 

24 """ 

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

26 

27 

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

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

30 

31 Parameters 

32 ---------- 

33 repo_root : Path 

34 The directory containing the GSB-managed repo 

35 revision : str 

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

37 keep_gsb_files : bool, optional 

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

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

40 pass in `keep_gsb_files = False`. 

41 

42 Returns 

43 ------- 

44 str 

45 The tag name of the new restored backup 

46 

47 Notes 

48 ----- 

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

50 

51 Raises 

52 ------ 

53 OSError 

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

55 ValueError 

56 If the specified revision does not exist 

57 """ 

58 _git.show(repo_root, revision) 

59 

60 LOGGER.log( 

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

62 ) 

63 try: 

64 orig_head = backup.create_backup( 

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

66 ) 

67 except ValueError as already_backed_up: 

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

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

70 

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

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

73 if keep_gsb_files: 

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

75 return backup.create_backup( 

76 repo_root, 

77 f"Restored to {revision}", 

78 tag_name=generate_restore_tag_name(revision), 

79 )