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": {
"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",
"build": "bunx --bun astro build",
"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),
includeOrganizations: z.array(z.string()).default([]),
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(),
});

View File

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

View File

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

View File

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

View File

@@ -113,7 +113,7 @@ export const POST: APIRoute = async ({ request }) => {
(config.githubConfig?.preserveOrgStructure ? "preserve" : "flat-user");
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
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");
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
repoData.isStarred; // Starred repos always go to org