Skip to content

Commit c92d09d

Browse files
authored
Merge pull request #63 from jaysomani/feat/gitea-content-endpoints
feat: Add Gitea repository content endpoints (tree, content, languages)
2 parents 0580493 + d4032cc commit c92d09d

File tree

4 files changed

+385
-9
lines changed

4 files changed

+385
-9
lines changed

src/VCS/Adapter/Git.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,27 @@ public function getType(): string
3434
{
3535
return self::TYPE_GIT;
3636
}
37+
38+
/**
39+
* Create a file in a repository
40+
*
41+
* @param string $owner Owner of the repository
42+
* @param string $repositoryName Name of the repository
43+
* @param string $filepath Path where file should be created
44+
* @param string $content Content of the file
45+
* @param string $message Commit message
46+
* @return array<mixed> Response from API
47+
*/
48+
abstract public function createFile(string $owner, string $repositoryName, string $filepath, string $content, string $message = 'Add file'): array;
49+
50+
/**
51+
* Create a branch in a repository
52+
*
53+
* @param string $owner Owner of the repository
54+
* @param string $repositoryName Name of the repository
55+
* @param string $newBranchName Name of the new branch
56+
* @param string $oldBranchName Name of the branch to branch from
57+
* @return array<mixed> Response from API
58+
*/
59+
abstract public function createBranch(string $owner, string $repositoryName, string $newBranchName, string $oldBranchName): array;
3760
}

src/VCS/Adapter/Git/GitHub.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ public function createRepository(string $owner, string $repositoryName, bool $pr
9494
return $response['body'] ?? [];
9595
}
9696

97+
/**
98+
* Create a file in a repository
99+
*
100+
* @param string $owner Owner of the repository
101+
* @param string $repositoryName Name of the repository
102+
* @param string $filepath Path where file should be created
103+
* @param string $content Content of the file
104+
* @param string $message Commit message
105+
* @return array<mixed> Response from API
106+
*/
107+
public function createFile(string $owner, string $repositoryName, string $filepath, string $content, string $message = 'Add file'): array
108+
{
109+
throw new Exception("Not implemented");
110+
}
111+
112+
/**
113+
* Create a branch in a repository
114+
*
115+
* @param string $owner Owner of the repository
116+
* @param string $repositoryName Name of the repository
117+
* @param string $newBranchName Name of the new branch
118+
* @param string $oldBranchName Name of the branch to branch from
119+
* @return array<mixed> Response from API
120+
*/
121+
public function createBranch(string $owner, string $repositoryName, string $newBranchName, string $oldBranchName): array
122+
{
123+
throw new Exception("Not implemented");
124+
}
125+
97126
/**
98127
* Search repositories for GitHub App
99128
* @param string $installationId ID of the installation

src/VCS/Adapter/Git/Gitea.php

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
use Utopia\Cache\Cache;
77
use Utopia\VCS\Adapter\Git;
88
use Utopia\VCS\Exception\RepositoryNotFound;
9+
use Utopia\VCS\Exception\FileNotFound;
910

1011
class Gitea extends Git
1112
{
13+
public const CONTENTS_FILE = 'file';
14+
15+
public const CONTENTS_DIRECTORY = 'dir';
16+
1217
protected string $endpoint = 'http://gitea:3000/api/v1';
1318

1419
protected string $accessToken;
@@ -147,22 +152,156 @@ public function getRepositoryName(string $repositoryId): string
147152

148153
public function getRepositoryTree(string $owner, string $repositoryName, string $branch, bool $recursive = false): array
149154
{
150-
throw new Exception("Not implemented yet");
155+
$url = "/repos/{$owner}/{$repositoryName}/git/trees/" . urlencode($branch) . ($recursive ? '?recursive=1' : '');
156+
157+
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
158+
159+
if (($response['headers']['status-code'] ?? 0) === 404) {
160+
return [];
161+
}
162+
163+
return array_column($response['body']['tree'] ?? [], 'path');
164+
}
165+
166+
/**
167+
* Create a file in a repository
168+
*
169+
* @param string $owner Owner of the repository
170+
* @param string $repositoryName Name of the repository
171+
* @param string $filepath Path where file should be created
172+
* @param string $content Content of the file
173+
* @param string $message Commit message
174+
* @return array<mixed> Response from API
175+
*/
176+
public function createFile(string $owner, string $repositoryName, string $filepath, string $content, string $message = 'Add file'): array
177+
{
178+
$url = "/repos/{$owner}/{$repositoryName}/contents/{$filepath}";
179+
180+
$response = $this->call(
181+
self::METHOD_POST,
182+
$url,
183+
['Authorization' => "token $this->accessToken"],
184+
[
185+
'content' => base64_encode($content),
186+
'message' => $message
187+
]
188+
);
189+
190+
$statusCode = $response['headers']['status-code'] ?? 0;
191+
if ($statusCode >= 400) {
192+
throw new Exception("Failed to create file {$filepath}: HTTP {$statusCode}");
193+
}
194+
195+
return $response['body'] ?? [];
196+
}
197+
198+
/**
199+
* Create a branch in a repository
200+
*
201+
* @param string $owner Owner of the repository
202+
* @param string $repositoryName Name of the repository
203+
* @param string $newBranchName Name of the new branch
204+
* @param string $oldBranchName Name of the branch to branch from
205+
* @return array<mixed> Response from API
206+
*/
207+
public function createBranch(string $owner, string $repositoryName, string $newBranchName, string $oldBranchName): array
208+
{
209+
$url = "/repos/{$owner}/{$repositoryName}/branches";
210+
211+
$response = $this->call(
212+
self::METHOD_POST,
213+
$url,
214+
['Authorization' => "token $this->accessToken"],
215+
[
216+
'new_branch_name' => $newBranchName,
217+
'old_branch_name' => $oldBranchName
218+
]
219+
);
220+
221+
$statusCode = $response['headers']['status-code'] ?? 0;
222+
if ($statusCode >= 400) {
223+
throw new Exception("Failed to create branch {$newBranchName}: HTTP {$statusCode}");
224+
}
225+
226+
return $response['body'] ?? [];
151227
}
152228

