fabrica

hanna/fabrica

2872 bytes
Raw
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Git-LFS object bookkeeping: which content-addressed objects (by sha256 oid)
6//! each repository has stored. The bytes themselves live on disk under
7//! `storage.lfs_dir`; this table answers "does this repo have this object?" for
8//! the batch API and access control.
9
10use sqlx::Row;
11
12use crate::{Store, StoreError, new_id, now_ms};
13
14impl Store {
15 /// Whether `repo_id` has an LFS object with this `oid` recorded.
16 ///
17 /// # Errors
18 ///
19 /// Returns [`StoreError::Query`] on a database failure.
20 pub async fn lfs_object_exists(&self, repo_id: &str, oid: &str) -> Result<bool, StoreError> {
21 let row = sqlx::query("SELECT 1 AS n FROM lfs_objects WHERE repo_id = $1 AND oid = $2")
22 .bind(repo_id)
23 .bind(oid)
24 .fetch_optional(&self.pool)
25 .await?;
26 Ok(row.is_some())
27 }
28
29 /// The stored size (bytes) of an LFS object in `repo_id`, if present.
30 ///
31 /// # Errors
32 ///
33 /// Returns [`StoreError::Query`] on a database failure.
34 pub async fn lfs_object_size(
35 &self,
36 repo_id: &str,
37 oid: &str,
38 ) -> Result<Option<i64>, StoreError> {
39 let row = sqlx::query("SELECT size AS n FROM lfs_objects WHERE repo_id = $1 AND oid = $2")
40 .bind(repo_id)
41 .bind(oid)
42 .fetch_optional(&self.pool)
43 .await?;
44 Ok(row.map(|r| r.try_get("n")).transpose()?)
45 }
46
47 /// Record that `repo_id` holds an LFS object (`oid`, `size`). Idempotent: a
48 /// repeat upload of the same object is a no-op.
49 ///
50 /// # Errors
51 ///
52 /// Returns [`StoreError::Query`] on a database failure.
53 pub async fn lfs_object_add(
54 &self,
55 repo_id: &str,
56 oid: &str,
57 size: i64,
58 ) -> Result<(), StoreError> {
59 sqlx::query(
60 "INSERT INTO lfs_objects (id, repo_id, oid, size, created_at) \
61 VALUES ($1, $2, $3, $4, $5) ON CONFLICT (repo_id, oid) DO NOTHING",
62 )
63 .bind(new_id())
64 .bind(repo_id)
65 .bind(oid)
66 .bind(size)
67 .bind(now_ms())
68 .execute(&self.pool)
69 .await?;
70 Ok(())
71 }
72
73 /// The total bytes of LFS objects tracked for `repo_id`.
74 ///
75 /// # Errors
76 ///
77 /// Returns [`StoreError::Query`] on a database failure.
78 pub async fn lfs_repo_bytes(&self, repo_id: &str) -> Result<i64, StoreError> {
79 let n: i64 =
80 sqlx::query("SELECT COALESCE(SUM(size), 0) AS n FROM lfs_objects WHERE repo_id = $1")
81 .bind(repo_id)
82 .fetch_one(&self.pool)
83 .await?
84 .try_get("n")?;
85 Ok(n)
86 }
87}