Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
165 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Composer from the workspace's own repositories, and go get from g1t.sh1import { data } from "react-router";
2
3import {
4 type Capability,
5 type Repo,
6 type Result,
7 type Viewer,
8 abilities,
9 can,
10 granted,
11 httpStatus,
A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so.12 mirrorWritable,
Composer from the workspace's own repositories, and go get from g1t.sh13 needs,
14 permission,
15} from "@g1t/contracts";
16
17import type { ViewerAccess } from "./access";
A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so.18import { mirrorReason } from "./mirror";
Merge project overview: one branch_drift call, spliced histories, cached tags, 6 repos calls instead of 2519import { projects, repos, work } from "./services.server";
Composer from the workspace's own repositories, and go get from g1t.sh20import { getViewer } from "./session.server";
21
22type Context = Parameters<typeof getViewer>[0];
23type RepoParams = { owner?: string; repo?: string };
24
25/**
26 * One count of a project's open issues and pull requests per request: the
27 * sidebar (root) and the project's tabs (its layout) both show them.
28 */
29const tallies = new WeakMap<object, Map<string, ReturnType<typeof work.counts>>>();
30
31export function countsFor(context: Context, params: RepoParams): ReturnType<typeof work.counts> {
32 const key = `${params.owner}/${params.repo}`.toLowerCase();
33 let seen = tallies.get(context);
34 if (!seen) tallies.set(context, (seen = new Map()));
35 let found = seen.get(key);
36 if (!found) {
37 found = work.counts({ namespace: params.owner ?? "", name: params.repo ?? "" }, getViewer(context));
38 seen.set(key, found);
39 }
40 return found;
41}
42
43/**
44 * The repositories of these ids the viewer can read: one call for all of
45 * them, then one each for any it leaves out (forks).
46 */
47export async function readableRepos(ids: string[], viewer: Viewer): Promise<Repo[]> {
48 if (ids.length === 0) return [];
49 const found = await repos.readable(ids, viewer).catch(() => [] as Repo[]);
50 const seen = new Set(found.map((repo) => repo.id));
51 const rest = await Promise.all(ids.filter((id) => !seen.has(id)).map((id) => repos.getById(id, viewer).catch(() => null)));
52 return [...found, ...rest.flatMap((repo) => (repo?.ok ? [repo.value] : []))];
53}
54
55/**
56 * One lookup of a repository per request: the repository's layout and the
57 * page under it load at the same time and both need it.
58 */
59const lookups = new WeakMap<object, Map<string, Promise<Result<Repo>>>>();
60
61export function repoFor(context: Context, params: RepoParams): Promise<Result<Repo>> {
62 const key = `${params.owner}/${params.repo}`.toLowerCase();
63 let seen = lookups.get(context);
64 if (!seen) lookups.set(context, (seen = new Map()));
65 let found = seen.get(key);
66 if (!found) {
67 found = repos.get({ namespace: params.owner ?? "", name: params.repo ?? "" }, getViewer(context));
68 seen.set(key, found);
69 }
70 return found;
71}
72
Merge project overview: one branch_drift call, spliced histories, cached tags, 6 repos calls instead of 2573/**
74 * One lookup of a project per request: the project's layout and its
75 * overview load at the same time and both need it.
76 */
77const projectLookups = new WeakMap<object, Map<string, ReturnType<typeof projects.get>>>();
78
79export function projectFor(context: Context, params: RepoParams): ReturnType<typeof projects.get> {
80 const key = `${params.owner}/${params.repo}`.toLowerCase();
81 let seen = projectLookups.get(context);
82 if (!seen) projectLookups.set(context, (seen = new Map()));
83 let found = seen.get(key);
84 if (!found) {
85 found = projects.get(params.owner ?? "", params.repo ?? "", getViewer(context));
86 seen.set(key, found);
87 }
88 return found;
89}
90
Composer from the workspace's own repositories, and go get from g1t.sh91/** The viewer's role on a repository and what it lets them do. */
92export function accessFor(viewer: Viewer, repo: Repo): ViewerAccess {
93 return {
94 role: permission(viewer, repo),
95 // A role of their own, not only because the repository is public.
96 insider: viewer ? granted(viewer, repo) != null : false,
97 can: abilities(viewer, repo),
98 };
99}
100
101/**
102 * The repository and the viewer's access to it, refusing with a 404 when
103 * they cannot read it and a 403 that says which role is needed when they
104 * can read it but not do `capability`.
105 */
106export async function requireRepo(context: Context, params: RepoParams, capability: Capability = "read") {
107 const viewer = getViewer(context);
108 const found = await repoFor(context, params);
109 if (!found.ok) {
110 if (found.error.code === "not_found" || found.error.code === "forbidden") throw data(null, { status: 404 });
111 throw data(found.error.message, { status: httpStatus(found.error) });
112 }
113 const access = accessFor(viewer, found.value);
114 if (!access.can.read) throw data(null, { status: 404 });
115 if (!access.can[capability]) throw data(needs(capability), { status: 403 });
116 return { viewer, repo: found.value, access };
117}
118
119/**
120 * Pages only people with a role of their own see (plans, memory,
121 * deployments, security, settings): a 404 for anyone else, as before.
122 */
123export async function requireInsider(context: Context, params: RepoParams, capability: Capability = "read") {
124 const found = await requireRepo(context, params, "read");
125 if (!found.access.insider) throw data(null, { status: 404 });
126 if (!found.access.can[capability]) throw data(needs(capability), { status: 403 });
127 return found;
128}
129
130/** The viewer's access, or none when the repository cannot be read. */
131export async function accessTo(context: Context, params: RepoParams): Promise<ViewerAccess> {
132 const found = await repoFor(context, params);
133 return found.ok ? accessFor(getViewer(context), found.value) : { role: null, insider: false, can: abilities(null, { id: "", namespace: "", isPrivate: true }) };
134}
135
136/**
137 * For an action: why the viewer may not do `capability` here, or null when
138 * they may. Not cached, since the action may change the repository.
139 */
140export async function refusal(context: Context, params: RepoParams, capability: Capability): Promise<string | null> {
141 const viewer = getViewer(context);
142 const found = await repos.get({ namespace: params.owner ?? "", name: params.repo ?? "" }, viewer);
143 if (!found.ok) return found.error.message;
144 return can(viewer, found.value, capability) ? null : needs(capability);
145}
146
147/** For an action whose page only people with `capability` see: a 403 that says why, otherwise nothing. */
148export async function requireCapability(context: Context, params: RepoParams, capability: Capability): Promise<void> {
149 const refused = await refusal(context, params, capability);
150 if (refused) throw data(refused, { status: 403 });
151}
A desktop release goes out with what can be built. Linux is built on g1t's machines in every release; Windows and macOS each wait on a repository variable: a machine registered for them, or for Windows a cross build on Linux once aka.ms and download.visualstudio.microsoft.com are workflow-only domains, which is where the first release stopped. A platform with no machine is skipped and the download page says it is coming, with a word for the visitor whose platform this release lacks. The guide and CONTRIBUTING say so.152
153/**
154 * For an action that would open, change or run something in the
155 * repository (an issue, a pull request, a label, a release, an agent, a
156 * deployment): a 409 that says why when it is a mirror that is not taken
157 * over (`mirrorWritable` in the contracts), otherwise nothing. The
158 * services refuse too; this answers before anything is tried. Settings,
159 * scans and anything that only reads stay open on a mirror.
160 */
161export async function requireWritableRepo(context: Context, params: RepoParams): Promise<void> {
162 const found = await repoFor(context, params);
163 if (!found.ok) return;
164 if (!mirrorWritable(found.value.mirror)) throw data(mirrorReason(found.value), { status: 409 });
165}

This file's history is long; its oldest lines are credited to the oldest commit read.