Coverage for repo_ctx / providers / base.py: 82%

38 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-25 17:42 +0100

1"""Abstract base class for repository providers.""" 

2from abc import ABC, abstractmethod 

3from dataclasses import dataclass 

4from typing import Optional, List 

5 

6 

7@dataclass 

8class ProviderProject: 

9 """Normalized project representation across providers.""" 

10 id: str 

11 name: str 

12 path: str 

13 description: Optional[str] 

14 default_branch: str 

15 web_url: Optional[str] 

16 

17 

18@dataclass 

19class ProviderFile: 

20 """Normalized file representation.""" 

21 path: str 

22 content: str 

23 size: int 

24 

25 

26class GitProvider(ABC): 

27 """Abstract base class for all repository providers.""" 

28 

29 @abstractmethod 

30 async def get_project(self, path: str) -> ProviderProject: 

31 """ 

32 Get project metadata. 

33 

34 Args: 

35 path: Provider-specific project identifier 

36 GitLab: "group/project" or "group/subgroup/project" 

37 GitHub: "owner/repo" 

38 Local: "/absolute/path" or "./relative/path" 

39 

40 Returns: 

41 ProviderProject with normalized metadata 

42 

43 Raises: 

44 ProviderNotFoundError: Project doesn't exist 

45 ProviderAuthError: Authentication failed 

46 """ 

47 pass 

48 

49 @abstractmethod 

50 async def get_default_branch(self, project: ProviderProject) -> str: 

51 """ 

52 Get default branch name (main, master, etc.). 

53 

54 Args: 

55 project: Project to query 

56 

57 Returns: 

58 Default branch name 

59 

60 Raises: 

61 ProviderError: Error getting branch information 

62 """ 

63 pass 

64 

65 @abstractmethod 

66 async def get_file_tree( 

67 self, 

68 project: ProviderProject, 

69 ref: str, 

70 recursive: bool = True 

71 ) -> List[str]: 

72 """ 

73 Get list of all file paths in repository. 

74 

75 Args: 

76 project: Project to query 

77 ref: Branch, tag, or commit SHA 

78 recursive: Include subdirectories 

79 

80 Returns: 

81 List of file paths relative to repo root 

82 

83 Raises: 

84 ProviderError: Error accessing file tree 

85 """ 

86 pass 

87 

88 @abstractmethod 

89 async def read_file( 

90 self, 

91 project: ProviderProject, 

92 path: str, 

93 ref: str 

94 ) -> ProviderFile: 

95 """ 

96 Read file contents. 

97 

98 Args: 

99 project: Project to query 

100 path: File path relative to repo root 

101 ref: Branch, tag, or commit SHA 

102 

103 Returns: 

104 ProviderFile with content and metadata 

105 

106 Raises: 

107 ProviderFileNotFoundError: File doesn't exist at ref 

108 """ 

109 pass 

110 

111 @abstractmethod 

112 async def read_config( 

113 self, 

114 project: ProviderProject, 

115 ref: str 

116 ) -> Optional[dict]: 

117 """ 

118 Read repo-ctx configuration file if it exists. 

119 

120 Searches for configuration files in this order: 

121 1. git_context.json (current name) 

122 2. .git_context.json 

123 3. repo_context.json 

124 4. .repo-ctx.json 

125 

126 Args: 

127 project: Project to query 

128 ref: Branch, tag, or commit SHA 

129 

130 Returns: 

131 Parsed JSON config or None if not found 

132 

133 Raises: 

134 ProviderError: Error reading configuration 

135 """ 

136 pass 

137 

138 @abstractmethod 

139 async def get_tags( 

140 self, 

141 project: ProviderProject, 

142 limit: int = 5 

143 ) -> List[str]: 

144 """ 

145 Get repository tags (most recent first). 

146 

147 Args: 

148 project: Project to query 

149 limit: Maximum number of tags to return 

150 

151 Returns: 

152 List of tag names 

153 

154 Raises: 

155 ProviderError: Error accessing tags 

156 """ 

157 pass 

158 

159 @abstractmethod 

160 async def list_projects_in_group( 

161 self, 

162 group_path: str, 

163 include_subgroups: bool = True 

164 ) -> List[ProviderProject]: 

165 """ 

166 List all projects in a group/organization. 

167 

168 Args: 

169 group_path: Group identifier 

170 GitLab: "group" or "group/subgroup" 

171 GitHub: "org" 

172 Local: Not supported 

173 

174 include_subgroups: Include nested groups (GitLab only) 

175 

176 Returns: 

177 List of projects in the group 

178 

179 Raises: 

180 ProviderNotFoundError: Group not found 

181 NotImplementedError: Provider doesn't support groups 

182 

183 Note: 

184 Not all providers support groups (e.g., local repos) 

185 """ 

186 pass