This repository has no description
1<script lang="ts">
2 import { resolve } from "$app/paths";
3 import { getAuth } from "$lib/auth.svelte";
4 import { createBobbinClient } from "$lib/api/client";
5 import { count } from "$lib/api/count";
6 import { createLoad } from "$lib/action.svelte";
7 import type { RepoInfo } from "./types";
8
9 interface Props {
10 repo: RepoInfo;
11 /**
12 * Overrides the SSH key lookup, for deterministic stories/tests.
13 * Left unset in real usage, in which case it's figured out from the API.
14 */
15 hasSshKey?: boolean;
16 }
17
18 let { repo, hasSshKey }: Props = $props();
19
20 const auth = getAuth();
21 const isOwner = $derived(auth.currentDid === repo.ownerDid);
22 // same host rewrite as the clone urls
23 const sshHost = $derived(
24 (repo.knot === "knot1.tangled.sh" ? "tangled.org" : repo.knot)
25 .replace(/^[a-z]+:\/\//, "")
26 .split(/[:/]/)[0]
27 );
28 const remote = $derived(`git@${sshHost}:${repo.repoDid ?? `${repo.ownerHandle}/${repo.name}`}`);
29
30 const keyStatus = createLoad(async (): Promise<boolean | undefined> => {
31 if (hasSshKey !== undefined) {
32 return hasSshKey;
33 }
34
35 const owner = isOwner;
36 const did = auth.currentDid;
37 const serviceUrl = auth.bobbinUrl;
38 if (!owner || !did) return undefined;
39 try {
40 const ctx = createBobbinClient({ serviceUrl });
41 const result = await count(ctx, "sh.tangled.publicKey.countKeys", did);
42 return result.count > 0;
43 } catch {
44 // safe fallback: guide the owner through generating a key.
45 return false;
46 }
47 });
48</script>
49
50{#snippet bullet(n: number)}
51 <span
52 class="mr-2 inline-flex size-5 shrink-0 items-center justify-center rounded-full bg-background-inset align-middle typography-monospace-small font-mono"
53 >
54 {n}
55 </span>
56{/snippet}
57
58{#snippet codeBlock(lines: string[])}
59 <pre class="overflow-x-auto rounded-sm bg-background-inset p-3 font-mono text-sm">{lines.join(
60 "\n"
61 )}</pre>
62{/snippet}
63
64{#if isOwner}
65 {#if keyStatus.loading || keyStatus.data === undefined}
66 <div class="py-6" aria-hidden="true"></div>
67 {:else if keyStatus.data}
68 <div class="flex w-full place-content-center">
69 <div class="flex w-fit flex-col gap-5 py-6 text-sm">
70 <p>This is an empty repository.</p>
71 <div class="flex flex-col gap-2">
72 <p class="text-foreground-subtle">…create a new repository on the command line</p>
73 {@render codeBlock([
74 `echo "# ${repo.name}" >> README.md`,
75 "git init",
76 "git add README.md",
77 'git commit -m "initial commit"',
78 `git branch -M ${repo.defaultBranch}`,
79 `git remote add origin ${remote}`,
80 `git push -u origin ${repo.defaultBranch}`
81 ])}
82 </div>
83 <div class="flex flex-col gap-2">
84 <p class="text-foreground-subtle">
85 …or push an existing repository from the command line
86 </p>
87 {@render codeBlock([
88 `git remote add origin ${remote}`,
89 `git branch -M ${repo.defaultBranch}`,
90 `git push -u origin ${repo.defaultBranch}`
91 ])}
92 </div>
93 </div>
94 </div>
95 {:else}
96 <div class="flex w-full place-content-center">
97 <div class="flex w-fit flex-col gap-4 py-6 text-sm">
98 <p>This is an empty repository. To get started:</p>
99 <p>
100 {@render bullet(1)}First, generate a new
101 <a
102 href="https://git-scm.com/book/en/v2/Git-on-the-Server-Generating-Your-SSH-Public-Key"
103 rel="noopener"
104 class="underline">SSH key pair</a
105 >.
106 </p>
107 <p>
108 {@render bullet(2)}Then add the public key from the
109 <a href={resolve("/settings/keys")} class="underline">keys page</a> in your settings.
110 </p>
111 <p>
112 {@render bullet(3)}Configure your remote to
113 <code class="rounded-sm bg-background-inset px-1 font-mono">{remote}</code>
114 </p>
115 <p>{@render bullet(4)}Push!</p>
116 </div>
117 </div>
118 {/if}
119{:else}
120 <p class="py-6 text-center text-foreground-subtle">This is an empty repository.</p>
121{/if}