diff --git a/nostr/commit-signatures.jsonl b/nostr/commit-signatures.jsonl index 494674f..9f7c09f 100644 --- a/nostr/commit-signatures.jsonl +++ b/nostr/commit-signatures.jsonl @@ -64,3 +64,4 @@ {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771845583,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix search and relay connections"]],"content":"Signed commit: fix search and relay connections","id":"24db15027960b244eb4c8664a3642c64684ebfef8c200250093dd047cd119e7d","sig":"561d15ae39b3bf7a5b8a67539a5cfa19d53cbaca9f904589ab7cb69e568ddf056d0d83ced4830cdfdc0b386f13c4bab930264a0f6144cbb833b187b5d452c4ae"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771847704,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"9566e4e2964d0a7b80cce1889092c4db333f89843b5d68906b3c3c568e4ba57d","sig":"8cf9166c630a8dc21bbc3dfaea4330c80c93bf7bc9e8d5d3be182fb11a3b96ea2e5969f452d3e2b309103b3e7fea8fc1aa6e5908d499d0696e9bfcd3859a8e32"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771849427,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","bug-fixes"]],"content":"Signed commit: bug-fixes","id":"1d4e6ff4059b064d7cdd465d623a606cfcc5d0565681a34f6384463d40cc8c71","sig":"f5fe3547289e994ff1a3b191607e76d778d318ca4538e70253406867ecef214c1be437dca373f9a461c9cf2ca2978a581b54a9d323baeb2c91851e9cc6ffbfd6"} +{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1771850840,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","rearrange repo pages"]],"content":"Signed commit: rearrange repo pages","id":"9f8b68f36189073807510a2dac268b466629ecbc6b8dca66ba809cbf3a36dab5","sig":"911debb546c23038bbf77a57bee089130c7cce3a51f2cfb385c3904ec39bc76b90dc9bef2e8e501824ecff13925523d802b6c916d07fef2718554f4f65e6f4d2"} diff --git a/src/lib/components/RepoHeaderEnhanced.svelte b/src/lib/components/RepoHeaderEnhanced.svelte index 0fbfe67..5c7c298 100644 --- a/src/lib/components/RepoHeaderEnhanced.svelte +++ b/src/lib/components/RepoHeaderEnhanced.svelte @@ -241,6 +241,20 @@ Create New Branch {/if} + {#if isMaintainer && currentBranch && currentBranch !== defaultBranch && onDeleteBranch} + + {/if} {#if onCopyEventId} - {/if} {/if} diff --git a/src/lib/services/git/file-manager.ts b/src/lib/services/git/file-manager.ts index 5e0a33b..efa0c51 100644 --- a/src/lib/services/git/file-manager.ts +++ b/src/lib/services/git/file-manager.ts @@ -1765,15 +1765,12 @@ export class FileManager { npub: string, repoName: string, branchName: string, - fromBranch: string = 'main' + fromBranch?: string ): Promise { // Security: Validate branch names to prevent path traversal if (!isValidBranchName(branchName)) { throw new Error(`Invalid branch name: ${branchName}`); } - if (!isValidBranchName(fromBranch)) { - throw new Error(`Invalid source branch name: ${fromBranch}`); - } const repoPath = this.getRepoPath(npub, repoName); @@ -1870,8 +1867,16 @@ export class FileManager { await this.removeWorktree(repoPath, worktreePath); } else { // Repo has branches - use normal branch creation + // Validate fromBranch if provided + if (fromBranch && !isValidBranchName(fromBranch)) { + throw new Error(`Invalid source branch name: ${fromBranch}`); + } + + // Use default branch if fromBranch not provided + const sourceBranch = fromBranch || await this.getDefaultBranch(npub, repoName).catch(() => 'main'); + // Use git worktree instead of cloning (much more efficient) - const workDir = await this.getWorktree(repoPath, fromBranch, npub, repoName); + const workDir = await this.getWorktree(repoPath, sourceBranch, npub, repoName); const workGit: SimpleGit = simpleGit(workDir); // Create and checkout new branch diff --git a/src/routes/api/repos/[npub]/[repo]/branches/+server.ts b/src/routes/api/repos/[npub]/[repo]/branches/+server.ts index afc3e64..2ae68c8 100644 --- a/src/routes/api/repos/[npub]/[repo]/branches/+server.ts +++ b/src/routes/api/repos/[npub]/[repo]/branches/+server.ts @@ -244,18 +244,30 @@ export const POST: RequestHandler = createRepoPostHandler( } } - // Get default branch if fromBranch not provided - // If repo has no branches, use 'master' as default + // Check if repo has any branches first + let hasBranches = false; + try { + const existingBranches = await fileManager.getBranches(context.npub, context.repo); + hasBranches = existingBranches.length > 0; + } catch (err) { + // If getBranches fails, assume no branches exist + logger.debug({ error: err, npub: context.npub, repo: context.repo }, 'Failed to get branches, assuming empty repo'); + hasBranches = false; + } + + // Get default branch if fromBranch not provided and repo has branches + // If repo has no branches, don't pass fromBranch (will use --orphan) let sourceBranch = fromBranch; - if (!sourceBranch) { + if (!sourceBranch && hasBranches) { try { sourceBranch = await fileManager.getDefaultBranch(context.npub, context.repo); } catch (err) { - // If getDefaultBranch fails (e.g., no branches exist), use 'master' as default - logger.debug({ error: err, npub: context.npub, repo: context.repo }, 'No default branch found, using master'); - sourceBranch = 'master'; + // If getDefaultBranch fails, use 'main' as default (only if branches exist) + logger.debug({ error: err, npub: context.npub, repo: context.repo }, 'No default branch found, using main'); + sourceBranch = 'main'; } } + // If repo has no branches, sourceBranch will be undefined/null, which createBranch will handle correctly await fileManager.createBranch(context.npub, context.repo, branchName, sourceBranch); return json({ success: true, message: 'Branch created successfully' }); diff --git a/src/routes/repos/[npub]/[repo]/+page.svelte b/src/routes/repos/[npub]/[repo]/+page.svelte index 23746d4..f944517 100644 --- a/src/routes/repos/[npub]/[repo]/+page.svelte +++ b/src/routes/repos/[npub]/[repo]/+page.svelte @@ -2806,15 +2806,8 @@ currentBranch = defaultBranch; } } else { - // No branches loaded yet or empty repo - set currentBranch from settings if not set - if (!currentBranch) { - try { - const settings = await settingsStore.getSettings(); - currentBranch = settings.defaultBranch || 'master'; - } catch { - currentBranch = 'master'; - } - } + // No branches exist - set currentBranch to null to show "no branches" in header + currentBranch = null; } } else if (response.status === 404) { // Check if this is a "not cloned" error - API fallback might be available @@ -3803,11 +3796,16 @@ error = null; try { - // If no branches exist, use default branch from settings - let fromBranch = newBranchFrom || currentBranch; - if (!fromBranch && branches.length === 0) { - const settings = await settingsStore.getSettings(); - fromBranch = settings.defaultBranch || 'master'; + // If no branches exist, don't pass fromBranch (will use --orphan) + // Otherwise, use the selected branch or current branch + let fromBranch: string | undefined = newBranchFrom || currentBranch || undefined; + + // Only include fromBranch if repo has branches + const requestBody: { branchName: string; fromBranch?: string } = { + branchName: newBranchName + }; + if (branches.length > 0 && fromBranch) { + requestBody.fromBranch = fromBranch; } const response = await fetch(`/api/repos/${npub}/${repo}/branches`, { @@ -3816,10 +3814,7 @@ 'Content-Type': 'application/json', ...buildApiHeaders() }, - body: JSON.stringify({ - branchName: newBranchName, - fromBranch: fromBranch || 'master' // Final fallback - }) + body: JSON.stringify(requestBody) }); if (!response.ok) {