Skip to content

Commit a1f0f09

Browse files
author
Your Name
committed
Merge branch 'feat/gitea-repository-operations' of https://github.com/jaysomani/vcs into feat/gitea-repository-operations
2 parents 0d4bb6c + 02d766e commit a1f0f09

2 files changed

Lines changed: 113 additions & 44 deletions

File tree

src/VCS/Adapter/Git/Gitea.php

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,14 @@ public function createOrganization(string $orgName): string
129129
*/
130130
public function searchRepositories(string $installationId, string $owner, int $page, int $per_page, string $search = ''): array
131131
{
132-
$allRepos = [];
132+
$filteredRepos = [];
133133
$currentPage = 1;
134+
$maxPages = 50;
134135

135-
while (true) {
136+
$neededForPage = $page * $per_page;
137+
$maxToCollect = $neededForPage + $per_page;
138+
139+
while ($currentPage <= $maxPages) {
136140
$queryParams = [
137141
'page' => $currentPage,
138142
'limit' => 100,
@@ -155,8 +159,12 @@ public function searchRepositories(string $installationId, string $owner, int $p
155159

156160
$responseBody = $response['body'] ?? [];
157161

162+
if (!is_array($responseBody)) {
163+
throw new Exception('Unexpected response body: ' . json_encode($responseBody));
164+
}
165+
158166
if (!array_key_exists('data', $responseBody)) {
159-
throw new Exception("Repositories list missing in the response.");
167+
throw new Exception("Repositories list missing in response: " . json_encode($responseBody));
160168
}
161169

162170
$repos = $responseBody['data'];
@@ -165,7 +173,16 @@ public function searchRepositories(string $installationId, string $owner, int $p
165173
break;
166174
}
167175

168-
$allRepos = array_merge($allRepos, $repos);
176+
foreach ($repos as $repo) {
177+
$repoOwner = $repo['owner']['login'] ?? '';
178+
if ($repoOwner === $owner) {
179+
$filteredRepos[] = $repo;
180+
181+
if (count($filteredRepos) >= $maxToCollect) {
182+
break 2;
183+
}
184+
}
185+
}
169186

170187
if (count($repos) < 100) {
171188
break;
@@ -174,13 +191,6 @@ public function searchRepositories(string $installationId, string $owner, int $p
174191
$currentPage++;
175192
}
176193

177-
$filteredRepos = array_filter($allRepos, function ($repo) use ($owner) {
178-
$repoOwner = $repo['owner']['login'] ?? '';
179-
return $repoOwner === $owner;
180-
});
181-
182-
$filteredRepos = array_values($filteredRepos);
183-
184194
$total = count($filteredRepos);
185195
$offset = ($page - 1) * $per_page;
186196
$pagedRepos = array_slice($filteredRepos, $offset, $per_page);
@@ -521,16 +531,9 @@ public function getUser(string $username): array
521531
throw new Exception("Not implemented yet");
522532
}
523533

524-
/**
525-
* Get owner name
526-
* @param string $installationId In Gitea context, this is the owner name itself
527-
* @return string Owner name
528-
*/
529534
public function getOwnerName(string $installationId): string
530535
{
531-
// Gitea doesn't have GitHub App installation concept
532-
// Return the installationId as-is since it represents the owner
533-
return $installationId;
536+
throw new Exception("getOwnerName() is not applicable for Gitea");
534537
}
535538

536539
public function getPullRequest(string $owner, string $repositoryName, int $pullRequestNumber): array
@@ -575,30 +578,49 @@ public function getPullRequestFromBranch(string $owner, string $repositoryName,
575578
*/
576579
public function listBranches(string $owner, string $repositoryName): array
577580
{
578-
$url = "/repos/{$owner}/{$repositoryName}/branches";
581+
$allBranches = [];
582+
$perPage = 50;
583+
$maxPages = 100;
579584

580-
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
585+
for ($currentPage = 1; $currentPage <= $maxPages; $currentPage++) {
586+
$url = "/repos/{$owner}/{$repositoryName}/branches?page={$currentPage}&limit={$perPage}";
581587

582-
$responseHeaders = $response['headers'] ?? [];
583-
$responseHeadersStatusCode = $responseHeaders['status-code'] ?? 0;
584-
if ($responseHeadersStatusCode >= 400) {
585-
return [];
586-
}
588+
$response = $this->call(self::METHOD_GET, $url, ['Authorization' => "token $this->accessToken"]);
587589

588-
$responseBody = $response['body'] ?? [];
590+
$responseHeaders = $response['headers'] ?? [];
591+
$responseHeadersStatusCode = $responseHeaders['status-code'] ?? 0;
589592

590-
if (!is_array($responseBody)) {
591-
return [];
592-
}
593+
if ($responseHeadersStatusCode === 404) {
594+
return [];
595+
}
596+
597+
if ($responseHeadersStatusCode >= 400) {
598+
if ($currentPage === 1) {
599+
throw new Exception("Failed to list branches: HTTP {$responseHeadersStatusCode}");
600+
}
601+
break;
602+
}
593603

594-
$names = [];
595-
foreach ($responseBody as $branch) {
596-
if (is_array($branch) && array_key_exists('name', $branch)) {
597-
$names[] = $branch['name'] ?? '';
604+
$responseBody = $response['body'] ?? [];
605+
606+
if (!is_array($responseBody)) {
607+
break;
608+
}
609+
610+
$pageCount = 0;
611+
foreach ($responseBody as $branch) {
612+
if (is_array($branch) && array_key_exists('name', $branch)) {
613+
$allBranches[] = $branch['name'] ?? '';
614+
$pageCount++;
615+
}
616+
}
617+
618+
if ($pageCount < $perPage) {
619+
break;
598620
}
599621
}
600622

601-
return $names;
623+
return $allBranches;
602624
}
603625

604626
/**

tests/VCS/Adapter/GiteaTest.php

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,48 @@ public function testSearchRepositories(): void
649649
}
650650
}
651651

652+
public function testSearchRepositoriesPagination(): void
653+
{
654+
$repo1 = 'test-pagination-1-' . \uniqid();
655+
$repo2 = 'test-pagination-2-' . \uniqid();
656+
657+
$this->vcsAdapter->createRepository(self::$owner, $repo1, false);
658+
$this->vcsAdapter->createRepository(self::$owner, $repo2, false);
659+
660+
try {
661+
// Test limit=1 only returns 1 repo
662+
$result = $this->vcsAdapter->searchRepositories('', self::$owner, 1, 1, 'test-pagination');
663+
664+
$this->assertSame(1, count($result['items']));
665+
$this->assertGreaterThanOrEqual(2, $result['total']);
666+
667+
// Test page 2
668+
$result2 = $this->vcsAdapter->searchRepositories('', self::$owner, 2, 1, 'test-pagination');
669+
$this->assertSame(1, count($result2['items']));
670+
} finally {
671+
$this->vcsAdapter->deleteRepository(self::$owner, $repo1);
672+
$this->vcsAdapter->deleteRepository(self::$owner, $repo2);
673+
}
674+
}
675+
676+
public function testSearchRepositoriesNoResults(): void
677+
{
678+
$result = $this->vcsAdapter->searchRepositories('', self::$owner, 1, 10, 'nonexistent-repo-xyz-' . \uniqid());
679+
680+
$this->assertIsArray($result);
681+
$this->assertEmpty($result['items']);
682+
$this->assertSame(0, $result['total']);
683+
}
684+
685+
public function testSearchRepositoriesInvalidOwner(): void
686+
{
687+
$result = $this->vcsAdapter->searchRepositories('', 'nonexistent-owner-' . \uniqid(), 1, 10);
688+
689+
$this->assertIsArray($result);
690+
$this->assertEmpty($result['items']);
691+
$this->assertSame(0, $result['total']);
692+
}
693+
652694
public function testDeleteRepository(): void
653695
{
654696
$repositoryName = 'test-delete-repository-' . \uniqid();
@@ -677,12 +719,10 @@ public function testDeleteNonExistingRepositoryFails(): void
677719

678720
public function testGetOwnerName(): void
679721
{
680-
// For Gitea, getOwnerName simply returns the installationId parameter
681-
// since Gitea doesn't have GitHub App installation concept
682-
$result = $this->vcsAdapter->getOwnerName(self::$owner);
722+
$this->expectException(\Exception::class);
723+
$this->expectExceptionMessage('not applicable for Gitea');
683724

684-
$this->assertIsString($result);
685-
$this->assertSame(self::$owner, $result);
725+
$this->vcsAdapter->getOwnerName('');
686726
}
687727

688728
public function testGetPullRequestFromBranch(): void
@@ -806,12 +846,19 @@ public function testListBranches(): void
806846

807847
// Create additional branches
808848
$this->vcsAdapter->createBranch(self::$owner, $repositoryName, 'feature-1', 'main');
809-
sleep(1);
810849
$this->vcsAdapter->createBranch(self::$owner, $repositoryName, 'feature-2', 'main');
811-
sleep(1);
812850

813-
// Test listBranches
814-
$branches = $this->vcsAdapter->listBranches(self::$owner, $repositoryName);
851+
$branches = [];
852+
$maxAttempts = 10;
853+
for ($attempt = 0; $attempt < $maxAttempts; $attempt++) {
854+
$branches = $this->vcsAdapter->listBranches(self::$owner, $repositoryName);
855+
856+
if (in_array('feature-1', $branches, true) && in_array('feature-2', $branches, true)) {
857+
break;
858+
}
859+
860+
usleep(500000);
861+
}
815862

816863
$this->assertIsArray($branches);
817864
$this->assertNotEmpty($branches);

0 commit comments

Comments
 (0)