More fixes

This commit is contained in:
Arunavo Ray
2025-07-18 00:52:03 +05:30
parent 251baeb1aa
commit 7bd862606b
7 changed files with 47 additions and 73 deletions

View File

@@ -7,7 +7,7 @@
}, },
"scripts": { "scripts": {
"setup": "bun install && bun run manage-db init", "setup": "bun install && bun run manage-db init",
"dev": "bunx --bun astro dev --port 4567", "dev": "bunx --bun astro dev --port 9876",
"dev:clean": "bun run cleanup-db && bun run manage-db init && bunx --bun astro dev", "dev:clean": "bun run cleanup-db && bun run manage-db init && bunx --bun astro dev",
"build": "bunx --bun astro build", "build": "bunx --bun astro build",
"cleanup-db": "rm -f gitea-mirror.db data/gitea-mirror.db", "cleanup-db": "rm -f gitea-mirror.db data/gitea-mirror.db",

View File

@@ -24,7 +24,7 @@ export const githubConfigSchema = z.object({
includePublic: z.boolean().default(true), includePublic: z.boolean().default(true),
includeOrganizations: z.array(z.string()).default([]), includeOrganizations: z.array(z.string()).default([]),
starredReposOrg: z.string().optional(), starredReposOrg: z.string().optional(),
mirrorStrategy: z.enum(["preserve", "single-org", "flat-user"]).default("preserve"), mirrorStrategy: z.enum(["preserve", "single-org", "flat-user", "mixed"]).default("preserve"),
defaultOrg: z.string().optional(), defaultOrg: z.string().optional(),
}); });

View File

