mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-28 17:42:38 +01:00
fix repo links to use external gitea url (#233)
This commit is contained in:
@@ -4,6 +4,7 @@ import { GitFork } from "lucide-react";
|
|||||||
import { SiGithub, SiGitea } from "react-icons/si";
|
import { SiGithub, SiGitea } from "react-icons/si";
|
||||||
import type { Repository } from "@/lib/db/schema";
|
import type { Repository } from "@/lib/db/schema";
|
||||||
import { getStatusColor } from "@/lib/utils";
|
import { getStatusColor } from "@/lib/utils";
|
||||||
|
import { buildGiteaWebUrl } from "@/lib/gitea-url";
|
||||||
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
||||||
|
|
||||||
interface RepositoryListProps {
|
interface RepositoryListProps {
|
||||||
@@ -15,11 +16,6 @@ export function RepositoryList({ repositories }: RepositoryListProps) {
|
|||||||
|
|
||||||
// Helper function to construct Gitea repository URL
|
// Helper function to construct Gitea repository URL
|
||||||
const getGiteaRepoUrl = (repository: Repository): string | null => {
|
const getGiteaRepoUrl = (repository: Repository): string | null => {
|
||||||
const rawBaseUrl = giteaConfig?.externalUrl || giteaConfig?.url;
|
|
||||||
if (!rawBaseUrl) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only provide Gitea links for repositories that have been or are being mirrored
|
// Only provide Gitea links for repositories that have been or are being mirrored
|
||||||
const validStatuses = ['mirroring', 'mirrored', 'syncing', 'synced'];
|
const validStatuses = ['mirroring', 'mirrored', 'syncing', 'synced'];
|
||||||
if (!validStatuses.includes(repository.status)) {
|
if (!validStatuses.includes(repository.status)) {
|
||||||
@@ -38,12 +34,7 @@ export function RepositoryList({ repositories }: RepositoryListProps) {
|
|||||||
repoPath = `${owner}/${repository.name}`;
|
repoPath = `${owner}/${repository.name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the base URL doesn't have a trailing slash
|
return buildGiteaWebUrl(giteaConfig, repoPath);
|
||||||
const baseUrl = rawBaseUrl.endsWith("/")
|
|
||||||
? rawBaseUrl.slice(0, -1)
|
|
||||||
: rawBaseUrl;
|
|
||||||
|
|
||||||
return `${baseUrl}/${repoPath}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import type { FilterParams } from "@/types/filter";
|
|||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { buildGiteaWebUrl } from "@/lib/gitea-url";
|
||||||
import { MirrorDestinationEditor } from "./MirrorDestinationEditor";
|
import { MirrorDestinationEditor } from "./MirrorDestinationEditor";
|
||||||
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
||||||
import {
|
import {
|
||||||
@@ -67,11 +68,6 @@ export function OrganizationList({
|
|||||||
|
|
||||||
// Helper function to construct Gitea organization URL
|
// Helper function to construct Gitea organization URL
|
||||||
const getGiteaOrgUrl = (organization: Organization): string | null => {
|
const getGiteaOrgUrl = (organization: Organization): string | null => {
|
||||||
const rawBaseUrl = giteaConfig?.externalUrl || giteaConfig?.url;
|
|
||||||
if (!rawBaseUrl) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only provide Gitea links for organizations that have been mirrored
|
// Only provide Gitea links for organizations that have been mirrored
|
||||||
const validStatuses = ['mirroring', 'mirrored'];
|
const validStatuses = ['mirroring', 'mirrored'];
|
||||||
if (!validStatuses.includes(organization.status || '')) {
|
if (!validStatuses.includes(organization.status || '')) {
|
||||||
@@ -84,12 +80,7 @@ export function OrganizationList({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the base URL doesn't have a trailing slash
|
return buildGiteaWebUrl(giteaConfig, orgName);
|
||||||
const baseUrl = rawBaseUrl.endsWith("/")
|
|
||||||
? rawBaseUrl.slice(0, -1)
|
|
||||||
: rawBaseUrl;
|
|
||||||
|
|
||||||
return `${baseUrl}/${orgName}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateDestination = async (orgId: string, newDestination: string | null) => {
|
const handleUpdateDestination = async (orgId: string, newDestination: string | null) => {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { SiGithub, SiGitea } from "react-icons/si";
|
|||||||
import type { Repository } from "@/lib/db/schema";
|
import type { Repository } from "@/lib/db/schema";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { formatLastSyncTime } from "@/lib/utils";
|
import { formatLastSyncTime } from "@/lib/utils";
|
||||||
|
import { buildGiteaWebUrl } from "@/lib/gitea-url";
|
||||||
import type { FilterParams } from "@/types/filter";
|
import type { FilterParams } from "@/types/filter";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
import { useGiteaConfig } from "@/hooks/useGiteaConfig";
|
||||||
@@ -124,10 +125,6 @@ export default function RepositoryTable({
|
|||||||
|
|
||||||
// Helper function to construct Gitea repository URL
|
// Helper function to construct Gitea repository URL
|
||||||
const getGiteaRepoUrl = (repository: Repository): string | null => {
|
const getGiteaRepoUrl = (repository: Repository): string | null => {
|
||||||
if (!giteaConfig?.url) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only provide Gitea links for repositories that have been or are being mirrored
|
// Only provide Gitea links for repositories that have been or are being mirrored
|
||||||
const validStatuses = ['mirroring', 'mirrored', 'syncing', 'synced', 'archived'];
|
const validStatuses = ['mirroring', 'mirrored', 'syncing', 'synced', 'archived'];
|
||||||
if (!validStatuses.includes(repository.status)) {
|
if (!validStatuses.includes(repository.status)) {
|
||||||
@@ -144,12 +141,7 @@ export default function RepositoryTable({
|
|||||||
repoPath = `${owner}/${repository.name}`;
|
repoPath = `${owner}/${repository.name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the base URL doesn't have a trailing slash
|
return buildGiteaWebUrl(giteaConfig, repoPath);
|
||||||
const baseUrl = giteaConfig.url.endsWith('/')
|
|
||||||
? giteaConfig.url.slice(0, -1)
|
|
||||||
: giteaConfig.url;
|
|
||||||
|
|
||||||
return `${baseUrl}/${repoPath}`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasAnyFilter = [
|
const hasAnyFilter = [
|
||||||
|
|||||||
45
src/lib/gitea-url.test.ts
Normal file
45
src/lib/gitea-url.test.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { describe, expect, it } from "bun:test";
|
||||||
|
import { buildGiteaWebUrl, getGiteaWebBaseUrl } from "@/lib/gitea-url";
|
||||||
|
|
||||||
|
describe("getGiteaWebBaseUrl", () => {
|
||||||
|
it("prefers externalUrl when both urls are present", () => {
|
||||||
|
const baseUrl = getGiteaWebBaseUrl({
|
||||||
|
url: "http://gitea:3000",
|
||||||
|
externalUrl: "https://git.example.com",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(baseUrl).toBe("https://git.example.com");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to url when externalUrl is missing", () => {
|
||||||
|
const baseUrl = getGiteaWebBaseUrl({
|
||||||
|
url: "http://gitea:3000",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(baseUrl).toBe("http://gitea:3000");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("trims a trailing slash", () => {
|
||||||
|
const baseUrl = getGiteaWebBaseUrl({
|
||||||
|
externalUrl: "https://git.example.com/",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(baseUrl).toBe("https://git.example.com");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("buildGiteaWebUrl", () => {
|
||||||
|
it("builds a full repository url and removes leading path slashes", () => {
|
||||||
|
const url = buildGiteaWebUrl(
|
||||||
|
{ externalUrl: "https://git.example.com/" },
|
||||||
|
"/org/repo"
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(url).toBe("https://git.example.com/org/repo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns null when no gitea url is configured", () => {
|
||||||
|
const url = buildGiteaWebUrl({}, "org/repo");
|
||||||
|
expect(url).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
28
src/lib/gitea-url.ts
Normal file
28
src/lib/gitea-url.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
interface GiteaUrlConfig {
|
||||||
|
url?: string | null;
|
||||||
|
externalUrl?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGiteaWebBaseUrl(
|
||||||
|
config?: GiteaUrlConfig | null
|
||||||
|
): string | null {
|
||||||
|
const rawBaseUrl = config?.externalUrl || config?.url;
|
||||||
|
if (!rawBaseUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawBaseUrl.endsWith("/") ? rawBaseUrl.slice(0, -1) : rawBaseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildGiteaWebUrl(
|
||||||
|
config: GiteaUrlConfig | null | undefined,
|
||||||
|
path: string
|
||||||
|
): string | null {
|
||||||
|
const baseUrl = getGiteaWebBaseUrl(config);
|
||||||
|
if (!baseUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedPath = path.replace(/^\/+/, "");
|
||||||
|
return normalizedPath ? `${baseUrl}/${normalizedPath}` : baseUrl;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user