90 lines
2.9 KiB
Rust
90 lines
2.9 KiB
Rust
use crate::GitError;
|
|
use crate::hook::sync::HookMetaDataSync;
|
|
use db::database::AppTransaction;
|
|
use models::repos::repo_lfs_object;
|
|
use sea_orm::*;
|
|
use std::collections::HashSet;
|
|
|
|
impl HookMetaDataSync {
|
|
pub async fn sync_lfs_objects(&self, txn: &AppTransaction) -> Result<(), GitError> {
|
|
let repo_id = self.repo.id;
|
|
|
|
let existing: Vec<repo_lfs_object::Model> = repo_lfs_object::Entity::find()
|
|
.filter(repo_lfs_object::Column::Repo.eq(repo_id))
|
|
.all(txn)
|
|
.await
|
|
.map_err(|e| GitError::IoError(format!("failed to query lfs objects: {}", e)))?;
|
|
|
|
let mut existing_oids: HashSet<String> = existing.into_iter().map(|o| o.oid).collect();
|
|
|
|
let local_oids = self.domain.lfs_object_list()?;
|
|
let now = chrono::Utc::now();
|
|
|
|
let mut new_objects = Vec::new();
|
|
|
|
for oid in local_oids {
|
|
let oid_str = oid.as_str().to_string();
|
|
|
|
if existing_oids.contains(&oid_str) {
|
|
existing_oids.remove(&oid_str);
|
|
continue;
|
|
}
|
|
|
|
let path = match self.domain.lfs_object_path(&oid) {
|
|
Ok(p) => p,
|
|
Err(e) => {
|
|
slog::warn!(
|
|
self.logger,
|
|
"invalid LFS OID in local objects directory: {}",
|
|
e
|
|
);
|
|
continue;
|
|
}
|
|
};
|
|
let size = if let Ok(meta) = std::fs::metadata(&path) {
|
|
meta.len() as i64
|
|
} else {
|
|
continue;
|
|
};
|
|
|
|
let storage_path = path.to_string_lossy().to_string();
|
|
|
|
new_objects.push(repo_lfs_object::ActiveModel {
|
|
repo: Set(repo_id),
|
|
oid: Set(oid_str),
|
|
size: Set(size),
|
|
storage_path: Set(storage_path),
|
|
uploaded_by: Set(None),
|
|
uploaded_at: Set(now),
|
|
..Default::default()
|
|
});
|
|
}
|
|
|
|
if !new_objects.is_empty() {
|
|
// Insert in batches
|
|
for chunk in new_objects.chunks(100) {
|
|
repo_lfs_object::Entity::insert_many(chunk.to_vec())
|
|
.exec(txn)
|
|
.await
|
|
.map_err(|e| {
|
|
GitError::IoError(format!("failed to insert lfs objects: {}", e))
|
|
})?;
|
|
}
|
|
}
|
|
|
|
// Remove objects that no longer exist on disk
|
|
if !existing_oids.is_empty() {
|
|
repo_lfs_object::Entity::delete_many()
|
|
.filter(repo_lfs_object::Column::Repo.eq(repo_id))
|
|
.filter(repo_lfs_object::Column::Oid.is_in(existing_oids))
|
|
.exec(txn)
|
|
.await
|
|
.map_err(|e| {
|
|
GitError::IoError(format!("failed to delete stale lfs objects: {}", e))
|
|
})?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|