@@ -312,13 +312,13 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
skipStarredIssues: false skipStarredIssues: false
}, },
giteaConfig: { giteaConfig: {
username: "giteauser", defaultOwner: "giteauser",
url: "https://gitea.example.com", url: "https://gitea.example.com",
token: "gitea-token", token: "gitea-token",
organization: "github-mirrors", defaultOrg: "github-mirrors",
visibility: "public", visibility: "public",
starredReposOrg: "starred", starredReposOrg: "starred",
preserveOrgStructure: false, preserveVisibility: false,
mirrorStrategy: "preserve" mirrorStrategy: "preserve"
} }
}; };
@@ -354,18 +354,7 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
expect(result).toBe("starred"); expect(result).toBe("starred");
}); });
test("preserve strategy: personal repos use personalReposOrg override", () => { // Removed test for personalReposOrg as this field no longer exists
const configWithOverride = {
...baseConfig,
giteaConfig: {
...baseConfig.giteaConfig!,
personalReposOrg: "my-personal-mirrors"
}
};
const repo = { ...baseRepo, organization: undefined };
const result = getGiteaRepoOwner({ config: configWithOverride, repository: repo });
expect(result).toBe("my-personal-mirrors");
});
test("preserve strategy: personal repos fallback to username when no override", () => { test("preserve strategy: personal repos fallback to username when no override", () => {
const repo = { ...baseRepo, organization: undefined }; const repo = { ...baseRepo, organization: undefined };
@@ -379,7 +368,7 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
expect(result).toBe("myorg"); expect(result).toBe("myorg");
}); });
test("mixed strategy: personal repos go to organization", () => { test("single-org strategy: personal repos go to defaultOrg", () => {
const configWithMixed = { const configWithMixed = {
...baseConfig, ...baseConfig,
giteaConfig: { giteaConfig: {
@@ -393,7 +382,7 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
expect(result).toBe("github-mirrors"); expect(result).toBe("github-mirrors");
}); });
test("mixed strategy: org repos preserve their structure", () => { test("single-org strategy: org repos also go to defaultOrg", () => {
const configWithMixed = { const configWithMixed = {
...baseConfig, ...baseConfig,
giteaConfig: { giteaConfig: {
@@ -407,18 +396,16 @@ describe("getGiteaRepoOwner - Organization Override Tests", () => {
expect(result).toBe("myorg"); expect(result).toBe("myorg");
}); });
test("mixed strategy: fallback to username if no org configs", () => { test("flat-user strategy: all repos go to defaultOwner", () => {
const configWithMixed = { const configWithFlatUser = {
...baseConfig, ...baseConfig,
giteaConfig: { giteaConfig: {
...baseConfig.giteaConfig!, ...baseConfig.giteaConfig!,
mirrorStrategy: "mixed" as const, mirrorStrategy: "flat-user" as const
organization: undefined,
personalReposOrg: undefined
} }
}; };
const repo = { ...baseRepo, organization: undefined }; const repo = { ...baseRepo, organization: "myorg" };
const result = getGiteaRepoOwner({ config: configWithMixed, repository: repo }); const result = getGiteaRepoOwner({ config: configWithFlatUser, repository: repo });
expect(result).toBe("giteauser"); expect(result).toBe("giteauser");
}); });
}); });

View File

@@ -64,7 +64,7 @@ export const getGiteaRepoOwnerAsync = async ({
throw new Error("GitHub or Gitea config is required."); throw new Error("GitHub or Gitea config is required.");
} }
if (!config.giteaConfig.username) { if (!config.giteaConfig.defaultOwner) {
throw new Error("Gitea username is required."); throw new Error("Gitea username is required.");
} }
@@ -96,11 +96,7 @@ export const getGiteaRepoOwnerAsync = async ({
} }
} }
// Check for personal repos override (when it's user's repo, not an organization) // For personal repos (not organization repos), fall back to the default strategy
if (!repository.organization && config.giteaConfig.personalReposOrg) {
console.log(`Using personal repos override: ${config.giteaConfig.personalReposOrg}`);
return config.giteaConfig.personalReposOrg;
}
// Fall back to existing strategy logic // Fall back to existing strategy logic
return getGiteaRepoOwner({ config, repository }); return getGiteaRepoOwner({ config, repository });
@@ -117,7 +113,7 @@ export const getGiteaRepoOwner = ({
throw new Error("GitHub or Gitea config is required."); throw new Error("GitHub or Gitea config is required.");
} }
if (!config.giteaConfig.username) { if (!config.giteaConfig.defaultOwner) {
throw new Error("Gitea username is required."); throw new Error("Gitea username is required.");
} }
@@ -137,7 +133,7 @@ export const getGiteaRepoOwner = ({
return repository.organization; return repository.organization;
} }
// Use personal repos override if configured, otherwise use username // Use personal repos override if configured, otherwise use username
return config.giteaConfig.personalReposOrg || config.giteaConfig.username; return config.giteaConfig.defaultOwner;
case "single-org": case "single-org":
// All non-starred repos go to the destination organization // All non-starred repos go to the destination organization
@@ -145,11 +141,11 @@ export const getGiteaRepoOwner = ({
return config.giteaConfig.organization; return config.giteaConfig.organization;
} }
// Fallback to username if no organization specified // Fallback to username if no organization specified
return config.giteaConfig.username; return config.giteaConfig.defaultOwner;
case "flat-user": case "flat-user":
// All non-starred repos go under the user account // All non-starred repos go under the user account
return config.giteaConfig.username; return config.giteaConfig.defaultOwner;
case "mixed": case "mixed":
// Mixed mode: personal repos to single org, organization repos preserve structure // Mixed mode: personal repos to single org, organization repos preserve structure
@@ -162,11 +158,11 @@ export const getGiteaRepoOwner = ({
return config.giteaConfig.organization; return config.giteaConfig.organization;
} }
// Fallback to username if no organization specified // Fallback to username if no organization specified
return config.giteaConfig.username; return config.giteaConfig.defaultOwner;
default: default:
// Default fallback // Default fallback
return config.giteaConfig.username; return config.giteaConfig.defaultOwner;
} }
}; };
@@ -268,7 +264,7 @@ export const mirrorGithubRepoToGitea = async ({
throw new Error("github config and gitea config are required."); throw new Error("github config and gitea config are required.");
} }
if (!config.giteaConfig.username) { if (!config.giteaConfig.defaultOwner) {
throw new Error("Gitea username is required."); throw new Error("Gitea username is required.");
} }
@@ -357,7 +353,7 @@ export const mirrorGithubRepoToGitea = async ({
const apiUrl = `${config.giteaConfig.url}/api/v1/repos/migrate`; const apiUrl = `${config.giteaConfig.url}/api/v1/repos/migrate`;
// Handle organization creation if needed for single-org or preserve strategies // Handle organization creation if needed for single-org or preserve strategies
if (repoOwner !== config.giteaConfig.username && !repository.isStarred) { if (repoOwner !== config.giteaConfig.defaultOwner && !repository.isStarred) {
// Need to create the organization if it doesn't exist // Need to create the organization if it doesn't exist
await getOrCreateGiteaOrg({ await getOrCreateGiteaOrg({
orgName: repoOwner, orgName: repoOwner,
@@ -383,11 +379,13 @@ export const mirrorGithubRepoToGitea = async ({
); );
//mirror releases //mirror releases
if (config.githubConfig?.mirrorReleases) {
await mirrorGitHubReleasesToGitea({ await mirrorGitHubReleasesToGitea({
config, config,
octokit, octokit,
repository, repository,
}); });
}
// clone issues // clone issues
// Skip issues for starred repos if skipStarredIssues is enabled // Skip issues for starred repos if skipStarredIssues is enabled
@@ -738,11 +736,13 @@ export async function mirrorGitHubRepoToGiteaOrg({
); );
//mirror releases //mirror releases
if (config.githubConfig?.mirrorReleases) {
await mirrorGitHubReleasesToGitea({ await mirrorGitHubReleasesToGitea({
config, config,
octokit, octokit,
repository, repository,
}); });
}
// Clone issues // Clone issues
// Skip issues for starred repos if skipStarredIssues is enabled // Skip issues for starred repos if skipStarredIssues is enabled
@@ -906,7 +906,7 @@ export async function mirrorGitHubOrgToGitea({
// Determine the target organization based on strategy // Determine the target organization based on strategy
if (mirrorStrategy === "single-org" && config.giteaConfig?.organization) { if (mirrorStrategy === "single-org" && config.giteaConfig?.organization) {
// For single-org strategy, use the configured destination organization // For single-org strategy, use the configured destination organization
targetOrgName = config.giteaConfig.organization; targetOrgName = config.giteaConfig.defaultOrg || config.giteaConfig.defaultOwner;
giteaOrgId = await getOrCreateGiteaOrg({ giteaOrgId = await getOrCreateGiteaOrg({
orgId: organization.id, orgId: organization.id,
orgName: targetOrgName, orgName: targetOrgName,
@@ -925,7 +925,7 @@ export async function mirrorGitHubOrgToGitea({
// For flat-user strategy, we shouldn't create organizations at all // For flat-user strategy, we shouldn't create organizations at all
// Skip organization creation and let individual repos be handled by getGiteaRepoOwner // Skip organization creation and let individual repos be handled by getGiteaRepoOwner
console.log(`Using flat-user strategy: repos will be placed under user account`); console.log(`Using flat-user strategy: repos will be placed under user account`);
targetOrgName = config.giteaConfig?.username || ""; targetOrgName = config.giteaConfig?.defaultOwner || "";
} }
//query the db with the org name and get the repos //query the db with the org name and get the repos
@@ -1082,7 +1082,7 @@ export const syncGiteaRepo = async ({
!config.userId || !config.userId ||
!config.giteaConfig?.url || !config.giteaConfig?.url ||
!config.giteaConfig?.token || !config.giteaConfig?.token ||
!config.giteaConfig?.username !config.giteaConfig?.defaultOwner
) { ) {
throw new Error("Gitea config is required."); throw new Error("Gitea config is required.");
} }
@@ -1405,7 +1405,7 @@ export async function mirrorGitHubReleasesToGitea({
config: Partial<Config>; config: Partial<Config>;
}) { }) {
if ( if (
!config.giteaConfig?.username || !config.giteaConfig?.defaultOwner ||
!config.giteaConfig?.token || !config.giteaConfig?.token ||
!config.giteaConfig?.url !config.giteaConfig?.url
) { ) {

View File

@@ -66,30 +66,17 @@ export const GET: APIRoute = async ({ request }) => {
baseConditions.push(eq(repositories.isStarred, false)); baseConditions.push(eq(repositories.isStarred, false));
} }
// Get total count with all user config filters applied // Get actual total count (without user config filters)
const totalConditions = [...baseConditions];
if (githubConfig.skipForks) {
totalConditions.push(eq(repositories.isForked, false));
}
if (!githubConfig.privateRepositories) {
totalConditions.push(eq(repositories.isPrivate, false));
}
const [totalCount] = await db const [totalCount] = await db
.select({ count: count() }) .select({ count: count() })
.from(repositories) .from(repositories)
.where(and(...totalConditions)); .where(and(...baseConditions));
// Get public count
const publicConditions = [...baseConditions, eq(repositories.isPrivate, false)];
if (githubConfig.skipForks) {
publicConditions.push(eq(repositories.isForked, false));
}
// Get public count (actual count, not filtered)
const [publicCount] = await db const [publicCount] = await db
.select({ count: count() }) .select({ count: count() })
.from(repositories) .from(repositories)
.where(and(...publicConditions)); .where(and(...baseConditions, eq(repositories.isPrivate, false)));
// Get private count (always show actual count regardless of config) // Get private count (always show actual count regardless of config)
const [privateCount] = await db const [privateCount] = await db

View File

@@ -113,7 +113,7 @@ export const POST: APIRoute = async ({ request }) => {
(config.githubConfig?.preserveOrgStructure ? "preserve" : "flat-user"); (config.githubConfig?.preserveOrgStructure ? "preserve" : "flat-user");
const shouldUseOrgMirror = const shouldUseOrgMirror =
owner !== config.giteaConfig?.username || // Different owner means org owner !== config.giteaConfig?.defaultOwner || // Different owner means org
mirrorStrategy === "single-org" || // Single-org strategy always uses org mirrorStrategy === "single-org" || // Single-org strategy always uses org
repoData.isStarred; // Starred repos always go to org repoData.isStarred; // Starred repos always go to org

View File

@@ -147,7 +147,7 @@ export const POST: APIRoute = async ({ request }) => {
(config.githubConfig?.preserveOrgStructure ? "preserve" : "flat-user"); (config.githubConfig?.preserveOrgStructure ? "preserve" : "flat-user");
const shouldUseOrgMirror = const shouldUseOrgMirror =
owner !== config.giteaConfig?.username || // Different owner means org owner !== config.giteaConfig?.defaultOwner || // Different owner means org
mirrorStrategy === "single-org" || // Single-org strategy always uses org mirrorStrategy === "single-org" || // Single-org strategy always uses org
repoData.isStarred; // Starred repos always go to org repoData.isStarred; // Starred repos always go to org