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.

Commit

Repos lists deleted repositories that can still be restored

Work's migration job paged only live repositories, so a repository deleted while it ran left its work items without a path, private, with their labels and old numbers unmerged. deleted_repos pages the others, with whether each is private, for the job that records them.

G1T-Session:
ses_01m56vxcstesp8b57jt5edge6y
syntaqxcommitted Parentfc89c5eBrowse files
3 files+58−10/3 viewed
+20−0
14801480 pub owner_id: String,
14811481 }
14821482
1483+/// `deleted_repos` takes [`AllIdsArgs`]: every repository that is not a
1484+/// fork and is deleted but not purged yet (so it may still be restored),
1485+/// by id, a page at a time, for work recording where such a repository's
1486+/// work items came from. Returns [`DeletedRepoPage`].
1487+#[derive(Clone, Debug, Default, Serialize, Deserialize)]
1488+pub struct DeletedRepoPage {
1489+ pub repos: Vec<RestorableRepo>,
1490+ /// Where the next page starts; null on the last.
1491+ pub next: Option<String>,
1492+}
1493+
1494+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1495+pub struct RestorableRepo {
1496+ pub id: String,
1497+ /// Its workspace's slug.
1498+ pub namespace: String,
1499+ pub name: String,
1500+ pub is_private: bool,
1501+}
1502+
14831503 /// `visibility`: which of these repositories (`namespace/name`) are
14841504 /// private, for billing, which pays for work on public ones from g1t's
14851505 /// open-source pool. A pull request's working copy answers as the
+8−0
30383038 let next = (repos.len() == limit as usize).then(|| repos.last().map(|repo| repo.id.clone())).flatten();
30393039 reply(&CreatorPage { repos, next })
30403040 }
3041+ // Work, once: where deleted repositories' work items came from.
3042+ "deleted_repos" => {
3043+ let a: AllIdsArgs = args(body)?;
3044+ let limit = a.limit.clamp(1, 500);
3045+ let repos = repos.registry.deleted_after(a.after.as_deref(), limit).await?;
3046+ let next = (repos.len() == limit as usize).then(|| repos.last().map(|repo| repo.id.clone())).flatten();
3047+ reply(&g1t_contracts::repos::DeletedRepoPage { repos, next })
3048+ }
30413049 "all_ids" => {
30423050 let a: AllIdsArgs = args(body)?;
30433051 let limit = a.limit.clamp(1, 500);
+30−1
554554 .collect())
555555 }
556556
557− /// Repositories that are not forks, by id, a page at a time.
557+ /// Repositories that are not forks and are deleted but not purged yet,
558+ /// by id after `after`, with whether each is private.
559+ pub async fn deleted_after(&self, after: Option<&str>, limit: u32) -> Result<Vec<g1t_contracts::repos::RestorableRepo>> {
560+ #[derive(Deserialize)]
561+ struct Row {
562+ id: String,
563+ namespace: String,
564+ name: String,
565+ is_private: u8,
566+ }
567+ Ok(self
568+ .db
569+ .prepare(
570+ "SELECT id, namespace, name, is_private FROM repos
571+ WHERE fork_of IS NULL AND deleted_at IS NOT NULL AND id > ? ORDER BY id LIMIT ?",
572+ )
573+ .bind(&[after.unwrap_or("").into(), limit.into()])?
574+ .all()
575+ .await?
576+ .results::<Row>()?
577+ .into_iter()
578+ .map(|row| g1t_contracts::repos::RestorableRepo {
579+ id: row.id,
580+ namespace: row.namespace,
581+ name: row.name,
582+ is_private: row.is_private != 0,
583+ })
584+ .collect())
585+ }
586+
558587 /// Repositories that are not forks, with who created each, by id after
559588 /// `after`.
560589 pub async fn creators_after(&self, after: Option<&str>, limit: u32) -> Result<Vec<g1t_contracts::repos::RepoCreator>> {

Comments

Sign in to comment.