Add local file conflict metadata
This commit is contained in:
parent
e1f36ffafb
commit
20c88af800
13 changed files with 673 additions and 15 deletions
|
|
@ -1,7 +1,10 @@
|
|||
pub mod service;
|
||||
|
||||
use geth_auth::{AuthExplanation, AuthOp, AuthOpKind};
|
||||
use geth_cas::{BlobInfoSummary, FileRoot, FileRootScan, LocalCas, hash_path};
|
||||
use geth_cas::{
|
||||
BlobInfoSummary, FileConflict, FileConflictKind, FileConflictResolution, FileConflictStatus,
|
||||
FileRoot, FileRootScan, LocalCas, hash_path,
|
||||
};
|
||||
use geth_config::{GethConfig, GethPaths, RelayMode};
|
||||
use geth_control::{
|
||||
CasBlob, ControlRequest, ControlResponse, KeychainStatusResponse, NodeIdResponse,
|
||||
|
|
@ -23,9 +26,9 @@ use geth_ssh_identity::{
|
|||
cert_request_id, certificate_id, openssh_krl_spec, revocation_id, ssh_public_key_fingerprint,
|
||||
};
|
||||
use geth_store::{
|
||||
Store, StoredAuthOp, StoredDbResource, StoredDocumentResource, StoredFileRoot,
|
||||
StoredKeychainOp, StoredKvEntry, StoredKvStore, StoredResource, StoredResourceSecret,
|
||||
StoredSshCertRequest, StoredSshCertificate, StoredSshRevocation,
|
||||
Store, StoredAuthOp, StoredDbResource, StoredDocumentResource, StoredFileConflict,
|
||||
StoredFileRoot, StoredKeychainOp, StoredKvEntry, StoredKvStore, StoredResource,
|
||||
StoredResourceSecret, StoredSshCertRequest, StoredSshCertificate, StoredSshRevocation,
|
||||
};
|
||||
use geth_types::{
|
||||
AuthOpId, Capability, KeyId, NodeId, PrincipalId, ResourceId, ResourceKind, ResourceName,
|
||||
|
|
@ -414,6 +417,81 @@ pub fn handle_request(
|
|||
},
|
||||
})
|
||||
}
|
||||
ControlRequest::CasConflictRecord {
|
||||
root,
|
||||
path,
|
||||
kind,
|
||||
detail,
|
||||
base_tree,
|
||||
local_tree,
|
||||
remote_tree,
|
||||
} => {
|
||||
geth_cas::validate_file_root_name(&root)?;
|
||||
if let Some(hash) = &base_tree {
|
||||
geth_cas::validate_hash(hash)?;
|
||||
}
|
||||
if let Some(hash) = &local_tree {
|
||||
geth_cas::validate_hash(hash)?;
|
||||
}
|
||||
if let Some(hash) = &remote_tree {
|
||||
geth_cas::validate_hash(hash)?;
|
||||
}
|
||||
let root_record = store
|
||||
.get_file_root_by_name(&root)?
|
||||
.ok_or_else(|| NodeError::ResourceNotFound(format!("file-root:{root}")))?;
|
||||
let kind = FileConflictKind::parse(&kind)?;
|
||||
let created_at = geth_store::now_ms();
|
||||
let conflict_id = generated_file_conflict_id(&root, &path, kind.as_str(), created_at);
|
||||
let conflict = StoredFileConflict {
|
||||
conflict_id,
|
||||
root_name: root,
|
||||
resource_id: root_record.resource_id,
|
||||
path,
|
||||
kind: kind.as_str().to_owned(),
|
||||
status: FileConflictStatus::Open.as_str().to_owned(),
|
||||
base_tree_hash: base_tree.map(|hash| hash.to_string()),
|
||||
local_tree_hash: local_tree.map(|hash| hash.to_string()),
|
||||
remote_tree_hash: remote_tree.map(|hash| hash.to_string()),
|
||||
detail,
|
||||
resolution: None,
|
||||
resolution_note: None,
|
||||
created_at_ms: created_at,
|
||||
resolved_at_ms: None,
|
||||
};
|
||||
store.upsert_file_conflict(&conflict)?;
|
||||
Ok(ControlResponse::CasConflictRecorded {
|
||||
conflict: file_conflict_from_stored(conflict)?,
|
||||
})
|
||||
}
|
||||
ControlRequest::CasConflictList { root } => {
|
||||
if let Some(root) = root.as_deref() {
|
||||
geth_cas::validate_file_root_name(root)?;
|
||||
}
|
||||
let conflicts = store
|
||||
.list_file_conflicts(root.as_deref())?
|
||||
.into_iter()
|
||||
.map(file_conflict_from_stored)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
Ok(ControlResponse::CasConflictList { conflicts })
|
||||
}
|
||||
ControlRequest::CasConflictResolve {
|
||||
conflict_id,
|
||||
resolution,
|
||||
note,
|
||||
} => {
|
||||
let resolution = FileConflictResolution::parse(&resolution)?;
|
||||
let mut conflict = store
|
||||
.get_file_conflict(&conflict_id)?
|
||||
.ok_or_else(|| NodeError::ResourceNotFound(conflict_id.clone()))?;
|
||||
conflict.status = FileConflictStatus::Resolved.as_str().to_owned();
|
||||
conflict.resolution = Some(resolution.as_str().to_owned());
|
||||
conflict.resolution_note = note;
|
||||
conflict.resolved_at_ms = Some(geth_store::now_ms());
|
||||
store.upsert_file_conflict(&conflict)?;
|
||||
Ok(ControlResponse::CasConflictResolved {
|
||||
conflict: file_conflict_from_stored(conflict)?,
|
||||
})
|
||||
}
|
||||
ControlRequest::KeychainInit { admin_key_path } => {
|
||||
let mut ops = Vec::new();
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
|
|
@ -1136,6 +1214,29 @@ fn file_root_from_stored(stored: &StoredFileRoot) -> FileRoot {
|
|||
}
|
||||
}
|
||||
|
||||
fn file_conflict_from_stored(stored: StoredFileConflict) -> Result<FileConflict, NodeError> {
|
||||
Ok(FileConflict {
|
||||
id: stored.conflict_id,
|
||||
root: stored.root_name,
|
||||
resource: stored.resource_id,
|
||||
path: stored.path,
|
||||
kind: FileConflictKind::parse(&stored.kind)?,
|
||||
status: FileConflictStatus::parse(&stored.status)?,
|
||||
base_tree: stored.base_tree_hash.map(Into::into),
|
||||
local_tree: stored.local_tree_hash.map(Into::into),
|
||||
remote_tree: stored.remote_tree_hash.map(Into::into),
|
||||
detail: stored.detail,
|
||||
resolution: stored
|
||||
.resolution
|
||||
.as_deref()
|
||||
.map(FileConflictResolution::parse)
|
||||
.transpose()?,
|
||||
resolution_note: stored.resolution_note,
|
||||
created_at_ms: stored.created_at_ms,
|
||||
resolved_at_ms: stored.resolved_at_ms,
|
||||
})
|
||||
}
|
||||
|
||||
fn ensure_resource_exists(store: &Store, resource_id: &str) -> Result<(), NodeError> {
|
||||
if store
|
||||
.list_resources()?
|
||||
|
|
@ -1240,6 +1341,13 @@ fn generated_grant_id(subject: &str, resource: &str, capability: &str) -> String
|
|||
)
|
||||
}
|
||||
|
||||
fn generated_file_conflict_id(root: &str, path: &str, kind: &str, created_at_ms: i64) -> String {
|
||||
format!(
|
||||
"file-conflict:{}",
|
||||
geth_crypto::blake3_hex(format!("{created_at_ms}\0{root}\0{path}\0{kind}").as_bytes())
|
||||
)
|
||||
}
|
||||
|
||||
fn generated_auth_op_id(
|
||||
kind: &str,
|
||||
resource: &str,
|
||||
|
|
|
|||
Loading…
Reference in a new issue