Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/git/index/util.py: 50%

50 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1"""Module containing index utilities""" 

2from functools import wraps 

3import os 

4import struct 

5import tempfile 

6 

7from git.compat import is_win 

8 

9import os.path as osp 

10 

11 

12# typing ---------------------------------------------------------------------- 

13 

14from typing import Any, Callable, TYPE_CHECKING 

15 

16from git.types import PathLike, _T 

17 

18if TYPE_CHECKING: 18 ↛ 19line 18 didn't jump to line 19, because the condition on line 18 was never true

19 from git.index import IndexFile 

20 

21# --------------------------------------------------------------------------------- 

22 

23 

24__all__ = ("TemporaryFileSwap", "post_clear_cache", "default_index", "git_working_dir") 

25 

26# { Aliases 

27pack = struct.pack 

28unpack = struct.unpack 

29 

30 

31# } END aliases 

32 

33 

34class TemporaryFileSwap(object): 

35 

36 """Utility class moving a file to a temporary location within the same directory 

37 and moving it back on to where on object deletion.""" 

38 

39 __slots__ = ("file_path", "tmp_file_path") 

40 

41 def __init__(self, file_path: PathLike) -> None: 

42 self.file_path = file_path 

43 self.tmp_file_path = str(self.file_path) + tempfile.mktemp("", "", "") 

44 # it may be that the source does not exist 

45 try: 

46 os.rename(self.file_path, self.tmp_file_path) 

47 except OSError: 

48 pass 

49 

50 def __del__(self) -> None: 

51 if osp.isfile(self.tmp_file_path): 

52 if is_win and osp.exists(self.file_path): 

53 os.remove(self.file_path) 

54 os.rename(self.tmp_file_path, self.file_path) 

55 # END temp file exists 

56 

57 

58# { Decorators 

59 

60 

61def post_clear_cache(func: Callable[..., _T]) -> Callable[..., _T]: 

62 """Decorator for functions that alter the index using the git command. This would 

63 invalidate our possibly existing entries dictionary which is why it must be 

64 deleted to allow it to be lazily reread later. 

65 

66 :note: 

67 This decorator will not be required once all functions are implemented 

68 natively which in fact is possible, but probably not feasible performance wise. 

69 """ 

70 

71 @wraps(func) 

72 def post_clear_cache_if_not_raised(self: "IndexFile", *args: Any, **kwargs: Any) -> _T: 

73 rval = func(self, *args, **kwargs) 

74 self._delete_entries_cache() 

75 return rval 

76 

77 # END wrapper method 

78 

79 return post_clear_cache_if_not_raised 

80 

81 

82def default_index(func: Callable[..., _T]) -> Callable[..., _T]: 

83 """Decorator assuring the wrapped method may only run if we are the default 

84 repository index. This is as we rely on git commands that operate 

85 on that index only.""" 

86 

87 @wraps(func) 

88 def check_default_index(self: "IndexFile", *args: Any, **kwargs: Any) -> _T: 

89 if self._file_path != self._index_path(): 

90 raise AssertionError( 

91 "Cannot call %r on indices that do not represent the default git index" % func.__name__ 

92 ) 

93 return func(self, *args, **kwargs) 

94 

95 # END wrapper method 

96 

97 return check_default_index 

98 

99 

100def git_working_dir(func: Callable[..., _T]) -> Callable[..., _T]: 

101 """Decorator which changes the current working dir to the one of the git 

102 repository in order to assure relative paths are handled correctly""" 

103 

104 @wraps(func) 

105 def set_git_working_dir(self: "IndexFile", *args: Any, **kwargs: Any) -> _T: 

106 cur_wd = os.getcwd() 

107 os.chdir(str(self.repo.working_tree_dir)) 

108 try: 

109 return func(self, *args, **kwargs) 

110 finally: 

111 os.chdir(cur_wd) 

112 # END handle working dir 

113 

114 # END wrapper 

115 

116 return set_git_working_dir 

117 

118 

119# } END decorators