Signed by hanna SSH key fingerprint: SHA256:4g9cWhkAAw8gwqhJUcVbSnGEvdGwklW+1Aa/fMUu59k
crates/config/src/lib.rs +1 −0 crates/config/src/types.rs +3 −0 crates/store/src/lfs.rs +87 −0 crates/store/src/lib.rs +1 −0 fabrica.example.toml +1 −0 migrations/postgres/0013_lfs.sql +10 −0 migrations/sqlite/0013_lfs.sql +10 −0 crates/config/src/lib.rs +1 −0 183 183 184 check_dir_creatable ( "storage.data_dir" , & config. storage. data_dir, & mut errors) ; 184 check_dir_creatable ( "storage.data_dir" , & config. storage. data_dir, & mut errors) ; 185 check_dir_creatable ( "storage.repo_dir" , & config. storage. repo_dir, & mut errors) ; 185 check_dir_creatable ( "storage.repo_dir" , & config. storage. repo_dir, & mut errors) ; 186 check_dir_creatable ( "storage.lfs_dir" , & config. storage. lfs_dir, & mut errors) ; 186 187 187 188 188 if config. mail. backend == MailBackend :: Smtp { 189 if config. mail. backend == MailBackend :: Smtp {
crates/config/src/types.rs +3 −0 278 pub data_dir: PathBuf , 278 pub data_dir: PathBuf , 279 279 280 pub repo_dir: PathBuf , 280 pub repo_dir: PathBuf , 281 282 pub lfs_dir: PathBuf , 281 } 283 } 282 284 283 impl Default for Storage { 285 impl Default for Storage { 285 Self { 287 Self { 286 data_dir: PathBuf :: from ( "/var/lib/fabrica" ) , 288 data_dir: PathBuf :: from ( "/var/lib/fabrica" ) , 287 repo_dir: PathBuf :: from ( "/var/lib/fabrica/repos" ) , 289 repo_dir: PathBuf :: from ( "/var/lib/fabrica/repos" ) , 290 lfs_dir: PathBuf :: from ( "/var/lib/fabrica/lfs" ) , 288 } 291 } 289 } 292 } 290 } 293 }
crates/store/src/lfs.rs +87 −0 1 2 3 4 5 6 7 8 9 10 use sqlx:: Row ; 11 12 use crate :: { Store , StoreError , new_id, now_ms} ; 13 14 impl Store { 15 16 17 18 19 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 30 31 32 33 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 48 49 50 51 52 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 74 75 76 77 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 }
crates/store/src/lib.rs +1 −0 31 mod issues; 31 mod issues; 32 mod keys; 32 mod keys; 33 mod labels; 33 mod labels; 34 mod lfs; 34 mod repos; 35 mod repos; 35 mod sessions; 36 mod sessions; 36 mod tokens; 37 mod tokens;
fabrica.example.toml +1 −0 41 [ storage ] 41 [ storage ] 42 data_dir = "/var/lib/fabrica" 42 data_dir = "/var/lib/fabrica" 43 repo_dir = "/var/lib/fabrica/repos" 43 repo_dir = "/var/lib/fabrica/repos" 44 lfs_dir = "/var/lib/fabrica/lfs" 44 45 45 [ database ] 46 [ database ] 46 url = "sqlite:///var/lib/fabrica/fabrica.db" 47 url = "sqlite:///var/lib/fabrica/fabrica.db"
migrations/postgres/0013_lfs.sql +10 −0 1 -- Git LFS: track which content-addressed objects (by sha256 oid) each repo has 2 -- stored. The bytes live on disk under storage.lfs_dir, sharded by oid prefix. 3 CREATE TABLE lfs_objects ( 4 id TEXT PRIMARY KEY , 5 repo_id TEXT NOT NULL REFERENCES repos ( id) ON DELETE CASCADE , 6 oid TEXT NOT NULL , 7 size BIGINT NOT NULL , 8 created_at BIGINT NOT NULL 9 ) ; 10 CREATE UNIQUE INDEX idx_lfs_objects_repo_oid ON lfs_objects ( repo_id, oid) ;
migrations/sqlite/0013_lfs.sql +10 −0 1 -- Git LFS: track which content-addressed objects (by sha256 oid) each repo has 2 -- stored. The bytes live on disk under storage.lfs_dir, sharded by oid prefix. 3 CREATE TABLE lfs_objects ( 4 id TEXT PRIMARY KEY , 5 repo_id TEXT NOT NULL REFERENCES repos ( id) ON DELETE CASCADE , 6 oid TEXT NOT NULL , 7 size BIGINT NOT NULL , 8 created_at BIGINT NOT NULL 9 ) ; 10 CREATE UNIQUE INDEX idx_lfs_objects_repo_oid ON lfs_objects ( repo_id, oid) ;