153229
public function listRepositoryLanguages(string $owner, string $repositoryName): array
154230
{
155-
throw new Exception("Not implemented yet");
231+
$url = "/repos/{$owner}/{$repositoryName}/languages";
232+
233+
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
234+
235+
if (isset($response['body'])) {
236+
return array_keys($response['body']);
237+
}
238+
239+
return [];
156240
}
157241

158242
public function getRepositoryContent(string $owner, string $repositoryName, string $path, string $ref = ''): array
159243
{
160-
throw new Exception("Not implemented yet");
244+
$url = "/repos/{$owner}/{$repositoryName}/contents/{$path}";
245+
if (!empty($ref)) {
246+
$url .= "?ref=" . urlencode($ref);
247+
}
248+
249+
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
250+
251+
if (($response['headers']['status-code'] ?? 0) !== 200) {
252+
throw new FileNotFound();
253+
}
254+
255+
$encoding = $response['body']['encoding'] ?? '';
256+
$content = '';
257+
258+
if ($encoding === 'base64') {
259+
$content = base64_decode($response['body']['content'] ?? '');
260+
} else {
261+
throw new FileNotFound();
262+
}
263+
264+
return [
265+
'sha' => $response['body']['sha'] ?? '',
266+
'size' => $response['body']['size'] ?? 0,
267+
'content' => $content
268+
];
161269
}
162270

163271
public function listRepositoryContents(string $owner, string $repositoryName, string $path = '', string $ref = ''): array
164272
{
165-
throw new Exception("Not implemented yet");
273+
$url = "/repos/{$owner}/{$repositoryName}/contents";
274+
if (!empty($path)) {
275+
$url .= "/{$path}";
276+
}
277+
if (!empty($ref)) {
278+
$url .= "?ref=" . urlencode($ref);
279+
}
280+
281+
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
282+
283+
if (($response['headers']['status-code'] ?? 0) === 404) {
284+
return [];
285+
}
286+
287+
$items = [];
288+
if (!empty($response['body'][0])) {
289+
$items = $response['body'];
290+
} elseif (!empty($response['body'])) {
291+
$items = [$response['body']];
292+
}
293+
294+
$contents = [];
295+
foreach ($items as $item) {
296+
$type = $item['type'] ?? 'file';
297+
$contents[] = [
298+
'name' => $item['name'] ?? '',
299+
'size' => $item['size'] ?? 0,
300+
'type' => $type === 'file' ? self::CONTENTS_FILE : self::CONTENTS_DIRECTORY
301+
];
302+
}
303+
304+
return $contents;
166305
}
167306

168307
public function deleteRepository(string $owner, string $repositoryName): bool

0 commit comments

Comments
 (0)