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
495 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.

Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.01//! Renaming a workspace: changing its slug, the first segment of its URLs,
2//! the way GitHub renames an organization.
3//!
4//! The workspace keeps its id, members, tokens and display name. Its old
5//! slug is recorded in `workspace_redirects`, pointing at the workspace's
6//! id, so that old addresses resolve to whatever the slug is now: renaming
7//! twice chains, because every old slug points at the same id. An old slug
8//! stays reserved for the workspace that had it for [`SLUG_HOLD_DAYS`], so
9//! nobody else can take it while links to it still redirect; the workspace
10//! itself can rename back to it. Renames are limited to one per
11//! [`RENAME_COOLDOWN_HOURS`] to stop churn.
12//!
13//! The rename publishes `workspace.renamed`; every other service moves the
14//! rows it keeps under the slug when it hears it.
15
16use g1t_contracts::events::{NewEvent, Publish, WorkspaceRenamed};
17use g1t_contracts::identity::*;
18use g1t_contracts::time::rfc3339;
A workflow's `uses: actions/setup-node@v4` means GitHub's `actions` again, whoever is on g1t. g1t looked for a repository on g1t before GitHub, and anyone could make a public workspace called `actions`, `docker` or `aws-actions` and have its `setup-node` run in every workflow that names GitHub's, with that job's secrets. Now another workspace's public repository answers only for a name GitHub has no public repository of; the caller's own workspace and g1t's own `g1t/…` still answer from g1t, and when GitHub can't be asked, GitHub's is used. The names of the GitHub accounts whose actions workflows use most can no longer be registered, renamed to, or taken by signing up with GitHub (which suggests the name with `-gh`); an account that has one keeps it, and mentions and invitations still find it. The Actions, authentication and workspaces guides say so.19use g1t_contracts::{FailureCode, Outcome, PrincipalKind, Role, is_action_owner_name, is_valid_namespace};
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.020use g1t_kit::now_ms;
21use serde::Deserialize;
22use worker::Result;
23
24use crate::Identity;
25
26const HOUR_MS: u64 = 60 * 60 * 1000;
27const DAY_MS: u64 = 24 * HOUR_MS;
28const SOURCE: &str = "identity";
29const TAKEN: &str = "That workspace name is taken.";
30/// How many times publishing the event is tried before giving up.
31const PUBLISH_ATTEMPTS: u32 = 3;
32
33/// The earliest `created_at` of a redirect that still holds its slug.
34pub fn hold_cutoff(now_ms: u64) -> String {
35 rfc3339(now_ms.saturating_sub(SLUG_HOLD_DAYS * DAY_MS))
36}
37
38/// Everything about a wanted slug that decides whether a workspace may
39/// take it, as read from the database.
40#[derive(Debug, Default)]
41pub struct Facts<'a> {
42 /// The workspace's id and its slug now.
43 pub workspace_id: &'a str,
44 pub current: &'a str,
45 /// The slug asked for, lowercased and trimmed.
46 pub wanted: &'a str,
47 /// Another person's username is `wanted`. The actor's own is theirs
48 /// to use, as when creating a workspace.
49 pub someone_elses_username: bool,
50 /// Another workspace's slug is `wanted`.
51 pub another_workspace: bool,
52 /// A redirect holds `wanted`: the workspace it points at, and when it
53 /// was made.
54 pub redirect: Option<(&'a str, &'a str)>,
55 /// When the workspace was last renamed, if ever.
56 pub last_renamed_at: Option<&'a str>,
57 /// A deleted workspace had `wanted`; it is never given to another.
58 pub deleted: bool,
Merge branch 'worktree-agent-a8385d293d42c913a'59 /// Staff made `wanted` an alias (aliases.rs); it stays theirs.
60 pub aliased: bool,
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.061 pub now_ms: u64,
62}
63
64/// Whether the rename `facts` describe is allowed: `Ok`, or why not, in
65/// words for the owner.
66pub fn check(facts: &Facts) -> std::result::Result<(), (FailureCode, String)> {
67 let refuse = |code, message: &str| Err((code, message.to_owned()));
68 if !is_valid_namespace(facts.wanted) {
69 return refuse(
70 FailureCode::Invalid,
71 "Workspace names use lowercase letters, digits and single hyphens, up to 39 characters, and cannot be a reserved word.",
72 );
73 }
A workflow's `uses: actions/setup-node@v4` means GitHub's `actions` again, whoever is on g1t. g1t looked for a repository on g1t before GitHub, and anyone could make a public workspace called `actions`, `docker` or `aws-actions` and have its `setup-node` run in every workflow that names GitHub's, with that job's secrets. Now another workspace's public repository answers only for a name GitHub has no public repository of; the caller's own workspace and g1t's own `g1t/…` still answer from g1t, and when GitHub can't be asked, GitHub's is used. The names of the GitHub accounts whose actions workflows use most can no longer be registered, renamed to, or taken by signing up with GitHub (which suggests the name with `-gh`); an account that has one keeps it, and mentions and invitations still find it. The Actions, authentication and workspaces guides say so.74 if is_action_owner_name(facts.wanted) {
75 return refuse(
76 FailureCode::Invalid,
77 "That name is a GitHub account whose actions workflows use, so it is kept for that account. If it is yours, contact support to prove it.",
78 );
79 }
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.080 if facts.wanted == facts.current {
81 return refuse(FailureCode::Invalid, "That is already this workspace's name.");
82 }
83 if let Some(last) = facts.last_renamed_at {
84 let cooldown_from = rfc3339(facts.now_ms.saturating_sub(RENAME_COOLDOWN_HOURS * HOUR_MS));
85 if last > cooldown_from.as_str() {
86 return refuse(
87 FailureCode::Conflict,
88 "A workspace can be renamed once a day. Try again tomorrow.",
89 );
90 }
91 }
Merge branch 'worktree-agent-a8385d293d42c913a'92 if facts.someone_elses_username || facts.another_workspace || facts.deleted || facts.aliased {
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.093 return refuse(FailureCode::Conflict, TAKEN);
94 }
95 if let Some((holder, created_at)) = facts.redirect
96 && holder != facts.workspace_id
97 && created_at >= hold_cutoff(facts.now_ms).as_str()
98 {
99 return refuse(FailureCode::Conflict, TAKEN);
100 }
101 Ok(())
102}
103
104/// A redirect as read with the slug its workspace has now.
105#[derive(Debug, Deserialize)]
106pub struct RedirectRow {
107 pub workspace_id: String,
108 /// The workspace's slug now.
109 pub slug: String,
110 pub created_at: String,
111}
112
113/// Where an old slug leads: the workspace's current slug, while the
114/// redirect still holds.
115pub fn resolve(row: Option<RedirectRow>, now_ms: u64) -> Option<String> {
116 row.filter(|row| row.created_at >= hold_cutoff(now_ms))
117 .map(|row| row.slug)
118}
119
120#[derive(Deserialize)]
121struct Target {
122 id: String,
123}
124
125impl Identity {
126 /// The redirect holding `slug`, if any, with its workspace's slug now.
127 async fn redirect(&self, slug: &str) -> Result<Option<RedirectRow>> {
128 self.db
129 .prepare(
130 "SELECT workspace_redirects.workspace_id, workspaces.slug,
131 workspace_redirects.created_at
132 FROM workspace_redirects
133 JOIN workspaces ON workspaces.id = workspace_redirects.workspace_id
134 WHERE workspace_redirects.old_slug = ?",
135 )
136 .bind(&[slug.into()])?
137 .first::<RedirectRow>(None)
138 .await
139 }
140
141 /// Whether `slug` is an old slug still reserved for the workspace that
Merge branch 'worktree-agent-a8385d293d42c913a'142 /// had it, or an alias staff set, so nobody else may register or create
143 /// it.
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0144 pub async fn slug_held(&self, slug: &str) -> Result<bool> {
Merge branch 'worktree-agent-a8385d293d42c913a'145 Ok(resolve(self.redirect(slug).await?, now_ms()).is_some() || self.is_alias(slug).await?)
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0146 }
147
Merge branch 'worktree-agent-a8385d293d42c913a'148 /// `resolve_slug`: the current slug for an old one still redirecting,
149 /// or for an alias (aliases.rs).
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0150 pub async fn resolve_slug(&self, a: SlugArgs) -> Result<Option<String>> {
151 let slug = a.slug.trim().to_lowercase();
Merge branch 'worktree-agent-a8385d293d42c913a'152 let in_use = self.get_workspace(SlugArgs { slug: slug.clone() }).await?.is_some();
153 if in_use {
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0154 return Ok(None);
155 }
Merge branch 'worktree-agent-a8385d293d42c913a'156 let alias = self.resolve_alias(SlugArgs { slug: slug.clone() }).await?;
157 let redirect = match alias {
158 Some(_) => None,
159 None => self.redirect(&slug).await?,
160 };
161 Ok(crate::aliases::resolve(in_use, alias, || resolve(redirect, now_ms())))
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0162 }
163
164 /// Checks a rename, returning the workspace's id when it is allowed.
165 async fn rename_allowed(&self, a: &RenameWorkspaceArgs) -> Result<Outcome<(String, String)>> {
166 let current = a.slug.trim().to_lowercase();
167 let wanted = a.new_slug.trim().to_lowercase();
168 if a.actor.kind != PrincipalKind::User || a.actor.role_in(&current) != Some(Role::Owner) {
169 return Ok(Outcome::fail(
170 FailureCode::Forbidden,
171 "Only an owner can rename a workspace.",
172 ));
173 }
174 if !a.actor.verified {
175 return Ok(Outcome::fail(
176 FailureCode::Forbidden,
177 "Confirm your email address before renaming a workspace.",
178 ));
179 }
180 let Some(workspace) = self
181 .db
182 .prepare("SELECT id FROM workspaces WHERE slug = ?")
183 .bind(&[current.as_str().into()])?
184 .first::<Target>(None)
185 .await?
186 else {
187 return Ok(Outcome::fail(FailureCode::NotFound, "Workspace not found."));
188 };
189 let someone_elses_username = self
190 .db
191 .prepare("SELECT id FROM users WHERE username = ? AND id != ?")
192 .bind(&[wanted.as_str().into(), a.actor.id.as_str().into()])?
193 .first::<serde_json::Value>(None)
194 .await?
195 .is_some();
196 let another_workspace = self
197 .db
198 .prepare("SELECT id FROM workspaces WHERE slug = ? AND id != ?")
199 .bind(&[wanted.as_str().into(), workspace.id.as_str().into()])?
200 .first::<serde_json::Value>(None)
201 .await?
202 .is_some();
203 let redirect = self.redirect(&wanted).await?;
204 let last_renamed_at = self
205 .db
206 .prepare("SELECT max(created_at) AS at FROM workspace_redirects WHERE workspace_id = ?")
207 .bind(&[workspace.id.as_str().into()])?
208 .first::<Option<String>>(Some("at"))
209 .await?
210 .flatten();
211 let facts = Facts {
212 workspace_id: &workspace.id,
213 current: &current,
214 wanted: &wanted,
215 someone_elses_username,
216 another_workspace,
217 redirect: redirect
218 .as_ref()
219 .map(|row| (row.workspace_id.as_str(), row.created_at.as_str())),
220 last_renamed_at: last_renamed_at.as_deref(),
221 deleted: self.slug_deleted(&wanted).await?,
Merge branch 'worktree-agent-a8385d293d42c913a'222 aliased: self.is_alias(&wanted).await?,
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0223 now_ms: now_ms(),
224 };
225 Ok(match check(&facts) {
226 Ok(()) => Outcome::Ok((workspace.id, wanted)),
227 Err((code, message)) => Outcome::fail(code, message),
228 })
229 }
230
231 pub async fn check_workspace_rename(&self, a: RenameWorkspaceArgs) -> Result<Outcome<bool>> {
232 Ok(match self.rename_allowed(&a).await? {
233 Outcome::Ok(_) => Outcome::Ok(true),
234 Outcome::Fail(failure) => Outcome::Fail(failure),
235 })
236 }
237
238 pub async fn rename_workspace(&self, a: RenameWorkspaceArgs) -> Result<Outcome<Workspace>> {
239 let (workspace_id, wanted) = match self.rename_allowed(&a).await? {
240 Outcome::Ok(allowed) => allowed,
241 Outcome::Fail(failure) => return Ok(Outcome::Fail(failure)),
242 };
243 let from = a.slug.trim().to_lowercase();
244 let now = rfc3339(now_ms());
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member245 // A workspace protected by its slug stays protected under the new
246 // one: the protection goes on its row (deletion.rs).
247 let protected = self.is_protected(&workspace_id, &from, false).await?;
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0248 self.db
249 .batch(vec![
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member250 self.db
251 .prepare("UPDATE workspaces SET protected = 1 WHERE id = ? AND ? = 1")
252 .bind(&[workspace_id.as_str().into(), u8::from(protected).into()])?,
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0253 // A redirect the workspace is renaming back to, or one whose
254 // hold has ended, gives way to the slug in use.
255 self.db
256 .prepare("DELETE FROM workspace_redirects WHERE old_slug = ?")
257 .bind(&[wanted.as_str().into()])?,
258 self.db
259 .prepare("UPDATE workspaces SET slug = ? WHERE id = ? AND slug = ?")
260 .bind(&[
261 wanted.as_str().into(),
262 workspace_id.as_str().into(),
263 from.as_str().into(),
264 ])?,
265 self.db
266 .prepare(
267 "INSERT OR REPLACE INTO workspace_redirects (old_slug, workspace_id, created_at)
268 VALUES (?, ?, ?)",
269 )
270 .bind(&[
271 from.as_str().into(),
272 workspace_id.as_str().into(),
273 now.as_str().into(),
274 ])?,
275 // Agents at work keep their scope: it names the repository
276 // by its path.
277 self.db
278 .prepare(
279 "UPDATE access_tokens SET agent_scope = json_set(agent_scope, '$.repo.namespace', ?)
280 WHERE agent_scope IS NOT NULL
281 AND json_extract(agent_scope, '$.repo.namespace') = ?",
282 )
283 .bind(&[wanted.as_str().into(), from.as_str().into()])?,
284 ])
285 .await?;
286 self.publish_renamed(WorkspaceRenamed {
287 workspace_id,
288 from,
289 to: wanted.clone(),
290 }, &a.actor.id)
291 .await;
292 Ok(match self.get_workspace(SlugArgs { slug: wanted }).await? {
293 Some(workspace) => Outcome::Ok(workspace),
294 None => Outcome::fail(FailureCode::NotFound, "Workspace not found."),
295 })
296 }
297
298 /// Tells every other service. The rename has happened by now, so a
299 /// failure is logged rather than undoing it.
300 async fn publish_renamed(&self, renamed: WorkspaceRenamed, actor: &str) {
301 let events = match self.env.service("EVENTS") {
302 Ok(events) => events,
303 Err(error) => {
304 worker::console_error!("workspace.renamed not published: {error}");
305 return;
306 }
307 };
308 let publish = Publish {
309 events: vec![NewEvent {
310 kind: "workspace.renamed",
311 source: SOURCE,
312 repo_id: None,
313 actor: Some(actor.to_owned()),
314 data: renamed,
315 }],
316 };
317 for attempt in 1..=PUBLISH_ATTEMPTS {
318 match g1t_kit::call::<_, serde_json::Value>(&events, "publish", &publish).await {
319 Ok(_) => return,
320 Err(error) => worker::console_error!(
321 "workspace.renamed publish attempt {attempt} failed: {error}"
322 ),
323 }
324 }
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use super::*;
331 use std::collections::HashMap;
332
333 const NOW: u64 = 1_790_918_179_123;
334
335 fn facts<'a>(current: &'a str, wanted: &'a str) -> Facts<'a> {
336 Facts {
337 workspace_id: "wsp_a",
338 current,
339 wanted,
340 now_ms: NOW,
341 ..Facts::default()
342 }
343 }
344
345 fn refused(facts: &Facts) -> FailureCode {
346 check(facts).unwrap_err().0
347 }
348
349 #[test]
350 fn validates_like_creation() {
351 assert!(check(&facts("acme", "acme-inc")).is_ok());
352 for bad in ["", "-acme", "acme-", "ac--me", "Acme", "acme_inc", "api", "settings", "pulls"] {
353 assert_eq!(refused(&facts("acme", bad)), FailureCode::Invalid, "{bad}");
354 }
355 assert_eq!(refused(&facts("acme", &"a".repeat(40))), FailureCode::Invalid);
356 assert_eq!(refused(&facts("acme", "acme")), FailureCode::Invalid);
357 }
358
359 #[test]
360 fn no_workspace_is_renamed_to_g1ts_names() {
361 for name in ["g1t", "g1t-agent", "G1T", "G1T-Agent"] {
362 assert_eq!(refused(&facts("acme", name)), FailureCode::Invalid, "{name}");
363 }
364 assert!(check(&facts("acme", "g1t-fans")).is_ok());
365 }
366
367 #[test]
A workflow's `uses: actions/setup-node@v4` means GitHub's `actions` again, whoever is on g1t. g1t looked for a repository on g1t before GitHub, and anyone could make a public workspace called `actions`, `docker` or `aws-actions` and have its `setup-node` run in every workflow that names GitHub's, with that job's secrets. Now another workspace's public repository answers only for a name GitHub has no public repository of; the caller's own workspace and g1t's own `g1t/…` still answer from g1t, and when GitHub can't be asked, GitHub's is used. The names of the GitHub accounts whose actions workflows use most can no longer be registered, renamed to, or taken by signing up with GitHub (which suggests the name with `-gh`); an account that has one keeps it, and mentions and invitations still find it. The Actions, authentication and workspaces guides say so.368 fn no_workspace_is_renamed_to_a_github_action_owner() {
369 for name in ["actions", "docker", "aws-actions"] {
370 assert_eq!(refused(&facts("acme", name)), FailureCode::Invalid, "{name}");
371 }
372 assert!(check(&facts("acme", "actions-team")).is_ok());
373 }
374
375 #[test]
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0376 fn refuses_names_in_use() {
377 let taken = Facts {
378 someone_elses_username: true,
379 ..facts("acme", "bob")
380 };
381 assert_eq!(refused(&taken), FailureCode::Conflict);
382 let taken = Facts {
383 another_workspace: true,
384 ..facts("acme", "globex")
385 };
386 assert_eq!(refused(&taken), FailureCode::Conflict);
387 let deleted = Facts {
388 deleted: true,
389 ..facts("acme", "initech")
390 };
391 assert_eq!(refused(&deleted), FailureCode::Conflict);
Merge branch 'worktree-agent-a8385d293d42c913a'392 let aliased = Facts {
393 aliased: true,
394 ..facts("acme", "flagon")
395 };
396 assert_eq!(refused(&aliased), FailureCode::Conflict);
Cleanup: clippy is quiet outside billing, the README says g1t, and http-cache-semantics is 4.3.0397 }
398
399 #[test]
400 fn an_old_slug_is_held_for_its_workspace_until_the_hold_ends() {
401 let recently = rfc3339(NOW - 10 * DAY_MS);
402 let long_ago = rfc3339(NOW - (SLUG_HOLD_DAYS + 1) * DAY_MS);
403 let held_by_other = Facts {
404 redirect: Some(("wsp_b", recently.as_str())),
405 ..facts("acme", "globex")
406 };
407 assert_eq!(refused(&held_by_other), FailureCode::Conflict);
408 let held_by_self = Facts {
409 redirect: Some(("wsp_a", recently.as_str())),
410 last_renamed_at: Some(recently.as_str()),
411 ..facts("acme-inc", "acme")
412 };
413 assert!(check(&held_by_self).is_ok(), "a workspace can rename back");
414 let expired = Facts {
415 redirect: Some(("wsp_b", long_ago.as_str())),
416 ..facts("acme", "globex")
417 };
418 assert!(check(&expired).is_ok(), "after the hold anyone can take it");
419 }
420
421 #[test]
422 fn renames_are_limited_to_one_a_day() {
423 let an_hour_ago = rfc3339(NOW - HOUR_MS);
424 let two_days_ago = rfc3339(NOW - 2 * DAY_MS);
425 let soon = Facts {
426 last_renamed_at: Some(an_hour_ago.as_str()),
427 ..facts("acme", "acme-inc")
428 };
429 assert_eq!(refused(&soon), FailureCode::Conflict);
430 let later = Facts {
431 last_renamed_at: Some(two_days_ago.as_str()),
432 ..facts("acme", "acme-inc")
433 };
434 assert!(check(&later).is_ok());
435 }
436
437 #[test]
438 fn hold_ends_after_the_hold_period() {
439 assert_eq!(hold_cutoff(NOW), rfc3339(NOW - SLUG_HOLD_DAYS * DAY_MS));
440 }
441
442 /// The tables, as `rename_workspace` changes them: slug by workspace
443 /// id, and old slug → (workspace id, when).
444 #[derive(Default)]
445 struct Tables {
446 workspaces: HashMap<&'static str, String>,
447 redirects: HashMap<String, (&'static str, String)>,
448 }
449
450 impl Tables {
451 /// The same steps, in the same order, as the batch.
452 fn rename(&mut self, id: &'static str, to: &str, at: u64) {
453 self.redirects.remove(to);
454 let from = self.workspaces.insert(id, to.to_owned()).unwrap();
455 self.redirects.insert(from, (id, rfc3339(at)));
456 }
457
458 /// As `redirect` + `resolve`.
459 fn resolve(&self, slug: &str, now: u64) -> Option<String> {
460 let row = self.redirects.get(slug).map(|(id, created_at)| RedirectRow {
461 workspace_id: (*id).to_owned(),
462 slug: self.workspaces[id].clone(),
463 created_at: created_at.clone(),
464 });
465 resolve(row, now)
466 }
467 }
468
469 #[test]
470 fn renames_chain_to_the_current_slug() {
471 let mut tables = Tables::default();
472 tables.workspaces.insert("wsp_a", "acme".into());
473 tables.rename("wsp_a", "acme-inc", NOW);
474 tables.rename("wsp_a", "acme-corp", NOW + 2 * DAY_MS);
475 let later = NOW + 3 * DAY_MS;
476 assert_eq!(tables.resolve("acme", later).as_deref(), Some("acme-corp"));
477 assert_eq!(tables.resolve("acme-inc", later).as_deref(), Some("acme-corp"));
478 assert_eq!(tables.resolve("unknown", later), None);
479 // Past the hold, the first old slug stops redirecting.
480 let much_later = NOW + (SLUG_HOLD_DAYS + 1) * DAY_MS;
481 assert_eq!(tables.resolve("acme", much_later), None);
482 assert_eq!(tables.resolve("acme-inc", much_later).as_deref(), Some("acme-corp"));
483 }
484
485 #[test]
486 fn renaming_back_drops_the_redirect_for_the_slug_in_use() {
487 let mut tables = Tables::default();
488 tables.workspaces.insert("wsp_a", "acme".into());
489 tables.rename("wsp_a", "acme-inc", NOW);
490 tables.rename("wsp_a", "acme", NOW + 2 * DAY_MS);
491 assert!(!tables.redirects.contains_key("acme"));
492 let later = NOW + 3 * DAY_MS;
493 assert_eq!(tables.resolve("acme-inc", later).as_deref(), Some("acme"));
494 }
495}

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